feat: enable raw data for all account headers#884
feat: enable raw data for all account headers#884askov wants to merge 1 commit intosolana-foundation:masterfrom
Conversation
|
@askov is attempting to deploy a commit to the Solana Foundation Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR introduces a reusable Key changes and observations:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant AccountCard
participant AccountCardBase
participant RawAccountRows
participant useRawAccountDataOnMount
participant SWR
participant RPC
User->>AccountCard: renders page
AccountCard->>AccountCardBase: rawContent=<RawAccountRows/> (not yet mounted)
AccountCardBase-->>User: shows parsed children (showRaw=false)
User->>AccountCardBase: clicks "Raw" button
AccountCardBase->>AccountCardBase: setShowRaw(true)
AccountCardBase->>RawAccountRows: mounts rawContent
RawAccountRows->>useRawAccountDataOnMount: pubkey
useRawAccountDataOnMount->>SWR: useSWRImmutable(key, fetcher)
SWR->>RPC: getAccountInfo(pubkey)
RawAccountRows-->>User: spinner (rawData = null/undefined)
alt Account exists
RPC-->>SWR: AccountInfo with data
SWR-->>useRawAccountDataOnMount: Uint8Array
useRawAccountDataOnMount-->>RawAccountRows: Uint8Array
RawAccountRows-->>User: HexData display
else Account not found
RPC-->>SWR: null
SWR-->>useRawAccountDataOnMount: null (data ?? null = null)
useRawAccountDataOnMount-->>RawAccountRows: null (same as loading!)
RawAccountRows-->>User: ⚠️ infinite spinner (bug)
end
Last reviewed commit: "refactor: extract Ac..." |
| async function fetchRawAccountData([, url, address]: [string, string, string]): Promise<Uint8Array | null> { | ||
| const connection = new Connection(url, 'confirmed'); | ||
| const info = await connection.getAccountInfo(new PublicKey(address)); | ||
| return info ? Uint8Array.from(info.data) : null; | ||
| } |
There was a problem hiding this comment.
New
Connection instantiated on every fetch
A brand-new Connection object is created inside the SWR fetcher on every invocation. While useSWRImmutable prevents redundant calls for the same cache key, this still creates an extra connection object every time the cache key changes (different cluster or account). The existing cluster providers already manage a shared Connection instance.
Consider consuming the Connection from the cluster context, or at minimum memoizing it at module level keyed by URL, rather than constructing one inside the fetcher.
| )} | ||
| </div> | ||
|
|
||
| <TableCardBody {...tableProps}>{showRaw ? rawContent : children}</TableCardBody> |
There was a problem hiding this comment.
rawContent is always mounted despite showRaw being false at start
AccountCardBase passes rawContent as a prop to AccountCard which immediately evaluates the JSX expression <RawAccountRows account={account} /> and creates the React element. However, since rawContent is only rendered in the tree when showRaw is true (via the ternary), RawAccountRows itself isn't mounted until the button is clicked — so the hook fires correctly on demand.
This is fine as-is, but it's worth noting that passing rawContent as a render prop () => <RawAccountRows /> instead of a pre-evaluated element would make the lazy-mounting intent more explicit and guard against future accidental eager rendering.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| export function useRawAccountDataOnMount(pubkey: PublicKey): Uint8Array | null { | ||
| const { url } = useCluster(); | ||
|
|
||
| const { data } = useSWRImmutable(getRawAccountDataKey(url, pubkey), fetchRawAccountData); | ||
|
|
||
| return data ?? null; | ||
| } |
There was a problem hiding this comment.
Indistinguishable loading vs. not-found state
useRawAccountDataOnMount returns null for both the initial loading state (SWR data is undefined, and undefined ?? null evaluates to null) and the case where fetchRawAccountData itself returns null (i.e., getAccountInfo found no account on chain).
BaseRawAccountRows treats any falsy rawData as "still loading" and shows a spinning indicator indefinitely. If a user visits a closed or non-existent account and clicks "Raw", the spinner will never resolve — there is no terminal state for "account not found".
The fix is to remove the ?? null coercion from the return value so that SWR's initial undefined (in-flight) remains distinct from the null that signals "account not found". The BaseRawAccountRowsProps type already allows rawData to be undefined, so the rendering logic just needs a third branch:
undefined→ loading spinnernull→ "Account data unavailable" messageUint8Array→ renderHexData
Description
AccountCardcomponent (@features/account) that encapsulates the card shell (header, Raw/Refresh buttons, raw account data view), eliminating duplicated card markup across 13 account section filesType of change
Screenshots
Testing
Related Issues
Checklist
build:infoscript to update build information