From 2a56d25de4c5593c82dac36427b0c18cff1650b6 Mon Sep 17 00:00:00 2001 From: Onno Visser <23527729+onnovisser@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:34:01 +0100 Subject: [PATCH] invest form --- sdk-consumer/src/components/Invest.tsx | 111 ++++++++++++++---- sdk-consumer/src/hooks/useAccount.ts | 6 +- .../src/hooks/useCentrifugeTransaction.ts | 22 ++-- sdk-consumer/src/hooks/usePool.ts | 7 +- 4 files changed, 103 insertions(+), 43 deletions(-) diff --git a/sdk-consumer/src/components/Invest.tsx b/sdk-consumer/src/components/Invest.tsx index 60dc8b8e2..ab6f096e5 100644 --- a/sdk-consumer/src/components/Invest.tsx +++ b/sdk-consumer/src/components/Invest.tsx @@ -1,41 +1,104 @@ -import { useAccount, useDisconnect, useEnsName } from 'wagmi' -import { useAccountBalance } from '../hooks/useAccount' -import { useActiveNetworks, useVaults } from '../hooks/usePool' +import { Button, Card, CurrencyInput, Shelf, Spinner, Stack, Text } from '@centrifuge/fabric' +import { PoolNetwork, Vault } from '@centrifuge/sdk' +import { useEffect, useRef, useState } from 'react' +import { useAccount } from 'wagmi' +import { useCentrifugeTransaction } from '../hooks/useCentrifugeTransaction' +import { useActiveNetworks, useVaultInvestment, useVaults } from '../hooks/usePool' import { ConnectionGuard } from './ConnectionGuard' const poolId = '2779829532' const trancheId = '0xac6bffc5fd68f7772ceddec7b0a316ca' export function Invest() { - const { data: networks } = useActiveNetworks(poolId) - console.log('active networks', networks) + const { data: networks, isLoading } = useActiveNetworks(poolId) + const ref = useRef() + if ((networks?.length ?? 0) > (ref.current?.length ?? 0)) { + ref.current = networks + } return ( - n.chainId) || []}> - - + + + {isLoading ? ( + + + + ) : ( + <> + Invest + n.chainId) || []}> + + + + )} + + ) } function InvestInner() { const { address } = useAccount() - const { disconnect } = useDisconnect() - const { data: ensName } = useEnsName({ address }) - const { data: balance, error, retry, isError } = useAccountBalance() const { data: vaults } = useVaults(poolId, trancheId, 11155111) + const { execute: executeClaim, isLoading: isClaiming } = useCentrifugeTransaction() + const { execute: executeInvest, isLoading: isInvesting } = useCentrifugeTransaction() + const [selectedVault, setVault] = useState() + const [amount, setAmount] = useState(0) + + useEffect(() => { + if (vaults?.length && (!selectedVault || !vaults.includes(selectedVault))) { + setVault(vaults[0]) + } + }, [vaults]) + + function submit() { + if (!selectedVault || !amount) return + executeInvest(selectedVault.increaseInvestOrder(amount)) + } + + function claim() { + if (!selectedVault) return + executeClaim(selectedVault.claim()) + } + + const { data: investment } = useVaultInvestment(selectedVault, address) return ( -
- {address &&
{ensName ? `${ensName} (${address})` : address}
} -

Your balance is {balance?.toFloat() ?? 'Loading...'}

- {error ? ( -
- Error {isError && 'fatal'} - -
- ) : null} - -
+ <> + {investment?.isAllowedToInvest === false && ( + + You are not allowed to invest in this vault + + )} + {investment?.pendingInvestCurrency.gt(0n) && ( + + You have a pending investment of {investment.pendingInvestCurrency.toFloat().toFixed(2)}{' '} + {investment.investmentCurrency.symbol} + + )} + {(investment?.claimableInvestShares.gt(0n) || investment?.claimableCancelInvestCurrency.gt(0n)) && ( + + + You have claimable shares or pending cancelation + + + + )} + setAmount(value)} + label="Amount" + currency={investment?.investmentCurrency.symbol} + secondaryLabel={`${investment?.investmentCurrencyBalance.toFloat().toFixed(2)} balance`} + disabled={ + investment?.isAllowedToInvest === false || + investment?.claimableInvestShares.gt(0n) || + investment?.claimableCancelInvestCurrency.gt(0n) + } + /> + + ) } diff --git a/sdk-consumer/src/hooks/useAccount.ts b/sdk-consumer/src/hooks/useAccount.ts index c9a88de89..a6c3e39df 100644 --- a/sdk-consumer/src/hooks/useAccount.ts +++ b/sdk-consumer/src/hooks/useAccount.ts @@ -3,11 +3,11 @@ import { useAccount } from 'wagmi' import { centrifuge } from '../centrifuge' import { useCentrifugeQuery } from './useCentrifugeQuery' -const tUSD = '0x8503b4452Bf6238cC76CdbEE223b46d7196b1c93' +// const tUSD = '0x8503b4452Bf6238cC76CdbEE223b46d7196b1c93' -export function useAccountBalance() { +export function useAccountBalance(asset?: string) { const { address } = useAccount() - const balance$ = useMemo(() => (address ? centrifuge.balance(tUSD, address) : undefined), [address]) + const balance$ = useMemo(() => (address && asset ? centrifuge.balance(asset, address) : undefined), [address]) console.log('balance$', balance$) return useCentrifugeQuery(balance$) } diff --git a/sdk-consumer/src/hooks/useCentrifugeTransaction.ts b/sdk-consumer/src/hooks/useCentrifugeTransaction.ts index 390cab185..1d9d3d483 100644 --- a/sdk-consumer/src/hooks/useCentrifugeTransaction.ts +++ b/sdk-consumer/src/hooks/useCentrifugeTransaction.ts @@ -1,30 +1,23 @@ import { OperationConfirmedStatus, Transaction } from '@centrifuge/sdk' -import * as React from 'react' +import { useState } from 'react' import { lastValueFrom, tap } from 'rxjs' +import { useConnectorClient } from 'wagmi' +import { centrifuge } from '../centrifuge' import { useTransactions } from '../components/Transactions/TransactionsProvider' -import { useVaults } from './usePool' export type CentrifugeTransactionOptions = { onSuccess?: (args: any[], result: OperationConfirmedStatus) => void onError?: (error: any) => void } -function Comp() { - const { data: vaults } = useVaults('2779829532', '0xac6bffc5fd68f7772ceddec7b0a316ca', 11155111) - const { execute, isLoading } = useCentrifugeTransaction() - - async function submit() { - const vault = vaults?.[0]! - execute(vault.increaseInvestOrder(100)) - } -} - export function useCentrifugeTransaction() { const { updateTransaction, addTransaction } = useTransactions() - const [status, setStatus] = React.useState<'idle' | 'loading' | 'success' | 'error'>() + const { data: client } = useConnectorClient() + const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle') async function execute(observable: Transaction) { setStatus('loading') + centrifuge.setSigner(client!) let lastId = '' try { const lastResult = await lastValueFrom( @@ -53,14 +46,15 @@ export function useCentrifugeTransaction() { }) ) ) + setStatus('success') return (lastResult as OperationConfirmedStatus).receipt } catch (e) { + setStatus('error') if (lastId) { updateTransaction(lastId, { status: 'failed', error: e, }) - setStatus('error') } throw e } diff --git a/sdk-consumer/src/hooks/usePool.ts b/sdk-consumer/src/hooks/usePool.ts index dfed11633..a59e98612 100644 --- a/sdk-consumer/src/hooks/usePool.ts +++ b/sdk-consumer/src/hooks/usePool.ts @@ -1,4 +1,4 @@ -import { Pool } from '@centrifuge/sdk' +import { Pool, Vault } from '@centrifuge/sdk' import { useMemo, useState } from 'react' import { switchMap } from 'rxjs' import { centrifuge } from '../centrifuge' @@ -30,4 +30,7 @@ export function useVaults(poolId: string, trancheId: string, chainId: number) { return useCentrifugeQuery(vaults$) } -export function useVaultInvestment() {} +export function useVaultInvestment(vault?: Vault, investor?: string) { + const investment$ = useMemo(() => (investor && vault ? vault.investment(investor) : undefined), [vault, investor]) + return useCentrifugeQuery(investment$) +}