Sitelet https://github.com/ChainSafe/canton-snap/pull/72/files
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
35 changes: 32 additions & 3 deletions packages/dapp/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ export default function App() {
const [connectError, setConnectError] = useState<string | null>(null);
const [reconnecting, setReconnecting] = useState(false);
const [dashboardTab, setDashboardTab] = useState<DashboardTab>(readTabFromHash);
// Token address to pre-select when opening the Transfer tab from a balances
// row's "Send →". Null on plain nav so Transfer falls back to the first token.
const [transferToken, setTransferToken] = useState<string | null>(null);

// Mirror dashboardTab into the URL hash so a refresh on /#balances stays on
// Balances instead of snapping back to Profile. Only mutate the hash while
Expand Down Expand Up @@ -120,10 +123,24 @@ export default function App() {
mm.disconnect();
setProfile(null);
clearAllSessions();
setTransferToken(null);
setDashboardTab("profile");
setPage("landing");
}

// Plain tab navigation (sidebar). Clears any pending pre-selection so the
// Transfer tab only honours a token when reached via a "Send →" row action.
const handleTabChange = useCallback((tab: DashboardTab) => {
setTransferToken(null);
setDashboardTab(tab);
}, []);

// "Send →" on a balances row: pre-select that token, then open Transfer.
const handleSendToken = useCallback((tokenAddress: string) => {
setTransferToken(tokenAddress);
setDashboardTab("transfer");
}, []);

const handleCustodial = useCallback(() => {
setMode("custodial");
setPage("custodial-pending");
Expand Down Expand Up @@ -330,16 +347,28 @@ export default function App() {
const sharedProps = {
address,
activeTab: dashboardTab,
onTabChange: setDashboardTab,
onTabChange: handleTabChange,
onDisconnect: handleDisconnect,
};

if (dashboardTab === "balances") {
return <DashboardBalancesPage {...sharedProps} keyMode={profile.keyMode} />;
return (
<DashboardBalancesPage
{...sharedProps}
keyMode={profile.keyMode}
onSendToken={handleSendToken}
/>
);
}

if (dashboardTab === "transfer") {
return <TransferPage {...sharedProps} keyMode={profile.keyMode} />;
return (
<TransferPage
{...sharedProps}
keyMode={profile.keyMode}
preselectTokenAddress={transferToken}
/>
);
}

if (dashboardTab === "activity") {
Expand Down
8 changes: 7 additions & 1 deletion packages/dapp/src/pages/DashboardBalancesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ interface Props {
onTabChange: (tab: DashboardTab) => void;
onDisconnect: () => void;
keyMode: "custodial" | "external";
/** Open the Transfer tab with this token pre-selected. */
onSendToken: (tokenAddress: string) => void;
}

type OfferRowState = "idle" | "preparing" | "signing" | "executing";
Expand Down Expand Up @@ -176,6 +178,7 @@ export function DashboardBalancesPage({
onTabChange,
onDisconnect,
keyMode,
onSendToken,
}: Props) {
const [fetchState, setFetchState] = useState<FetchState | null>(null);
const [offers, setOffers] = useState<OffersState | null>(null);
Expand Down Expand Up @@ -470,7 +473,10 @@ export function DashboardBalancesPage({
</p>
<p className={styles.amountLabel}>{token.symbol}</p>
</div>
<button className={styles.sendRowBtn} onClick={() => onTabChange("transfer")}>
<button
className={styles.sendRowBtn}
onClick={() => onSendToken(token.address)}
>
Send →
</button>
</div>
Expand Down
25 changes: 23 additions & 2 deletions packages/dapp/src/pages/TransferPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ interface Props {
onTabChange: (tab: DashboardTab) => void;
onDisconnect: () => void;
keyMode: "custodial" | "external";
/** Token address to pre-select on mount (set when opened via a balances "Send →"). */
preselectTokenAddress?: string | null;
}

function TokenAvatar({ symbol }: { symbol: string }) {
Expand Down Expand Up @@ -229,7 +231,14 @@ function TokenDropdown({ tokens, selected, balances, onSelect }: TokenDropdownPr
);
}

export function TransferPage({ address, activeTab, onTabChange, onDisconnect, keyMode }: Props) {
export function TransferPage({
address,
activeTab,
onTabChange,
onDisconnect,
keyMode,
preselectTokenAddress,
}: Props) {
const [step, setStep] = useState<Step>("details");
const [tokens, setTokens] = useState<TokenConfig[]>([]);
const [tokensLoading, setTokensLoading] = useState(true);
Expand All @@ -248,6 +257,12 @@ export function TransferPage({ address, activeTab, onTabChange, onDisconnect, ke
const snap = useSnap();
const isNonCustodial = keyMode === "external";

// Pre-selection captured at mount — it's fixed for the lifetime of this
// page (only set when navigating in from a balances "Send →"). Held in a
// ref so the fetch effect can honour it without taking it as a dependency,
// which would otherwise refetch the token list/balances on every change.
const preselectRef = useRef(preselectTokenAddress);

// Load token list then fetch all balances
useEffect(() => {
let cancelled = false;
Expand All @@ -259,7 +274,13 @@ export function TransferPage({ address, activeTab, onTabChange, onDisconnect, ke
const list = await getTokens(NETWORK.middlewareUrl);
if (cancelled) return;
setTokens(list);
if (list.length > 0) setSelectedToken(list[0]);
if (list.length > 0) {
const pre = preselectRef.current;
const match = pre
? list.find((t) => t.address.toLowerCase() === pre.toLowerCase())
: undefined;
setSelectedToken(match ?? list[0]);
}
Comment thread
sadiq1971 marked this conversation as resolved.
const entries = await Promise.all(
list.map(async (t) => {
try {
Expand Down
Loading