Skip to content

Commit

Permalink
refactor: Create a new PoolContext for holding Pool related data.
Browse files Browse the repository at this point in the history
  • Loading branch information
kovipu committed Dec 7, 2024
1 parent 8e618b3 commit 61d4d16
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 198 deletions.
5 changes: 4 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Outlet, RouterProvider, createBrowserRouter } from 'react-router-dom';

import Footer from '@components/Footer';
import Nav from '@components/Nav';
import { PoolProvider } from '@contexts/pool-context';
import { WalletProvider } from '@contexts/wallet-context';
import BorrowPage from '@pages/_borrow/BorrowPage';
import LandingPage from '@pages/_landing/LandingPage';
Expand Down Expand Up @@ -39,7 +40,9 @@ const App = () => {
return (
<React.StrictMode>
<WalletProvider>
<RouterProvider router={router} />
<PoolProvider>
<RouterProvider router={router} />
</PoolProvider>
</WalletProvider>
</React.StrictMode>
);
Expand Down
4 changes: 3 additions & 1 deletion src/components/WalletCard/AssetsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button } from '@components/Button';
import { Loading } from '@components/Loading';
import { usePools } from '@contexts/pool-context';
import { useWallet } from '@contexts/wallet-context';
import { formatAmount, toDollarsFormatted } from '@lib/formatting';
import type { SupportedCurrency } from 'currencies';
Expand Down Expand Up @@ -55,7 +56,8 @@ interface TableRowProps {
}

const TableRow = ({ receivables, ticker }: TableRowProps) => {
const { wallet, prices, signTransaction, refetchBalances } = useWallet();
const { wallet, signTransaction, refetchBalances } = useWallet();
const { prices } = usePools();
const [isWithdrawing, setIsWithdrawing] = useState(false);

if (receivables === 0n) return null;
Expand Down
4 changes: 3 additions & 1 deletion src/components/WalletCard/LoansModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useState } from 'react';

import { Button } from '@components/Button';
import { Loading } from '@components/Loading';
import { usePools } from '@contexts/pool-context';
import { useWallet } from '@contexts/wallet-context';
import { contractClient as loanManagerClient } from '@contracts/loan_manager';
import { formatAmount, toDollarsFormatted } from '@lib/formatting';
Expand Down Expand Up @@ -57,7 +58,8 @@ interface TableRowProps {
}

const TableRow = ({ liabilities, ticker }: TableRowProps) => {
const { wallet, prices, signTransaction, refetchBalances } = useWallet();
const { wallet, signTransaction, refetchBalances } = useWallet();
const { prices } = usePools();
const [isRepaying, setIsRepaying] = useState(false);

if (liabilities === 0n) return null;
Expand Down
4 changes: 3 additions & 1 deletion src/components/WalletCard/WalletCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Loading } from '@components/Loading';
import { usePools } from '@contexts/pool-context';
import { type PositionsRecord, type PriceRecord, useWallet } from '@contexts/wallet-context';
import { formatCentAmount, toCents } from '@lib/formatting';
import type { SupportedCurrency } from 'currencies';
Expand All @@ -13,7 +14,8 @@ const ASSET_MODAL_ID = 'assets-modal';
const LOANS_MODAL_ID = 'loans-modal';

const WalletCard = () => {
const { wallet, openConnectWalletModal, positions, prices } = useWallet();
const { wallet, openConnectWalletModal, positions } = useWallet();
const { prices } = usePools();

if (!wallet) {
return (
Expand Down
97 changes: 97 additions & 0 deletions src/contexts/pool-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { type PropsWithChildren, createContext, useCallback, useContext, useEffect, useState } from 'react';

import { contractClient as loanManagerClient } from '@contracts/loan_manager';
import type { SupportedCurrency } from 'currencies';
import { CURRENCY_BINDINGS } from 'src/currency-bindings';

export type PriceRecord = {
[K in SupportedCurrency]: bigint;
};

export type PoolState = {
totalBalance: bigint;
availableBalance: bigint;
apr: bigint;
};

export type PoolRecord = {
[K in SupportedCurrency]: PoolState;
};

export type PoolContext = {
prices: PriceRecord | null;
pools: PoolRecord | null;
refetchPools: () => void;
};

const Context = createContext<PoolContext>({
prices: null,
pools: null,
refetchPools: () => {},
});

const fetchAllPrices = async (): Promise<PriceRecord> => {
const [XLM, wBTC, wETH, USDC, EURC] = await Promise.all([
fetchPriceData('XLM'),
fetchPriceData('BTC'),
fetchPriceData('ETH'),
fetchPriceData('USDC'),
fetchPriceData('EURC'),
]);
return { XLM, wBTC, wETH, USDC, EURC };
};

const fetchPriceData = async (ticker: string): Promise<bigint> => {
try {
const { result } = await loanManagerClient.get_price({ token: ticker });
return result;
} catch (error) {
console.error(`Error fetching price data: for ${ticker}`, error);
return 0n;
}
};

const fetchPoolState = async (ticker: SupportedCurrency): Promise<PoolState> => {
const { contractClient } = CURRENCY_BINDINGS[ticker];
const { result: totalBalance } = await contractClient.get_contract_balance();
const { result: availableBalance } = await contractClient.get_available_balance();
const { result: apr } = await contractClient.get_interest();
return { totalBalance, availableBalance, apr };
};

const fetchPools = async (): Promise<PoolRecord> => {
const [XLM, wBTC, wETH, USDC, EURC] = await Promise.all([
fetchPoolState('XLM'),
fetchPoolState('wBTC'),
fetchPoolState('wETH'),
fetchPoolState('USDC'),
fetchPoolState('EURC'),
]);
return { XLM, wBTC, wETH, USDC, EURC };
};

export const PoolProvider = ({ children }: PropsWithChildren) => {
const [prices, setPrices] = useState<PriceRecord | null>(null);
const [pools, setPools] = useState<PoolRecord | null>(null);

const refetchPools = useCallback(() => {
fetchAllPrices()
.then((res) => setPrices(res))
.catch((err) => console.error('Error fetching prices', err));
fetchPools()
.then((res) => setPools(res))
.catch((err) => console.error('Error fetching pools', err));
}, []);

useEffect(() => {
refetchPools();

// Set up a timer for every ledger (~6 secs) to refetch state.
const intervalId = setInterval(refetchPools, 6000);
return () => clearInterval(intervalId);
}, [refetchPools]);

return <Context.Provider value={{ prices, pools, refetchPools }}>{children}</Context.Provider>;
};

export const usePools = (): PoolContext => useContext(Context);
39 changes: 4 additions & 35 deletions src/contexts/wallet-context.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { FREIGHTER_ID, StellarWalletsKit, WalletNetwork, allowAllModules } from '@creit.tech/stellar-wallets-kit';
import type * as StellarSdk from '@stellar/stellar-sdk';
import { type PropsWithChildren, createContext, useContext, useEffect, useState } from 'react';
import { type PropsWithChildren, createContext, useCallback, useContext, useEffect, useState } from 'react';

import { contractClient as loanManagerClient } from '@contracts/loan_manager';
import { getBalances } from '@lib/horizon';
import { type SupportedCurrency, isSupportedCurrency } from 'currencies';
import { CURRENCY_BINDINGS_ARR } from '../currency-bindings';
Expand Down Expand Up @@ -41,7 +40,6 @@ export type WalletContext = {
wallet: Wallet | null;
walletBalances: BalanceRecord | null;
positions: PositionsRecord;
prices: PriceRecord | null;
openConnectWalletModal: () => void;
disconnectWallet: () => void;
refetchBalances: () => void;
Expand All @@ -66,7 +64,6 @@ const Context = createContext<WalletContext>({
wallet: null,
walletBalances: null,
positions: {},
prices: null,
openConnectWalletModal: () => {},
disconnectWallet: () => {},
refetchBalances: () => {},
Expand Down Expand Up @@ -114,27 +111,6 @@ const createBalanceRecord = (balances: StellarSdk.Horizon.HorizonApi.BalanceLine
} as BalanceRecord,
);

const fetchAllPrices = async (): Promise<PriceRecord> => {
const [XLM, wBTC, wETH, USDC, EURC] = await Promise.all([
fetchPriceData('XLM'),
fetchPriceData('BTC'),
fetchPriceData('ETH'),
fetchPriceData('USDC'),
fetchPriceData('EURC'),
]);
return { XLM, wBTC, wETH, USDC, EURC };
};

const fetchPriceData = async (token: string): Promise<bigint> => {
try {
const { result } = await loanManagerClient.get_price({ token });
return result;
} catch (error) {
console.error(`Error fetching price data: for ${token}`, error);
return 0n;
}
};

interface WalletState {
name: string;
timeout: Date;
Expand Down Expand Up @@ -163,9 +139,8 @@ export const WalletProvider = ({ children }: PropsWithChildren) => {
const [wallet, setWallet] = useState<Wallet | null>(null);
const [walletBalances, setWalletBalances] = useState<BalanceRecord | null>(null);
const [positions, setPositions] = useState<PositionsRecord>({});
const [prices, setPrices] = useState<PriceRecord | null>(null);

const loadWallet = async (name: string) => {
const loadWallet = useCallback(async (name: string) => {
try {
const { address } = await kit.getAddress();
setWallet(createWalletObj(name, address));
Expand All @@ -180,21 +155,16 @@ export const WalletProvider = ({ children }: PropsWithChildren) => {
console.error('Loading wallet failed', err);
deleteWalletState();
}
};
}, []);

// Set initial wallet on load.
// biome-ignore lint: useEffect is ass
useEffect(() => {
const walletState = loadWalletState();

if (walletState && new Date().getTime() < walletState.timeout.getTime()) {
loadWallet(walletState.name);
}

fetchAllPrices()
.then((res) => setPrices(res))
.catch((err) => console.error('Error fetching prices', err));
}, []);
}, [loadWallet]);

const signTransaction: SignTransaction = async (tx, opts) => {
return kit.signTransaction(tx, opts);
Expand Down Expand Up @@ -234,7 +204,6 @@ export const WalletProvider = ({ children }: PropsWithChildren) => {
wallet,
walletBalances,
positions,
prices,
openConnectWalletModal,
disconnectWallet,
refetchBalances,
Expand Down
4 changes: 3 additions & 1 deletion src/pages/_borrow/BorrowModal/BorrowModal.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { usePools } from '@contexts/pool-context';
import { useWallet } from '@contexts/wallet-context';
import type { CurrencyBinding } from 'src/currency-bindings';
import { BorrowStep } from './BorrowStep';
Expand All @@ -12,7 +13,8 @@ export interface BorrowModalProps {

export const BorrowModal = ({ modalId, onClose, currency, totalSupplied }: BorrowModalProps) => {
const { name, ticker } = currency;
const { wallet, walletBalances, signTransaction, refetchBalances, prices } = useWallet();
const { wallet, walletBalances, signTransaction, refetchBalances } = useWallet();
const { prices } = usePools();

const closeModal = () => {
refetchBalances();
Expand Down
Loading

0 comments on commit 61d4d16

Please sign in to comment.