Skip to content

Commit 4bdfc4c

Browse files
authored
fix: Solana and WalletConnect Web3Modal conflicts (#164)
1 parent 689cef0 commit 4bdfc4c

25 files changed

+395
-440
lines changed

.changeset/eight-bears-prove.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"@fuel-connectors/walletconnect-connector": patch
3+
---
4+
5+
- Add `currentEvmAccount` method to `WalletConnectConnector`, which will return the current ethereum account connected.
6+
- Fixed Wallet Connect Web3Modal instances conflicting and replacing Solana's
7+
- Fixed issue where Wallet Connect's Web3Modal would reference a different Wagmi config instance.
8+
- WalletConnect connector now recovers the last active connection during initialization
9+
- Updated wagmi and @wagmi/core to 2.11.3
10+
- Updated @wagmi/connectors to 5.0.26

.changeset/fuel-labs-ci.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
"@fuels/connectors": patch
3+
---
4+

.github/workflows/pr-release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
release-pr:
88
name: 'Release PR to npm'
99
runs-on: buildjet-4vcpu-ubuntu-2204
10-
# comment out if:false to enable release PR to npm
10+
# Comment if:false to enable release PR to npm
1111
if: false
1212
permissions: write-all
1313
steps:

examples/react-app/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"@fuels/react": "0.20.0",
1515
"@radix-ui/react-toast": "1.1.5",
1616
"@tanstack/react-query": "5.35.1",
17-
"@wagmi/connectors": "4.3.3",
18-
"@wagmi/core": "2.9.1",
17+
"@wagmi/connectors": "5.0.26",
18+
"@wagmi/core": "2.12.2",
1919
"clsx": "2.1.1",
2020
"fuels": "0.92.0",
2121
"react": "18.3.1",

examples/react-next/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
"@fuels/connectors": "workspace:*",
1212
"@fuels/react": "0.20.0",
1313
"@tanstack/react-query": "5.35.1",
14-
"@wagmi/connectors": "4.3.3",
14+
"@wagmi/connectors": "5.0.26",
1515
"fuels": "0.92.0",
1616
"next": "14.2.3",
1717
"react": "18.3.1",
1818
"react-dom": "18.3.1",
19-
"wagmi": "2.8.1"
19+
"wagmi": "2.11.3"
2020
},
2121
"devDependencies": {
2222
"@tanstack/react-query-devtools": "5.35.1",

examples/react-next/src/components/Providers.tsx

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,19 @@
33
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
44
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
55

6-
import {
7-
BakoSafeConnector,
8-
FuelWalletConnector,
9-
FuelWalletDevelopmentConnector,
10-
FueletWalletConnector,
11-
SolanaConnector,
12-
WalletConnectConnector,
13-
} from '@fuels/connectors';
6+
import { defaultConnectors } from '@fuels/connectors';
147
import { FuelProvider } from '@fuels/react';
158

169
const queryClient = new QueryClient();
1710

11+
const fuelConfig = {
12+
connectors: defaultConnectors({ devMode: true }),
13+
};
14+
1815
export const Providers = ({ children }: { children: React.ReactNode }) => {
1916
return (
2017
<QueryClientProvider client={queryClient}>
21-
<FuelProvider
22-
theme="dark"
23-
fuelConfig={{
24-
connectors: [
25-
new FuelWalletConnector(),
26-
new FuelWalletDevelopmentConnector(),
27-
new BakoSafeConnector(),
28-
new FueletWalletConnector(),
29-
new WalletConnectConnector(),
30-
new SolanaConnector(),
31-
],
32-
}}
33-
>
18+
<FuelProvider theme="dark" fuelConfig={fuelConfig}>
3419
{children}
3520
</FuelProvider>
3621

packages/connectors/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"dependencies": {
2424
"@ethereumjs/util": "9.0.3",
2525
"@ethersproject/bytes": "5.7.0",
26-
"@wagmi/core": "2.9.1",
26+
"@wagmi/core": "2.12.2",
2727
"@web3modal/wagmi": "5.0.0",
2828
"viem": "2.10.2",
2929
"socket.io-client": "4.7.2",

packages/connectors/src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const DEFAULT_WC_PROJECT_ID = '00000000000000000000000000000000';

packages/connectors/src/defaultConnectors.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,26 @@ import { FueletWalletConnector } from '@fuel-connectors/fuelet-wallet';
66
import { SolanaConnector } from '@fuel-connectors/solana-connector';
77
import { WalletConnectConnector } from '@fuel-connectors/walletconnect-connector';
88
import type { Config } from '@wagmi/core';
9+
import type { ProviderType } from '@web3modal/solana/dist/types/src/utils/scaffold';
910
import type { FuelConnector } from 'fuels';
1011
import type { BurnerWalletConfig } from '../../burner-wallet-connector/src/types';
1112

12-
const DEFAULT_WC_PROJECT_ID = '00000000000000000000000000000000';
13-
1413
type DefaultConnectors = {
1514
devMode?: boolean;
1615
wcProjectId?: string;
1716
burnerWalletConfig?: BurnerWalletConfig;
1817
ethWagmiConfig?: Config;
18+
solanaConfig?: ProviderType;
1919
};
2020

2121
export function defaultConnectors({
2222
devMode,
23-
wcProjectId = DEFAULT_WC_PROJECT_ID,
23+
wcProjectId,
2424
burnerWalletConfig,
2525
ethWagmiConfig,
26+
solanaConfig: _solanaConfig,
2627
}: DefaultConnectors = {}): Array<FuelConnector> {
27-
const connectors = [
28+
const connectors: Array<FuelConnector> = [
2829
new FuelWalletConnector(),
2930
new BakoSafeConnector(),
3031
new FueletWalletConnector(),

packages/solana-connector/src/SolanaConnector.ts

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import { SOLANA_ICON, TESTNET_URL } from './constants';
2222
import { predicates } from './generated/predicate';
2323
import type { Maybe, SolanaConfig } from './types';
2424
import { PredicateAccount } from './utils/Predicate';
25-
import { createSolanaProvider } from './utils/solanaProvider';
25+
import { createSolanaConfig } from './utils/solanaConfig';
26+
import { createSolanaWeb3ModalInstance } from './utils/web3Modal';
2627
import { getSignatureIndex } from './utils/witness';
2728

2829
export class SolanaConnector extends FuelConnector {
@@ -46,32 +47,42 @@ export class SolanaConnector extends FuelConnector {
4647
predicateAddress: string | null = null;
4748

4849
private predicateAccount: PredicateAccount;
49-
private config: SolanaConfig = {};
50+
private config: SolanaConfig = {} as SolanaConfig;
5051
private svmAddress: string | null = null;
5152
private subscriptions: Array<() => void> = [];
5253

53-
constructor(config: SolanaConfig = {}) {
54+
constructor(config: SolanaConfig) {
5455
super();
55-
56+
this.configProviders(config);
5657
this.predicateAccount = new PredicateAccount(
5758
config.predicateConfig ?? predicates['verification-predicate'],
5859
);
60+
}
5961

60-
this.configProviders(config);
62+
modalFactory(config?: SolanaConfig) {
63+
const solanaConfig = createSolanaConfig(config?.projectId);
64+
65+
return createSolanaWeb3ModalInstance({
66+
projectId: config?.projectId,
67+
solanaConfig,
68+
});
6169
}
6270

6371
// createModal re-instanciates the modal to update singletons from web3modal
6472
createModal() {
6573
this.destroy();
66-
const { walletConnectModal } = createSolanaProvider(this.config);
67-
this.web3Modal = walletConnectModal;
74+
const web3Modal = this.modalFactory(this.config);
75+
this.web3Modal = web3Modal;
6876
ApiController.prefetch();
6977
this.setupWatchers();
7078
}
7179

72-
async configProviders(config: SolanaConfig = {}) {
80+
providerFactory(config?: SolanaConfig) {
81+
return config?.fuelProvider || FuelProvider.create(TESTNET_URL);
82+
}
83+
configProviders(config: SolanaConfig) {
7384
this.config = Object.assign(config, {
74-
fuelProvider: config.fuelProvider || FuelProvider.create(TESTNET_URL),
85+
fuelProvider: this.providerFactory(config),
7586
});
7687
}
7788

@@ -95,23 +106,32 @@ export class SolanaConnector extends FuelConnector {
95106
return account ? [account] : [];
96107
}
97108

109+
// Solana Web3Modal is Canary and not yet stable
110+
// It shares the same events as WalletConnect, hence validations must be made in order to avoid running connections with EVM Addresses instead of Solana Addresses
98111
setupWatchers() {
99112
this.subscriptions.push(
100113
this.web3Modal.subscribeEvents((event) => {
101114
switch (event.data.event) {
115+
case 'MODAL_OPEN':
116+
// Ensures that the Solana Web3Modal config is applied over pre-existing states (e.g. WC Connect Web3Modal)
117+
this.createModal();
118+
break;
102119
case 'CONNECT_SUCCESS': {
120+
const address = this.web3Modal.getAddress() || '';
121+
122+
if (!address || address.startsWith('0x')) {
123+
return;
124+
}
103125
this.emit(this.events.connection, true);
104126
this.emit(
105127
this.events.currentAccount,
106-
this.predicateAccount.getPredicateAddress(
107-
this.web3Modal.getAddress() ?? '',
108-
),
128+
this.predicateAccount.getPredicateAddress(address),
109129
);
110130
this.emit(
111131
this.events.accounts,
112132
this.predicateAccount.getPredicateAccounts(this.svmAccounts()),
113133
);
114-
this.svmAddress = this.web3Modal.getAddress() ?? '';
134+
this.svmAddress = address;
115135
break;
116136
}
117137
case 'DISCONNECT_SUCCESS': {
@@ -177,7 +197,11 @@ export class SolanaConnector extends FuelConnector {
177197
* ============================================================
178198
*/
179199
async ping(): Promise<boolean> {
180-
await this.configProviders();
200+
if (!this.config?.fuelProvider) {
201+
this.config = Object.assign(this.config, {
202+
fuelProvider: this.providerFactory(this.config),
203+
});
204+
}
181205
return true;
182206
}
183207

packages/solana-connector/src/constants.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,15 @@ export const solanaDevnet = {
2929
chain: 'solana',
3030
};
3131

32-
export const SolanaChains = {
32+
export const solanaChains = {
3333
MAINNET: solana,
3434
TESTNET: solanaTestnet,
3535
DEVNET: solanaDevnet,
3636
};
37+
export const DEFAULT_PROJECT_ID = '00000000000000000000000000000000';
38+
39+
export const DEFAULT_CHAINS = [
40+
solanaChains.MAINNET,
41+
solanaChains.TESTNET,
42+
solanaChains.DEVNET,
43+
];

packages/solana-connector/src/test/solanaConnector.test.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
import path from 'node:path';
22
import { launchNodeAndGetWallets } from '@fuel-ts/account/test-utils';
3-
import type { Asset, Network, Provider } from 'fuels';
4-
import {
5-
afterAll,
6-
beforeAll,
7-
beforeEach,
8-
describe,
9-
expect,
10-
test,
11-
} from 'vitest';
3+
import type { Asset, Network } from 'fuels';
4+
import { beforeAll, describe, expect, test } from 'vitest';
125
import { SolanaConnector } from '../SolanaConnector';
13-
import { TESTNET_URL } from '../constants';
146

157
describe('Solana Connector', () => {
16-
const connector = new SolanaConnector({ projectId: '0000' });
8+
const projectId = '0000';
9+
10+
const connector = new SolanaConnector({ projectId });
1711

1812
const snapshotPath = path.join(__dirname, '');
1913

packages/solana-connector/src/test/testConnector.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import { SolanaConnector } from '../index';
44

55
export class testWalletConnectConnector extends SolanaConnector {
66
constructor(fuelProvider: Provider) {
7-
super();
7+
super({
8+
fuelProvider: fuelProvider,
9+
});
810
this.fuelProvider = fuelProvider;
911
}
1012

packages/solana-connector/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { Web3Modal } from '@web3modal/solana';
12
import type { ProviderType } from '@web3modal/solana/dist/types/src/utils/scaffold';
23
import type { Provider as FuelProvider, JsonAbi } from 'fuels';
34

@@ -10,7 +11,6 @@ export type SolanaConfig = {
1011
fuelProvider?: FuelProvider | Promise<FuelProvider>;
1112
projectId?: string;
1213
predicateConfig?: SolanaPredicateConfig;
13-
solanaConfig?: ProviderType;
1414
};
1515

1616
export interface GetAccounts {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {
2+
type Web3Modal,
3+
createWeb3Modal,
4+
defaultSolanaConfig,
5+
} from '@web3modal/solana';
6+
import { DEFAULT_CHAINS, DEFAULT_PROJECT_ID } from '../constants';
7+
8+
export function createSolanaConfig(projectId = DEFAULT_PROJECT_ID) {
9+
return defaultSolanaConfig({
10+
enableInjected: true,
11+
chains: DEFAULT_CHAINS,
12+
projectId,
13+
metadata: {
14+
name: 'Web3Modal',
15+
description: 'Web3Modal Laboratory',
16+
url: 'https://lab.web3modal.com',
17+
icons: ['https://avatars.githubusercontent.com/u/37784886'],
18+
},
19+
});
20+
}

packages/solana-connector/src/utils/solanaProvider.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)