diff --git a/src/components/Nip61WalletViewer.tsx b/src/components/Nip61WalletViewer.tsx
index cb2023e..2d5f70b 100644
--- a/src/components/Nip61WalletViewer.tsx
+++ b/src/components/Nip61WalletViewer.tsx
@@ -13,7 +13,6 @@ import {
Send,
Download,
RefreshCw,
- Settings,
Coins,
Loader2,
Wallet,
@@ -21,11 +20,13 @@ import {
ChevronRight,
ChevronDown,
ArrowDownLeft,
+ ArrowUpRight,
Search,
Landmark,
Radio,
} from "lucide-react";
import { toast } from "sonner";
+import { use$ } from "applesauce-react/hooks";
import { Button } from "@/components/ui/button";
import {
Tooltip,
@@ -46,12 +47,10 @@ import {
DialogFooter,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
-import { Switch } from "@/components/ui/switch";
import {
WalletBalance,
WalletHeader,
WalletHistoryList,
- TransactionRow,
type HistoryItem,
} from "@/components/wallet";
import { CodeCopyButton } from "@/components/CodeCopyButton";
@@ -206,6 +205,57 @@ function historyToItem(entry: WalletHistory): HistoryItem {
};
}
+/**
+ * History entry row that subscribes to meta$ for amounts
+ */
+function HistoryEntryRow({
+ entry,
+ blurred,
+ onClick,
+}: {
+ entry: WalletHistory;
+ blurred: boolean;
+ onClick: () => void;
+}) {
+ // Subscribe to meta$ observable to get direction and amount
+ const meta = use$(() => entry.meta$, [entry]);
+
+ const direction = meta?.direction || "in";
+ const amount = meta?.amount || 0;
+
+ return (
+
+
+ {direction === "in" ? (
+
+ ) : (
+
+ )}
+
+
+ {formatTimestamp(entry.event.created_at, "datetime")}
+
+ {!entry.unlocked && (
+ (locked)
+ )}
+
+
+
+
+ {blurred
+ ? "✦✦✦✦"
+ : `${direction === "in" ? "+" : "-"}${amount.toLocaleString()}`}
+
+
+
+ );
+}
+
export default function Nip61WalletViewer() {
const { state, toggleWalletBalancesBlur } = useGrimoire();
const { isLoggedIn } = useAccount();
@@ -221,8 +271,6 @@ export default function Nip61WalletViewer() {
unlock,
unlocking,
error,
- syncEnabled,
- toggleSyncEnabled,
} = useNip61Wallet();
const [refreshing, setRefreshing] = useState(false);
@@ -231,7 +279,6 @@ export default function Nip61WalletViewer() {
const [detailDialogOpen, setDetailDialogOpen] = useState(false);
const [showRawTransaction, setShowRawTransaction] = useState(false);
const [copiedRawTx, setCopiedRawTx] = useState(false);
- const [settingsOpen, setSettingsOpen] = useState(false);
const blurred = state.walletBalancesBlurred ?? false;
@@ -265,34 +312,11 @@ export default function Nip61WalletViewer() {
const renderHistoryEntry = useCallback(
(item: HistoryItem) => {
const entry = item.data as WalletHistory;
-
- // If not unlocked, show placeholder
- if (!entry.unlocked) {
- return (
- Locked
- }
- onClick={() => handleTransactionClick(entry)}
- />
- );
- }
-
return (
-
- {formatTimestamp(entry.event.created_at, "datetime")}
-
- }
onClick={() => handleTransactionClick(entry)}
/>
);
@@ -424,19 +448,6 @@ export default function Nip61WalletViewer() {
)}
-
-
-
-
-
- Settings
-
}
/>
@@ -498,7 +509,8 @@ export default function Nip61WalletViewer() {
{/* Transaction Detail Dialog */}
-
-
- {/* Settings Dialog */}
-
+ showRaw={showRawTransaction}
+ onToggleRaw={() => setShowRawTransaction(!showRawTransaction)}
+ copiedRaw={copiedRawTx}
+ onCopyRaw={() => {
+ if (selectedTransaction) {
+ navigator.clipboard.writeText(
+ JSON.stringify(selectedTransaction.event, null, 2),
+ );
+ setCopiedRawTx(true);
+ setTimeout(() => setCopiedRawTx(false), 2000);
+ }
+ }}
+ blurred={blurred}
+ />
);
}
+
+/**
+ * Transaction detail dialog component
+ */
+function TransactionDetailDialog({
+ transaction,
+ open,
+ onOpenChange,
+ showRaw,
+ onToggleRaw,
+ copiedRaw,
+ onCopyRaw,
+ blurred,
+}: {
+ transaction: WalletHistory | null;
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ showRaw: boolean;
+ onToggleRaw: () => void;
+ copiedRaw: boolean;
+ onCopyRaw: () => void;
+ blurred: boolean;
+}) {
+ // Subscribe to meta$ for transaction details
+ const meta = use$(() => transaction?.meta$, [transaction]);
+
+ const direction = meta?.direction || "in";
+ const amount = meta?.amount || 0;
+
+ return (
+
+ );
+}
diff --git a/src/hooks/useNip61Wallet.ts b/src/hooks/useNip61Wallet.ts
index a1af725..de8f51a 100644
--- a/src/hooks/useNip61Wallet.ts
+++ b/src/hooks/useNip61Wallet.ts
@@ -24,7 +24,6 @@ import {
WALLET_HISTORY_KIND,
} from "@/services/nip61-wallet";
import { kinds, relaySet } from "applesauce-core/helpers";
-import { useGrimoire } from "@/core/state";
// Import casts to enable user.wallet$ property
import "applesauce-wallet/casts";
@@ -44,7 +43,6 @@ export type WalletState =
*/
export function useNip61Wallet() {
const { pubkey, canSign } = useAccount();
- const { state: appState, setCashuWalletSyncEnabled } = useGrimoire();
const [unlocking, setUnlocking] = useState(false);
const [error, setError] = useState(null);
const [discoveryComplete, setDiscoveryComplete] = useState(false);
@@ -190,10 +188,12 @@ export function useNip61Wallet() {
return Object.fromEntries(entries);
}, [balance]);
- // Toggle sync setting
- const toggleSyncEnabled = useCallback(() => {
- setCashuWalletSyncEnabled(!appState.cashuWalletSyncEnabled);
- }, [appState.cashuWalletSyncEnabled, setCashuWalletSyncEnabled]);
+ // Compute effective relays (wallet relays + user outbox relays)
+ const effectiveRelays = useMemo(() => {
+ const walletRelays = relays || [];
+ const userOutboxes = outboxes || [];
+ return relaySet(walletRelays, userOutboxes);
+ }, [relays, outboxes]);
return {
// State machine
@@ -214,17 +214,13 @@ export function useNip61Wallet() {
tokens,
history,
mints,
- relays,
+ relays: effectiveRelays, // Combined wallet + outbox relays
received, // Received nutzap IDs
// Actions
unlock,
unlocking,
- // Sync setting
- syncEnabled: appState.cashuWalletSyncEnabled ?? false,
- toggleSyncEnabled,
-
// Error state
error,