Skip to content

Commit

Permalink
feat: replace wcm with appkit, create options mapping function
Browse files Browse the repository at this point in the history
  • Loading branch information
tomiir committed Dec 19, 2024
1 parent 1463ac8 commit e8decc1
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 16 deletions.
3 changes: 2 additions & 1 deletion providers/ethereum-provider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
"prettier": "prettier --check '{src,test}/**/*.{js,ts,jsx,tsx}'"
},
"dependencies": {
"@reown/appkit": "1.6.1",
"@walletconnect/jsonrpc-http-connection": "1.0.8",
"@walletconnect/jsonrpc-provider": "1.0.14",
"@walletconnect/jsonrpc-types": "1.0.4",
"@walletconnect/jsonrpc-utils": "1.0.8",
"@walletconnect/keyvaluestorage": "1.1.1",
"@walletconnect/modal": "2.7.0",
"@walletconnect/sign-client": "2.17.3",
"@walletconnect/types": "2.17.3",
"@walletconnect/universal-provider": "2.17.3",
Expand All @@ -59,6 +59,7 @@
"ethereum-test-network": "0.1.6",
"ethers": "5.6.9",
"uint8arrays": "3.1.0",
"viem": "^2.21.55",
"web3": "1.7.5"
}
}
35 changes: 20 additions & 15 deletions providers/ethereum-provider/src/EthereumProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export type RpcMethod =
| "wallet_getCallsStatus"
| "wallet_showCallsStatus";


export type RpcEvent = "accountsChanged" | "chainChanged" | "message" | "disconnect" | "connect";

export interface EthereumRpcMap {
Expand Down Expand Up @@ -289,7 +290,7 @@ export class EthereumProvider implements IEthereumProvider {
const session = await new Promise<SessionTypes.Struct | undefined>(
async (resolve, reject) => {
if (this.rpc.showQrModal) {
this.modal?.subscribeModal((state: { open: boolean }) => {
this.modal?.subscribeState((state: { open: boolean }) => {
// the modal was closed so reject the promise
if (!state.open && !this.signer.session) {
this.signer.abortPairingAttempt();
Expand Down Expand Up @@ -330,7 +331,7 @@ export class EthereumProvider implements IEthereumProvider {
this.signer.logger.error(error);
throw error;
} finally {
if (this.modal) this.modal.closeModal();
if (this.modal) this.modal.close();
}
}

Expand All @@ -350,7 +351,7 @@ export class EthereumProvider implements IEthereumProvider {
const result = await new Promise<AuthTypes.AuthenticateResponseResult>(
async (resolve, reject) => {
if (this.rpc.showQrModal) {
this.modal?.subscribeModal((state: { open: boolean }) => {
this.modal?.subscribeState((state: { open: boolean }) => {
// the modal was closed so reject the promise
if (!state.open && !this.signer.session) {
this.signer.abortPairingAttempt();
Expand Down Expand Up @@ -388,7 +389,7 @@ export class EthereumProvider implements IEthereumProvider {
this.signer.logger.error(error);
throw error;
} finally {
if (this.modal) this.modal.closeModal();
if (this.modal) this.modal.close();
}
}

Expand Down Expand Up @@ -475,8 +476,8 @@ export class EthereumProvider implements IEthereumProvider {
if (this.rpc.showQrModal) {
// to refresh the QR we have to close the modal and open it again
// until proper API is provided by walletconnect modal
this.modal?.closeModal();
this.modal?.openModal({ uri });
this.modal?.close();
this.modal?.open({ view: 'ConnectingWalletConnectBasic', uri });
}
this.events.emit("display_uri", uri);
});
Expand Down Expand Up @@ -586,19 +587,23 @@ export class EthereumProvider implements IEthereumProvider {
this.registerEventListeners();
await this.loadPersistedSession();
if (this.rpc.showQrModal) {
let WalletConnectModalClass;
let appKit;
try {
const { WalletConnectModal } = await import("@walletconnect/modal");
WalletConnectModalClass = WalletConnectModal;
const { createAppKit } = await import("@reown/appkit");
const { convertWCMToAppKitOptions } = await import("./wcmToAppKit");
const options = convertWCMToAppKitOptions({ ...this.rpc.qrModalOptions, metadata: this.rpc.metadata, projectId: this.rpc.projectId });

if (!options.networks.length) {
throw new Error("No networks found for WalletConnect·");
}

appKit = createAppKit(options);
} catch {
throw new Error("To use QR modal, please install @walletconnect/modal package");
throw new Error("To use QR modal, please install @reown/appkit package");
}
if (WalletConnectModalClass) {
if (appKit) {
try {
this.modal = new WalletConnectModalClass({
projectId: this.rpc.projectId,
...this.rpc.qrModalOptions,
});
this.modal = appKit
} catch (e) {
this.signer.logger.error(e);
throw new Error("Could not generate WalletConnectModal Instance");
Expand Down
107 changes: 107 additions & 0 deletions providers/ethereum-provider/src/wcmToAppKit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import type { AppKitOptions } from '@reown/appkit';
import type { WalletConnectModalConfig } from './types';
import type { AppKitNetwork } from '@reown/appkit/networks';
import * as chains from '@reown/appkit/networks';
import type { EthereumProviderOptions } from './EthereumProvider';

function convertThemeVariables(wcmTheme?: WalletConnectModalConfig['themeVariables']): AppKitOptions['themeVariables'] | undefined {
if (!wcmTheme) return undefined;

return {
'--w3m-font-family': wcmTheme['--wcm-font-family'],
'--w3m-accent': wcmTheme['--wcm-accent-color'],
'--w3m-color-mix': wcmTheme['--wcm-background-color'],
'--w3m-z-index': wcmTheme['--wcm-z-index'] ? Number(wcmTheme['--wcm-z-index']) : undefined,

'--w3m-qr-color': wcmTheme['--wcm-accent-color'],

// Optional: Set master controls for sizing
'--w3m-font-size-master': wcmTheme['--wcm-text-medium-regular-size'],
'--w3m-border-radius-master': wcmTheme['--wcm-container-border-radius'],
'--w3m-color-mix-strength': 8 // Default value, adjust as needed
};
}

export function convertWCMToAppKitOptions(wcmConfig: WalletConnectModalConfig & { metadata?: EthereumProviderOptions['metadata'] }): AppKitOptions {
// Convert chains to AppKitNetwork format
const networks: AppKitNetwork[] = wcmConfig.chains?.map(chain =>
Object.values(chains).find((chainData) => String((chainData as AppKitNetwork)?.id) === chain)
).filter(Boolean) as AppKitNetwork[];


// Ensure at least one network is present
if (networks.length === 0) {
throw new Error('At least one chain must be specified');
}

const defaultNetwork = networks.find(network => network.id === wcmConfig.defaultChain?.id);
const appKitOptions: AppKitOptions = {
projectId: wcmConfig.projectId,
networks: networks as [AppKitNetwork, ...AppKitNetwork[]],
// Theme mapping
themeMode: wcmConfig.themeMode,
themeVariables: convertThemeVariables(wcmConfig.themeVariables),

// Chain and wallet images
chainImages: wcmConfig.chainImages,
connectorImages: wcmConfig.walletImages,

// Default network from defaultChain
defaultNetwork,

// Privacy and terms URLs
metadata: {
...wcmConfig.metadata,
name: wcmConfig.metadata?.name || 'WalletConnect',
description: wcmConfig.metadata?.description || 'Connect to WalletConnect-compatible wallets',
url: wcmConfig.metadata?.url || 'https://walletconnect.org',
icons: wcmConfig.metadata?.icons || ['https://walletconnect.org/walletconnect-logo.png'],
},

// Features mapping
showWallets: true, // Default to true unless explicitly disabled

// Explorer options mapping
featuredWalletIds: wcmConfig.explorerRecommendedWalletIds === 'NONE' ? [] :
(Array.isArray(wcmConfig.explorerRecommendedWalletIds) ? wcmConfig.explorerRecommendedWalletIds : []),

excludeWalletIds: wcmConfig.explorerExcludedWalletIds === 'ALL' ? [] :
(Array.isArray(wcmConfig.explorerExcludedWalletIds) ? wcmConfig.explorerExcludedWalletIds : []),

// Additional AppKit-specific options that don't have direct WCM equivalents
allowUnsupportedChain: false, // Default to false for safety
enableWallets: true, // Default to true
enableEIP6963: false, // Default to false
enableCoinbase: true, // Default to true
enableInjected: true, // Default to true
enableWalletConnect: true // Default to true
};

// Add mobile and desktop wallets as custom wallets if provided
if (wcmConfig.mobileWallets?.length || wcmConfig.desktopWallets?.length) {
const customWallets = [
...(wcmConfig.mobileWallets || []).map(wallet => ({
id: wallet.id,
name: wallet.name,
links: {
native: wallet.links.native,
universal: wallet.links.universal
}
})),
...(wcmConfig.desktopWallets || []).map(wallet => ({
id: wallet.id,
name: wallet.name,
links: {
native: wallet.links.native,
universal: wallet.links.universal
}
}))
];

if (customWallets.length > 0) {
appKitOptions.customWallets = customWallets;
}
}

return appKitOptions;
}

0 comments on commit e8decc1

Please sign in to comment.