diff --git a/contracts/loan_manager/src/contract.rs b/contracts/loan_manager/src/contract.rs index 0b7ec88d..ef22dcca 100644 --- a/contracts/loan_manager/src/contract.rs +++ b/contracts/loan_manager/src/contract.rs @@ -15,7 +15,7 @@ mod loan_pool { // This is the real address of the Reflector Oracle in testnet. // We use the same adress to mock it for testing. -const REFLECTOR_ADDRESS: &str = "CBKZFI26PDCZUJ5HYYKVB5BWCNYUSNA5LVL4R2JTRVSOB4XEP7Y34OPN"; +const REFLECTOR_ADDRESS: &str = "CCYOZJCOPG34LLQQ7N24YXBM7LL62R7ONMZ3G6WZAAYPB5OYKOMJRN63"; #[allow(dead_code)] pub trait LoansTrait { @@ -36,6 +36,7 @@ pub trait LoansTrait { token_collateral_amount: i128, ) -> i128; fn get_loan(e: &Env, addr: Address) -> Loan; + fn get_price(e: &Env, token: Symbol) -> i128; } #[allow(dead_code)] @@ -210,6 +211,16 @@ impl LoansTrait for LoansContract { panic!() // TODO: It should be panic_with_error or something and give out detailed error. } } + + fn get_price(e: &Env, token: Symbol) -> i128 { + let reflector_address = Address::from_string(&String::from_str(e, REFLECTOR_ADDRESS)); + let reflector_contract = oracle::Client::new(e, &reflector_address); + + let asset = Asset::Other(token); + + let asset_pricedata = reflector_contract.lastprice(&asset).unwrap(); + asset_pricedata.price + } } #[cfg(test)] diff --git a/contracts/loan_pool/src/contract.rs b/contracts/loan_pool/src/contract.rs index 821fd46d..6cdcb770 100644 --- a/contracts/loan_pool/src/contract.rs +++ b/contracts/loan_pool/src/contract.rs @@ -14,7 +14,7 @@ contractmeta!( ); // TODO: get this dynamically when creating the contract. -const LOAN_MANAGER_ADDRESS: &str = "CDIK5MXMF5F3TRW7XHPMUXGHDKBH2SESVDSG2RFGOP2GHXOPCDHTC7VO"; +const LOAN_MANAGER_ADDRESS: &str = "CBCAJ6EHX4NEDXLLIZEVOTNMXOBMOGJMMX6X7ARVNTUGJX5DTXAGZM3R"; #[allow(dead_code)] pub trait LoanPoolTrait { diff --git a/src/pages/_borrow/BorrowableAssetCard.tsx b/src/pages/_borrow/BorrowableAssetCard.tsx index 9ee7f88f..24558ee2 100644 --- a/src/pages/_borrow/BorrowableAssetCard.tsx +++ b/src/pages/_borrow/BorrowableAssetCard.tsx @@ -5,7 +5,7 @@ import type { Currency } from 'src/currencies'; import { useWallet } from 'src/stellar-wallet'; // Temporary hack to use XLM pool for all loans and collaterals. -const XLM_LOAN_POOL_ID = 'CCME5C2PJFCWGW5O5MCO4O6X3AUJLD6XHVH3ZJHC7SD7XK5OTPJRPHF7'; +const XLM_LOAN_POOL_ID = 'CCRWVENKGBUX7EP273GOUMY542VWRFEEIHUICTTDDG5ESLSDNENCH6AT'; interface BorrowableAssetCardProps { currency: Currency; diff --git a/src/pages/_lend/LendableAssetCard.tsx b/src/pages/_lend/LendableAssetCard.tsx index a734bf49..266fed8d 100644 --- a/src/pages/_lend/LendableAssetCard.tsx +++ b/src/pages/_lend/LendableAssetCard.tsx @@ -1,5 +1,6 @@ import { Button } from '@components/Button'; import { Card } from '@components/Card'; +import loanManager from '@contracts/loan_manager'; import { useCallback, useEffect, useState } from 'react'; import type { Currency } from 'src/currencies'; import { useWallet } from 'src/stellar-wallet'; @@ -12,11 +13,11 @@ export const LendableAssetCard = ({ currency }: LendableAssetCardProps) => { const { icon, name, symbol, loanPoolContract } = currency; const { wallet, signTransaction } = useWallet(); - const [totalSupplied, setTotalSupplied] = useState('0'); - const [supplyAPY, setSupplyAPY] = useState('0.00%'); + const [totalSupplied, setTotalSupplied] = useState(null); + const [totalSuppliedPrice, setTotalSuppliedPrice] = useState(null); + const [supplyAPY, setSupplyAPY] = useState('0.00%'); - // Memoize fetchContractData so it doesn't get recreated on every render - const fetchContractData = useCallback(async () => { + const fetchAvailableContractBalance = useCallback(async () => { if (!loanPoolContract) return; try { @@ -25,7 +26,7 @@ export const LendableAssetCard = ({ currency }: LendableAssetCardProps) => { const supplied_lo = BigInt(supplied.simulation.result.retval._value._attributes.lo); const supplied_combined = (supplied_hi << BigInt(64)) + supplied_lo; - setTotalSupplied(formatSuppliedAmount(supplied_combined)); + setTotalSupplied(supplied_combined); // const apy = await loanPoolContract.getSupplyAPY(); // setSupplyAPY(formatAPY(apy)); } catch (error) { @@ -33,7 +34,10 @@ export const LendableAssetCard = ({ currency }: LendableAssetCardProps) => { } }, [loanPoolContract]); // Dependency on loanPoolContract - const formatSuppliedAmount = useCallback((amount: bigint) => { + const formatSuppliedAmount = useCallback((amount: bigint | null) => { + if (amount === BigInt(0)) return '0'; + if (!amount) return 'Loading'; + const ten_k = BigInt(10_000 * 10_000_000); const one_m = BigInt(1_000_000 * 10_000_000); switch (true) { @@ -46,14 +50,52 @@ export const LendableAssetCard = ({ currency }: LendableAssetCardProps) => { } }, []); + const fetchPriceData = useCallback(async () => { + if (!loanManager) return; + + try { + const currentPrice = await loanManager.get_price({ token: currency.symbol }); + const price_hi = BigInt(currentPrice.simulation.result.retval._value._attributes.hi); + const price_lo = BigInt(currentPrice.simulation.result.retval._value._attributes.lo); + const price_combined = (price_hi << BigInt(64)) + price_lo; + console.log(price_combined); + + setTotalSuppliedPrice(price_combined); + } catch (error) { + console.error('Error fetchin price data:', error); + } + }, [currency.symbol]); + + const formatSuppliedAmountPrice = useCallback( + (price: bigint | null) => { + if (totalSupplied === BigInt(0)) return '$0'; + if (!totalSupplied || !price) return 'Loading'; + + const ten_k = BigInt(10_000 * 10_000_000); + const one_m = BigInt(1_000_000 * 10_000_000); + const total_price = ((price / BigInt(10_000_000)) * totalSupplied) / BigInt(10_000_000); + console.log(total_price); + switch (true) { + case total_price > one_m: + return `$${(Number(total_price) / (1_000_000 * 10_000_000)).toFixed(2)}M`; + case total_price > ten_k: + return `$${(Number(total_price) / (1_000 * 10_000_000)).toFixed(1)}K`; + default: + return `$${(Number(total_price) / 10_000_000).toFixed(1)}`; + } + }, + [totalSupplied], + ); + useEffect(() => { // Fetch contract data immediately and set an interval to run every 6 seconds - fetchContractData(); - const intervalId = setInterval(fetchContractData, 6000); + fetchAvailableContractBalance(); + fetchPriceData(); + const intervalId = setInterval(fetchAvailableContractBalance, 6000); // Cleanup function to clear the interval on component unmount return () => clearInterval(intervalId); - }, [fetchContractData]); // Now dependent on the memoized function + }, [fetchAvailableContractBalance, fetchPriceData]); // Now dependent on the memoized function const handleDepositClick = async () => { if (!wallet) { @@ -72,7 +114,7 @@ export const LendableAssetCard = ({ currency }: LendableAssetCardProps) => { } catch (err) { alert(`Error depositing: ${JSON.stringify(err)}`); } - fetchContractData(); + fetchAvailableContractBalance(); }; return ( @@ -86,8 +128,8 @@ export const LendableAssetCard = ({ currency }: LendableAssetCardProps) => {

Total Supplied

-

{totalSupplied}

-

$5.82M

+

{formatSuppliedAmount(totalSupplied)}

+

{formatSuppliedAmountPrice(totalSuppliedPrice)}