Skip to content

Commit

Permalink
feat: Reconnect to Wallet Connect session on signing (#251)
Browse files Browse the repository at this point in the history
  • Loading branch information
rossbulat authored Oct 26, 2024
2 parents 9181f6c + e44180f commit 52f2219
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 43 deletions.
1 change: 1 addition & 0 deletions packages/app/src/contexts/WalletConnect/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ export const defaultWalletConnect: WalletConnectContextInterface = {
updateWcSession: () => Promise.resolve(),
disconnectWcSession: () => Promise.resolve(),
wcSessionActive: false,
fetchAccounts: (directoryId) => Promise.resolve([]),
signWcTx: (caip, payload, from) => Promise.resolve(null),
};
37 changes: 35 additions & 2 deletions packages/app/src/contexts/WalletConnect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getSdkError } from '@walletconnect/utils';
import { useTabs } from 'contexts/Tabs';
import { getUnixTime } from 'date-fns';
import { isSuperset } from '@w3ux/utils';
import type { ChainId } from 'config/networks/types';

export const WalletConnectContext =
createContext<WalletConnectContextInterface>(defaults.defaultWalletConnect);
Expand Down Expand Up @@ -106,8 +107,6 @@ export const WalletConnectProvider = ({
(chain) => `polkadot:${chain.genesisHash.substring(2).substring(0, 32)}`
);

console.log(caips);

// If there are no chains connected, return early.
if (!caips.length) {
return;
Expand Down Expand Up @@ -282,6 +281,39 @@ export const WalletConnectProvider = ({
return result?.signature || null;
};

const fetchAccounts = async (chainid: ChainId): Promise<string[]> => {
// Retrieve a new session or get current one.
const wcSession = await initializeWcSession();
if (wcSession === null) {
return [];
}

// Get accounts from session.
const walletConnectAccounts = Object.values(wcSession.namespaces)
.map((namespace: AnyJson) => namespace.accounts)
.flat();

// Get the caip of the active chain.
const caip = connectedChains
.find((chain) => chain.specName === chainid)
?.genesisHash.substring(2)
.substring(0, 32);

// Only get accounts for the currently selected `caip`.
let filteredAccounts = walletConnectAccounts.filter((wcAccount) => {
const prefix = wcAccount.split(':')[1];
return prefix === caip;
});

// grab account addresses from CAIP account formatted accounts
filteredAccounts = filteredAccounts.map((wcAccount) => {
const address = wcAccount.split(':')[2];
return address;
});

return filteredAccounts;
};

// On initial render, initiate the WalletConnect provider.
useEffect(() => {
if (!wcProvider.current) {
Expand Down Expand Up @@ -328,6 +360,7 @@ export const WalletConnectProvider = ({
disconnectWcSession,
wcInitialized,
wcSessionActive,
fetchAccounts,
signWcTx,
}}
>
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/contexts/WalletConnect/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0

import type { AnyFunction, AnyJson } from '@w3ux/types';
import type { ChainId } from 'config/networks/types';

export interface WalletConnectContextInterface {
connectProvider: () => Promise<void>;
Expand All @@ -10,6 +11,7 @@ export interface WalletConnectContextInterface {
initializeWcSession: () => Promise<AnyJson>;
updateWcSession: () => Promise<void>;
disconnectWcSession: () => Promise<void>;
fetchAccounts: (directoryId: ChainId) => Promise<string[]>;
signWcTx: (
caip: string,
payload: AnyJson,
Expand Down
32 changes: 3 additions & 29 deletions packages/app/src/library/ConnectOverlay/ManageWalletConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import type { WCAccount } from '@w3ux/react-connect-kit/types';
import { remToUnit } from '@w3ux/utils';
import { NetworkDirectory } from 'config/networks';
import { useWalletConnect } from 'contexts/WalletConnect';
import type { AnyJson } from '@w3ux/types';
import { useChainSpaceEnv } from 'contexts/ChainSpaceEnv';
import { iconRefresh, iconLink } from '@polkadot-cloud/icons/duotone';
import { CloudIcon } from '@polkadot-cloud/icons';
Expand All @@ -34,6 +33,7 @@ export const ManageWalletConnect = ({
removeWcAccount,
} = useWcAccounts();
const {
fetchAccounts,
wcInitialized,
wcSessionActive,
connectProvider,
Expand Down Expand Up @@ -89,34 +89,8 @@ export const ManageWalletConnect = ({

setImportActive(true);

// Retrieve a new session or get current one.
const wcSession = await initializeWcSession();
if (wcSession === null) {
return;
}

// Get accounts from session.
const walletConnectAccounts = Object.values(wcSession.namespaces)
.map((namespace: AnyJson) => namespace.accounts)
.flat();

// Get the caip of the active chain.
const caip = connectedChains
.find((chain) => chain.specName === directoryId)
?.genesisHash.substring(2)
.substring(0, 32);

// Only get accounts for the currently selected `caip`.
let filteredAccounts = walletConnectAccounts.filter((wcAccount) => {
const prefix = wcAccount.split(':')[1];
return prefix === caip;
});

// grab account addresses from CAIP account formatted accounts
filteredAccounts = filteredAccounts.map((wcAccount) => {
const address = wcAccount.split(':')[2];
return address;
});
// Fetch accounts from Wallet Connect.
const filteredAccounts = await fetchAccounts(directoryId);

// Save accounts to local storage.
filteredAccounts.forEach((address) => {
Expand Down
14 changes: 7 additions & 7 deletions packages/app/src/library/Overlay/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@
align-items: center;
padding: 0 3rem;
position: fixed;
z-index: 100;
z-index: 90;

/* click anywhere behind modal content to close */
.close {
@include modal-position;

z-index: 98;
z-index: 88;
cursor: default;
}
}
Expand All @@ -93,7 +93,7 @@
height: 100%;
position: relative;
overflow: hidden auto;
z-index: 99;
z-index: 89;
max-width: 800px;
-ms-overflow-style: none;
scrollbar-width: none;
Expand Down Expand Up @@ -182,7 +182,7 @@
.modal-container {
@include modal-position;

z-index: 99;
z-index: 89;

> div {
height: 100%;
Expand All @@ -196,7 +196,7 @@
position: fixed;
width: 100%;
height: 100%;
z-index: 98;
z-index: 88;
cursor: default;
}
}
Expand Down Expand Up @@ -415,7 +415,7 @@
background: var(--modal-background-color);
transition: backdrop-filter 0.25s;
backdrop-filter: blur(2px);
z-index: 99;
z-index: 89;
}

.modal-padding {
Expand All @@ -442,7 +442,7 @@
& {
border-radius: 0.6rem;
position: relative;
z-index: 99;
z-index: 89;
max-height: 100%;
width: 100%;
max-width: 600px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { faSquarePen } from '@fortawesome/free-solid-svg-icons';
import { useExtrinsicData } from 'library/SubmitTx/ExtrinsicDataProvider';
import { useChainSpaceEnv } from 'contexts/ChainSpaceEnv';
import { useWalletConnect } from 'contexts/WalletConnect';
import type { ChainId } from 'config/networks/types';

export const WalletConnect = ({
onSubmit,
Expand All @@ -29,10 +30,13 @@ export const WalletConnect = ({
getTxSignature,
getTxPayloadValue,
} = useTxMeta();
const { signWcTx } = useWalletConnect();
const { getChainIdCaip } = useChainSpaceEnv();
const { accountHasSigner } = useImportedAccounts();
const { instanceId, chainId, ss58Prefix, valid } = useExtrinsicData();
const { signWcTx, wcSessionActive, fetchAccounts, connectProvider } =
useWalletConnect();

const from = getSender(instanceId);

// Store whether the user is currently signing a transaction.
const [isSgning, setIsSigning] = useState<boolean>(false);
Expand All @@ -56,22 +60,32 @@ export const WalletConnect = ({
buttonDisabled = disabled;
} else {
buttonOnClick = async () => {
const from = getSender(instanceId);
setIsSigning(true);

// If Wallet Connect session is not active, re-connect.
if (!wcSessionActive) {
await connectProvider();
}

const caip = getChainIdCaip(chainId);
const wcAccounts = await fetchAccounts(chainId as ChainId);

// Re-fetch accounts here to ensure that the signer address still exists.
const accountExists = from && wcAccounts.includes(from);

const payload = getTxPayloadValue(instanceId);
if (!from || !payload) {
if (!from || !payload || !accountExists) {
setIsSigning(false);
return;
}
setIsSigning(true);

try {
const signature = await signWcTx(caip, payload, from);
if (signature) {
setTxSignature(instanceId, signature);
}
} catch (e) {
// Silent Error.
setIsSigning(false);
}
setIsSigning(false);
};
Expand Down

0 comments on commit 52f2219

Please sign in to comment.