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

Prevent "no multisig" from being displayed before we checked #390

Merged
merged 10 commits into from
Oct 11, 2023
Merged
3 changes: 2 additions & 1 deletion packages/ui/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { AuthRequests, Extension, TxRequests } from './Extension'
import { MultisigInfo, rejectCurrentMultisigTxs } from '../utils/rejectCurrentMultisigTxs'
import { InjectedAccountWitMnemonic } from '../fixtures/injectedAccounts'
import 'cypress-wait-until'

// ***********************************************
// This example commands.ts shows you how to
Expand Down Expand Up @@ -67,7 +68,7 @@ Cypress.Commands.add('rejectAuth', (id: number, reason: string) => {
})

Cypress.Commands.add('getTxRequests', () => {
return cy.wait(500).then(() => cy.wrap(extension.getTxRequests()))
return cy.wrap(extension.getTxRequests())
})

Cypress.Commands.add('approveTx', (id: number) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/cypress/support/page-objects/landingPage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const landingPage = {
watchAccountButton: () => cy.get('[data-cy=button-watch-address]'),
accountsOrRpcLoader: () => cy.get('[data-cy="loader-accounts-rpc-connection"]'),
accountsLoader: () => cy.get('[data-cy="loader-accounts-connection"]'),
noAccountFoundError: () => cy.get('[data-cy="text-no-account-found"]')
}
5 changes: 4 additions & 1 deletion packages/ui/cypress/tests/login.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import { injectedAccounts } from '../fixtures/injectedAccounts'
import { landingPageUrl } from '../fixtures/landingData'
import { landingPage } from '../support/page-objects/landingPage'
import { topMenuItems } from '../support/page-objects/topMenuItems'
import { waitForAuthRequest } from '../utils/waitForAuthRequests'

describe('Connect Account', () => {
beforeEach(() => {
cy.visit(landingPageUrl)
cy.initExtension(injectedAccounts)
topMenuItems.connectButton().click()
landingPage.accountsOrRpcLoader().should('contain', 'Loading accounts')
landingPage.accountsLoader().should('contain', 'Loading accounts')
})

it('Reject connection', () => {
waitForAuthRequest()
cy.getAuthRequests().then((authRequests) => {
const requests = Object.values(authRequests)
// we should have 1 connection request to the extension
Expand All @@ -26,6 +28,7 @@ describe('Connect Account', () => {
})

it('Connects with Alice', () => {
waitForAuthRequest()
const AliceAddress = Object.values(injectedAccounts)[0].address
cy.getAuthRequests().then((authRequests) => {
const requests = Object.values(authRequests)
Expand Down
8 changes: 6 additions & 2 deletions packages/ui/cypress/tests/transactions.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { multisigPage } from '../support/page-objects/multisigPage'
import { notifications } from '../support/page-objects/notifications'
import { sendTxModal } from '../support/page-objects/sendTxModal'
import { topMenuItems } from '../support/page-objects/topMenuItems'
import { waitForAuthRequest } from '../utils/waitForAuthRequests'
import { waitForTxRequest } from '../utils/waitForTxRequests'

const AliceAddress = Object.values(injectedAccounts)[0].address

Expand All @@ -20,7 +22,8 @@ describe('Perform transactions', () => {
cy.visit(landingPageUrl)
cy.initExtension(injectedAccounts)
topMenuItems.connectButton().click()
landingPage.accountsOrRpcLoader().should('contain', 'Loading accounts')
landingPage.accountsLoader().should('contain', 'Loading accounts')
waitForAuthRequest()
cy.getAuthRequests().then((authRequests) => {
const requests = Object.values(authRequests)
// we should have 1 connection request to the extension
Expand All @@ -38,9 +41,9 @@ describe('Perform transactions', () => {
multisigPage.newTransactionButton().click()
sendTxModal.sendTxTitle().should('be.visible')
fillAndSubmitTransactionForm()
waitForTxRequest()
cy.getTxRequests().then((req) => {
const txRequests = Object.values(req)
console.log('txRequests', JSON.stringify(txRequests))
cy.wrap(txRequests.length).should('eq', 1)
cy.wrap(txRequests[0].payload.address).should('eq', AliceAddress)
sendTxModal.buttonSend().should('be.disabled')
Expand All @@ -67,6 +70,7 @@ describe('Perform transactions', () => {
multisigPage.newTransactionButton().click()
sendTxModal.sendTxTitle().should('be.visible')
fillAndSubmitTransactionForm()
waitForTxRequest()
cy.getTxRequests().then((req) => {
const txRequests = Object.values(req)
cy.wrap(txRequests.length).should('eq', 1)
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/cypress/utils/waitForAuthRequests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const waitForAuthRequest = () =>
cy.waitUntil(() => cy.getAuthRequests().then((req) => Object.entries(req).length > 0))
2 changes: 2 additions & 0 deletions packages/ui/cypress/utils/waitForTxRequests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const waitForTxRequest = () =>
cy.waitUntil(() => cy.getTxRequests().then((req) => Object.entries(req).length > 0))
1 change: 1 addition & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@typescript-eslint/parser": "^6.7.2",
"@vitejs/plugin-react": "^4.0.4",
"cypress": "^13.2.0",
"cypress-wait-until": "^2.0.1",
"eslint": "^8.49.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-react-app": "^7.0.1",
Expand Down
1 change: 0 additions & 1 deletion packages/ui/src/components/modals/ChangeMultisig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { Button } from '../library'
import { ModalCloseButton } from '../library/ModalCloseButton'
import { useGetSortAddress } from '../../hooks/useGetSortAddress'
import { useGetMultisigAddress } from '../../contexts/useGetMultisigAddress'
import BN from 'bn.js'

interface Props {
onClose: () => void
Expand Down
13 changes: 8 additions & 5 deletions packages/ui/src/contexts/AccountsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface IAccountContext {
selectedSigner?: Signer
allowConnectionToExtension: () => void
isAllowedToConnectToExtension: boolean
isLocalStorageSetupDone: boolean
}

const AccountContext = createContext<IAccountContext | undefined>(undefined)
Expand All @@ -38,6 +39,7 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {
const ownAddressList = useMemo(() => ownAccountList.map((a) => a.address), [ownAccountList])
const [accountGotRequested, setAccountGotRequested] = useState(false)
const { chainInfo } = useApi()
const [isLocalStorageSetupDone, setIsLocalStorageSetupDone] = useState(false)
// update the current account list with the right network prefix
// this will run for every network change
useEffect(() => {
Expand Down Expand Up @@ -67,8 +69,6 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {

const getaccountList = useCallback(
async (isEthereum: boolean): Promise<void> => {
setIsAccountLoading(true)

web3Enable(DAPP_NAME)
.then(
(ext) => {
Expand Down Expand Up @@ -131,6 +131,7 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {

if (!accountGotRequested && isAllowedToConnectToExtension) {
setAccountGotRequested(true)
setIsAccountLoading(true)
// delay the request by 500ms
// race condition see https://github.com/polkadot-js/extension/issues/938
setTimeout(() => {
Expand All @@ -142,9 +143,9 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {
getaccountList,
isAccountLoading,
isAllowedToConnectToExtension,
accountGotRequested,
chainInfo,
isExtensionError
isExtensionError,
accountGotRequested
])

useEffect(() => {
Expand All @@ -153,6 +154,7 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {
if (previouslyAllowed === 'true') {
setIsAllowedToConnectToExtension(true)
}
setIsLocalStorageSetupDone(true)
}
}, [isAllowedToConnectToExtension])

Expand Down Expand Up @@ -181,7 +183,8 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {
getAccountByAddress,
selectedSigner,
allowConnectionToExtension,
isAllowedToConnectToExtension
isAllowedToConnectToExtension,
isLocalStorageSetupDone
}}
>
{children}
Expand Down
8 changes: 7 additions & 1 deletion packages/ui/src/contexts/MultiProxyContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@ const MultiProxyContextProvider = ({ children }: MultisigContextProps) => {
),
[selectedMultiProxy, ownAddressList]
)
const [isRefreshingMultiProxyList, setIsRefreshingMultiProxyList] = useState(false)

const refreshPureToQueryAndMultisigList = useCallback(
(data: MultisigsBySignatoriesOrWatchedSubscription | null) => {
setIsRefreshingMultiProxyList(true)
// we do have an answer, but there is no multisig
if (!!data?.accountMultisigs && data.accountMultisigs.length === 0) {
setPureToQuery([])
Expand Down Expand Up @@ -123,11 +125,14 @@ const MultiProxyContextProvider = ({ children }: MultisigContextProps) => {
// add the selection to the pure to query
setPureToQuery(Array.from(pureToQuerySet))
}

setIsRefreshingMultiProxyList(false)
},
[]
)

const refreshWatchedPureList = useCallback((data: PureByIdsSubscription | null) => {
setIsRefreshingMultiProxyList(true)
const pureProxyMap = new Map<string, Omit<MultiProxy, 'proxy'>>()
// we do have an answer, but there is nothing
if (!!data?.accounts && data.accounts.length === 0) {
Expand Down Expand Up @@ -174,6 +179,7 @@ const MultiProxyContextProvider = ({ children }: MultisigContextProps) => {
)

setPureProxyList(pureProxyArray)
setIsRefreshingMultiProxyList(false)
}, [])

const ownAddressIds = useAccountId(ownAddressList)
Expand Down Expand Up @@ -277,7 +283,7 @@ const MultiProxyContextProvider = ({ children }: MultisigContextProps) => {
selectedMultiProxy,
multiProxyList,
selectMultiProxy,
isLoading: isMultisigsubLoading || isPureSubLoading,
isLoading: isMultisigsubLoading || isPureSubLoading || isRefreshingMultiProxyList,
selectedHasProxy,
error: isMultisigSubError || isPureSubError,
getMultisigByAddress,
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/contexts/WalletConnectContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const WalletConnectContextProvider = ({ children }: WalletConnectContextProps) =
const core = useMemo(
() =>
new Core({
logger: 'info',
logger: undefined, // use 'debug' to get more insight
projectId: import.meta.env.VITE_WALLETCONNECT_PROJECT_ID
// relayUrl: relayerRegionURL ?? import.meta.env.VITE_WALLETCONNECT_PUBLIC_RELAY_URL
}),
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/contexts/WatchedAddressesContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface IWatchedAddressesContext {
addWatchedAccount: (address: string) => void
removeWatchedAccount: (address: string) => void
watchedAddresses: string[]
isInitialized: boolean
}

const WatchedAddressesContext = createContext<IWatchedAddressesContext | undefined>(undefined)
Expand Down Expand Up @@ -84,7 +85,8 @@ const WatchedAddressesContextProvider = ({ children }: WatchedAddressesProps) =>
value={{
addWatchedAccount,
removeWatchedAccount,
watchedAddresses
watchedAddresses,
isInitialized
}}
>
{children}
Expand Down
70 changes: 70 additions & 0 deletions packages/ui/src/hooks/useDisplayError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {
HiOutlineArrowTopRightOnSquare as LaunchIcon,
HiOutlineExclamationCircle as ErrorOutlineIcon
} from 'react-icons/hi2'

import { styled } from '@mui/material/styles'
import { useAccounts } from '../contexts/AccountsContext'
import { Link } from '../components/library'
import { Center } from '../components/layout/Center'
import { useWatchedAddresses } from '../contexts/WatchedAddressesContext'
import { useMultiProxy } from '../contexts/MultiProxyContext'

export const useDisplayError = () => {
const { isExtensionError, isAccountLoading } = useAccounts()
const { watchedAddresses } = useWatchedAddresses()
const { error: multisigQueryError } = useMultiProxy()

if (isExtensionError && watchedAddresses.length === 0 && !isAccountLoading) {
return (
<CenterStyled>
<h3 data-cy="text-no-account-found">
No account found. Please connect at least one in a wallet extension. More info at{' '}
<Linkstyled
href="https://wiki.polkadot.network/docs/wallets-and-extensions"
target="_blank"
rel="noreferrer"
>
wiki.polkadot.network
<LaunchIcon
className="launchIcon"
size={20}
/>
</Linkstyled>
</h3>
</CenterStyled>
)
}

if (multisigQueryError) {
return (
<CenterStyled>
<ErrorMessageStyled>
<ErrorOutlineIcon size={64} />
<div>An error occurred.</div>
</ErrorMessageStyled>
</CenterStyled>
)
}

return null
}

const Linkstyled = styled(Link)`
display: inline-flex;
padding-left: 0.2rem;
align-items: center;

.launchIcon {
margin-left: 0.5rem;
}
`

const CenterStyled = styled(Center)`
text-align: center;
`

const ErrorMessageStyled = styled('div')`
text-align: center;
margin-top: 1rem;
`
62 changes: 62 additions & 0 deletions packages/ui/src/hooks/useDisplayLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { styled } from '@mui/material/styles'
import { useMultiProxy } from '../contexts/MultiProxyContext'
import { useApi } from '../contexts/ApiContext'
import { Box, CircularProgress } from '@mui/material'
import { useNetwork } from '../contexts/NetworkContext'
import { useAccounts } from '../contexts/AccountsContext'
import { useWatchedAddresses } from '../contexts/WatchedAddressesContext'

export const useDisplayLoader = () => {
const { isLoading: isLoadingMultisigs } = useMultiProxy()
const { api } = useApi()
const { selectedNetworkInfo } = useNetwork()
const { isAccountLoading, isLocalStorageSetupDone } = useAccounts()
const { isInitialized: isWatchAddressInitialized } = useWatchedAddresses()

if (!isWatchAddressInitialized || !isLocalStorageSetupDone) {
return (
<LoaderBoxStyled data-cy="loader-initialization">
<CircularProgress />
Initialization...
</LoaderBoxStyled>
)
}

if (!api) {
return (
<LoaderBoxStyled data-cy="loader-rpc-connection">
<CircularProgress />
{`Connecting to the node at ${selectedNetworkInfo?.rpcUrl}`}
</LoaderBoxStyled>
)
}

if (isAccountLoading) {
return (
<LoaderBoxStyled data-cy="loader-accounts-connection">
<CircularProgress />
Loading accounts...
</LoaderBoxStyled>
)
}

if (isLoadingMultisigs) {
return (
<LoaderBoxStyled data-cy="loader-accounts-connection">
<CircularProgress />
<div>Loading your multisigs...</div>
</LoaderBoxStyled>
)
}

return null
}

const LoaderBoxStyled = styled(Box)`
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
padding: 1rem;
`
2 changes: 1 addition & 1 deletion packages/ui/src/hooks/usePendingTx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const usePendingTx = (multiProxy?: MultiProxy) => {
setIsLoading(false)
})
.catch(console.error)
}, [api, multisigs])
}, [api, chainInfo, multisigs])

useEffect(() => {
refresh()
Expand Down
Loading
Loading