1- import { useState } from "react" ;
1+ import { useState , useMemo } from "react" ;
22
33import Link from "next/link" ;
44import usePendingTransactions from "@/hooks/usePendingTransactions" ;
55import useUserWallets from "@/hooks/useUserWallets" ;
6+ import useWalletBalances from "@/hooks/useWalletBalances" ;
67import { Wallet } from "@/types/wallet" ;
78import { getFirstAndLast } from "@/utils/strings" ;
89import { api } from "@/utils/api" ;
910import { useUserStore } from "@/lib/zustand/user" ;
11+ import { useSiteStore } from "@/lib/zustand/site" ;
12+ import { buildMultisigWallet } from "@/utils/common" ;
13+ import { addressToNetwork } from "@/utils/multisigSDK" ;
1014
1115import { Button } from "@/components/ui/button" ;
1216import PageHeader from "@/components/common/page-header" ;
1317import CardUI from "@/components/common/card-content" ;
1418import RowLabelInfo from "@/components/common/row-label-info" ;
1519import SectionTitle from "@/components/common/section-title" ;
20+ import WalletBalance from "./WalletBalance" ;
21+ import EmptyWalletsState from "./EmptyWalletsState" ;
22+ import SectionExplanation from "./SectionExplanation" ;
1623
1724
1825export default function PageWallets ( ) {
@@ -35,6 +42,14 @@ export default function PageWallets() {
3542 } ,
3643 ) ;
3744
45+ // Filter wallets for balance fetching (only non-archived or all if showing archived)
46+ const walletsForBalance = wallets ?. filter (
47+ ( wallet ) => showArchived || ! wallet . isArchived ,
48+ ) as Wallet [ ] | undefined ;
49+
50+ // Fetch balances with rate limiting
51+ const { balances, loadingStates } = useWalletBalances ( walletsForBalance ) ;
52+
3853 return (
3954 < div className = "flex flex-col gap-4" >
4055 < >
@@ -53,15 +68,7 @@ export default function PageWallets() {
5368 </ PageHeader >
5469
5570 < div className = "grid grid-cols-1 gap-4 lg:grid-cols-3" >
56- { wallets && wallets . length === 0 && (
57- < div className = "col-span-3 text-center text-muted-foreground" >
58- No wallets,{ " " }
59- < Link href = "/wallets/new-wallet-flow/save" >
60- < b className = "cursor-pointer text-white" > create one</ b >
61- </ Link >
62- ?
63- </ div >
64- ) }
71+ { wallets && wallets . length === 0 && < EmptyWalletsState /> }
6572 { wallets &&
6673 wallets
6774 . filter ( ( wallet ) => showArchived || ! wallet . isArchived )
@@ -72,14 +79,30 @@ export default function PageWallets() {
7279 ? 1
7380 : - 1 ,
7481 )
75- . map ( ( wallet ) => (
76- < CardWallet key = { wallet . id } wallet = { wallet as Wallet } />
77- ) ) }
82+ . map ( ( wallet ) => {
83+ const walletBalance = balances [ wallet . id ] ?? null ;
84+ const walletLoadingState = loadingStates [ wallet . id ] ?? "idle" ;
85+ // Debug log
86+ if ( process . env . NODE_ENV === "development" ) {
87+ console . log ( `Wallet ${ wallet . id } : balance=${ walletBalance } , loadingState=${ walletLoadingState } ` ) ;
88+ }
89+ return (
90+ < CardWallet
91+ key = { wallet . id }
92+ wallet = { wallet as Wallet }
93+ balance = { walletBalance }
94+ loadingState = { walletLoadingState }
95+ />
96+ ) ;
97+ } ) }
7898 </ div >
7999
80100 { newPendingWallets && newPendingWallets . length > 0 && (
81101 < >
82102 < SectionTitle > New Wallets to be created</ SectionTitle >
103+ < SectionExplanation
104+ description = "These are wallets you have initiated but not yet created on-chain. Complete the wallet creation process to deploy them."
105+ />
83106 < div className = "grid grid-cols-1 gap-4 lg:grid-cols-3" >
84107 { newPendingWallets
85108 . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
@@ -99,6 +122,9 @@ export default function PageWallets() {
99122 < SectionTitle >
100123 New Wallets awaiting creation
101124 </ SectionTitle >
125+ < SectionExplanation
126+ description = "These are wallets you have been invited to join as a signer. You can view details and accept or decline the invitation."
127+ />
102128 < div className = "grid grid-cols-1 gap-4 lg:grid-cols-3" >
103129 { getUserNewWalletsNotOwner
104130 . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
@@ -113,22 +139,50 @@ export default function PageWallets() {
113139 ) ;
114140}
115141
116- function CardWallet ( { wallet } : { wallet : Wallet } ) {
142+ function CardWallet ( {
143+ wallet,
144+ balance,
145+ loadingState,
146+ } : {
147+ wallet : Wallet ;
148+ balance : number | null ;
149+ loadingState : "idle" | "loading" | "loaded" | "error" ;
150+ } ) {
151+ const network = useSiteStore ( ( state ) => state . network ) ;
117152 const { transactions : pendingTransactions } = usePendingTransactions ( {
118153 walletId : wallet . id ,
119154 } ) ;
120155
156+ // Rebuild the multisig wallet to get the correct canonical address for display
157+ // This ensures we show the correct address even if wallet.address was built incorrectly
158+ const displayAddress = useMemo ( ( ) => {
159+ try {
160+ const walletNetwork = wallet . signersAddresses . length > 0
161+ ? addressToNetwork ( wallet . signersAddresses [ 0 ] ! )
162+ : network ;
163+ const mWallet = buildMultisigWallet ( wallet , walletNetwork ) ;
164+ if ( mWallet ) {
165+ return mWallet . getScript ( ) . address ;
166+ }
167+ } catch ( error ) {
168+ console . error ( `Error building wallet for display: ${ wallet . id } ` , error ) ;
169+ }
170+ // Fallback to wallet.address if rebuild fails (legacy support)
171+ return wallet . address ;
172+ } , [ wallet , network ] ) ;
173+
121174 return (
122175 < Link href = { `/wallets/${ wallet . id } ` } >
123176 < CardUI
124177 title = { `${ wallet . name } ${ wallet . isArchived ? " (Archived)" : "" } ` }
125178 description = { wallet . description }
126179 cardClassName = ""
127180 >
181+ < WalletBalance balance = { balance } loadingState = { loadingState } />
128182 < RowLabelInfo
129183 label = "Address"
130- value = { getFirstAndLast ( wallet . address ) }
131- copyString = { wallet . address }
184+ value = { getFirstAndLast ( displayAddress ) }
185+ copyString = { displayAddress }
132186 />
133187 < RowLabelInfo
134188 label = "DRep ID"
0 commit comments