Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
tolgahan-arikan committed Dec 16, 2024
1 parent 4b9013e commit 7256887
Show file tree
Hide file tree
Showing 8 changed files with 935 additions and 296 deletions.
26 changes: 26 additions & 0 deletions packages/kit/src/hooks/useCheckWaasFeeOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client'

import { FeeOption, Transaction } from '@0xsequence/waas'
import { useConnections } from 'wagmi'

export function useCheckWaasFeeOptions(): (params: { transactions: Transaction[]; chainId: number }) => Promise<{
feeQuote: string | undefined
feeOptions: FeeOption[] | undefined
isSponsored: boolean
}> {
const connections = useConnections()
const waasConnector = connections.find(c => c.connector.id.includes('waas'))?.connector

return async ({ transactions, chainId }) => {
if (!waasConnector) {
throw new Error('WaaS connector not found')
}

const waasProvider = (waasConnector as any).sequenceWaasProvider
if (!waasProvider) {
throw new Error('WaaS provider not found')
}

return waasProvider.checkTransactionFeeOptions({ transactions, chainId })
}
}
1 change: 1 addition & 0 deletions packages/kit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export { useOpenConnectModal } from './hooks/useOpenConnectModal'
export { useTheme } from './hooks/useTheme'
export { useWalletSettings } from './hooks/useWalletSettings'
export { useWaasFeeOptions } from './hooks/useWaasFeeOptions'
export { useCheckWaasFeeOptions } from './hooks/useCheckWaasFeeOptions'
export { useWaasSignInEmail } from './hooks/useWaasSignInEmail'
export { useSignInEmail } from './hooks/useSignInEmail'
export { useProjectAccessKey } from './hooks/useProjectAccessKey'
Expand Down
53 changes: 53 additions & 0 deletions packages/wallet/src/shared/Alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Box, Button, Text } from '@0xsequence/design-system'
import React, { ComponentProps } from 'react'

export type AlertProps = {
title: string
description: string
secondaryDescription?: string
variant: 'negative' | 'warning' | 'positive'
buttonProps?: ComponentProps<typeof Button>
children?: React.ReactNode
}

export const Alert = ({ title, description, secondaryDescription, variant, buttonProps, children }: AlertProps) => {
return (
<Box borderRadius="md" background={variant}>
<Box
background="backgroundOverlay"
borderRadius="md"
paddingX={{ sm: '4', md: '5' }}
paddingY="4"
width="full"
flexDirection="column"
gap="3"
>
<Box width="full" flexDirection={{ sm: 'column', md: 'row' }} gap="2" justifyContent="space-between">
<Box flexDirection="column" gap="1">
<Text variant="normal" color="text100" fontWeight="medium">
{title}
</Text>

<Text variant="normal" color="text50" fontWeight="medium">
{description}
</Text>

{secondaryDescription && (
<Text variant="normal" color="text80" fontWeight="medium">
{secondaryDescription}
</Text>
)}
</Box>

{buttonProps ? (
<Box background={variant} borderRadius="sm" width={'min'} height={'min'}>
<Button variant="emphasis" shape="square" flexShrink="0" {...buttonProps} />
</Box>
) : null}
</Box>

{children}
</Box>
</Box>
)
}
134 changes: 134 additions & 0 deletions packages/wallet/src/shared/FeeOptionSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { Box, Button, Text } from '@0xsequence/design-system'
import { ZeroAddress, formatUnits, parseUnits } from 'ethers'
import React from 'react'

import { Alert, AlertProps } from './Alert'

interface FeeOptionToken {
name: string
decimals?: number
contractAddress: string | null
}

interface FeeOption {
token: FeeOptionToken
value: string
balance?: string
}

interface FeeOptionSelectorProps {
txnFeeOptions: FeeOption[]
feeOptionBalances: { tokenName: string; decimals: number; balance: string }[]
selectedFeeOptionAddress: string | undefined
setSelectedFeeOptionAddress: (address: string) => void
checkTokenBalancesForFeeOptions: () => void
isRefreshingBalance: boolean
}

const isBalanceSufficient = (balance: string, fee: string, decimals: number) => {
const balanceBN = parseUnits(balance, decimals)
const feeBN = parseUnits(fee, decimals)
return balanceBN >= feeBN
}

export const FeeOptionSelector: React.FC<FeeOptionSelectorProps> = ({
txnFeeOptions,
feeOptionBalances,
selectedFeeOptionAddress,
setSelectedFeeOptionAddress,
checkTokenBalancesForFeeOptions,
isRefreshingBalance
}) => {
const [feeOptionAlert, setFeeOptionAlert] = React.useState<AlertProps | undefined>()

const sortedOptions = [...txnFeeOptions].sort((a, b) => {
const balanceA = feeOptionBalances.find(balance => balance.tokenName === a.token.name)
const balanceB = feeOptionBalances.find(balance => balance.tokenName === b.token.name)
const isSufficientA = balanceA ? isBalanceSufficient(balanceA.balance, a.value, a.token.decimals || 0) : false
const isSufficientB = balanceB ? isBalanceSufficient(balanceB.balance, b.value, b.token.decimals || 0) : false
return isSufficientA === isSufficientB ? 0 : isSufficientA ? -1 : 1
})

return (
<Box marginTop="3" width="full">
<Text variant="normal" color="text100" fontWeight="bold">
Select a fee option
</Text>
<Box flexDirection="column" marginTop="2" gap="2">
{sortedOptions.map((option, index) => {
const balance = feeOptionBalances.find(b => b.tokenName === option.token.name)
const isSufficient = isBalanceSufficient(balance?.balance || '0', option.value, option.token.decimals || 0)
return (
<Box
key={index}
padding="3"
borderRadius="md"
background={
selectedFeeOptionAddress === (option.token.contractAddress ?? ZeroAddress)
? 'gradientBackdrop'
: 'backgroundRaised'
}
onClick={() => {
if (isSufficient) {
setSelectedFeeOptionAddress(option.token.contractAddress ?? ZeroAddress)
setFeeOptionAlert(undefined)
} else {
setFeeOptionAlert({
title: `Insufficient ${option.token.name} balance`,
description: `Please select another fee option or add funds to your wallet.`,
variant: 'warning'
})
}
}}
cursor={isSufficient ? 'pointer' : 'default'}
opacity={isSufficient ? '100' : '50'}
>
<Box flexDirection="row" justifyContent="space-between" alignItems="center">
<Box flexDirection="column">
<Text variant="small" color="text100" fontWeight="bold">
{option.token.name}
</Text>
<Text variant="xsmall" color="text80">
Fee:{' '}
{parseFloat(formatUnits(BigInt(option.value), option.token.decimals || 0)).toLocaleString(undefined, {
maximumFractionDigits: 6
})}
</Text>
</Box>
<Box flexDirection="column" alignItems="flex-end">
<Text variant="xsmall" color="text80">
Balance:
</Text>
<Text variant="xsmall" color="text100">
{parseFloat(formatUnits(BigInt(balance?.balance || '0'), option.token.decimals || 0)).toLocaleString(
undefined,
{ maximumFractionDigits: 6 }
)}
</Text>
</Box>
</Box>
</Box>
)
})}
</Box>
<Box marginTop="3" alignItems="flex-end" justifyContent="center" flexDirection="column">
<Button
size="sm"
onClick={checkTokenBalancesForFeeOptions}
label={isRefreshingBalance ? 'Refreshing...' : 'Refresh Balance'}
disabled={isRefreshingBalance}
/>
{feeOptionAlert && (
<Box marginTop="3">
<Alert
title={feeOptionAlert.title}
description={feeOptionAlert.description}
secondaryDescription={feeOptionAlert.secondaryDescription}
variant={feeOptionAlert.variant}
/>
</Box>
)}
</Box>
</Box>
)
}
4 changes: 3 additions & 1 deletion packages/wallet/src/shared/KitWalletProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export const KitWalletContent = ({ children }: KitWalletProviderProps) => {
navigation.location === 'history' ||
navigation.location === 'search' ||
navigation.location === 'search-view-all' ||
navigation.location === 'settings-currency'
navigation.location === 'settings-currency' ||
navigation.location === 'send-coin' ||
navigation.location === 'send-collectible'

useEffect(() => {
if (openWalletModal) {
Expand Down
Loading

0 comments on commit 7256887

Please sign in to comment.