Skip to content

Commit

Permalink
add network check and switch
Browse files Browse the repository at this point in the history
minor ux improvements
  • Loading branch information
troopdegen committed Oct 20, 2024
1 parent 174bdda commit b280322
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 21 deletions.
32 changes: 25 additions & 7 deletions src/app/admin/creditalent/underWriterDepositWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react'
import { Address, formatUnits, parseEther } from 'viem'
import { useAccount, useReadContract, useWriteContract } from 'wagmi'
import { useBalanceOf } from '../../../hooks/useBalanceOf'
import { useBalanceOf } from '@/hooks/useBalanceOf'
import { ERC20ABI } from '@/components/onchain/abis/erc20'
import CreditTalentCenterABI from '@/components/onchain/abis/CreditTalentCenter'

Expand All @@ -24,17 +24,24 @@ export default function UnderWriterDepositWidget() {
const xocBalance = useBalanceOf({
tokenAddress: xocContract,
walletAddress: accountAddress as Address,
chainId: 8453,
})

const formatBalance = (balance: string) => {
const parsedBalance = parseFloat(balance)
return isNaN(parsedBalance) ? '0.00' : parsedBalance
}

const formattedXocBalance = xocBalance ? formatBalance(xocBalance.balance) : '0.00'
const formattedXocBalance = xocBalance
? formatBalance(xocBalance.balance)
: '0.00'

// Hook to read the XOC contract allowance
const { data: xocAllowance, isError, isLoading } = useReadContract({
const {
data: xocAllowance,
isError,
isLoading,
} = useReadContract({
address: xocContract,
abi: ERC20ABI,
functionName: 'allowance',
Expand Down Expand Up @@ -163,7 +170,9 @@ export default function UnderWriterDepositWidget() {
{/* Input field */}
<div className="mb-6">
<label className="block text-gray-700">
{action === 'Deposit' ? 'Indica la cantidad a depositar:' : 'Indica la cantidad a retirar:'}
{action === 'Deposit'
? 'Indica la cantidad a depositar:'
: 'Indica la cantidad a retirar:'}
</label>
<input
type="number"
Expand All @@ -175,13 +184,17 @@ export default function UnderWriterDepositWidget() {
<div className="flex flex-col items-start justify-between">
<div className="mb-2">
<span className="mr-1 text-gray-500">{`Balance: ${formattedXocBalance || 0}`}</span>
<span className="cursor-pointer font-bold text-primary hover:underline" onClick={handleXOCMaxClick}>
<span
className="cursor-pointer font-bold text-primary hover:underline"
onClick={handleXOCMaxClick}
>
MAX
</span>
</div>
<div className="text-gray-500">{`Allowance: ${xocAllowanceState}`}</div>
</div>
{xocError && <p className="mt-2 text-red-500">{xocError}</p>} {/* Display error */}
{xocError && <p className="mt-2 text-red-500">{xocError}</p>}{' '}
{/* Display error */}
</div>

{/* Submit button */}
Expand All @@ -197,7 +210,12 @@ export default function UnderWriterDepositWidget() {
}
}}
>
{requiresApproval ? 'Aprobar' : action === 'Deposit' ? 'Depositar' : 'Retirar'} {/* Dynamic button label */}
{requiresApproval
? 'Aprobar'
: action === 'Deposit'
? 'Depositar'
: 'Retirar'}{' '}
{/* Dynamic button label */}
</button>
</div>
)
Expand Down
26 changes: 22 additions & 4 deletions src/app/cartera/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import Link from 'next/link'

import PageWithAppbar from '@/components/layout/pageWithAppbar'
import { Button } from '@/components/ui/button'
import { useDynamicContext } from '@dynamic-labs/sdk-react-core'
import {
useDynamicContext,
useSwitchNetwork,
} from '@dynamic-labs/sdk-react-core'
import {
Card,
CardContent,
Expand All @@ -13,7 +16,7 @@ import {
CardTitle,
} from '@/components/ui/card'
import { ArrowLeftRight, LoaderCircle, PiggyBank } from 'lucide-react'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import CarteraWidget from '@/components/onchain/carteraWidget'
import { useBalanceOf } from '@/hooks/useBalanceOf'
import { useAccount } from 'wagmi'
Expand All @@ -23,16 +26,31 @@ import AhorraModalButton from '@/components/ux/ahorraModalButton'

export default function Cartera() {
const [basename, setBasename] = useState('')
const { user } = useDynamicContext()
const [isSwitchingNetwork, setIsSwitchingNetwork] = useState(false)
const { user, primaryWallet } = useDynamicContext()
const switchNetwork = useSwitchNetwork()

const { address: walletAddress } = useAccount()
const { address: walletAddress, chainId } = useAccount()
const tokenAddress = '0xa411c9Aa00E020e4f88Bc19996d29c5B7ADB4ACf' // $XOC address

const { balance, balanceStatus } = useBalanceOf({
tokenAddress,
walletAddress: walletAddress as Address,
})

useEffect(() => {
async function handleSwitchNetwork() {
if (primaryWallet) {
setIsSwitchingNetwork(true)
await switchNetwork({ wallet: primaryWallet, network: 8453 })
}
}

if (primaryWallet && chainId !== 8453 && !isSwitchingNetwork) {
handleSwitchNetwork()
}
}, [chainId, isSwitchingNetwork, primaryWallet, switchNetwork])

return (
<PageWithAppbar>
<div className="page gap-y-8 text-center md:max-w-screen-sm">
Expand Down
24 changes: 24 additions & 0 deletions src/app/creditalent/solicitudes/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,38 @@ import { LoanApplicationExtended } from '@/types/api'
import { DenyModalButton } from '@/components/onchain/denyModalButton'
import { ApproveModalButton } from '@/components/onchain/approveModalButton'
import UnderwriterModal from '@/components/onchain/underwriterModal'
import { useEffect, useState } from 'react'
import {
useDynamicContext,
useSwitchNetwork,
} from '@dynamic-labs/sdk-react-core'
import { useAccount } from 'wagmi'

export default function Solicitudes() {
const [isSwitchingNetwork, setIsSwitchingNetwork] = useState(false)
const { primaryWallet } = useDynamicContext()
const switchNetwork = useSwitchNetwork()
const { chainId } = useAccount()

const { data: loanApplicationsData, status: loanApplicationsQueryStatus } =
useQuery({
queryKey: ['loanApplicationsKey'],
queryFn: () => fetchLoanApplications(),
})

useEffect(() => {
async function handleSwitchNetwork() {
if (primaryWallet) {
setIsSwitchingNetwork(true)
await switchNetwork({ wallet: primaryWallet, network: 84532 })
}
}

if (primaryWallet && chainId !== 84532 && !isSwitchingNetwork) {
handleSwitchNetwork()
}
}, [chainId, isSwitchingNetwork, primaryWallet, switchNetwork])

return (
<PageWithAppbar>
<div className="page gap-y-8 px-8 text-center">
Expand Down
21 changes: 16 additions & 5 deletions src/components/onchain/underwriterModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { useEffect, useState } from 'react'
import { Address, formatUnits, parseEther } from 'viem'
import { useAccount, useReadContract, useWriteContract } from 'wagmi'
import {
useAccount,
useReadContract,
useWaitForTransactionReceipt,
useWriteContract,
} from 'wagmi'
import { useBalanceOf } from '@/hooks/useBalanceOf'
import { ERC20ABI } from '@/components/onchain/abis/erc20'
import CreditTalentCenterABI from '@/components/onchain/abis/CreditTalentCenter'
Expand All @@ -26,10 +31,16 @@ export default function UnderwriterModal() {
const [xocError, setXocError] = useState<string | null>(null)
const [requiresApproval, setRequiresApproval] = useState(false) // Track approval need

const { writeContract: deposit } = useWriteContract()
const { writeContract: approveERC20 } = useWriteContract()
const { writeContract: withdraw } = useWriteContract()
const { writeContractAsync: deposit } = useWriteContract()
const { writeContractAsync: approveERC20, data: approveHash } =
useWriteContract()
const { writeContractAsync: withdraw } = useWriteContract()

const { isSuccess: isSuccessApproveTxReceipt } = useWaitForTransactionReceipt(
{
hash: approveHash,
},
)
const xocBalance = useBalanceOf({
tokenAddress: xocContract,
walletAddress: accountAddress as Address,
Expand Down Expand Up @@ -217,7 +228,7 @@ export default function UnderwriterModal() {
onClick={() => {
if (requiresApproval) {
handleApproval() // Call handleApproval when approval is needed
} else if (action === 'Deposit' && !xocError) {
} else if (action === 'Deposit' && isSuccessApproveTxReceipt) {
handleDeposit() // Call handleDeposit if deposit is selected
} else if (action === 'Withdraw' && !xocError) {
handleWithdrawal() // Call handleWithdrawal if withdraw is selected
Expand Down
23 changes: 22 additions & 1 deletion src/controllers/loanApplication/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import prisma from '@/utils/prisma'
import { Loan } from '@prisma/client'

// Create a new LoanApplication
export const createLoanApplication = async (data: {
Expand Down Expand Up @@ -90,14 +91,34 @@ export const updateLoanApplicationById = async (
applicantId: number
}>,
) => {
let loan: Loan | null = null
try {
const updatedLoanApplication = await prisma.loanApplication.update({
where: { id },
data: {
...data,
},
})
return updatedLoanApplication
if (
data.status === 'PENDING' &&
updatedLoanApplication.status === 'APPROVED'
) {
const futureDate = new Date()
futureDate.setDate(futureDate.getDate() + 30)

loan = await prisma.loan.create({
data: {
amount: updatedLoanApplication.amount,
pendingBalance: updatedLoanApplication.amount,
dueDate: futureDate,
walletId: updatedLoanApplication.walletId,
borrowerId: updatedLoanApplication.applicantId,
creditLineId: updatedLoanApplication.creditLineId,
loanApplicationId: updatedLoanApplication.id,
},
})
}
return { updatedLoanApplication, loan }
} catch (error) {
if (error instanceof Error) {
throw new Error(`Error updating LoanApplication: ${error.message}`)
Expand Down
4 changes: 4 additions & 0 deletions src/hooks/useBalanceOf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const ERC20ABI = [
interface TokenBalanceProps {
tokenAddress: Address
walletAddress: Address
chainId?: number
}

/**
Expand All @@ -39,6 +40,7 @@ interface TokenBalanceProps {
export function useBalanceOf({
tokenAddress,
walletAddress,
chainId = 8453,
}: TokenBalanceProps) {
const [balance, setBalance] = useState<string>('0') // State to store the balance
const [decimals, setDecimals] = useState<number>(18) // Default to 18 decimals
Expand All @@ -54,6 +56,7 @@ export function useBalanceOf({
abi: ERC20ABI,
functionName: 'balanceOf',
args: [walletAddress],
chainId,
})

// Hook to read the decimals from the contract
Expand All @@ -65,6 +68,7 @@ export function useBalanceOf({
address: tokenAddress,
abi: ERC20ABI,
functionName: 'decimals',
chainId,
})

// Effect to handle updates to data, error, and loading state
Expand Down
12 changes: 8 additions & 4 deletions src/providers/onchainProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ import { EthereumWalletConnectors } from '@dynamic-labs/ethereum'
import { DynamicWagmiConnector } from '@dynamic-labs/wagmi-connector'
import { createConfig, WagmiProvider } from 'wagmi'
import { http } from 'viem'
import { baseSepolia } from 'viem/chains'
import { base, baseSepolia, mainnet } from 'viem/chains'
import { useRouter } from 'next/navigation'

// const alchemyApiKey = process.env.NEXT_PUBLIC_ALCHEMY_API ?? undefined
const alchemyApiKey = process.env.NEXT_PUBLIC_ALCHEMY_API ?? undefined

const config = createConfig({
chains: [baseSepolia],
chains: [base, baseSepolia, mainnet],
multiInjectedProviderDiscovery: false,
transports: {
[baseSepolia.id]: http('https://sepolia.base.org'),
[base.id]: http(`https://base-mainnet.g.alchemy.com/v2/${alchemyApiKey}`),
[baseSepolia.id]: http(
`https://base-sepolia.g.alchemy.com/v2/${alchemyApiKey}`,
),
[mainnet.id]: http(`https://eth-mainnet.g.alchemy.com/v2/${alchemyApiKey}`),
},
})

Expand Down

0 comments on commit b280322

Please sign in to comment.