feat: add collateral selection
This commit is contained in:
parent
d63da050ad
commit
3554e8ce86
|
@ -1,17 +1,56 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useLendingReserve, useTokenName, useUserAccounts, useUserBalance } from '../../hooks';
|
||||
import { LendingReserve, LendingReserveParser } from "../../models/lending";
|
||||
import { useCollateralBalance, useLendingReserve, useLendingReserves, useTokenName, useUserAccounts, useUserBalance } from '../../hooks';
|
||||
import { LendingReserve, LendingReserveParser } from "../../models";
|
||||
import { TokenIcon } from "../TokenIcon";
|
||||
import { formatNumber } from "../../utils/utils";
|
||||
import { Button, Card } from "antd";
|
||||
import { formatNumber, getTokenName } from "../../utils/utils";
|
||||
import { Button, Card, Select } from "antd";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { cache, useAccount } from "../../contexts/accounts";
|
||||
import { cache, ParsedAccount, useAccount } from "../../contexts/accounts";
|
||||
import { NumericInput } from "../Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
import { useConnection, useConnectionConfig } from "../../contexts/connection";
|
||||
import { useWallet } from "../../contexts/wallet";
|
||||
import { borrow } from '../../actions';
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import './style.less';
|
||||
import { Token } from "@solana/spl-token";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
const CollateralSelector = (props: {
|
||||
mint?: string,
|
||||
onMintChange: (id: string) => void;
|
||||
}) => {
|
||||
const { reserveAccounts } = useLendingReserves();
|
||||
const { tokenMap } = useConnectionConfig();
|
||||
|
||||
return <Select
|
||||
size="large"
|
||||
showSearch
|
||||
style={{ minWidth: 120 }}
|
||||
placeholder="Collateral"
|
||||
value={props.mint}
|
||||
onChange={(item) => {
|
||||
if (props.onMintChange) {
|
||||
props.onMintChange(item);
|
||||
}
|
||||
}}
|
||||
filterOption={(input, option) =>
|
||||
option?.name?.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}
|
||||
>
|
||||
{reserveAccounts.map(reserve => {
|
||||
const mint = reserve.info.liquidityMint.toBase58();
|
||||
const address = reserve.pubkey.toBase58();
|
||||
const name = getTokenName(tokenMap, mint);
|
||||
return <Option key={address} value={address} name={name} title={address}>
|
||||
<div key={address} style={{ display: "flex", alignItems: "center" }}>
|
||||
<TokenIcon mintAddress={mint} />
|
||||
{name}
|
||||
</div>
|
||||
</Option>
|
||||
})}
|
||||
</Select>;
|
||||
}
|
||||
|
||||
export const BorrowInput = (props: { className?: string, reserve: LendingReserve, address: PublicKey }) => {
|
||||
const connection = useConnection();
|
||||
|
@ -22,32 +61,43 @@ export const BorrowInput = (props: { className?: string, reserve: LendingReserve
|
|||
const borrowReserve = props.reserve;
|
||||
const borrowReserveAddress = props.address;
|
||||
|
||||
const [collateralReserve, setCollateralReserve] = useState<LendingReserve>();
|
||||
const [collateralReserveMint, setCollateralReserveMint] = useState<string>();
|
||||
|
||||
const collateralReserveAddress = useMemo(() => {
|
||||
return cache.byParser(LendingReserveParser)
|
||||
.find(acc => cache.get(acc) === collateralReserve);
|
||||
}, [collateralReserve])
|
||||
|
||||
const collateralReserve = useMemo(() => {
|
||||
const id: string = cache.byParser(LendingReserveParser)
|
||||
.find(acc => acc === collateralReserveMint) || '';
|
||||
|
||||
return cache.get(id) as ParsedAccount<LendingReserve>;
|
||||
}, [collateralReserveMint])
|
||||
|
||||
const collateral = useCollateralBalance(collateralReserve?.info);
|
||||
|
||||
const name = useTokenName(borrowReserve?.liquidityMint);
|
||||
const {
|
||||
balance: tokenBalance,
|
||||
accounts: fromAccounts
|
||||
} = useUserBalance(collateralReserve?.liquidityMint);
|
||||
} = useUserBalance(collateralReserve?.info.collateralMint);
|
||||
// const collateralBalance = useUserBalance(reserve?.collateralMint);
|
||||
|
||||
if(collateral) {
|
||||
debugger;
|
||||
}
|
||||
|
||||
const onBorrow = useCallback(() => {
|
||||
if(!collateralReserve || !collateralReserveAddress) {
|
||||
if (!collateralReserve) {
|
||||
return;
|
||||
}
|
||||
|
||||
debugger;
|
||||
|
||||
borrow(
|
||||
fromAccounts[0],
|
||||
parseFloat(value),
|
||||
borrowReserve,
|
||||
borrowReserveAddress,
|
||||
collateralReserve,
|
||||
new PublicKey(collateralReserveAddress),
|
||||
collateralReserve.info,
|
||||
collateralReserve.pubkey,
|
||||
connection,
|
||||
wallet);
|
||||
}, [value, borrowReserve, fromAccounts, borrowReserveAddress]);
|
||||
|
@ -83,6 +133,13 @@ export const BorrowInput = (props: { className?: string, reserve: LendingReserve
|
|||
/>
|
||||
<div>{name}</div>
|
||||
</div>
|
||||
<div className="borrow-input-title">
|
||||
Select collateral account?
|
||||
</div>
|
||||
<CollateralSelector
|
||||
mint={collateralReserveMint}
|
||||
onMintChange={setCollateralReserveMint}
|
||||
/>
|
||||
|
||||
<Button type="primary" onClick={onBorrow} disabled={fromAccounts.length === 0}>Borrow</Button>
|
||||
</div>
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useLendingReserve, useTokenName, useUserAccounts, useUserBalance, useCollateralBalance } from './../../hooks';
|
||||
import { LendingReserve, LendingReserveParser } from "../../models/lending";
|
||||
import { TokenIcon } from "../../components/TokenIcon";
|
||||
import React, { } from "react";
|
||||
import { useTokenName, useUserBalance, useCollateralBalance } from './../../hooks';
|
||||
import { LendingReserve } from "../../models/lending";
|
||||
import { formatNumber } from "../../utils/utils";
|
||||
import { Button, Card } from "antd";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { cache, useAccount } from "../../contexts/accounts";
|
||||
import { NumericInput } from "../../components/Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
import { useWallet } from "../../contexts/wallet";
|
||||
import { deposit } from './../../actions/deposit';
|
||||
import { Card } from "antd";
|
||||
import './style.less';
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
|
|
|
@ -1,30 +1,11 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useLendingReserve, useTokenName, useUserAccounts, useUserBalance } from './../../hooks';
|
||||
import { LendingReserve, LendingReserveParser } from "../../models/lending";
|
||||
import { TokenIcon } from "../../components/TokenIcon";
|
||||
import { formatNumber } from "../../utils/utils";
|
||||
import { Button, Card } from "antd";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { cache, useAccount } from "../../contexts/accounts";
|
||||
import { NumericInput } from "../../components/Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
import { useWallet } from "../../contexts/wallet";
|
||||
import { deposit } from './../../actions/deposit';
|
||||
import React, { useState } from "react";
|
||||
import { LendingReserve } from "../../models/lending";
|
||||
import { Card } from "antd";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import './style.less';
|
||||
|
||||
export const ReserveStatus = (props: { className?: string, reserve: LendingReserve, address: PublicKey }) => {
|
||||
const connection = useConnection();
|
||||
const { wallet } = useWallet();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
const reserve = props.reserve;
|
||||
const address = props.address;
|
||||
|
||||
const name = useTokenName(reserve?.liquidityMint);
|
||||
const { balance: tokenBalance, accounts: fromAccounts } = useUserBalance(reserve?.liquidityMint);
|
||||
|
||||
const [] = useState('');
|
||||
|
||||
const bodyStyle: React.CSSProperties = {
|
||||
display: 'flex',
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import React, { useMemo } from "react";
|
||||
import { useCollateralBalance, useLendingReserve, useTokenName, useUserAccounts, useUserBalance } from './../../hooks';
|
||||
import { LendingReserve, LendingReserveParser } from "../../models/lending";
|
||||
import { TokenIcon } from "../../components/TokenIcon";
|
||||
import { formatNumber, formatPct, fromLamports } from "../../utils/utils";
|
||||
import React from "react";
|
||||
import { useCollateralBalance, useTokenName, useUserBalance } from './../../hooks';
|
||||
import { LendingReserve } from "../../models/lending";
|
||||
import { formatNumber, fromLamports } from "../../utils/utils";
|
||||
import { Button, Card, Typography } from "antd";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { useAccount, useMint } from "../../contexts/accounts";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useMint } from "../../contexts/accounts";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
const { Text } = Typography;
|
||||
|
@ -24,7 +23,6 @@ export const UserLendingCard = (props: {
|
|||
const { balance: tokenBalance } = useUserBalance(props.reserve.liquidityMint);
|
||||
const { balance: collateralBalance } = useCollateralBalance(props.reserve);
|
||||
|
||||
const totalLiquidity = fromLamports(props.reserve.totalLiquidity.toNumber(), liquidityMint);
|
||||
|
||||
// TODO: calculate
|
||||
const borrowed = 0;
|
||||
|
|
|
@ -352,13 +352,17 @@ export const getMultipleAccounts = async (
|
|||
.map(
|
||||
(a) =>
|
||||
a.array.map((acc) => {
|
||||
if(!acc) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { data, ...rest } = acc;
|
||||
const obj = {
|
||||
...rest,
|
||||
data: Buffer.from(data[0], "base64"),
|
||||
} as AccountInfo<Buffer>;
|
||||
return obj;
|
||||
}) as AccountInfo<Buffer>[]
|
||||
}).filter(_ => _) as AccountInfo<Buffer>[]
|
||||
)
|
||||
.flat();
|
||||
return { keys, array };
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import React, { useCallback, useContext, useEffect, useState } from "react";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useConnection } from "./connection";
|
||||
import { LENDING_PROGRAM_ID } from "./../constants/ids";
|
||||
import { LendingReserveLayout, LendingMarketLayout, LendingMarket, LendingMarketParser, isLendingReserve, isLendingMarket, LendingReserveParser, LendingReserve } from "./../models/lending";
|
||||
import { cache, getMultipleAccounts, ParsedAccount } from "./accounts";
|
||||
import { AccountInfo, PublicKey } from "@solana/web3.js";
|
||||
import { isForInStatement } from "typescript";
|
||||
import { LendingMarketParser, isLendingReserve, isLendingMarket, LendingReserveParser, LendingReserve } from "./../models/lending";
|
||||
import { cache, getMultipleAccounts } from "./accounts";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
|
||||
export interface LendingContextState {
|
||||
|
||||
|
@ -64,7 +63,6 @@ export const useLending = () => {
|
|||
await getMultipleAccounts(connection, toQuery, "single").then(
|
||||
({ keys, array }) => {
|
||||
return array.map((obj, index) => {
|
||||
const pubKey = new PublicKey(keys[index]);
|
||||
// TODO: add to cache
|
||||
|
||||
return obj;
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
import { PublicKey } from "@solana/web3.js";
|
||||
import { useMemo } from "react";
|
||||
import { useAccount, useMint } from "../contexts/accounts";
|
||||
import { useMint } from "../contexts/accounts";
|
||||
import { LendingReserve } from "../models/lending";
|
||||
import { fromLamports } from "../utils/utils";
|
||||
import { useUserAccounts } from "./useUserAccounts";
|
||||
import { useUserBalance } from "./useUserBalance";
|
||||
|
||||
export function useCollateralBalance(reserve?: LendingReserve) {
|
||||
const mint = useMint(reserve?.collateralMint);
|
||||
const { balance: nativeBalance, accounts } = useUserBalance(reserve?.collateralMint, true);
|
||||
const { balanceLamports, accounts } = useUserBalance(reserve?.collateralMint);
|
||||
|
||||
const balance = fromLamports((reserve?.totalLiquidity.toNumber() || 0) * (nativeBalance / (reserve?.collateralMintSupply.toNumber() || 1)), mint);
|
||||
const collateralRatioLamports =
|
||||
(reserve?.totalLiquidity.toNumber() || 0) *
|
||||
(balanceLamports / (reserve?.collateralMintSupply.toNumber() || 1));
|
||||
|
||||
return { balance, accounts };
|
||||
return {
|
||||
balance: fromLamports(collateralRatioLamports, mint),
|
||||
balanceLamports: collateralRatioLamports,
|
||||
accounts
|
||||
};
|
||||
}
|
|
@ -4,7 +4,7 @@ import { useMint } from "../contexts/accounts";
|
|||
import { fromLamports } from "../utils/utils";
|
||||
import { useUserAccounts } from "./useUserAccounts";
|
||||
|
||||
export function useUserBalance(mint?: PublicKey, inLamports = false) {
|
||||
export function useUserBalance(mint?: PublicKey) {
|
||||
const { userAccounts } = useUserAccounts();
|
||||
const mintInfo = useMint(mint);
|
||||
const accounts = useMemo(() => {
|
||||
|
@ -13,11 +13,14 @@ export function useUserBalance(mint?: PublicKey, inLamports = false) {
|
|||
.sort((a, b) => b.info.amount.sub(a.info.amount).toNumber());
|
||||
}, [userAccounts]);
|
||||
|
||||
const balance = useMemo(() => {
|
||||
const result = accounts
|
||||
const balanceLamports = useMemo(() => {
|
||||
return accounts
|
||||
.reduce((res, item) => res += item.info.amount.toNumber(), 0);
|
||||
return inLamports ? result : fromLamports(result , mintInfo);
|
||||
},[accounts, mintInfo]);
|
||||
|
||||
return { balance, accounts };
|
||||
return {
|
||||
balance: fromLamports(balanceLamports, mintInfo),
|
||||
balanceLamports,
|
||||
accounts,
|
||||
};
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
import {
|
||||
AccountInfo,
|
||||
Connection,
|
||||
PublicKey,
|
||||
sendAndConfirmRawTransaction,
|
||||
SYSVAR_CLOCK_PUBKEY,
|
||||
SYSVAR_RENT_PUBKEY,
|
||||
TransactionInstruction,
|
||||
|
@ -10,7 +8,6 @@ import {
|
|||
import BN from "bn.js";
|
||||
import * as BufferLayout from "buffer-layout";
|
||||
import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../../constants/ids";
|
||||
import { sendTransaction } from "../../contexts/connection";
|
||||
import * as Layout from "./../../utils/layout";
|
||||
import { LendingInstruction } from './lending';
|
||||
|
||||
|
|
|
@ -1,23 +1,14 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useLendingReserve, useTokenName, useUserAccounts, useUserBalance } from '../../hooks';
|
||||
import { LendingReserve, LendingReserveParser } from "../../models/lending";
|
||||
import { TokenIcon } from "../../components/TokenIcon";
|
||||
import { formatNumber } from "../../utils/utils";
|
||||
import { Button, Card } from "antd";
|
||||
import React, { } from "react";
|
||||
import { useLendingReserve } from '../../hooks';
|
||||
import { useParams } from "react-router-dom";
|
||||
import { cache, useAccount } from "../../contexts/accounts";
|
||||
import { NumericInput } from "../../components/Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
import { useWallet } from "../../contexts/wallet";
|
||||
import { deposit } from '../../actions/deposit';
|
||||
import './style.less';
|
||||
|
||||
import { BorrowInput } from '../../components/BorrowInput';
|
||||
import { SideReserveOverview, SideReserveOverviewMode } from '../../components/SideReserveOverview';
|
||||
|
||||
export const BorrowReserveView = () => {
|
||||
const connection = useConnection();
|
||||
const { wallet } = useWallet();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const lendingReserve = useLendingReserve(id);
|
||||
const reserve = lendingReserve?.info;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo } from "react";
|
||||
import { useCollateralBalance, useTokenName, useUserAccounts, useUserBalance } from '../../../hooks';
|
||||
import React from "react";
|
||||
import { useCollateralBalance, useTokenName, useUserBalance } from '../../../hooks';
|
||||
import { LendingReserve } from "../../../models/lending";
|
||||
import { TokenIcon } from "../../../components/TokenIcon";
|
||||
import { formatNumber } from "../../../utils/utils";
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useLendingReserve, useTokenName, useUserAccounts, useUserBalance } from '../../hooks';
|
||||
import { LendingReserve, LendingReserveParser } from "../../models/lending";
|
||||
import { TokenIcon } from "../../components/TokenIcon";
|
||||
import { formatNumber } from "../../utils/utils";
|
||||
import { Button, Card } from "antd";
|
||||
import React, { } from "react";
|
||||
import { useLendingReserve } from '../../hooks';
|
||||
import { useParams } from "react-router-dom";
|
||||
import { cache, useAccount } from "../../contexts/accounts";
|
||||
import { NumericInput } from "../../components/Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
import { useWallet } from "../../contexts/wallet";
|
||||
import { deposit } from '../../actions/deposit';
|
||||
import './style.less';
|
||||
|
||||
import { DepositInput } from '../../components/DepositInput';
|
||||
|
@ -17,8 +8,6 @@ import { DepositInfoLine } from '../../components/DepositInfoLine';
|
|||
import { SideReserveOverview, SideReserveOverviewMode } from '../../components/SideReserveOverview';
|
||||
|
||||
export const DepositReserveView = () => {
|
||||
const connection = useConnection();
|
||||
const { wallet } = useWallet();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const lendingReserve = useLendingReserve(id);
|
||||
const reserve = lendingReserve?.info;
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
import React, { useMemo } from "react";
|
||||
import { useLendingReserves, useTokenName, useUserAccounts, useUserBalance } from '../../hooks';
|
||||
import { LendingReserve } from "../../models/lending";
|
||||
import { TokenIcon } from "../../components/TokenIcon";
|
||||
import { formatNumber } from "../../utils/utils";
|
||||
import { Button } from "antd";
|
||||
import React from "react";
|
||||
import { useLendingReserves } from '../../hooks';
|
||||
import { LendingReserveItem } from "./item";
|
||||
import './itemStyle.less';
|
||||
|
||||
|
|
|
@ -1,24 +1,12 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useLendingReserve, useTokenName, useUserAccounts, useUserBalance } from './../../hooks';
|
||||
import { LendingReserve, LendingReserveParser } from "../../models/lending";
|
||||
import { TokenIcon } from "../../components/TokenIcon";
|
||||
import { formatNumber } from "../../utils/utils";
|
||||
import { Button, Card } from "antd";
|
||||
import React, { } from "react";
|
||||
import { useLendingReserve } from './../../hooks';
|
||||
import { useParams } from "react-router-dom";
|
||||
import { cache, useAccount } from "../../contexts/accounts";
|
||||
import { NumericInput } from "../../components/Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
import { useWallet } from "../../contexts/wallet";
|
||||
import { deposit } from './../../actions/deposit';
|
||||
import './style.less';
|
||||
|
||||
import { DepositInput } from '../../components/DepositInput';
|
||||
import { UserLendingCard } from './../../components/UserLendingCard';
|
||||
import { ReserveStatus } from './../../components/ReserveStatus';
|
||||
|
||||
export const ReserveView = () => {
|
||||
const connection = useConnection();
|
||||
const { wallet } = useWallet();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const lendingReserve = useLendingReserve(id);
|
||||
const reserve = lendingReserve?.info;
|
||||
|
|
Loading…
Reference in New Issue