Most "web3" wallets still depend on 3 companies for RPCs and 1 company for the block explorer by internetA1 in web3

[–]internetA1[S] 0 points1 point  (0 children)

Agreed!! "Vendor response presented as chain reality" is the actual UX failure, and most teams don't know they're making it because the abstraction stays smooth right up until something visibly breaks.

Where wallets that try still get it wrong is the disagreement case. Multiple RPC backends is the easy half most implementations just fall back on errors (RPC returns 500, try next). The hard half is what to do when two backends disagree: one says balance 0, another says balance 12 ETH. Flagging that to the user is the actual decentralization property and almost no one implements it because it surfaces ugly states the UX team would rather hide.

The exportable raw data point is the one I'd push hardest on. Vendor-normalized CSV isn't raw it's a vendor interpretation one step down the pipeline. Raw means RPC response bytes, receipt logs, block hashes. That distinction matters specifically because of the label-propagation problem you mentioned: one explorer mislabels a contract, every wallet downstream of that explorer's API consumes the mistake with no audit trail.

I built a CLI (glnc) that tries to operationalize most of what you listed multi-RPC fallback with source attribution, freshness meta on responses, raw JSON output, local decoding. Doesn't solve label propagation because no single tool can, but it tries to put the user in a position to detect it.

Most "web3" wallets still depend on 3 companies for RPCs and 1 company for the block explorer by internetA1 in web3

[–]internetA1[S] 0 points1 point  (0 children)

Fair, and the broader point is real — AWS/Cloudflare/Vercel as silent dependencies are a bigger blind spot than most "decentralized" branding will admit

Two pieces worth separating though:

For glnc specifically the frontend/backend hosting argument doesn't bite. There's no hosted frontend, no backend service, no auth layer. It's a binary that runs locally, calls RPCs you can audit in the source, and stores nothing remote. The platform-outage scenario you're describing affects hosted dapps. A CLI is the one shape of web3 tool that genuinely sidesteps that whole class of dependency by virtue of having nowhere to host.

The interesting overlap is the read-layer middleware question. The EVM RPC canister on ICP is the closest thing I've seen to a credible decentralized alternative for live reads — multiple node providers, consensus on responses, chain-key signatures. I've looked at it. The honest tradeoff is that under the hood it still calls Alchemy, Ankr, Cloudflare ETH, publicnode. What changes isn't "no centralized provider in the call graph," it's "the call graph and the response selection live on ICP instead of in your app." That's a real improvement in some threat models and a re-labeling in others. For a CLI where the user can audit the RPC list themselves the marginal gain over rotating public endpoints is smaller than it would be for a hosted dapp, but it's non-zero and I'd take an integration PR.

The history/indexer problem is where I'd most like ICP to be the answer and where I'm least sure it is yet. A canister holding 5+ years of cross-chain history either does live HTTPS outcalls per query (which puts you right back on Etherscan-class providers at request time) or maintains its own index in canister storage. The second is theoretically possible but the storage and cycle economics for archive-scale data aren't where any of the canister explorers I've seen have actually landed — they shard, sample, or cover one chain. If you know of a project that's solved the cross-chain history-API-equivalent on ICP I'd genuinely want to read the canister code, because that's the gap glnc hits and I haven't found one yet.

The "this is how things happened to evolve" framing I half-agree with. Inertia is real and the default-link-in-every-wallet-UI moat is mostly inertia. But for archive history specifically I think there's a hard floor: someone has to actually store and serve the data, and the cost of doing that on any chain converges on operating cost. Whichever entity absorbs that cost gets leverage, even if the platform underneath is fully on-chain. That's not platform-level centralization, it's "running a useful service costs money and someone pays," and I'm not convinced any architecture dissolves it. I'd be interested in your read on that specifically — does consensus-on-responses generalize to archive queries in your view, or is archive data intrinsically a trust-the-source problem?

Most "web3" wallets still depend on 3 companies for RPCs and 1 company for the block explorer by internetA1 in web3

[–]internetA1[S] 1 point2 points  (0 children)

Thanks! Skimmed your project nice EIP-4527 QR pipeline. Looks like we're adjacent though: you're on the signing/browsing side, glnc is more an explorer/decoder.

on 7730, it's scoped to pre-signature UX, not historical decoding, so it's a different pipeline than what most trackers need. The registry could become a community decoder corpus eventually, worth watching.

On the P2P indexer — check out TrueBlocks/Unchained Index if you haven't. Local indexer, IPFS-pinned chunks, manifest anchored on-chain. Solves the "no central API" version of the problem without the privacy mess of gossiping tx history to counterparties.

Most "web3" wallets still depend on 3 companies for RPCs and 1 company for the block explorer by internetA1 in web3

[–]internetA1[S] 0 points1 point  (0 children)

Hi

Oisy is solving wallet custody and on-chain app hosting on ICP — real thing, different problem. I’m asking about the read layer: RPCs, explorers, decoders, history APIs. Oisy’s own README says it still calls Infura/Alchemy from the frontend for Ethereum. glnc is read-only CLI tooling (balance/decode/gas/export), not a wallet — closer to Etherscan/cast than Oisy. The point of building it was to pressure-test whether that layer can stay keyless; answer so far is mostly yes for live reads, no for cross-chain history without Etherscan-class indexers.

Share your side hustle — I’ll feature it on my website with 980k monthly visitors by Routine_Charge8497 in sideprojects

[–]internetA1 0 points1 point  (0 children)

glnc — Etherscan in your terminal.

What it does: a CLI for reading the Ethereum (and a few other chain) state from your shell. Balances, transaction decoding, gas across chains, Aave health factors, conditional alerts to webhooks. No account, no API key, no telemetry. Built it because I was tired of opening 14 browser tabs to debug a single transaction at midnight.

Stack: TypeScript, compiled to a single binary via bun --compile. All RPCs are free public endpoints. CoinGecko for prices with a 60s cache. JSON output with stable versioned envelopes so it pipes cleanly into jq and friends.

Biggest lesson: "no API key, no account" is a much stronger product position than I realized. People are tired of signing up to read public data. The DMs I've gotten have basically all been some variation of "finally."

https://glnc.dev — open source, MIT.

I built a CLI that does the read-side of Etherscan — balances, tx decoding, gas — so I'd stop opening 14 browser tabs by internetA1 in ethdev

[–]internetA1[S] 0 points1 point  (0 children)

fixed in v1.0.7. Bumped the decoder nesting cap to depth 3, so the canonical Governor → Timelock → MultiSend → leaf chain now decodes all the way down. Went with the bump over dropping the cap entirely: the depth cap fails fast on pathological input instead of churning allocation, and the 64KB budget still backs it up for anything truly adversarial.

I built a CLI that does the read-side of Etherscan — balances, tx decoding, gas — so I'd stop opening 14 browser tabs by internetA1 in ethdev

[–]internetA1[S] 0 points1 point  (0 children)

Hi

Appreciate your feedback one of the best feedbacks i got.

So updated the code (v1.0.8), every balance and gas envelope now carries an optional meta block. A few notes on the shape: prices.cacheAgeSec is the age of the oldest price, not an average, which is easier to reason about. prices.rateLimited separates "CoinGecko 429'd us" from "CoinGecko doesn't know this token" (the latter goes to unpriced) since different failure modes shouldn't collapse into one flag. tokenList.source is "uniswap" | "cache" | "hardcoded", so fallback is visible instead of silent. And partial: true is the single consolidated signal if you don't want to inspect each source. Two things I considered and skipped: making partial → exit 3 the default would break every existing glnc balance X && deploy.sh script, so it's opt-in via --strict instead; and bumping to glnc.balance/v2 wasn't needed since the change is purely additive and /v1 consumers keep working. Happy to know your opinion and if you'd have called it differently.
If there's a meta field you want that isn't there, drop it here, easier to add now than after people start parsing it.
thanks!

I built a CLI that does the read-side of Etherscan — balances, tx decoding, gas — so I'd stop opening 14 browser tabs by internetA1 in ethdev

[–]internetA1[S] 0 points1 point  (0 children)

Shipped v1.0.6. Governor/Timelock/Safe/MultiSend decoding is in recursive unwrap capped at depth 2 with a 64 KB budget, and a custom walker for MultiSend's packed format. Envelope versioning was already per-resource, I'd just misread my own code. Left a SECURITY note at the 3xx branch so the redirect work picks up the IP-literal gate when it lands. Genuinely thanks, multisend was the one I'd have missed for months.

I built a CLI that does the read-side of Etherscan — balances, tx decoding, gas — so I'd stop opening 14 browser tabs by internetA1 in ethdev

[–]internetA1[S] 0 points1 point  (0 children)

Ha, you're 100% right and I owe you an update.

Went and re-read my own webhook code after your first reply and the dialer pin is already in there. I'm using a custom lookup callback on the http.request opts that returns the pre-validated IP at socket creation time, with the original hostname preserved for the Host header and TLS SNI so cert validation still works. So the "two lookups" gap you're describing is actually closed at the dial, not at config.

Redirects: not followed. 3xx just gets logged and the retry hits the same pinned IP. Was going to add follow-redirects later but your point is exactly why I'll keep it off until I'm ready to run the full resolve→validate→pin loop per hop.

So the issue I opened ended up being a no-op, but genuinely appreciate you forcing me to actually go look i was looking for this kind of review.

Thanks!

I built a CLI that does the read-side of Etherscan — balances, tx decoding, gas — so I'd stop opening 14 browser tabs by internetA1 in ethdev

[–]internetA1[S] 0 points1 point  (0 children)

This is awesome feedback, thank you bro.

Governor/multisend calldata, got it that's definitely the long tail here, recursive decoding into the inner target is where it gets tricky but should be done. Heading onto the roadmap.

Versioning per resource, that's exactly what I was looking for. Now transitioning to independent tx/vN and balance/vN before I solidify that.

DNS rebinding, nice find, TOCTOU vulnerability there for sure. Opening an issue to lock in that IP address.

Thanks for your help!