Skip to content
Open
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
30 changes: 28 additions & 2 deletions src/commands/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ function renderBalances(opts: {
// positions may exist but couldn't be read, so say so instead of rendering
// nothing.
stocksUnavailable?: boolean;
// True when the Solana wallet couldn't be resolved and Solana was dropped from
// the queried set: holdings may exist but weren't scanned. Same contract as
// stocksUnavailable — without it, "no Solana tokens" is indistinguishable from
// "Solana was never checked".
solanaUnavailable?: boolean;
// Hyperliquid funds/positions live off-chain (account-wide), so they render
// once, after the tokens + stocks — independent of the queried network.
hyperliquid?: HyperliquidBalanceSummary | null;
Expand All @@ -339,6 +344,7 @@ function renderBalances(opts: {
tokens,
stocks = [],
stocksUnavailable = false,
solanaUnavailable = false,
hyperliquid = null,
evmAddress,
solAddress,
Expand All @@ -361,6 +367,7 @@ function renderBalances(opts: {
tokens,
stocks,
...(stocksUnavailable ? { stocksUnavailable } : {}),
...(solanaUnavailable ? { solanaUnavailable } : {}),
hyperliquid,
});
} else {
Expand All @@ -374,6 +381,7 @@ function renderBalances(opts: {
tokens,
stocks,
...(stocksUnavailable ? { stocksUnavailable } : {}),
...(solanaUnavailable ? { solanaUnavailable } : {}),
hyperliquid,
});
}
Expand Down Expand Up @@ -421,6 +429,13 @@ function renderBalances(opts: {
console.log(
` ${c.dim(`Checked: ${networks.join(", ")} (${networks.length} chains)`)}\n`
);
if (solanaUnavailable) {
console.log(
` ${c.yellow(
"Solana was not checked (wallet could not be resolved) — any Solana holdings are not shown. Retry in a moment."
)}\n`
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TTY warning skips single-chain path

Medium Severity

The TTY solanaUnavailable note sits only inside the multi-network branch, while stocksUnavailable is emitted for both single and multi. After a non-explicit Solana drop that leaves one EVM network, single is true and the yellow warning never prints, so interactive output still looks like Solana was scanned and empty. JSON and TSV already surface the flag in that case.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 347d369. Configure here.

}
// Stocks span both chains — print the table once, after the token output.
printStockPositions(stocks);
Expand Down Expand Up @@ -460,6 +475,12 @@ function renderBalances(opts: {
"warning: tokenized-stock positions unavailable (upstream fetch failed) — stock rows omitted\n"
);
}
if (solanaUnavailable) {
// Stderr so the TSV on stdout stays parseable.
process.stderr.write(
"warning: solana not checked (wallet could not be resolved) — solana rows omitted\n"
);
}
if (hlHasData(hyperliquid)) {
console.log(
`HL\taccountValue\t\t${usd(hyperliquid.balanceUsd)}\t${
Expand Down Expand Up @@ -738,9 +759,12 @@ export function registerWalletCommands(program: Command): void {
}

// Resolve the Solana address only if a Solana network is in scope. In
// the default all-chains view a missing Solana wallet is skipped
// silently; an explicit Solana request surfaces the error.
// the default all-chains view a missing Solana wallet drops Solana from
// the scan rather than failing the whole balance; an explicit Solana
// request surfaces the error. Either way the drop is reported, so a
// caller can tell "no Solana tokens" from "Solana was never checked".
let solAddress: string | undefined;
let solanaUnavailable = false;
const hasSolana = networks.some((n) =>
isSolanaChainId(networkToChainId.get(n) ?? -1)
);
Expand All @@ -756,6 +780,7 @@ export function registerWalletCommands(program: Command): void {
networkToChainId.delete(network);
}
}
solanaUnavailable = true;
}
}

Expand All @@ -777,6 +802,7 @@ export function registerWalletCommands(program: Command): void {
tokens,
stocks,
stocksUnavailable: stocksFetchFailed(assets),
solanaUnavailable,
hyperliquid: assets.data.hyperliquid ?? null,
evmAddress: walletAddress,
solAddress,
Expand Down