Skip to content
Draft
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
6 changes: 3 additions & 3 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@fortawesome/react-fontawesome": "^3.1.1",
"@ledgerhq/hw-transport-webhid": "^6.30.10",
"@polkawatch/ddp-client": "^3.0.1",
"@reown/appkit": "^1.8.15",
"@tanstack/react-query": "^5.90.12",
"@w3ux/extension-assets": "^2.3.1",
"@w3ux/factories": "^2.2.1",
Expand All @@ -30,9 +31,8 @@
"@w3ux/react-polkicon": "^3.3.0",
"@w3ux/utils": "^2.3.0",
"@w3ux/validator-assets": "^1.2.3",
"@walletconnect/ethereum-provider": "~2.23.1",
"@walletconnect/modal": "^2.7.0",
"@walletconnect/universal-provider": "^2.22.4",
"@walletconnect/sign-client": "^2.23.1",
"@walletconnect/universal-provider": "^2.23.1",
"@walletconnect/utils": "^2.22.4",
"@zondax/ledger-substrate": "^2.0.0",
"assets": "workspace:*",
Expand Down
84 changes: 61 additions & 23 deletions packages/app/src/contexts/WalletConnect/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright 2025 @polkadot-cloud/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import { type AppKit, createAppKit } from '@reown/appkit/core'
import { defineChain } from '@reown/appkit/networks'
import { createSafeContext } from '@w3ux/hooks'
import { WalletConnectModal } from '@walletconnect/modal'
import UniversalProvider from '@walletconnect/universal-provider'
import { UniversalProvider } from '@walletconnect/universal-provider'
import { getSdkError } from '@walletconnect/utils'
import { getStakingChain } from 'consts/util'
import { getStakingChain, getStakingChainData } from 'consts/util'
import { useApi } from 'contexts/Api'
import { useNetwork } from 'contexts/Network'
import { getUnixTime } from 'date-fns'
Expand All @@ -31,13 +32,16 @@ export const WalletConnectProvider = ({
}) => {
const { network } = useNetwork()
const { isReady, getChainSpec } = useApi()
const { genesisHash } = getChainSpec(getStakingChain(network))

const chainSpec = getChainSpec(getStakingChain(network))
const { genesisHash } = chainSpec
const { unit, units, name, endpoints } = getStakingChainData(network)

// The WalletConnect provider
const wcProvider = useRef<UniversalProvider | null>(null)
const wcProvider = useRef<InstanceType<typeof UniversalProvider> | null>(null)

// The WalletConnect modal handler
const wcModal = useRef<WalletConnectModal | null>(null)
const wcModal = useRef<AppKit | null>(null)

// Track whether pairing has been initiated
const pairingInitiated = useRef<boolean>(false)
Expand Down Expand Up @@ -71,12 +75,40 @@ export const WalletConnectProvider = ({
relayUrl: 'wss://relay.walletconnect.com',
})

const modal = new WalletConnectModal({
projectId: wcProjectId,
const polkadot = defineChain({
id: genesisHash.substring(2).substring(0, 32),
name: name,
nativeCurrency: { name: name, symbol: unit, decimals: units },
rpcUrls: {
default: {
http: [],
wss: endpoints.rpc[0],
},
},
blockExplorers: {
default: {
name: `Subscan`,
url: `https://${network}.subscan.io/`,
},
},
chainNamespace: 'polkadot',
caipNetworkId: `polkadot:${genesisHash.substring(2).substring(0, 32)}`,
})

const modal = createAppKit({
projectId: wcProjectId,
networks: [polkadot],
// biome-ignore lint/suspicious/noExplicitAny: <version mismatch>
universalProvider: provider as any,
manualWCControl: true,
})
wcProvider.current = provider

// listen to display_uri event and feed modal with uri
provider.on('display_uri', (uri: string) => {
modal.open({ uri })
})

// Subscribe to session delete
wcProvider.current.on('session_delete', () => {
disconnectWcSession()
Expand Down Expand Up @@ -115,7 +147,7 @@ export const WalletConnectProvider = ({
polkadot: {
methods: ['polkadot_signTransaction', 'polkadot_signMessage'],
chains: caips,
events: ['chainChanged", "accountsChanged'],
events: ['chainChanged', 'accountsChanged'],
},
}

Expand Down Expand Up @@ -178,7 +210,7 @@ export const WalletConnectProvider = ({
chains: caips,
accounts: [],
methods: ['polkadot_signTransaction', 'polkadot_signMessage'],
events: ['chainChanged", "accountsChanged'],
events: ['chainChanged', 'accountsChanged'],
},
},
})
Expand All @@ -188,16 +220,22 @@ export const WalletConnectProvider = ({
// Initiate a new Wallet Connect session, if not already wcInitialized
const initializeWcSession =
async (): Promise<WalletConnectSession | null> => {
if (wcInitialized) {
let wcSession
if (wcProvider.current?.session) {
wcSession = wcProvider.current.session
} else {
wcSession = await initializeNewSession()
try {
if (wcInitialized) {
let wcSession
if (wcProvider.current?.session) {
wcSession = wcProvider.current.session
} else {
wcSession = await initializeNewSession()
}

setWcSessionActive(true)
return wcSession
}

setWcSessionActive(true)
return wcSession
} catch {
// Close modal on error
wcModal.current?.close()
setWcSessionActive(false)
}
return null
}
Expand All @@ -210,14 +248,14 @@ export const WalletConnectProvider = ({

// Summon Wallet Connect modal that presents QR Code
if (wcMeta?.uri) {
wcModal.current!.openModal({ uri: wcMeta.uri })
wcModal.current?.open({ uri: wcMeta.uri })
}

// Get session from approval
const newWcSession = await wcMeta?.approval()

// Close modal on approval completion
wcModal.current!.closeModal()
wcModal.current?.close()

// Update session data in provider
if (wcProvider.current) {
Expand Down Expand Up @@ -310,10 +348,10 @@ export const WalletConnectProvider = ({

// On initial render, initiate the WalletConnect provider
useEffect(() => {
if (!wcProvider.current) {
if (!wcProvider.current && isReady && genesisHash !== '0x') {
initProvider()
}
}, [])
}, [isReady, genesisHash])

// Initially, all active chains (in all tabs) must be connected and ready for the initial provider
// connection
Expand Down
Loading