Skip to content

Commit

Permalink
fix: wallet connect refresh now disconnect previous session (#3102)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnthecat authored Feb 4, 2025
1 parent d4f056f commit 99473c6
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/renderer/domains/network/accounts/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const $populated = restore(

const populateFx = createEffect((): Promise<AnyAccount[]> => storageService.accounts2.readAll());

const createAccountsFx = createEffect(async (accounts: AnyAccount[]): Promise<AnyAccount[]> => {
const createAccountsFx = createEffect(async (accounts: AnyAccountDraft[]): Promise<AnyAccount[]> => {
return storageService.accounts2
.createAll(accounts.map(a => ({ ...a, id: accountsService.uniqId(a) })))
.then(x => x ?? []);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { attach, combine, createEvent, createStore, sample } from 'effector';
import { createGate } from 'effector-react';
import { spread } from 'patronum';

import { type WcAccount } from '@/shared/core';
import { type AnyAccount, accounts } from '@/domains/network';
import { assert } from '@/shared/lib/utils';
import { type AnyAccount, type AnyAccountDraft, accounts } from '@/domains/network';
import { networkModel } from '@/entities/network';
import { walletConnect, walletConnectService } from '@/features/wallet-wallet-connect';
import { ReconnectStep } from '../lib/constants';
Expand Down Expand Up @@ -32,7 +34,7 @@ const updateSessionFx = attach({
chains: Object.values(chains).map(c => c.chainId),
};
},
effect: walletConnect.restoreSession,
effect: walletConnect.refreshSession,
});

const $reconnectStep = createStore<ReconnectStep>(ReconnectStep.NOT_STARTED).reset(flow.close);
Expand All @@ -51,20 +53,39 @@ sample({
},
fn: ({ accounts, chains }, { result: session }) => {
const wcAccounts = accounts.filter(walletConnectService.isWalletConnectAccount);
const accountsToUpdate = walletConnectService.getAccountsFromSession(session, Object.values(chains));
const updates: WcAccount[] = [];
const accountsFromSession = walletConnectService.getAccountsFromSession(session, Object.values(chains));
const create: AnyAccountDraft<WcAccount>[] = [];
const update: WcAccount[] = [];

for (const { accountId, chain } of accountsToUpdate) {
const name = wcAccounts.map(a => a.name).at(0) ?? 'unknown';
const walletId = wcAccounts.map(a => a.walletId).at(0);

assert(walletId, "Can't get walletId from accounts");

for (const { accountId, chain } of accountsFromSession) {
const account = wcAccounts.find(a => a.accountId === accountId && a.chainId === chain.chainId);

if (account) {
updates.push(walletConnectService.updateAccount(account, session));
update.push(walletConnectService.updateAccount(account, session));
} else {
create.push(
walletConnectService.createAccount({
walletId,
name,
accountId,
chainId: chain.chainId,
session,
}),
);
}
}

return updates;
return { create, update };
},
target: accounts.updateAccounts,
target: spread({
create: accounts.createAccounts,
update: accounts.updateAccounts,
}),
});

sample({
Expand Down
37 changes: 35 additions & 2 deletions src/renderer/features/wallet-wallet-connect/lib/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import {
AccountType,
type Chain,
type ChainId,
CryptoType,
type NovaWalletWallet,
SigningType,
type Wallet,
type WalletConnectWallet,
WalletType,
type WcAccount,
} from '@/shared/core';
import { nonNullable, nullable, toAccountId } from '@/shared/lib/utils';
import { type AccountId } from '@/shared/polkadotjs-schemas';
import { type AnyAccount, accountsService } from '@/domains/network';
import { type AnyAccount, type AnyAccountDraft, accountsService } from '@/domains/network';

import {
DEFAULT_POLKADOT_EVENTS,
Expand Down Expand Up @@ -94,6 +96,34 @@ function getAccountsFromSession(session: SessionTypes.Struct, chains: Chain[]) {
return res;
}

type CreateAccountParams = {
walletId: number;
name: string;
accountId: AccountId;
chainId: ChainId;
session: SessionTypes.Struct;
};

function createAccount({
walletId,
name,
accountId,
chainId,
session,
}: CreateAccountParams): AnyAccountDraft<WcAccount> {
return {
type: 'chain',
walletId,
name,
accountId,
accountType: AccountType.WALLET_CONNECT,
signingType: SigningType.WALLET_CONNECT,
cryptoType: CryptoType.SR25519,
chainId: chainId,
signingExtras: { pairingTopic: session?.pairingTopic, sessionTopic: session?.topic },
};
}

function updateAccount(account: WcAccount, session: SessionTypes.Struct): WcAccount {
return {
...account,
Expand All @@ -105,7 +135,9 @@ function updateAccount(account: WcAccount, session: SessionTypes.Struct): WcAcco
}

function isConnected(sessions: Record<string, SessionTypes.Struct>, pairingTopic: string): boolean {
return pairingTopic in sessions;
const session = sessions[pairingTopic];

return nonNullable(session) && session.acknowledged;
}

function isAccountConnected(sessions: Record<string, SessionTypes.Struct>, account: AnyAccount): boolean {
Expand Down Expand Up @@ -133,5 +165,6 @@ export const walletConnectService = {
getAccountsFromSession,

createNamespaces,
createAccount,
updateAccount,
};
58 changes: 45 additions & 13 deletions src/renderer/features/wallet-wallet-connect/model/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { isObject } from 'lodash';
import { readonly } from 'patronum';

import { type ChainId } from '@/shared/core';
import { nonNullable, nullable } from '@/shared/lib/utils';
import { assert, nonNullable, nullable } from '@/shared/lib/utils';
import { walletConnectService } from '../lib/service';

import { signClient } from './signClient';
Expand Down Expand Up @@ -66,6 +66,28 @@ const createSessionFx = createEffect(
},
);

const removeSessionFx = attach({
source: { client: signClient.$client },
async effect({ client }, { pairingTopic }: { pairingTopic: string }) {
assert(client, 'WalletConnect Client not found');

const sessions = client.session.getAll();
const session = sessions.find(s => s.pairingTopic === pairingTopic);

if (!session) return;

const reason = getSdkError('USER_DISCONNECTED');

return client.disconnect({
topic: session.topic,
reason,
});
},
});

/**
* Try to get actual session or create a new one.
*/
const restoreSessionFx = attach({
source: { client: signClient.$client, sessions: $sessions },
async effect({ client, sessions }, { pairingTopic, chains }: { pairingTopic?: string; chains: ChainId[] }) {
Expand All @@ -91,22 +113,31 @@ const restoreSessionFx = attach({
},
});

const removeSessionFx = attach({
/**
* Kill previous session and create a new one.
*/
const refreshSessionFx = attach({
source: { client: signClient.$client },
async effect({ client }, { pairingTopic }: { pairingTopic: string }) {
if (nullable(client)) throw new Error('WalletConnect Client not found');

const sessions = client.session.getAll();
const session = sessions.find(s => s.pairingTopic === pairingTopic);
async effect({ client }, { pairingTopic, chains }: { pairingTopic?: string; chains: ChainId[] }) {
assert(client, 'WalletConnect Client not found');

if (!session) return;
// killing existing session
if (pairingTopic) {
await removeSessionFx({ pairingTopic });
}

const reason = getSdkError('USER_DISCONNECTED');
try {
// trying to restore not expiring session
return await createSessionFx({ client, chains, pairingTopic });
} catch (e) {
// direct reject should be handled immediately
if (isObject(e) && 'code' in e && e.code === SDK_ERRORS.USER_REJECTED.code) {
throw e;
}

return client.disconnect({
topic: session.topic,
reason,
});
// creating new session (with qr code scanning)
return await createSessionFx({ client, chains });
}
},
});

Expand Down Expand Up @@ -163,6 +194,7 @@ export const walletConnect = {

createSession: createSessionFx,
restoreSession: restoreSessionFx,
refreshSession: refreshSessionFx,
removeSession: removeSessionFx,
removePairing: removePairingFx,
};

0 comments on commit 99473c6

Please sign in to comment.