Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connect wallet modal ui update #130

Merged
merged 16 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions apps/demo-react/components/WalletsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default function WalletsModal(props: { isDarkTheme: boolean }) {
metrics={metrics}
shouldInvertWalletIcon={isDarkTheme}
linkDontHaveWallet={LINK_DONT_HAVE_WALLET_DEFAULT}
walletsPinnedConfig={['okx', 'browserExtension']}
alx-khramov marked this conversation as resolved.
Show resolved Hide resolved
/>
);
}
23 changes: 19 additions & 4 deletions packages/connect-wallet-modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,26 @@ Use it like this:
<WalletsModalForEth {...props} />
```

#### How to hide a wallet
You can hide one or several wallet connection buttons from the list of wallets in the modal.
Use the `hiddenWallets` property like this:
#### How to configure the wallets list
You can control displayed wallet connection buttons from the list of wallets in the modal.
Wallets will be displayed in the specified sequence.
Use the `walletsDisplayConfig` property like this:
alx-khramov marked this conversation as resolved.
Show resolved Hide resolved
```tsx
<WalletsModalForEth
hiddenWallets={['Metamask']}
walletsDisplayConfig={[
'metamask',
'walletconnect',
'brave',
'dappBrowserInjected',
]}
/>
```

#### How to pin certain wallet at top of the list
You can pin certain wallets to display it at the top of the list.
Use the `walletsPinnedConfig` property like this:
```tsx
<WalletsModalForEth
walletsPinnedConfig={['dappBrowserInjected']}
/>
```
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,53 @@ import {
ConnectBrowser,
} from '../../connectButtons';
import { WalletsModal } from './WalletsModal';
import type {
ButtonComponentsByConnectorId,
WalletsDisplayPriorityConfig,
WalletsModalProps,
} from './types';
import type { WalletIdsEthereum } from '@reef-knot/wallets-list';
import type { WalletsModalProps } from './types';

const buttonComponentsByConnectorId: ButtonComponentsByConnectorId = {
default: ConnectInjected, // fallback
browserExtension: ConnectBrowser,
walletConnect: ConnectWC,
coinbaseWallet: ConnectCoinbase,
ledgerHID: ConnectLedger,
};
type WalletsModalEthProps = WalletsModalProps<WalletIdsEthereum>;

const buttonComponentsByConnectorId: WalletsModalEthProps['buttonComponentsByConnectorId'] =
{
default: ConnectInjected, // fallback
browserExtension: ConnectBrowser,
walletconnect: ConnectWC,
coinbase: ConnectCoinbase,
ledgerHID: ConnectLedger,
};

const walletsDisplayPriorityDefault: WalletsDisplayPriorityConfig = {
promoted: ['okx', 'browserExtension'],
default: [
const WALLETS_DISPLAY_CONFIG_DEFAULT: WalletsModalEthProps['walletsDisplayConfig'] =
[
'browserExtension',
'metamask',
'ledgerHID',
'ledgerLive',
'walletconnect',
'coinbase',
'trust',
'okx',
'exodus',
'brave',
'bitkeep',
'bitget',
'xdefi',
'imToken',
'coin98',
'ambire',
'safe',
'dAppBrowserInjected',
],
};
'dappBrowserInjected',
];

const WALLETS_PINNED_CONFIG_DEFAULT: WalletsModalEthProps['walletsPinnedConfig'] =
['browserExtension'];

type WalletsModalForEthProps = Omit<
WalletsModalProps,
'buttonComponentsByConnectorId' | 'walletDataList' | 'walletsDisplayPriority'
WalletsModalEthProps,
| 'buttonComponentsByConnectorId'
| 'walletDataList'
| 'walletsDisplayConfig'
| 'walletsPinnedConfig'
> & {
walletsDisplayPriority?: WalletsDisplayPriorityConfig;
walletsDisplayConfig?: WalletsModalEthProps['walletsDisplayConfig'];
walletsPinnedConfig?: WalletsModalEthProps['walletsPinnedConfig'];
};

export function WalletsModalForEth(props: WalletsModalForEthProps) {
Expand All @@ -57,8 +64,11 @@ export function WalletsModalForEth(props: WalletsModalForEthProps) {
<WalletsModal
{...props}
walletDataList={walletDataList}
walletsDisplayPriority={
props.walletsDisplayPriority || walletsDisplayPriorityDefault
walletsDisplayConfig={
props.walletsDisplayConfig || WALLETS_DISPLAY_CONFIG_DEFAULT
}
walletsPinnedConfig={
props.walletsPinnedConfig || WALLETS_PINNED_CONFIG_DEFAULT
}
buttonComponentsByConnectorId={buttonComponentsByConnectorId}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
metrics,
buttonComponentsByConnectorId,
walletDataList,
hiddenWallets,
walletsDisplayPriority,
walletsDisplayConfig,
walletsPinnedConfig,
walletsDisplayInitialCount = 6,
linkDontHaveWallet,
} = passedDownProps;
Expand All @@ -62,11 +62,11 @@

const walletsListFull = useMemo(() => {
return sortWalletsList({
hiddenWallets,
walletDataList,
walletsDisplayPriority,
walletsDisplayConfig,
walletsPinnedConfig,
});
}, [hiddenWallets, walletDataList, walletsDisplayPriority]);
}, [walletDataList, walletsDisplayConfig, walletsPinnedConfig]);

const walletsList = useMemo(() => {
if (!isShownOtherWallets) {
Expand Down Expand Up @@ -125,7 +125,7 @@
<Subtitle>
Choose wallet{' '}
{linkDontHaveWallet && (
<Link href={linkDontHaveWallet}>I don't have a wallet</Link>

Check failure on line 128 in packages/connect-wallet-modal/src/components/WalletsModal/components/ConnectWalletModal/ConnectWalletModal.tsx

View workflow job for this annotation

GitHub Actions / check-all

`'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`
)}
</Subtitle>
{isShownOtherWallets && (
Expand Down Expand Up @@ -166,6 +166,7 @@
const WalletComponent =
buttonComponentsByConnectorId[walletData.connector.id] ??
buttonComponentsByConnectorId.default;
if (!WalletComponent) return null;
return (
<WalletComponent
key={walletData.walletId}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
import { WalletAdapterData } from '@reef-knot/types';
import { WalletsDisplayPriorityConfig, WalletsModalProps } from '../../types';
import { WalletsModalProps } from '../../types';

type GetWalletsListArgs = {
walletDataList: WalletAdapterData[];
hiddenWallets: WalletsModalProps['hiddenWallets'];
walletsDisplayPriority: WalletsDisplayPriorityConfig;
walletsDisplayConfig: WalletsModalProps['walletsDisplayConfig'];
walletsPinnedConfig: WalletsModalProps['walletsPinnedConfig'];
};

export function sortWalletsList({
walletDataList = [],
hiddenWallets = [],
walletsDisplayPriority,
walletDataList,
walletsDisplayConfig,
walletsPinnedConfig,
}: GetWalletsListArgs) {
const priority = [
...walletsDisplayPriority.promoted,
...walletsDisplayPriority.default,
];
const filteredWalletData = walletsDisplayConfig.reduce(
(walletsList, walletId) => {
const walletData = walletDataList.find((w) => w.walletId === walletId);

const sortedWalletData = [...walletDataList].sort(
(a, b) => priority.indexOf(a.walletId) - priority.indexOf(b.walletId),
);
if (!walletData) return walletsList;

const filteredWalletData = sortedWalletData.reduce(
(walletsList, walletData) => {
const { walletId, detector, autoConnectOnly } = walletData;
const { detector, autoConnectOnly } = walletData;

// Filtering wallets marked as hidden and auto connect only
if (autoConnectOnly || hiddenWallets.includes(walletId)) {
return walletsList;
}
if (autoConnectOnly) return walletsList;

if (walletsDisplayPriority.promoted.includes(walletId)) {
// Put the promoted wallets on the first place, above all another
walletsList.promoted.push(walletData);
if (walletsPinnedConfig.includes(walletId)) {
// Put the pinned wallets on the first place, above all another
walletsList.pinned.push(walletData);
} else if (detector?.()) {
// If condition is true (usually means that a wallet is detected),
// move it to the first place in the wallets list, so a user can see it right away
Expand All @@ -44,14 +37,20 @@ export function sortWalletsList({
return walletsList;
},
{
promoted: [] as WalletAdapterData[],
pinned: [] as WalletAdapterData[],
detected: [] as WalletAdapterData[],
default: [] as WalletAdapterData[],
},
);

const pinsSorted = [...filteredWalletData.pinned].sort(
(a, b) =>
walletsPinnedConfig.indexOf(a.walletId) -
walletsPinnedConfig.indexOf(b.walletId),
);

return [
...filteredWalletData.promoted,
...pinsSorted,
...filteredWalletData.detected,
...filteredWalletData.default,
];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComponentType } from 'react';
import { ModalProps } from '@reef-knot/ui-react';
import { WalletAdapterData } from '@reef-knot/types';
import type { ComponentType } from 'react';
import type { ModalProps } from '@reef-knot/ui-react';
import type { WalletAdapterData } from '@reef-knot/types';

export type Metrics = {
events?: {
Expand All @@ -9,25 +9,20 @@ export type Metrics = {
};
};

export type ButtonComponentsByConnectorId = {
[K: string]: ComponentType<ButtonsCommonProps>;
export type ButtonComponentsByConnectorId<I extends string> = {
[K in I | 'default']?: ComponentType<ButtonsCommonProps>;
};

export type WalletsDisplayPriorityConfig = {
promoted: string[];
default: string[];
};

export type WalletsModalProps = ModalProps & {
buttonComponentsByConnectorId: ButtonComponentsByConnectorId;
export type WalletsModalProps<I extends string = string> = ModalProps & {
buttonComponentsByConnectorId: ButtonComponentsByConnectorId<I>;
walletDataList: WalletAdapterData[];
hiddenWallets?: string[];
shouldInvertWalletIcon?: boolean;
buttonsFullWidth?: boolean;
metrics?: Metrics;
termsLink?: string;
privacyNoticeLink?: string;
walletsDisplayPriority: WalletsDisplayPriorityConfig;
walletsDisplayConfig: I[];
walletsPinnedConfig: I[];
walletsDisplayInitialCount?: number;
linkDontHaveWallet?: string;
};
Expand Down
2 changes: 0 additions & 2 deletions packages/types/src/walletAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,3 @@ export interface WalletAdapterArgs {
walletconnectProjectId?: string;
}
export type WalletAdapterType = (args: WalletAdapterArgs) => WalletAdapterData;

export type WalletsListType = Record<string, WalletAdapterType>;
87 changes: 50 additions & 37 deletions packages/wallets-list/src/ethereum.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
import { WalletsListType } from '@reef-knot/types';
import { BrowserExtension } from '@reef-knot/wallet-adapter-browser-extension';
import { MetaMask } from '@reef-knot/wallet-adapter-metamask';
import { Okx } from '@reef-knot/wallet-adapter-okx';
import { Exodus } from '@reef-knot/wallet-adapter-exodus';
import { WalletConnect } from '@reef-knot/wallet-adapter-walletconnect';
import { Ambire } from '@reef-knot/wallet-adapter-ambire';
import { BitKeep } from '@reef-knot/wallet-adapter-bitkeep';
import { Coin98 } from '@reef-knot/wallet-adapter-coin98';
import { Brave } from '@reef-knot/wallet-adapter-brave';
import { ImToken } from '@reef-knot/wallet-adapter-imtoken';
import { Trust } from '@reef-knot/wallet-adapter-trust';
import { Xdefi } from '@reef-knot/wallet-adapter-xdefi';
import { Coinbase } from '@reef-knot/wallet-adapter-coinbase';
import { Ledger } from '@reef-knot/wallet-adapter-ledger-hid';
import { LedgerLive } from '@reef-knot/wallet-adapter-ledger-live';
import { DAppBrowserInjected } from '@reef-knot/wallet-adapter-dapp-browser-injected';
import { Safe } from '@reef-knot/wallet-adapter-safe';
import {
BrowserExtension,
id as idBrowserExtension,
} from '@reef-knot/wallet-adapter-browser-extension';
import { MetaMask, id as idMetaMask } from '@reef-knot/wallet-adapter-metamask';
import { Okx, id as idOkx } from '@reef-knot/wallet-adapter-okx';
import { Exodus, id as idExodus } from '@reef-knot/wallet-adapter-exodus';
import {
WalletConnect,
id as idWalletConnect,
} from '@reef-knot/wallet-adapter-walletconnect';
import { Ambire, id as idAmbire } from '@reef-knot/wallet-adapter-ambire';
import { BitKeep, id as idBitKeep } from '@reef-knot/wallet-adapter-bitkeep';
import { Coin98, id as idCoin98 } from '@reef-knot/wallet-adapter-coin98';
import { Brave, id as idBrave } from '@reef-knot/wallet-adapter-brave';
import { ImToken, id as idImToken } from '@reef-knot/wallet-adapter-imtoken';
import { Trust, id as idTrust } from '@reef-knot/wallet-adapter-trust';
import { Xdefi, id as idXdefi } from '@reef-knot/wallet-adapter-xdefi';
import { Coinbase, id as idCoinbase } from '@reef-knot/wallet-adapter-coinbase';
import { Ledger, id as idLedger } from '@reef-knot/wallet-adapter-ledger-hid';
import {
LedgerLive,
id as idLedgerLive,
} from '@reef-knot/wallet-adapter-ledger-live';
import {
DAppBrowserInjected,
id as idDAppBrowserInjected,
} from '@reef-knot/wallet-adapter-dapp-browser-injected';
import { Safe, id as idSafe } from '@reef-knot/wallet-adapter-safe';

export const WalletsListEthereum: WalletsListType = {
browserExtension: BrowserExtension,
metamask: MetaMask,
okx: Okx,
walletconnect: WalletConnect,
ledgerHID: Ledger,
ledgerLive: LedgerLive,
exodus: Exodus,
ambire: Ambire,
bitkeep: BitKeep,
coin98: Coin98,
brave: Brave,
imtoken: ImToken,
trust: Trust,
xdefi: Xdefi,
coinbase: Coinbase,
dAppBrowserInjected: DAppBrowserInjected,
safe: Safe,
};
export const WalletsListEthereum = {
[idBrowserExtension]: BrowserExtension,
[idMetaMask]: MetaMask,
[idOkx]: Okx,
[idWalletConnect]: WalletConnect,
[idLedger]: Ledger,
[idLedgerLive]: LedgerLive,
[idExodus]: Exodus,
[idAmbire]: Ambire,
[idBitKeep]: BitKeep,
[idCoin98]: Coin98,
[idBrave]: Brave,
[idImToken]: ImToken,
[idTrust]: Trust,
[idXdefi]: Xdefi,
[idCoinbase]: Coinbase,
[idDAppBrowserInjected]: DAppBrowserInjected,
[idSafe]: Safe,
} as const;

export type WalletIdsEthereum = keyof typeof WalletsListEthereum;
7 changes: 5 additions & 2 deletions packages/wallets/ambire/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { WalletAdapterType } from '@reef-knot/types';
import { getWalletConnectConnector } from '@reef-knot/wallets-helpers';
import WalletIcon from './icons/ambire.svg';

export const id = 'ambire';
export const name = 'Ambire';

export const Ambire: WalletAdapterType = ({
walletconnectProjectId,
chains,
}) => ({
walletName: 'Ambire',
walletId: 'ambire',
walletName: name,
walletId: id,
icon: WalletIcon,
connector: getWalletConnectConnector({
chains,
Expand Down
Loading
Loading