Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add validation & error handling ux improvements #161

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/issue_template/bug_report_task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: Bug report task
about: Create a bug report task to help us fix an existing bug
---

#### **Description**

<!-- A clear and concise description of what the bug is. -->

#### **Steps To Reproduce**

<!-- Steps that can be followed to reproduce the bug.

1. Navigate to the '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

-->

#### **Actual result**

<!-- A clear and concise description of what actually happened. -->

#### **Expected result**

<!-- A clear and concise description of what you expected to happen. -->

#### **Attachments**

<!-- If applicable, add screenshots or video to help explain your problem. -->

#### **Additional context**

<!-- Add any other context about the problem here. -->
19 changes: 19 additions & 0 deletions .github/issue_template/common_task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: Common task
about: Create a common task to implement a feature, do refactor, or update docs
---

## Description

<!-- A couple of sentences explaining the proposed task. -->

## Acceptance Criteria
- [ ] _Your acceptance criteria_

#### **Attachments**

<!-- If applicable, add screenshots, video, or documentation to help explain your task. -->

## Additional context

<!-- Add any other context feature request here. -->
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ yarn-error.log*

# vercel
.vercel

.idea
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mento-protocol/mento-web",
"version": "2.2.2",
"version": "2.3.0",
"description": "A simple DApp for Celo Mento exchanges",
"keywords": [
"Celo",
Expand Down
8 changes: 7 additions & 1 deletion src/components/nav/ConnectButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Identicon } from 'src/components/Identicon'
import { SolidButton } from 'src/components/buttons/SolidButton'
import { BalancesSummary } from 'src/components/nav/BalancesSummary'
import { NetworkModal } from 'src/components/nav/NetworkModal'
import { cleanupStaleWalletSessions } from 'src/config/wallets'
import ClipboardDark from 'src/images/icons/clipboard-plus-dark.svg'
import Clipboard from 'src/images/icons/clipboard-plus.svg'
import CubeDark from 'src/images/icons/cube-dark.svg'
Expand All @@ -24,6 +25,11 @@ export function ConnectButton() {
const { openConnectModal } = useConnectModal()
const { disconnect } = useDisconnect()

const onClickConnect = () => {
cleanupStaleWalletSessions()
openConnectModal?.()
}

const onClickCopy = async () => {
if (!address) return
await tryClipboardSet(address)
Expand Down Expand Up @@ -91,7 +97,7 @@ export function ConnectButton() {
styles="sm:mr-3"
/>
}
onClick={openConnectModal}
onClick={onClickConnect}
>
<div className="hidden sm:block">Connect</div>
</SolidButton>
Expand Down
30 changes: 16 additions & 14 deletions src/components/nav/NetworkModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { toast } from 'react-toastify'
import { ChainMetadata, allChains, chainIdToChain } from 'src/config/chains'
import { cleanupStaleWalletSessions } from 'src/config/wallets'
import { reset as accountReset } from 'src/features/accounts/accountSlice'
import { reset as blockReset } from 'src/features/blocks/blockSlice'
import { resetTokenPrices } from 'src/features/chart/tokenPriceSlice'
Expand All @@ -25,6 +26,7 @@ export function NetworkModal({ isOpen, close }: Props) {
try {
if (!switchNetworkAsync) throw new Error('switchNetworkAsync undefined')
logger.debug('Resetting and switching to network', c.name)
cleanupStaleWalletSessions()
await switchNetworkAsync(c.chainId)
dispatch(blockReset())
dispatch(accountReset())
Expand All @@ -38,9 +40,9 @@ export function NetworkModal({ isOpen, close }: Props) {

return (
<Modal isOpen={isOpen} close={close} title="Network details" width="max-w-md">
<div className="px-4 sm:px-6 w-full justify-between items-end inline-flex">
<div className="w-full py-3 sm:py-4 bg-gray-100 dark:bg-zinc-900 rounded-xl font-inter border border-gray-200 dark:border-zinc-800 flex-col justify-start items-center gap-4 inline-flex">
<div className="px-3 sm:px-4 w-full justify-between items-end inline-flex">
<div className="inline-flex items-end justify-between w-full px-4 sm:px-6">
<div className="inline-flex flex-col items-center justify-start w-full gap-4 py-3 bg-gray-100 border border-gray-200 sm:py-4 dark:bg-zinc-900 rounded-xl font-inter dark:border-zinc-800">
<div className="inline-flex items-end justify-between w-full px-3 sm:px-4">
<div className="text-neutral-500 dark:text-gray-400 text-[14px] sm:text-[15px] font-normal leading-tight">
Connected to:
</div>
Expand All @@ -49,7 +51,7 @@ export function NetworkModal({ isOpen, close }: Props) {
</div>
</div>
<div className="w-full h-[0px] border-t border-gray-200 dark:border-zinc-800"></div>
<div className="px-3 sm:px-4 w-full justify-between items-end inline-flex">
<div className="inline-flex items-end justify-between w-full px-3 sm:px-4">
<div className="text-neutral-500 dark:text-gray-400 text-[14px] sm:text-[15px] font-normal leading-tight">
Block Number:
</div>
Expand All @@ -58,7 +60,7 @@ export function NetworkModal({ isOpen, close }: Props) {
</div>
</div>
<div className="w-full h-[0px] border-t border-gray-200 dark:border-zinc-800"></div>
<div className="px-3 sm:px-4 w-full justify-between items-end inline-flex">
<div className="inline-flex items-end justify-between w-full px-3 sm:px-4">
<div className="text-neutral-500 dark:text-gray-400 text-[14px] sm:text-[15px] font-normal leading-tight">
Node Rpc Url:
</div>
Expand All @@ -69,7 +71,7 @@ export function NetworkModal({ isOpen, close }: Props) {
</div>
</div>
<div className="mt-4 sm:mt-6 w-full h-[0px] border-t border-gray-200 dark:border-zinc-800"></div>
<div className="py-4 sm:py-6 px-4 sm:px-6 w-full justify-start items-start gap-4 inline-flex font-inter">
<div className="inline-flex items-start justify-start w-full gap-4 px-4 py-4 sm:py-6 sm:px-6 font-inter">
{allChains.map((c) => (
<button
onClick={() => switchToNetwork(c)}
Expand Down Expand Up @@ -97,27 +99,27 @@ export function NetworkModal({ isOpen, close }: Props) {
}
/*
<div className="grow shrink basis-0 h-[50px] px-4 py-3 rounded-lg border border border border border-gray-950 justify-center items-center flex">
<div className="justify-start items-center gap-1 flex">
<div className="flex items-center justify-start gap-1">
<div className="text-gray-950 text-[16px] font-semibold leading-relaxed">Baklava</div>
</div>
</div>


<div className="relative flex flex-col items-center">
<div className="flex justify-between items-center mt-3">
<div className="mr-2 w-28 text-left text-sm">Connected to:</div>
<div className="flex items-center justify-between mt-3">
<div className="mr-2 text-sm text-left w-28">Connected to:</div>
<div className="w-48 ml-1 text-sm">{currentChain?.name || 'Unknown'}</div>
</div>
<div className="flex justify-between items-center mt-3">
<div className="mr-2 w-28 text-left text-sm">Block Number:</div>
<div className="flex items-center justify-between mt-3">
<div className="mr-2 text-sm text-left w-28">Block Number:</div>
<div className="w-48 ml-1 text-sm">{latestBlock?.number || 'Unknown'}</div>
</div>
<div className="flex justify-between items-center mt-3">
<div className="mr-2 w-28 text-left text-sm">Node Rpc Url:</div>
<div className="flex items-center justify-between mt-3">
<div className="mr-2 text-sm text-left w-28">Node Rpc Url:</div>
<div className="w-48 ml-1 text-sm">{shortenUrl(currentChain?.rpcUrl) || 'Unknown'}</div>
</div>
<HrDivider classes="my-6" />
<div className="flex items-center space-x-6 pb-2">
<div className="flex items-center pb-2 space-x-6">
{allChains.map((c) => (
<button
onClick={() => switchToNetwork(c)}
Expand Down
2 changes: 1 addition & 1 deletion src/config/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const STALE_BLOCK_TIME = 25000 // 25 seconds
export const EXCHANGE_RATE_STALE_TIME = 5000 // 5 second
export const BALANCE_STALE_TIME = 5000 // 5 seconds
export const STATUS_POLLER_DELAY = 5000 // 5 seconds
export const SWAP_QUOTE_REFETCH_INTERVAL = 5000 // 5 seconds
export const SWAP_QUOTE_REFETCH_INTERVAL = 7000 // 5 seconds
export const SIGN_OPERATION_TIMEOUT = 90000 // 90 seconds

export const STALE_TOKEN_PRICE_TIME = 900000 // 15 minutes
Expand Down
16 changes: 16 additions & 0 deletions src/config/exchanges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ export const AlfajoresExchanges: Exchange[] = [
'0x5E0E3c9419C42a1B04e2525991FB1A2C467AB8bF',
],
},
{
providerAddr: '0x9B64E8EaBD1a035b148cE970d3319c5C3Ad53EC3',
id: '0x1c9378bd0973ff313a599d3effc654ba759f8ccca655ab6d6ce5bd39a212943b',
assets: [
'0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1',
'0xe6A57340f0df6E020c1c0a80bC6E13048601f0d4',
],
},
]

export const BaklavaExchanges: Exchange[] = [
Expand Down Expand Up @@ -366,6 +374,14 @@ export const CeloExchanges: Exchange[] = [
'0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B',
],
},
{
providerAddr: '0x22d9db95E6Ae61c104A7B6F6C78D7993B94ec901',
id: '0x1c9378bd0973ff313a599d3effc654ba759f8ccca655ab6d6ce5bd39a212943b',
assets: [
'0x765DE816845861e75A25fCA122bb6898B8B1282a',
'0x8A567e2aE79CA692Bd748aB832081C45de4041eA',
],
},
]

export const MentoExchanges: Record<ChainId, Array<Exchange>> = {
Expand Down
13 changes: 13 additions & 0 deletions src/config/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export enum TokenId {
eXOF = 'eXOF',
cKES = 'cKES',
PUSO = 'PUSO',
cCOP = 'cCOP',
}

export const NativeStableTokenIds = [TokenId.cUSD, TokenId.cEUR, TokenId.cREAL]
Expand Down Expand Up @@ -113,6 +114,14 @@ export const PUSO: Token = Object.freeze({
decimals: 18,
})

export const cCOP: Token = Object.freeze({
id: TokenId.cCOP,
symbol: TokenId.cCOP,
name: 'cCOP',
color: Color.usdcBlue,
decimals: 18,
})

export const Tokens: Record<TokenId, Token> = {
CELO,
cUSD,
Expand All @@ -125,6 +134,7 @@ export const Tokens: Record<TokenId, Token> = {
eXOF,
cKES,
PUSO,
cCOP,
}

export const TokenAddresses: Record<ChainId, Record<TokenId, Address>> = Object.freeze({
Expand All @@ -140,6 +150,7 @@ export const TokenAddresses: Record<ChainId, Record<TokenId, Address>> = Object.
[TokenId.eXOF]: '0xB0FA15e002516d0301884059c0aaC0F0C72b019D',
[TokenId.cKES]: '0x1E0433C1769271ECcF4CFF9FDdD515eefE6CdF92',
[TokenId.PUSO]: '0x5E0E3c9419C42a1B04e2525991FB1A2C467AB8bF',
[TokenId.cCOP]: '0xe6A57340f0df6E020c1c0a80bC6E13048601f0d4',
},
[ChainId.Baklava]: {
[TokenId.CELO]: '0xdDc9bE57f553fe75752D61606B94CBD7e0264eF8',
Expand All @@ -153,6 +164,7 @@ export const TokenAddresses: Record<ChainId, Record<TokenId, Address>> = Object.
[TokenId.eXOF]: '0x64c1D812673E93Bc036AdC3D547d9950696DA5Af',
[TokenId.cKES]: '0x8813Ae180017057d0Cf98C930cED1E7101B97370',
[TokenId.PUSO]: '',
[TokenId.cCOP]: '',
},
[ChainId.Celo]: {
[TokenId.CELO]: '0x471EcE3750Da237f93B8E339c536989b8978a438',
Expand All @@ -166,6 +178,7 @@ export const TokenAddresses: Record<ChainId, Record<TokenId, Address>> = Object.
[TokenId.eXOF]: '0x73F93dcc49cB8A239e2032663e9475dd5ef29A08',
[TokenId.cKES]: '0x456a3D042C0DbD3db53D5489e98dFb038553B0d0',
[TokenId.PUSO]: '0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B',
[TokenId.cCOP]: '0x8A567e2aE79CA692Bd748aB832081C45de4041eA',
},
})

Expand Down
28 changes: 28 additions & 0 deletions src/config/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@rainbow-me/rainbowkit/wallets'
import { Valora } from 'src/config/celoWallets'
import { config } from 'src/config/config'
import { logger } from 'src/utils/logger'

export function getWalletConnectors(chains: Chain[]) {
const connectorConfig = {
Expand All @@ -24,3 +25,30 @@ export function getWalletConnectors(chains: Chain[]) {
trustWallet(connectorConfig),
]
}

/**
* Remove wallet connect local storage data
* @dev We got into an issue where the walletconnect data was in a corrupted state
* and causing issues with wallet connection. This will remove the data from
* localStorage to clean up the state.
*/
export const cleanupStaleWalletSessions = () => {
logger.debug('Clearing wallet connect local storage data')
const wcStorageKeys = Object.keys(localStorage).filter(
(key) => key.startsWith('wc@') || key.startsWith('walletconnect')
)

logger.debug(`Found ${wcStorageKeys.length} wallet connect keys`)

wcStorageKeys.forEach((key) => {
try {
const item = localStorage.getItem(key)
if (!item) return

localStorage.removeItem(key)
logger.debug(`Removed wallet connect value for key: ${key}`)
} catch (error) {
logger.error(`Failed to remove wallet connect value for key: ${key}`, error)
}
})
}
4 changes: 2 additions & 2 deletions src/features/swap/SwapConfirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { toastToYourSuccess } from 'src/components/TxSuccessToast'
import { Button3D } from 'src/components/buttons/3DButton'
import { TokenId, Tokens } from 'src/config/tokens'
import { useAppDispatch, useAppSelector } from 'src/features/store/hooks'
import { setFormValues } from 'src/features/swap/swapSlice'
import { setConfirmView, setFormValues } from 'src/features/swap/swapSlice'
import { SwapFormValues } from 'src/features/swap/types'
import { useApproveTransaction } from 'src/features/swap/useApproveTransaction'
import { useSwapQuote } from 'src/features/swap/useSwapQuote'
Expand Down Expand Up @@ -142,7 +142,7 @@ export function SwapConfirmCard({ formValues }: Props) {
}, [isApproveTxSuccess, isSwapTxLoading, isSwapTxSuccess, sendSwapTx, chainId, dispatch])

const onClickBack = () => {
dispatch(setFormValues(null))
dispatch(setConfirmView(false))
}

const onClickRefresh = () => {
Expand Down
Loading