Skip to content

Commit

Permalink
🩹Fix multiple strategies handle
Browse files Browse the repository at this point in the history
  • Loading branch information
MattPoblete committed Nov 21, 2024
1 parent 5036ea1 commit 584379a
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 105 deletions.
52 changes: 29 additions & 23 deletions apps/dapp/src/components/DeployVault/AddNewStrategyButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '@/components/ui/dialog'
import { getTokenSymbol } from '@/helpers/getTokenInfo'
import { StrategyMethod, useStrategyCallback } from '@/hooks/useStrategy'
import { getDefaultStrategies, pushAmount, pushAsset, setAmountByAddress } from '@/store/lib/features/vaultStore'
import { getDefaultStrategies, pushAsset, setAssetAmount } from '@/store/lib/features/vaultStore'
import { useAppDispatch, useAppSelector } from '@/store/lib/storeHooks'
import { Asset, Strategy } from '@/store/lib/types'
import {
Expand All @@ -30,6 +30,7 @@ import { MdAdd } from 'react-icons/md'
import { Checkbox } from '../ui/checkbox'
import { CheckboxCard } from '../ui/checkbox-card'
import { InputGroup } from '../ui/input-group'
import { NumberInputField, NumberInputRoot } from '../ui/number-input'

interface AmountInputProps {
amount: number
Expand All @@ -44,7 +45,7 @@ function AddNewStrategyButton() {
const [open, setOpen] = useState<boolean>(false)
const newVault = useAppSelector((state) => state.newVault)
const [defaultStrategies, setDefaultStrategies] = useState<any[]>([])
const [selectedAsset, setSelectedAsset] = useState<Asset>({ address: '', strategies: [], symbol: '' })
const [selectedAsset, setSelectedAsset] = useState<Asset>({ address: '', strategies: [], symbol: '', amount: 0 })
const [assets, setAssets] = useState<Asset[]>([])
const [amountInput, setAmountInput] = useState<AmountInputProps>({ amount: 0, enabled: false })

Expand Down Expand Up @@ -102,6 +103,11 @@ function AddNewStrategyButton() {

const handleAmountInput = async (e: any) => {
const input = e.target.value
if (!input) {
console.log('input is empty')
setSelectedAsset({ ...selectedAsset, amount: 0 })
}
console.log(input)
const decimalRegex = /^(\d+)?(\.\d{0,7})?$/
if (!decimalRegex.test(input)) return
if (input.startsWith('.')) {
Expand All @@ -122,15 +128,11 @@ function AddNewStrategyButton() {
}
const exists = strategyExists(selectedAsset.strategies[0]!)
if (exists) {
if (amountInput.enabled && amountInput.amount! > 0) {
await dispatch(setAmountByAddress({ address: selectedAsset.address, amount: amountInput.amount }))
} else if (amountInput.enabled == false || amountInput.amount! == 0) {
await dispatch(setAmountByAddress({ address: selectedAsset.address, amount: 0 }))
}

}
await dispatch(pushAsset(newAsset))
if (!exists && amountInput.enabled && amountInput.amount! > 0) {
await dispatch(pushAmount(amountInput.amount!))
await dispatch(setAssetAmount({ address: newAsset.address, amount: amountInput.amount! }))
}
resetForm()
}
Expand All @@ -154,6 +156,7 @@ function AddNewStrategyButton() {
<Stack key={index} my={2}>
<CheckboxCard
checked={strategyExists(strategy) || selectedAsset.strategies.some((str) => str.address === strategy.address)}
disabled={strategyExists(strategy)}
onCheckedChange={(e) => handleSelectStrategy(!!e.checked, strategy)}
label={strategy.name}
/>
Expand All @@ -172,24 +175,27 @@ function AddNewStrategyButton() {

</Grid>
}
{amountInput.enabled && (
<Grid templateColumns={['1fr', null, 'repeat(12, 2fr)']}>
<GridItem alignContent={'center'} colStart={1}>
<Text fontSize={'sm'}>Amount:</Text>
</GridItem>
<GridItem colStart={8} colEnd={13}>
<InputGroup
endElement={`${selectedAsset.symbol}`}
>
<Input onChange={handleAmountInput} value={amountInput.amount} />
</InputGroup>
</GridItem>
</Grid>
)}
</Stack>
)}
</For>

{amountInput.enabled && (
<Grid templateColumns={['1fr', null, 'repeat(12, 2fr)']}>
<GridItem alignContent={'center'} colStart={1}>
<Text fontSize={'sm'}>Amount:</Text>
</GridItem>
<GridItem colStart={8} colEnd={13}>
<InputGroup
endElement={`${selectedAsset.symbol}`}
>
<NumberInputRoot
onChange={handleAmountInput}
>
<NumberInputField />
</NumberInputRoot>
</InputGroup>
</GridItem>
</Grid>
)}
</DialogBody>
<DialogFooter>
<Button variant='ghost' mr={3} onClick={() => setOpen(false)}>
Expand Down
10 changes: 5 additions & 5 deletions apps/dapp/src/components/DeployVault/ConfirmDelpoyModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@ export const ConfirmDelpoyModal = ({ isOpen, onClose }: { isOpen: boolean, onClo
});
const assetParamsScValVec = xdr.ScVal.scvVec(assetParamsScVal);
const amountsScVal = newVault.assets.map((asset, index) => {
const parsedAmount = newVault.amounts[index] || 0;
const parsedAmount = newVault.assets[index]?.amount || 0;
const truncatedAmount = Math.floor(parsedAmount * 1e7) / 1e7;
const convertedAmount = Number(truncatedAmount) * Math.pow(10, 7)
if (newVault.amounts.length === 0) return nativeToScVal(0, { type: "i128" });
if (newVault.assets[index]?.amount === 0) return nativeToScVal(0, { type: "i128" });
return nativeToScVal(convertedAmount, { type: "i128" });
});
/* const amountsScVal = newVault.amounts.map((amount) => {
Expand All @@ -197,7 +197,7 @@ export const ConfirmDelpoyModal = ({ isOpen, onClose }: { isOpen: boolean, onClo
let result: any;


if (newVault.amounts.length === 0) {
if (newVault.assets[0]?.amount === undefined) {
const createDefindexParams: xdr.ScVal[] = [
emergencyManager.toScVal(),
feeReceiver.toScVal(),
Expand All @@ -221,7 +221,7 @@ export const ConfirmDelpoyModal = ({ isOpen, onClose }: { isOpen: boolean, onClo
txModal.handleError(e.toString());
return
}
} else {
} else if (newVault.assets[0]?.amount! > 0) {
if (!address) throw new Error('Address not found')
const caller = new Address(address);
const createDefindexParams: xdr.ScVal[] = [
Expand Down Expand Up @@ -255,7 +255,7 @@ export const ConfirmDelpoyModal = ({ isOpen, onClose }: { isOpen: boolean, onClo
const idleFunds = newVault.assets.map((asset, index) => {
return {
address: asset.address,
amount: newVault.amounts[index] || 0
amount: newVault.assets[index]?.amount || 0
}
})
const tempVault: VaultData = {
Expand Down
93 changes: 42 additions & 51 deletions apps/dapp/src/components/DeployVault/DeployVault.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import {
Button,
For,
Box,
HStack,
Text,
Stack,
} from '@chakra-ui/react'
import AddNewStrategyButton from './AddNewStrategyButton'
import { useAppDispatch, useAppSelector } from '@/store/lib/storeHooks'
import { ConfirmDelpoyModal } from './ConfirmDelpoyModal'
import { removeAmountByIndex, removeAsset, setName, setSymbol } from '@/store/lib/features/vaultStore'
import { removeStrategy, setName, setSymbol } from '@/store/lib/features/vaultStore'
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '../ui/dialog'
import { Asset } from '@/store/lib/types'
import { Asset, Strategy } from '@/store/lib/types'
import { shortenAddress } from '@/helpers/address'
import { Tooltip } from '../ui/tooltip'
import { FaRegTrashCan } from "react-icons/fa6";
Expand All @@ -22,7 +25,6 @@ export const DeployVault = () => {
const dispatch = useAppDispatch()
//const strategies: Strategy[] = []//useAppSelector(state => state.newVault.strategies)
const assets: Asset[] = useAppSelector(state => state.newVault.assets)
const amounts: number[] = useAppSelector(state => state.newVault.amounts)
const vaultName = useAppSelector(state => state.newVault.name)
const vaultSymbol = useAppSelector(state => state.newVault.symbol)
const [openConfirm, setOpenConfirm] = useState<boolean>(false)
Expand All @@ -39,9 +41,8 @@ export const DeployVault = () => {
await dispatch(setSymbol(e.target.value))
}

const handleRemoveAsset = (asset: Asset, index: number) => {
dispatch(removeAmountByIndex(index))
dispatch(removeAsset(asset.address))
const handleRemoveStrategy = (strategy: Strategy) => {
dispatch(removeStrategy(strategy))
}

return (
Expand All @@ -64,34 +65,31 @@ export const DeployVault = () => {
<AddNewStrategyButton />
</GridItem>
</Grid>
<Grid
templateColumns={['1fr', null, 'repeat(12, 1fr)']}
alignSelf={'end'}
alignContent={'center'}
mb={4}
gap={6}>
<For each={assets}>
{(asset, j) => (
<GridItem colSpan={6} key={j}>
<Card.Root>
<Card.Header>
<Grid
templateColumns={['1fr', null, 'repeat(12, 1fr)']}
>
<GridItem colSpan={11}>
<Card.Title>{asset.strategies[0] ? asset.strategies[0].name : shortenAddress(asset.strategies[0]!.address)}</Card.Title>
</GridItem>
<GridItem css={{ cursor: 'pointer' }} onClick={() => handleRemoveAsset(asset, j)}>
<Box>
<FaRegTrashCan />
</Box>
</GridItem>
</Grid>
</Card.Header>
<Card.Body>
<ul>
<For each={asset.strategies}>
{(strategy, index) => (
<For each={assets}>
{(asset, j) => (
<Stack key={j}>
<Text>{asset.symbol}</Text>
{asset.amount && <Text>Initial deposit: {asset.amount}</Text>}
<HStack w='full' justifyContent={'space-evenly'}>
<For each={asset.strategies}>
{(strategy, index) => (
<Card.Root key={index}>
<Card.Header>
<Grid
templateColumns={['1fr', null, 'repeat(12, 1fr)']}
>
<GridItem colSpan={11}>
<Card.Title>{strategy.name ?? shortenAddress(strategy.address)}</Card.Title>
</GridItem>
<GridItem css={{ cursor: 'pointer' }} onClick={() => handleRemoveStrategy(strategy)}>
<Box>
<FaRegTrashCan />
</Box>
</GridItem>
</Grid>
</Card.Header>
<Card.Body>
<ul>
<Box key={index}>
<li>
Strategy asset: {asset.symbol}
Expand All @@ -103,24 +101,17 @@ export const DeployVault = () => {
Strategy Address: {shortenAddress(strategy.address)}
</li>
</Tooltip>
{(amounts[j]! > 0) && <li>Initial deposit: ${amounts[j]} {asset.symbol}</li>}
</Box>
)}
</For>
</ul>
</Card.Body>
</Card.Root>
</GridItem>
)}
</For>
</Grid>
{/* {assets.length > 0 &&
<Grid templateColumns={['1fr', null, 'repeat(8, 2fr)']} dir='reverse'>
<GridItem colStart={[1, null, 8]} textAlign={['center', null, 'end']}>
<h2>Total: {totalValues}</h2>
</GridItem>
</Grid>
} */}

</ul>
</Card.Body>
</Card.Root>
)}
</For>
</HStack>
</Stack>
)}
</For>
</DialogBody>
<DialogFooter>
<DialogRoot open={openConfirm} onOpenChange={(e) => setOpenConfirm(e.open)}>
Expand Down
10 changes: 5 additions & 5 deletions apps/dapp/src/components/DeployVault/VaultPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const CustomInputField = ({
<IconButton
aria-label='Connected address'
size={'sm'}
variant={'ghost'}
onClick={() => handleClick(address!)}
>
<FaRegPaste />
Expand Down Expand Up @@ -181,8 +182,7 @@ export const dropdownData = {
export const VaultPreview: React.FC<VaultPreviewProps> = ({ data, accordionValue, setAccordionValue, formControl, setFormControl }) => {

const dispatch = useAppDispatch()
const amounts = useAppSelector(state => state.newVault.amounts)

const newVault = useAppSelector(state => state.newVault)
const handleManagerChange = (input: string) => {
const isValid = isValidAddress(input)
while (!isValid) {
Expand Down Expand Up @@ -289,7 +289,7 @@ export const VaultPreview: React.FC<VaultPreviewProps> = ({ data, accordionValue
<Table.Cell>Name</Table.Cell>
<Table.Cell textAlign={'center'}>Address</Table.Cell>
<Table.Cell textAlign={'center'} >Asset</Table.Cell>
{amounts.length > 0 && (
{newVault.assets.some((asset) => asset.amount) && (
<Table.Cell textAlign={'center'}>Initial deposit</Table.Cell>
)}
</Table.Row>
Expand All @@ -302,8 +302,8 @@ export const VaultPreview: React.FC<VaultPreviewProps> = ({ data, accordionValue
{asset.strategies[0]?.address ? shortenAddress(asset.strategies[0]?.address) : '-'}
</Table.Cell>
<Table.Cell textAlign={'center'}>{asset.symbol}</Table.Cell>
{amounts.length > 0 && (
<Table.Cell textAlign={'center'}>${amounts[index]} {asset.symbol}</Table.Cell>
{(asset.amount && asset.amount > 0) && (
<Table.Cell textAlign={'center'}>${asset.amount} {asset.symbol}</Table.Cell>
)}
</Table.Row>
))}
Expand Down
37 changes: 17 additions & 20 deletions apps/dapp/src/store/lib/features/vaultStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const initialState: NewVaultState = {
symbol: "",
vaultShare: 0,
assets: [],
amounts: [],
TVL: 0,
}

Expand Down Expand Up @@ -65,12 +64,13 @@ export const newVaultSlice = createSlice({
state.vaultShare = action.payload;
}),
pushAsset: ((state, action: PayloadAction<Asset>) => {
const alreadyExists = state.assets.find(asset => asset.address === action.payload.address && asset.strategies.length === action.payload.strategies.length)
if(alreadyExists) {
console.warn('Asset already exists')
return;
} else {
const assetIndex = state.assets.findIndex(asset => asset.address === action.payload.address);
if (assetIndex === -1) {
state.assets.push(action.payload);
} else if (assetIndex !== -1) {
action.payload.strategies.forEach(strategy => {
state.assets[assetIndex]!.strategies.push(strategy);
});
}
}),
resetAssets: ((state) => {
Expand All @@ -82,18 +82,12 @@ export const newVaultSlice = createSlice({
pushStrategy: ((state, action: PayloadAction<Strategy>) => {
state.assets.find(asset => asset.address === action.payload.address)?.strategies.push(action.payload);
}),
pushAmount: ((state, action: PayloadAction<number>) => {
state.amounts?.push(action.payload);
}),
setAmountByAddress: ((state, action: PayloadAction<{address:string, amount:number}>) => {
const index = state.assets.findIndex(asset => asset.address === action.payload.address);
if(index !== -1) {
state.amounts[index] = action.payload.amount;
setAssetAmount: ((state, action: PayloadAction<{address:string, amount:number}>) => {
const assetIndex = state.assets.findIndex(asset => asset.address === action.payload.address);
if (assetIndex !== -1) {
state.assets[assetIndex]!.amount = Number(state.assets[assetIndex]!.amount || 0) + Number(action.payload.amount);
}
}),
removeAmountByIndex: ((state, action: PayloadAction<number>) => {
state.amounts?.splice(action.payload, 1);
}),
openEditVault: ((state, action: PayloadAction<VaultData>) => {
state.name = action.payload.name;
state.manager = action.payload.manager;
Expand All @@ -111,9 +105,13 @@ export const newVaultSlice = createSlice({
state.symbol = "";
state.vaultShare = 0;
state.assets = [];
state.amounts = [];
state.TVL = 0;
}),
removeStrategy: ((state, action: PayloadAction<Strategy>) => {
state.assets.forEach(asset => {
asset.strategies = asset.strategies.filter(strategy => strategy.address !== action.payload.address);
});
}),
}
})

Expand All @@ -125,13 +123,12 @@ export const {
setFeeReceiver,
setVaultShare,
pushAsset,
pushAmount,
removeAsset,
removeAmountByIndex,
resetAssets,
openEditVault,
resetNewVault,
setAmountByAddress
removeStrategy,
setAssetAmount,
} = newVaultSlice.actions

// Other code such as selectors can use the imported `RootState` type
Expand Down
Loading

0 comments on commit 584379a

Please sign in to comment.