Skip to content

Commit 5f9243b

Browse files
authored
Support EIP-6963: Multi Injected Provider Discovery (#312)
* connectorlist * remove: transparent family logo * install mipd * squircle spinner * scroll component * include midp wallets in default config * useWallets hook + configs * update connector list * use wallet hook, new connector routes, replacing config logic * icon cleanup + connect fixes * fix: deeplinks * edge cases, fix mobile routes and missing elements * override cleanup * spinner configs * more configs * config updates * avoid duplicate wallets * types * allow scanning if connector not ready * consolidate wallet checks * fix: mobile scroll + walletconnect border radius * align configs, flags for smaller icons, misc. updates * fix: missing download url change * bring recent to top * safe app update * fix: injected mismatches * fix: mm icon size * fix: remove doubled up wallets * add: more scroll available tooltip * update: click to scroll tooltip * update: hide legacy connectors without a name * cleanup * fix: duplicate wallet detection * remove: unnecessary iconBackground prop * add: family logo to other wallets icon * fix: missed file * Fix typo: MIDP > MIPD * mobile other wallets cleanup * fix: do not hoist walletconnect to top of list * cleanup logos * rename old EIP-1193 to legacy * avoid doubling up on logos * mobile border radius * eip6963 config for Family wallet * fix: types * fix: legacy injected wallets * dev log * temp dev log getting this deployed on vercel is the best way to test on an in-app wallet browser (cant use localhost). using alert because there are no dev tools in these in-app browsers * dev * remove dev
1 parent 5e20cb6 commit 5f9243b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1892
-1308
lines changed

Diff for: examples/testbench/src/pages/iframe.tsx

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { NextPage } from 'next';
2+
3+
const Ledger: NextPage = () => {
4+
return (
5+
<>
6+
<iframe src="/" style={{ width: '100%', height: '100vh' }} />
7+
</>
8+
);
9+
};
10+
11+
export default Ledger;

Diff for: packages/connectkit/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"buffer": "^6.0.3",
4343
"detect-browser": "^5.3.0",
4444
"framer-motion": "^6.3.11",
45+
"mipd": "^0.0.5",
4546
"qrcode": "^1.5.0",
4647
"react-transition-state": "^1.1.4",
4748
"react-use-measure": "^2.1.1",

Diff for: packages/connectkit/src/assets/logos.tsx

+16-37
Large diffs are not rendered by default.

Diff for: packages/connectkit/src/components/Common/Alert/index.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import React from 'react';
21
import { AlertProps } from './types';
32
import { AlertContainer, IconContainer } from './styles';
43

5-
const Alert = ({ children, icon }: AlertProps) => {
4+
const Alert = ({ children, error, icon }: AlertProps) => {
65
return (
7-
<AlertContainer>
6+
<AlertContainer $error={error}>
87
{icon && <IconContainer>{icon}</IconContainer>}
98
<div>{children}</div>
109
</AlertContainer>

Diff for: packages/connectkit/src/components/Common/Alert/styles.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import styled from './../../../styles/styled';
22
import { motion } from 'framer-motion';
33
import defaultTheme from '../../../constants/defaultTheme';
4+
import { css } from 'styled-components';
45

5-
export const AlertContainer = styled(motion.div)`
6+
export const AlertContainer = styled(motion.div)<{ $error?: boolean }>`
67
display: flex;
78
gap: 8px;
89
position: relative;
@@ -28,6 +29,14 @@ export const AlertContainer = styled(motion.div)`
2829
border-radius: 24px;
2930
text-align: center;
3031
}
32+
33+
${($error) => {
34+
if ($error)
35+
return css`
36+
color: #fff;
37+
background: var(--ck-body-color-danger, red);
38+
`;
39+
}}
3140
`;
3241

3342
export const IconContainer = styled(motion.div)`
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export type AlertProps = {
22
children?: React.ReactNode;
33
icon?: React.ReactNode;
4+
error?: boolean;
45
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import { useContext, routes } from '../../ConnectKit';
2+
3+
import {
4+
ConnectorsContainer,
5+
ConnectorButton,
6+
ConnectorLabel,
7+
ConnectorIcon,
8+
RecentlyUsedTag,
9+
} from './styles';
10+
11+
import { useWallets } from '../../../hooks/useWallets';
12+
import { useInjectedWallet } from '../../../hooks/connectors/useInjectedWallet';
13+
import { isInjectedConnector, isWalletConnectConnector } from '../../../utils';
14+
15+
import { useWalletConnectUri } from '../../../hooks/connectors/useWalletConnectUri';
16+
import { useLastConnector } from '../../../hooks/useLastConnector';
17+
import useIsMobile from '../../../hooks/useIsMobile';
18+
19+
import { ScrollArea } from '../../Common/ScrollArea';
20+
import Alert from '../Alert';
21+
22+
const ConnectorList = () => {
23+
const context = useContext();
24+
const isMobile = useIsMobile();
25+
26+
const { uri } = useWalletConnectUri();
27+
const { lastConnectorId } = useLastConnector();
28+
const injectedWallet = useInjectedWallet();
29+
30+
const wallets = useWallets();
31+
32+
const walletsToDisplay =
33+
context.options?.hideRecentBadge ||
34+
lastConnectorId === 'walletConnect-WalletConnect' // do not hoist walletconnect to top of list
35+
? wallets
36+
: [
37+
// move last used wallet to top of list
38+
// using .filter and spread to avoid mutating original array order with .sort
39+
...wallets.filter(
40+
(wallet) =>
41+
lastConnectorId ===
42+
`${wallet.connector.id}-${wallet.connector.name}`
43+
),
44+
...wallets.filter(
45+
(wallet) =>
46+
lastConnectorId !==
47+
`${wallet.connector.id}-${wallet.connector.name}`
48+
),
49+
];
50+
51+
return (
52+
<ScrollArea mobileDirection={'horizontal'}>
53+
{walletsToDisplay.length === 0 && (
54+
<Alert error>No connectors found in ConnectKit config.</Alert>
55+
)}
56+
{walletsToDisplay.length > 0 && (
57+
<ConnectorsContainer
58+
$mobile={isMobile}
59+
$totalResults={walletsToDisplay.length}
60+
>
61+
{walletsToDisplay.map((wallet) => {
62+
const {
63+
id,
64+
name,
65+
shortName,
66+
icon,
67+
iconConnector,
68+
connector,
69+
createUri,
70+
} = wallet;
71+
72+
let deeplink = isMobile ? createUri?.(uri ?? '') : undefined;
73+
74+
const redirectToMoreWallets =
75+
isMobile && isWalletConnectConnector(id);
76+
77+
if (isInjectedConnector(id) && !injectedWallet.enabled) return null;
78+
if (redirectToMoreWallets) deeplink = undefined; // mobile redirects to more wallets page
79+
80+
const walletInfo =
81+
isInjectedConnector(wallet.id) && injectedWallet.enabled
82+
? // && injectedWallet.wallet.name === wallet.name
83+
{
84+
name: injectedWallet.wallet.name,
85+
shortName:
86+
injectedWallet.wallet.shortName ??
87+
injectedWallet.wallet.name,
88+
icon: injectedWallet.wallet.icon,
89+
//iconRadius: 0,
90+
}
91+
: {
92+
name: name,
93+
shortName: shortName ?? name,
94+
icon: iconConnector ?? icon,
95+
iconRadius: wallet.id === 'walletConnect' ? 0 : undefined,
96+
};
97+
98+
const ButtonInner = ({
99+
disabled = false,
100+
}: {
101+
disabled?: boolean;
102+
}) => (
103+
<ConnectorButton
104+
as={deeplink ? 'a' : undefined}
105+
href={deeplink ? deeplink : undefined}
106+
disabled={disabled || context.route !== routes.CONNECTORS}
107+
onClick={
108+
deeplink
109+
? undefined
110+
: () => {
111+
if (redirectToMoreWallets) {
112+
context.setRoute(routes.MOBILECONNECTORS);
113+
} else {
114+
context.setRoute(routes.CONNECT);
115+
context.setConnector({ id: id, name: name });
116+
}
117+
}
118+
}
119+
>
120+
<ConnectorIcon
121+
data-small={wallet.iconShouldShrink}
122+
style={{
123+
borderRadius: walletInfo.iconRadius,
124+
}}
125+
>
126+
{walletInfo.icon}
127+
</ConnectorIcon>
128+
<ConnectorLabel>
129+
{isMobile ? walletInfo.shortName : walletInfo.name}
130+
{!context.options?.hideRecentBadge &&
131+
lastConnectorId === `${connector.id}-${connector.name}` && (
132+
<RecentlyUsedTag>
133+
<span>Recent</span>
134+
</RecentlyUsedTag>
135+
)}
136+
</ConnectorLabel>
137+
</ConnectorButton>
138+
);
139+
/*
140+
if (!connector.ready && injectedWallet.enabled) {
141+
return (
142+
<Tooltip
143+
key={id}
144+
xOffset={18}
145+
message={
146+
<div style={{ width: 230, padding: '6px 4px' }}>
147+
{name} Unavailable as {injectedWallet?.wallet?.name} is
148+
installed. Disable {injectedWallet?.wallet?.name} to
149+
connect with {name}.
150+
</div>
151+
}
152+
delay={0}
153+
>
154+
<ButtonInner disabled />
155+
</Tooltip>
156+
);
157+
}
158+
*/
159+
return <ButtonInner key={id} />;
160+
})}
161+
</ConnectorsContainer>
162+
)}
163+
</ScrollArea>
164+
);
165+
};
166+
167+
export default ConnectorList;

0 commit comments

Comments
 (0)