Skip to content
Merged
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
50 changes: 46 additions & 4 deletions src/components/btc-wallet/XpubPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,30 @@ import React, { useContext, useEffect, useState } from "react";
import { AppContext } from "../../store/AppContext";
import { useFeature } from "../../hooks/useFeature";
import { PageContent } from "../index";
import { constants, getBtcPurpose } from "../../util/helpers";

const { Search, TextArea } = Input;
const SEARCH_ID = "xpub-data";

const WALLET_TYPE_LABELS = {
[constants.BTC_PURPOSE_LEGACY]: "Legacy",
[constants.BTC_PURPOSE_WRAPPED_SEGWIT]: "Wrapped SegWit",
[constants.BTC_PURPOSE_SEGWIT]: "Native SegWit",
} as const;

interface XpubPageProps {
session: any;
}

const XpubPage: React.FC<XpubPageProps> = ({ session }) => {
const context = useContext(AppContext);
const { isMobile } = useContext(AppContext);
const { SUPPORTS_XPUB } = useFeature();
const [xpub, setXpub] = useState<string | null>(null);
const [windowWidth, setWindowWidth] = useState<number | undefined>(
document.getElementById("main-content-inner")?.offsetWidth
);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
updateXpubAddress();
Expand All @@ -34,17 +43,31 @@ const XpubPage: React.FC<XpubPageProps> = ({ session }) => {
const updateXpubAddress = async () => {
if (!session) return;

// Get the active BTC purpose (wallet type)
const btcPurpose = getBtcPurpose();
if (btcPurpose === constants.BTC_PURPOSE_NONE) {
setError("BTC Wallet is hidden. Please enable it in settings to view XPUB.");
return;
}

setLoading(true);
setError(null);

try {
// Use the active wallet's BTC purpose as the derivation path
const addresses = await session.client?.getAddresses({
startPath: [44 + 0x80000000, 0 + 0x80000000, 0 + 0x80000000],
flag: 6,
startPath: [btcPurpose, constants.BTC_COIN, 0 + constants.HARDENED_OFFSET],
flag: 6, // LatticeGetAddressesFlag.secp256k1Xpub
});

if (addresses && addresses.length > 0) {
setXpub(addresses[0]);
} else {
setError("No XPUB returned from device");
}
} catch (err) {
console.error("Error fetching XPUB:", err);
setError("Failed to fetch XPUB from device");
} finally {
setLoading(false);
}
Expand All @@ -61,15 +84,18 @@ const XpubPage: React.FC<XpubPageProps> = ({ session }) => {
}
};

const walletTypeLabel = WALLET_TYPE_LABELS[getBtcPurpose()] || "Unknown";

const renderXpubBox = () => {
if (context.isMobile) {
if (isMobile) {
return (
<div>
<TextArea
id={SEARCH_ID}
value={xpub}
autoSize={{ minRows: 1, maxRows: 3 }}
style={{ margin: "30px 0 0 0", textAlign: "center" }}
readOnly
/>
<Button
type="primary"
Expand All @@ -89,6 +115,7 @@ const XpubPage: React.FC<XpubPageProps> = ({ session }) => {
enterButton={<CopyOutlined />}
onSearch={copyXpub}
style={{ margin: "30px 0 0 0", textAlign: "center" }}
readOnly
/>
);
};
Expand All @@ -103,6 +130,17 @@ const XpubPage: React.FC<XpubPageProps> = ({ session }) => {
);
}

if (error) {
return (
<div>
<p style={{ color: '#ff4d4f', marginBottom: 16 }}>{error}</p>
<Button onClick={updateXpubAddress}>
Retry
</Button>
</div>
);
}

if (loading) {
return (
<div style={{ padding: "50px 0" }}>
Expand All @@ -118,6 +156,9 @@ const XpubPage: React.FC<XpubPageProps> = ({ session }) => {
const xpubUrl = `https://www.blockchain.com/explorer/assets/btc/xpub/${xpub}`;
return (
<div>
<p style={{ marginBottom: 16, fontSize: '14px', color: '#666' }}>
Wallet Type: <strong>{walletTypeLabel}</strong>
</p>
<Row justify="center">
<QRCodeSVG
value={xpubUrl}
Expand All @@ -129,6 +170,7 @@ const XpubPage: React.FC<XpubPageProps> = ({ session }) => {
</div>
);
}

return (
<div>
<p>No XPUB address found</p>
Expand Down