diff --git a/src/components/Nav.tsx b/src/components/Nav.tsx index 1e52bce..80c30d1 100644 --- a/src/components/Nav.tsx +++ b/src/components/Nav.tsx @@ -1,17 +1,13 @@ -import { type PropsWithChildren, useEffect, useRef } from 'react'; +import type { PropsWithChildren } from 'react'; import { Link, useLocation } from 'react-router-dom'; import { useWallet } from 'src/stellar-wallet'; import logo from '/public/laina_v3_shrinked.png'; +import { Button } from './Button'; +import Identicon from './Identicon'; export default function Nav() { const { pathname } = useLocation(); - const { createConnectWalletButton } = useWallet(); - - const buttonWrapperRef = useRef(null); - - useEffect(() => { - buttonWrapperRef.current && createConnectWalletButton(buttonWrapperRef.current); - }, [createConnectWalletButton]); + const { wallet, openConnectWalletModal, disconnectWallet } = useWallet(); const isIndex = pathname === '/'; @@ -30,7 +26,26 @@ export default function Nav() { Assets -
+ {!wallet ? ( + + ) : ( +
+
+ +
+
    +
  • +

    {wallet.displayName}

    +

    {wallet.name}

    +
  • +
  • + +
  • +
+
+ )} ); } diff --git a/src/components/WalletCard/WalletCard.tsx b/src/components/WalletCard/WalletCard.tsx index 4b28a4d..8dcfe4c 100644 --- a/src/components/WalletCard/WalletCard.tsx +++ b/src/components/WalletCard/WalletCard.tsx @@ -13,13 +13,16 @@ const ASSET_MODAL_ID = 'assets-modal'; const LOANS_MODAL_ID = 'loans-modal'; const WalletCard = () => { - const { wallet, positions, prices } = useWallet(); + const { wallet, openConnectWalletModal, positions, prices } = useWallet(); if (!wallet) { return ( - +

My Account

-

To view your assets, connect a wallet first.

+

To view your assets, connect a wallet first.

+
); } @@ -35,8 +38,7 @@ const WalletCard = () => {

{wallet.displayName}

- {/* TODO: Get wallet type from the kit. */} -

Freighter

+

{wallet.name}

diff --git a/src/stellar-wallet.tsx b/src/stellar-wallet.tsx index 1566a11..04f2824 100644 --- a/src/stellar-wallet.tsx +++ b/src/stellar-wallet.tsx @@ -1,14 +1,22 @@ -import { FREIGHTER_ID, StellarWalletsKit, WalletNetwork, allowAllModules } from '@creit.tech/stellar-wallets-kit'; +import { + FREIGHTER_ID, + type ISupportedWallet, + StellarWalletsKit, + WalletNetwork, + allowAllModules, +} from '@creit.tech/stellar-wallets-kit'; import * as StellarSdk from '@stellar/stellar-sdk'; import { type PropsWithChildren, createContext, useContext, useEffect, useState } from 'react'; import { contractClient as loanManagerClient } from '@contracts/loan_manager'; import type { SupportedCurrency } from 'currencies'; +import { isNil } from 'ramda'; import { CURRENCY_BINDINGS_ARR } from './currency-bindings'; const HorizonServer = new StellarSdk.Horizon.Server('https://horizon-testnet.stellar.org/'); export type Wallet = { + name: string; address: string; displayName: string; }; @@ -38,7 +46,8 @@ export type WalletContext = { walletBalances: BalanceRecord; positions: PositionsRecord; prices: PriceRecord | null; - createConnectWalletButton: (container: HTMLElement) => void; + openConnectWalletModal: () => void; + disconnectWallet: () => void; refetchBalances: () => void; signTransaction: SignTransaction; }; @@ -59,7 +68,8 @@ const Context = createContext({ walletBalances: {}, positions: {}, prices: null, - createConnectWalletButton: () => {}, + openConnectWalletModal: () => {}, + disconnectWallet: () => {}, refetchBalances: () => {}, signTransaction: () => Promise.reject(), }); @@ -70,7 +80,8 @@ const kit: StellarWalletsKit = new StellarWalletsKit({ modules: allowAllModules(), }); -const createWalletObj = (address: string): Wallet => ({ +const createWalletObj = (name: string, address: string): Wallet => ({ + name, address, displayName: `${address.slice(0, 4)}...${address.slice(-4)}`, }); @@ -119,25 +130,32 @@ const fetchPriceData = async (token: string): Promise => { }; export const WalletProvider = ({ children }: PropsWithChildren) => { - const [address, setAddress] = useState(null); + const [wallet, setWallet] = useState(null); const [walletBalances, setWalletBalances] = useState({}); const [positions, setPositions] = useState({}); const [prices, setPrices] = useState(null); - const setWallet = async (address: string) => { - setAddress(address); - const { balances } = await HorizonServer.loadAccount(address); - setWalletBalances(createBalanceRecord(balances)); - setPositions(await fetchAllPositions(address)); + const loadWallet = async (name: string) => { + try { + const { address } = await kit.getAddress(); + setWallet(createWalletObj(name, address)); + const { balances } = await HorizonServer.loadAccount(address); + setWalletBalances(createBalanceRecord(balances)); + setPositions(await fetchAllPositions(address)); + localStorage.setItem('wallet-connected', name); + } catch (err) { + console.error('Loading wallet failed', err); + localStorage.removeItem('wallet-connected'); + } }; // Set initial wallet on load. // biome-ignore lint: useEffect is ass useEffect(() => { - kit - .getAddress() - .then(({ address }) => setWallet(address)) - .catch((err) => console.log('No initial wallet.', err)); + const walletConnected = localStorage.getItem('wallet-connected'); + if (!isNil(walletConnected)) { + loadWallet(walletConnected); + } fetchAllPrices() .then((res) => setPrices(res)) .catch((err) => console.error('Error fetching prices', err)); @@ -148,32 +166,34 @@ export const WalletProvider = ({ children }: PropsWithChildren) => { return signedTxXdr; }; - const createConnectWalletButton = (container: HTMLElement) => { - kit.createButton({ - container, - onConnect: ({ address }) => setWallet(address), - onDisconnect: () => { - setAddress(null); - setWalletBalances({}); + const openConnectWalletModal = () => { + kit.openModal({ + onWalletSelected: ({ name }) => { + loadWallet(name); }, }); }; + const disconnectWallet = () => { + setWallet(null); + setWalletBalances({}); + setPositions({}); + localStorage.removeItem('wallet-connected'); + }; + const refetchBalances = async () => { - if (!address) return; + if (!wallet) return; try { - const { balances } = await HorizonServer.loadAccount(address); + const { balances } = await HorizonServer.loadAccount(wallet.address); setWalletBalances(createBalanceRecord(balances)); - const positions = await fetchAllPositions(address); + const positions = await fetchAllPositions(wallet.address); setPositions(positions); } catch (err) { console.error('Error fetching balances', err); } }; - const wallet: Wallet | null = address ? createWalletObj(address) : null; - return ( { walletBalances, positions, prices, - createConnectWalletButton, + openConnectWalletModal, + disconnectWallet, refetchBalances, signTransaction, }}