Skip to content
Open
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
68 changes: 60 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
"preview": "vite preview"
},
"dependencies": {
"@breeztech/breez-sdk-liquid": "^0.10.2",
"@breeztech/breez-sdk-liquid": "^0.11.12",
"@headlessui/react": "^1.7.17",
"@noble/hashes": "^2.0.1",
"@scure/bip32": "^2.0.1",
Comment thread
dangeross marked this conversation as resolved.
"bip39": "^3.1.0",
"buffer": "^6.0.3",
"crypto-browserify": "^3.12.0",
Expand All @@ -37,4 +39,4 @@
"vite-plugin-top-level-await": "^1.3.1",
"vite-plugin-wasm": "^3.2.2"
}
}
}
64 changes: 50 additions & 14 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import React, { useEffect, useState, useCallback, useRef } from 'react';
import { GetInfoResponse, Payment, SdkEvent } from '@breeztech/breez-sdk-liquid/web';
import * as walletService from './services/walletService';
import { deriveKleverMnemonic } from './services/bip85';
import LoadingSpinner from './components/LoadingSpinner';
import { ToastProvider, useToast } from './contexts/ToastContext';
import { PartnerProvider, usePartner, storePartner, clearStoredPartner } from './contexts/PartnerContext';

// Import our page components
import HomePage from './pages/HomePage';
import RestorePage from './pages/RestorePage';
import GeneratePage from './pages/GeneratePage';
import WalletPage from './pages/WalletPage';
import DiagnosticsPage from './pages/DiagnosticsPage';

// Main App without toast functionality
const AppContent: React.FC = () => {
// Screen navigation state
const [currentScreen, setCurrentScreen] = useState<'home' | 'restore' | 'generate' | 'wallet'>('home');
const [currentScreen, setCurrentScreen] = useState<'home' | 'restore' | 'generate' | 'wallet' | 'diagnostics' | 'rescanSwaps'>('home');

const { isKleverMode, partner, partnerMismatch } = usePartner();

const [isConnected, setIsConnected] = useState<boolean>(false);
const [isLoading, setIsLoading] = useState<boolean>(true);
Expand Down Expand Up @@ -148,9 +153,19 @@ const AppContent: React.FC = () => {
// Try to connect with saved mnemonic on app startup
useEffect(() => {
const checkForExistingWallet = async () => {
const savedMnemonic = walletService.getSavedMnemonic();
const savedMnemonic = walletService.getMnemonic();

if (savedMnemonic) {
// If partner context changed, clear stored wallet and start fresh
if (partnerMismatch) {
console.log('Partner mismatch detected, clearing stored wallet...');
walletService.clearMnemonic();
clearStoredPartner();
setCurrentScreen('home');
setIsLoading(false);
return;
}

try {
setIsLoading(true);
await connectWallet(savedMnemonic, false);
Expand Down Expand Up @@ -206,14 +221,22 @@ const AppContent: React.FC = () => {
const connectWallet = async (mnemonic: string, restore: boolean) => {
try {
setIsLoading(true);
setIsRestoring(restore); // Mark that we're restoring data
setIsRestoring(restore); // Mark that we're restoring data
setError(null);

// Initialize wallet with mnemonic
await walletService.initWallet(mnemonic);
let seed: number[] | undefined;
if (isKleverMode) {
// In Klever mode, derive mnemonic via BIP-85 and pass its string bytes as seed
const derived = deriveKleverMnemonic(mnemonic, 0);
seed = derived.mnemonicBytes;
}

// Save mnemonic for future use
walletService.saveMnemonic(mnemonic);
// Initialize wallet: use the seed when set, else use the mnemonic
await walletService.initWallet(mnemonic, seed);

// Save the original mnemonic (so re-derivation works on reload)
walletService.setMnemonic(mnemonic);
storePartner(partner);

// Get wallet info and transactions
const info = await walletService.getWalletInfo();
Expand Down Expand Up @@ -244,8 +267,9 @@ const AppContent: React.FC = () => {
await walletService.disconnect();
}

// Clear the stored mnemonic
// Clear the stored mnemonic and partner
walletService.clearMnemonic();
clearStoredPartner();

// Reset state
setIsConnected(false);
Expand All @@ -269,6 +293,8 @@ const AppContent: React.FC = () => {
const navigateToRestore = () => setCurrentScreen('restore');
const navigateToGenerate = () => setCurrentScreen('generate');
const navigateToHome = () => setCurrentScreen('home');
const navigateToDiagnostics = () => setCurrentScreen('diagnostics');
const navigateToWallet = () => setCurrentScreen('wallet');
const clearError = () => setError(null);

// Determine which screen to render
Expand Down Expand Up @@ -320,6 +346,14 @@ const AppContent: React.FC = () => {
error={error}
onClearError={clearError}
onLogout={handleLogout}
onOpenDiagnostics={navigateToDiagnostics}
/>
);

case 'diagnostics':
return (
<DiagnosticsPage
onBack={navigateToWallet}
/>
);

Expand All @@ -334,13 +368,15 @@ const AppContent: React.FC = () => {
// Wrap the App with ToastProvider
function App() {
return (
<ToastProvider>
<div className="flex-grow flex main-wrapper">
<div className="flex-grow max-w-4xl mx-auto">
<AppContent />
<PartnerProvider>
<ToastProvider>
<div className="flex-grow flex main-wrapper">
<div id="content-root" className="flex-grow max-w-4xl mx-auto relative">
<AppContent />
</div>
</div>
</div>
</ToastProvider>
</ToastProvider>
</PartnerProvider>
);
}

Expand Down
12 changes: 6 additions & 6 deletions src/components/CollapsingWalletHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ interface CollapsingWalletHeaderProps {
walletInfo: GetInfoResponse | null;
usdRate: number | null;
scrollProgress: number;
onLogout: () => void;
onMenuOpen: () => void;
}

const CollapsingWalletHeader: React.FC<CollapsingWalletHeaderProps> = ({
walletInfo,
scrollProgress,
usdRate,
onLogout,
onMenuOpen,
}) => {
if (!walletInfo) return null;

Expand All @@ -36,13 +36,13 @@ const CollapsingWalletHeader: React.FC<CollapsingWalletHeaderProps> = ({
return (
<div className="card-no-border transition-all duration-200 overflow-hidden relative">
<button
onClick={onLogout}
onClick={onMenuOpen}
className="text-[rgb(var(--text-white))] absolute top-4 left-4 z-10"
aria-label="Sign out"
title="Sign out"
aria-label="Open menu"
title="Menu"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
{/* Main Balance - always visible but scales down */}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReceivePaymentDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ const ReceivePaymentDialog: React.FC<ReceivePaymentDialogProps> = ({ isOpen, onC
try {
// Generate lightning invoice using walletService
const prepareResponse = await walletService.prepareReceivePayment({
paymentMethod: 'lightning',
paymentMethod: 'bolt11Invoice',
amount: {
type: 'bitcoin',
payerAmountSat: amountSats,
Expand Down
Loading