Skip to content

Commit

Permalink
Merge pull request #805 from airgap-it/feat/wc_error_notification
Browse files Browse the repository at this point in the history
Feat/wc error notification
  • Loading branch information
jsamol authored Sep 4, 2024
2 parents 491655a + 0f2128c commit 5559a82
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -542,9 +542,7 @@ export class WalletConnectCommunicationClient extends CommunicationClient {
const signClient = await this.getSignClient()

if (!signClient) {
const fun = this.eventHandlers.get(ClientEvents.CLOSE_ALERT)
fun && fun()
return
throw new Error('Failed to connect to the relayer.')
}

const lastIndex = signClient.session.keys.length - 1
Expand Down Expand Up @@ -586,7 +584,11 @@ export class WalletConnectCommunicationClient extends CommunicationClient {
}
}

const { uri, approval } = await signClient.connect(connectParams)
const { uri, approval } = await signClient.connect(connectParams).catch((error) => {
logger.error(`Init error: ${error.message}`)
localStorage && localStorage.setItem(StorageKey.WC_INIT_ERROR, error.message)
throw new Error(error.message)
})

// Extract topic from uri. Format is wc:topic@2...
const topic = getStringBetween(uri, ':', '@')
Expand Down Expand Up @@ -1312,13 +1314,34 @@ export class WalletConnectCommunicationClient extends CommunicationClient {
return this.session
}

private async tryConnectToRelayer() {
const urls = new Set([
this.wcOptions.opts.relayUrl,
undefined,
'wss://relay.walletconnect.com',
'wss://relay.walletconnect.org'
])
const errMessages = new Set()

for (const relayUrl of urls) {
try {
return await Client.init({ ...this.wcOptions.opts, relayUrl })
} catch (err: any) {
errMessages.add(err.message)
logger.warn(`Failed to connect to ${relayUrl}: ${err.message}`)
}
}
throw new Error(`Failed to connect to relayer: ${Array.from(errMessages).join(',')}`)
}

private async getSignClient(): Promise<Client | undefined> {
if (this.signClient === undefined) {
try {
this.signClient = await Client.init(this.wcOptions.opts)
this.signClient = await this.tryConnectToRelayer()
this.subscribeToSessionEvents(this.signClient)
} catch (error: any) {
logger.error(error.message)
localStorage && localStorage.setItem(StorageKey.WC_INIT_ERROR, error.message)
return undefined
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/beacon-types/src/types/storage/StorageKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export enum StorageKey {
MULTI_NODE_SETUP_DONE = 'beacon:multi-node-setup',
USER_ID = 'beacon:user-id',
ENABLE_METRICS = 'beacon:enable_metrics',
WC_INIT_ERROR = 'beacon:wc-init-error',
WC_2_CORE_PAIRING = 'wc@2:core:0.3:pairing',
WC_2_CLIENT_SESSION = 'wc@2:client:0.3:session',
WC_2_CORE_KEYCHAIN = 'wc@2:core:0.3:keychain',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const defaultValues: StorageKeyReturnDefaults = {
[StorageKey.WC_2_CLIENT_SESSION]: undefined,
[StorageKey.USER_ID]: undefined,
[StorageKey.ENABLE_METRICS]: undefined,
[StorageKey.WC_INIT_ERROR]: undefined,
[StorageKey.WC_2_CORE_PAIRING]: undefined,
[StorageKey.WC_2_CORE_KEYCHAIN]: undefined,
[StorageKey.WC_2_CORE_MESSAGES]: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface StorageKeyReturnType {
[StorageKey.MULTI_NODE_SETUP_DONE]: boolean | undefined
[StorageKey.USER_ID]: string | undefined
[StorageKey.ENABLE_METRICS]: boolean | undefined
[StorageKey.WC_INIT_ERROR]: string | undefined
[StorageKey.WC_2_CLIENT_SESSION]: string | undefined
[StorageKey.WC_2_CORE_PAIRING]: string | undefined
[StorageKey.WC_2_CORE_KEYCHAIN]: string | undefined
Expand Down
22 changes: 0 additions & 22 deletions packages/beacon-ui/src/components/qr/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,28 +75,6 @@ const QR: Component<QRProps> = (props: QRProps) => {
{`Scan QR code with a ${
props.isWalletConnect ? 'WalletConnect' : 'Beacon'
}-compatible wallet.`}
{props.onClickLearnMore && (
<span
class="qr-more-info"
onClick={() => {
if (props.onClickLearnMore) props.onClickLearnMore()
}}
>
Learn more
</span>
)}
</span>
)}

{!props.isMobile && props.onClickLearnMore && (
<span
style={{ 'margin-top': 'auto' }}
class="qr-more-info"
onClick={() => {
if (props.onClickLearnMore) props.onClickLearnMore()
}}
>
Learn more
</span>
)}
</div>
Expand Down
194 changes: 114 additions & 80 deletions packages/beacon-ui/src/ui/alert/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const [currentInfo, setCurrentInfo] = createSignal<
const [analytics, setAnalytics] = createSignal<AnalyticsInterface | undefined>(undefined)
const [displayQrExtra, setDisplayQrExtra] = createSignal<boolean>(false)
const [pairingExpired, setPairingExpired] = createSignal(false)
const [isWCWorking, setIsWCWorking] = createSignal(true)
type VoidFunction = () => void
let dispose: null | VoidFunction = null

Expand Down Expand Up @@ -451,21 +452,33 @@ const openAlert = async (config: AlertConfig): Promise<string> => {

// check whether the uri contains a valid symmetric key or not
if (!parseUri(uri).symKey) {
handleCloseAlert()
setTimeout(
() =>
openAlert({
title: 'Error',
body: 'Network error occurred. Please check your internet connection.'
}),
500
)
return ''
setIsWCWorking(false)
}

return uri
}

const generateWCError = (title: string) => {
const errorMessage = localStorage ? localStorage.getItem(StorageKey.WC_INIT_ERROR) : undefined
const description: any = (
<>
<h3 style={{ color: '#FF4136', margin: '0.6px' }}>A network error occurred.</h3>
<h4>
This issue does not concern your wallet or dApp. If the problem persists, please report
it to the Beacon team{' '}
<span
style={{ 'text-decoration': 'underline', color: '#007bff', cursor: 'pointer' }}
onClick={() => setCurrentInfo('help')}
>
here
</span>
</h4>
{errorMessage && <span>{errorMessage}</span>}
</>
)
return <Info title={title} description={description} border />
}

const handleNewTab = async (config: AlertConfig, wallet?: MergedWallet) => {
if (!wallet) {
return
Expand Down Expand Up @@ -594,6 +607,13 @@ const openAlert = async (config: AlertConfig): Promise<string> => {
if (wallet && wallet.supportedInteractionStandards?.includes('wallet_connect')) {
const uri = await generateLink()

if (!uri && wallet?.name.toLowerCase().includes('kukai')) {
setCodeQR('error')
setInstallState(wallet)
setIsLoading(false)
return
}

if (uri) {
if (_isMobileOS && wallet.types.includes('ios') && wallet.types.length === 1) {
handleDeepLinking(wallet, uri)
Expand Down Expand Up @@ -746,17 +766,25 @@ const openAlert = async (config: AlertConfig): Promise<string> => {
icon: currentWallet()?.image
})
)
const isConnected =
!currentWallet()?.supportedInteractionStandards?.includes('wallet_connect') || isWCWorking()
return (
<QR
isWalletConnect={
currentWallet()?.supportedInteractionStandards?.includes('wallet_connect') || false
}
isMobile={isMobile}
walletName={currentWallet()?.name || 'AirGap'}
code={codeQR()}
onClickLearnMore={handleClickLearnMore}
onClickQrCode={handleClickQrCode}
/>
<>
{isConnected ? (
<QR
isWalletConnect={
currentWallet()?.supportedInteractionStandards?.includes('wallet_connect') || false
}
isMobile={isMobile}
walletName={currentWallet()?.name || 'AirGap'}
code={codeQR()}
onClickLearnMore={handleClickLearnMore}
onClickQrCode={handleClickQrCode}
/>
) : (
generateWCError(`Connect with ${currentWallet()?.name} Mobile`)
)}
</>
)
}

Expand Down Expand Up @@ -878,72 +906,78 @@ const openAlert = async (config: AlertConfig): Promise<string> => {
(currentWallet()?.types.length as number) <= 1 && (
<QRCode isMobile={true} />
)}
{isMobile() && currentWallet()?.types.includes('ios') && (
<Info
border
title={`Connect with ${currentWallet()?.name} Mobile`}
description={''}
buttons={[
{
label: 'Use App',
type: 'primary',
onClick: async () => {
const wallet = currentWallet()

if (!wallet) {
return
}
{isMobile() &&
currentWallet()?.types.includes('ios') &&
(!currentWallet()?.supportedInteractionStandards?.includes(
'wallet_connect'
) || isWCWorking() ? (
<Info
border
title={`Connect with ${currentWallet()?.name} Mobile`}
description={''}
buttons={[
{
label: 'Use App',
type: 'primary',
onClick: async () => {
const wallet = currentWallet()

if (!wallet) {
return
}

let syncCode = ''
if (
wallet.supportedInteractionStandards?.includes('wallet_connect')
) {
syncCode = (await wcPayload)?.uri ?? ''
} else {
syncCode = await new Serializer().serialize(await p2pPayload)
let syncCode = ''
if (
wallet.supportedInteractionStandards?.includes('wallet_connect')
) {
syncCode = (await wcPayload)?.uri ?? ''
} else {
syncCode = await new Serializer().serialize(await p2pPayload)
}
handleDeepLinking(wallet, syncCode)
}
handleDeepLinking(wallet, syncCode)
}
]}
downloadLink={
currentWallet()?.name.toLowerCase().includes('kukai') && isIOS(window)
? {
label: 'Get Kukai Mobile >',
url: 'https://ios.kukai.app'
}
: undefined
}
]}
downloadLink={
currentWallet()?.name.toLowerCase().includes('kukai') && isIOS(window)
? {
label: 'Get Kukai Mobile >',
url: 'https://ios.kukai.app'
}
: undefined
}
onShowQRCodeClick={async () => {
const syncCode =
currentWallet()?.supportedInteractionStandards?.includes(
'wallet_connect'
)
? (await wcPayload)?.uri ?? ''
: await new Serializer().serialize(await p2pPayload)

const wallet = currentWallet()

if (!syncCode.length || !wallet) {
handleCloseAlert()
return
}
onShowQRCodeClick={async () => {
const syncCode =
currentWallet()?.supportedInteractionStandards?.includes(
'wallet_connect'
)
? (await wcPayload)?.uri ?? ''
: await new Serializer().serialize(await p2pPayload)

const wallet = currentWallet()

if (!syncCode.length || !wallet) {
handleCloseAlert()
return
}

if (
_isMobileOS &&
wallet.types.includes('ios') &&
wallet.types.length === 1
) {
handleDeepLinking(wallet, syncCode)
} else {
setCodeQR(syncCode)
}
if (
_isMobileOS &&
wallet.types.includes('ios') &&
wallet.types.length === 1
) {
handleDeepLinking(wallet, syncCode)
} else {
setCodeQR(syncCode)
}

setCurrentInfo('qr')
setDisplayQrExtra(true)
}}
/>
)}
setCurrentInfo('qr')
setDisplayQrExtra(true)
}}
/>
) : (
generateWCError(`Connect with ${currentWallet()?.name} Mobile`)
))}
</div>
)}
{currentInfo() === 'qr' && (
Expand Down

0 comments on commit 5559a82

Please sign in to comment.