Skip to content

Commit

Permalink
invest form
Browse files Browse the repository at this point in the history
  • Loading branch information
onnovisser committed Dec 17, 2024
1 parent e85138c commit 2a56d25
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 43 deletions.
111 changes: 87 additions & 24 deletions sdk-consumer/src/components/Invest.tsx
Original file line number Diff line number Diff line change
@@ -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<PoolNetwork[]>()
if ((networks?.length ?? 0) > (ref.current?.length ?? 0)) {
ref.current = networks
}
return (
<ConnectionGuard networks={networks?.map((n) => n.chainId) || []}>
<InvestInner />
</ConnectionGuard>
<Card maxWidth={400} mx="auto" p={2} backgroundColor="backgroundSecondary">
<Stack gap={2}>
{isLoading ? (
<Shelf justifyContent="center">
<Spinner />
</Shelf>
) : (
<>
<Text variant="heading1">Invest</Text>
<ConnectionGuard networks={ref.current?.map((n) => n.chainId) || []}>
<InvestInner />
</ConnectionGuard>
</>
)}
</Stack>
</Card>
)
}

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<Vault>()
const [amount, setAmount] = useState<number | ''>(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 (
<div>
{address && <div>{ensName ? `${ensName} (${address})` : address}</div>}
<h1>Your balance is {balance?.toFloat() ?? 'Loading...'}</h1>
{error ? (
<div>
Error {isError && 'fatal'}
<button type="button" onClick={() => retry()}>
Retry
</button>
</div>
) : null}
<button onClick={() => disconnect()}>Disconnect</button>
</div>
<>
{investment?.isAllowedToInvest === false && (
<Text variant="body2" color="statusCritical">
You are not allowed to invest in this vault
</Text>
)}
{investment?.pendingInvestCurrency.gt(0n) && (
<Text variant="body2" color="statusWarning">
You have a pending investment of {investment.pendingInvestCurrency.toFloat().toFixed(2)}{' '}
{investment.investmentCurrency.symbol}
</Text>
)}
{(investment?.claimableInvestShares.gt(0n) || investment?.claimableCancelInvestCurrency.gt(0n)) && (
<Stack gap={1}>
<Text variant="body2" color="statusWarning">
You have claimable shares or pending cancelation
</Text>
<Button loading={isClaiming} onClick={claim} small>
Claim
</Button>
</Stack>
)}
<CurrencyInput
value={amount}
onChange={(value) => 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)
}
/>
<Button onClick={submit} disabled={!amount} loading={isInvesting}>
Invest
</Button>
</>
)
}
6 changes: 3 additions & 3 deletions sdk-consumer/src/hooks/useAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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$)
}
22 changes: 8 additions & 14 deletions sdk-consumer/src/hooks/useCentrifugeTransaction.ts
Original file line number Diff line number Diff line change
@@ -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(
Expand Down Expand Up @@ -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
}
Expand Down
7 changes: 5 additions & 2 deletions sdk-consumer/src/hooks/usePool.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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$)
}

0 comments on commit 2a56d25

Please sign in to comment.