@arcblock/did-connect-react 3.3.10 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Connect/assets/locale.js +4 -2
- package/lib/Connect/components/login-item/connect-choose-list.js +120 -114
- package/lib/Connect/components/login-item/connect-provider-list.js +187 -180
- package/lib/Connect/components/login-item/login-method-item.js +63 -47
- package/lib/Connect/components/login-item/passkey-login-item.js +17 -15
- package/lib/Connect/components/login-item/wallet-login-options.js +42 -40
- package/lib/Connect/connect.js +503 -0
- package/lib/Connect/contexts/state.js +74 -65
- package/lib/Connect/fallback-connect.js +53 -0
- package/lib/Connect/hooks/provider-list.js +45 -29
- package/lib/Connect/index.js +13 -502
- package/lib/Connect/plugins/email/list-item.js +19 -18
- package/lib/Connect/use-connect.js +10 -10
- package/lib/OAuth/context.js +3 -3
- package/lib/Passkey/actions.js +80 -75
- package/lib/Passkey/context.js +3 -3
- package/lib/Passkey/dialog.js +7 -7
- package/lib/Session/assets/did-spaces-guide-cover.svg.js +74 -98
- package/lib/Session/index.js +189 -189
- package/lib/package.json.js +1 -1
- package/lib/utils.js +2 -2
- package/package.json +8 -8
- package/src/Connect/assets/locale.js +2 -0
- package/src/Connect/components/login-item/connect-choose-list.jsx +12 -5
- package/src/Connect/components/login-item/connect-provider-list.jsx +11 -4
- package/src/Connect/components/login-item/login-method-item.jsx +24 -7
- package/src/Connect/components/login-item/passkey-login-item.jsx +3 -1
- package/src/Connect/components/login-item/wallet-login-options.jsx +3 -2
- package/src/Connect/connect.jsx +618 -0
- package/src/Connect/contexts/state.jsx +10 -0
- package/src/Connect/fallback-connect.jsx +47 -0
- package/src/Connect/hooks/provider-list.js +48 -17
- package/src/Connect/index.jsx +8 -605
- package/src/Connect/plugins/email/list-item.jsx +3 -2
- package/src/Connect/use-connect.jsx +1 -1
- package/src/Passkey/actions.jsx +5 -0
- package/src/Session/assets/did-spaces-guide-cover.svg +1 -128
- package/src/Session/index.jsx +3 -4
- package/src/utils.js +2 -2
package/lib/package.json.js
CHANGED
package/lib/utils.js
CHANGED
|
@@ -6,7 +6,7 @@ import c from "js-cookie";
|
|
|
6
6
|
import l from "lodash/isNil";
|
|
7
7
|
import T from "lodash/isString";
|
|
8
8
|
import m from "lodash/isUndefined";
|
|
9
|
-
import { createAxios as P,
|
|
9
|
+
import { createAxios as P, getBlockletSDK as x } from "@blocklet/js-sdk";
|
|
10
10
|
import { withQuery as L } from "ufo";
|
|
11
11
|
import { isValid as w, isFromPublicKey as S } from "@arcblock/did";
|
|
12
12
|
import { getSafeUrl as C } from "@arcblock/ux/lib/Util/security";
|
|
@@ -137,7 +137,7 @@ async function be() {
|
|
|
137
137
|
o.searchParams.delete(f);
|
|
138
138
|
const t = JSON.parse(a.from(r, "base64").toString("utf-8"));
|
|
139
139
|
if (T(t.forceConnected) && m(t.sourceAppPid)) {
|
|
140
|
-
const s = await
|
|
140
|
+
const s = await x().user.getUserPublicInfo({ did: t.forceConnected });
|
|
141
141
|
m(s?.sourceAppPid) || (t.sourceAppPid = s.sourceAppPid);
|
|
142
142
|
}
|
|
143
143
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcblock/did-connect-react",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Client side library to work with DID Connect by ArcBlock.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -32,17 +32,17 @@
|
|
|
32
32
|
"url": "https://github.com/ArcBlock/ux/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@arcblock/bridge": "3.
|
|
36
|
-
"@arcblock/did": "^1.
|
|
37
|
-
"@arcblock/icons": "3.
|
|
38
|
-
"@arcblock/react-hooks": "3.
|
|
39
|
-
"@arcblock/ws": "^1.
|
|
35
|
+
"@arcblock/bridge": "3.4.1",
|
|
36
|
+
"@arcblock/did": "^1.28.1",
|
|
37
|
+
"@arcblock/icons": "3.4.1",
|
|
38
|
+
"@arcblock/react-hooks": "3.4.1",
|
|
39
|
+
"@arcblock/ws": "^1.28.1",
|
|
40
40
|
"@blocklet/constant": "^1.17.7",
|
|
41
41
|
"@fontsource/lexend": "^5.2.9",
|
|
42
42
|
"@iconify-icons/logos": "^1.2.36",
|
|
43
43
|
"@iconify-icons/material-symbols": "^1.2.58",
|
|
44
44
|
"@iconify/react": "^5.2.1",
|
|
45
|
-
"@ocap/util": "^1.
|
|
45
|
+
"@ocap/util": "^1.28.1",
|
|
46
46
|
"@simplewebauthn/browser": "^13.1.0",
|
|
47
47
|
"ahooks": "^3.8.5",
|
|
48
48
|
"axios": "^1.10.0",
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
82
82
|
"jest": "^29.7.0"
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "6101f8f54333c0c376437160147a0b15a1548111"
|
|
85
85
|
}
|
|
@@ -71,6 +71,7 @@ export default {
|
|
|
71
71
|
didConnectTitle: 'DID Connect',
|
|
72
72
|
didConnectDescription: 'Decentralized identities and apps, W3C DID-based, future-ready.',
|
|
73
73
|
noAuthenticationProvider: 'No authentication provider configured',
|
|
74
|
+
lastUsed: 'Last Used',
|
|
74
75
|
},
|
|
75
76
|
zh: {
|
|
76
77
|
generateError: '二维码生成失败',
|
|
@@ -143,5 +144,6 @@ export default {
|
|
|
143
144
|
didConnectTitle: 'DID Connect',
|
|
144
145
|
didConnectDescription: '面向未来的基于 W3C DID 去中心化身份和应用',
|
|
145
146
|
noAuthenticationProvider: '未配置任何身份验证提供者',
|
|
147
|
+
lastUsed: '上次使用',
|
|
146
148
|
},
|
|
147
149
|
};
|
|
@@ -48,7 +48,8 @@ export default function ConnectChooseList({
|
|
|
48
48
|
const passkeyLoginRef = useRef(null);
|
|
49
49
|
const { loginOAuth, logoutOAuth, t, oauthState } = useOAuth();
|
|
50
50
|
const { passkeyState } = usePasskey();
|
|
51
|
-
const { extraParams, locale, connectState, plugins, setPlugins, setSelectedPlugin, getPlugin } =
|
|
51
|
+
const { extraParams, locale, connectState, plugins, setPlugins, setSelectedPlugin, getPlugin, lastLoginMethod } =
|
|
52
|
+
useStateContext();
|
|
52
53
|
|
|
53
54
|
const handleLoginOAuth = useMemoizedFn(async (item) => {
|
|
54
55
|
localStorage.setItem(GA_LAST_LOGIN_METHOD, item.provider);
|
|
@@ -111,7 +112,7 @@ export default function ConnectChooseList({
|
|
|
111
112
|
if (magicToken && showEmailLogin && plugins.some((plugin) => plugin.name === LOGIN_PROVIDER.EMAIL)) {
|
|
112
113
|
const plugin = getPlugin(LOGIN_PROVIDER.EMAIL);
|
|
113
114
|
if (plugin.state.status === 'idle') {
|
|
114
|
-
localStorage.setItem(GA_LAST_LOGIN_METHOD,
|
|
115
|
+
localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.EMAIL);
|
|
115
116
|
plugin.state.reset();
|
|
116
117
|
plugin.state.magicToken = magicToken;
|
|
117
118
|
connectState.chooseMethod = LOGIN_PROVIDER.EMAIL;
|
|
@@ -160,6 +161,8 @@ export default function ConnectChooseList({
|
|
|
160
161
|
]}>
|
|
161
162
|
{showMobileLogin && (
|
|
162
163
|
<MobileLoginItem
|
|
164
|
+
t={t}
|
|
165
|
+
isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.WALLET}
|
|
163
166
|
ref={walletLoginRef}
|
|
164
167
|
tokenState={tokenState}
|
|
165
168
|
sx={[size === 'small' ? { p: 1 } : { p: 2 }]}
|
|
@@ -167,7 +170,7 @@ export default function ConnectChooseList({
|
|
|
167
170
|
tokenKey={tokenKey}
|
|
168
171
|
disableSwitchApp={disableSwitchApp}
|
|
169
172
|
onClick={async () => {
|
|
170
|
-
localStorage.setItem(GA_LAST_LOGIN_METHOD,
|
|
173
|
+
localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.WALLET);
|
|
171
174
|
tokenState.reset();
|
|
172
175
|
await onReset();
|
|
173
176
|
tokenState.status = 'created';
|
|
@@ -181,13 +184,15 @@ export default function ConnectChooseList({
|
|
|
181
184
|
)}
|
|
182
185
|
{showWebLogin && (
|
|
183
186
|
<WebLoginItem
|
|
187
|
+
isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.WALLET}
|
|
184
188
|
ref={webLoginRef}
|
|
185
189
|
tokenState={tokenState}
|
|
186
190
|
webWalletUrl={webWalletUrl}
|
|
191
|
+
t={t}
|
|
187
192
|
sx={[size === 'small' ? { p: 1 } : { p: 2 }]}
|
|
188
193
|
disableSwitchApp={disableSwitchApp}
|
|
189
194
|
onClick={() => {
|
|
190
|
-
localStorage.setItem(GA_LAST_LOGIN_METHOD,
|
|
195
|
+
localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.WALLET);
|
|
191
196
|
// HACK: 在点击插件登录时,直接将状态置为扫码中,避免插件登录时的状态切换
|
|
192
197
|
tokenState.status = 'scanned';
|
|
193
198
|
connectState.chooseMethod = 'wallet-web';
|
|
@@ -222,6 +227,8 @@ export default function ConnectChooseList({
|
|
|
222
227
|
{showOAuthLogin
|
|
223
228
|
? oauthProviderList.map((item) => (
|
|
224
229
|
<LoginMethodItem
|
|
230
|
+
t={t}
|
|
231
|
+
isLatest={lastLoginMethod && lastLoginMethod === item.provider}
|
|
225
232
|
key={item.provider}
|
|
226
233
|
title={LOGIN_PROVIDER_NAME[item.provider]}
|
|
227
234
|
icon={
|
|
@@ -254,7 +261,7 @@ export default function ConnectChooseList({
|
|
|
254
261
|
behavior={passkeyBehavior}
|
|
255
262
|
sx={[size === 'small' ? { p: 1 } : { p: 2 }]}
|
|
256
263
|
onClick={() => {
|
|
257
|
-
localStorage.setItem(GA_LAST_LOGIN_METHOD,
|
|
264
|
+
localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.PASSKEY);
|
|
258
265
|
const connectFn = passkeyLoginRef.current.connect;
|
|
259
266
|
connectState.chooseMethod = 'passkey';
|
|
260
267
|
connectState.retryConnect = () => {
|
|
@@ -65,6 +65,7 @@ export default function ConnectProviderList({
|
|
|
65
65
|
getPlugin,
|
|
66
66
|
showWalletOptions,
|
|
67
67
|
setShowWalletOptions,
|
|
68
|
+
lastLoginMethod,
|
|
68
69
|
} = useStateContext();
|
|
69
70
|
|
|
70
71
|
const t = useMemoizedFn((key, data = {}) => {
|
|
@@ -127,7 +128,7 @@ export default function ConnectProviderList({
|
|
|
127
128
|
});
|
|
128
129
|
|
|
129
130
|
const handleMobileLoginClick = useMemoizedFn(async () => {
|
|
130
|
-
localStorage.setItem(GA_LAST_LOGIN_METHOD,
|
|
131
|
+
localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.WALLET);
|
|
131
132
|
tokenState.reset();
|
|
132
133
|
await onReset();
|
|
133
134
|
tokenState.status = 'created';
|
|
@@ -139,7 +140,7 @@ export default function ConnectProviderList({
|
|
|
139
140
|
});
|
|
140
141
|
|
|
141
142
|
const handleWebLoginClick = useMemoizedFn(() => {
|
|
142
|
-
localStorage.setItem(GA_LAST_LOGIN_METHOD,
|
|
143
|
+
localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.WALLET);
|
|
143
144
|
// HACK: 在点击插件登录时,直接将状态置为扫码中,避免插件登录时的状态切换
|
|
144
145
|
tokenState.status = 'scanned';
|
|
145
146
|
connectState.chooseMethod = 'wallet-web';
|
|
@@ -178,7 +179,7 @@ export default function ConnectProviderList({
|
|
|
178
179
|
) {
|
|
179
180
|
const plugin = getPlugin(LOGIN_PROVIDER.EMAIL);
|
|
180
181
|
if (plugin.state.status === 'idle') {
|
|
181
|
-
localStorage.setItem(GA_LAST_LOGIN_METHOD,
|
|
182
|
+
localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.EMAIL);
|
|
182
183
|
plugin.state.reset();
|
|
183
184
|
plugin.state.magicToken = magicToken;
|
|
184
185
|
connectState.chooseMethod = LOGIN_PROVIDER.EMAIL;
|
|
@@ -215,6 +216,8 @@ export default function ConnectProviderList({
|
|
|
215
216
|
if (browser.mobile.any && !showWalletOptions) {
|
|
216
217
|
return (
|
|
217
218
|
<MobileLoginItem
|
|
219
|
+
t={t}
|
|
220
|
+
isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.WALLET}
|
|
218
221
|
key={LOGIN_PROVIDER.WALLET}
|
|
219
222
|
ref={walletLoginRef}
|
|
220
223
|
tokenState={tokenState}
|
|
@@ -233,6 +236,8 @@ export default function ConnectProviderList({
|
|
|
233
236
|
hideQRCode || (!hideQRCode && (isSameProtocol || extension) && (!browser.mobile.any || extension));
|
|
234
237
|
return shouldShowWebLoginItem ? (
|
|
235
238
|
<WebLoginItem
|
|
239
|
+
t={t}
|
|
240
|
+
isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.WALLET}
|
|
236
241
|
key={LOGIN_PROVIDER.WALLET}
|
|
237
242
|
ref={webLoginRef}
|
|
238
243
|
tokenState={tokenState}
|
|
@@ -265,7 +270,7 @@ export default function ConnectProviderList({
|
|
|
265
270
|
behavior={passkeyBehavior}
|
|
266
271
|
sx={[size === 'small' ? { p: 1 } : { p: 2 }]}
|
|
267
272
|
onClick={() => {
|
|
268
|
-
localStorage.setItem(GA_LAST_LOGIN_METHOD,
|
|
273
|
+
localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.PASSKEY);
|
|
269
274
|
const connectFn = passkeyLoginRef.current.connect;
|
|
270
275
|
connectState.chooseMethod = 'passkey';
|
|
271
276
|
connectState.retryConnect = () => {
|
|
@@ -305,6 +310,8 @@ export default function ConnectProviderList({
|
|
|
305
310
|
if (item.type === 'oauth') {
|
|
306
311
|
return (
|
|
307
312
|
<LoginMethodItem
|
|
313
|
+
t={t}
|
|
314
|
+
isLatest={lastLoginMethod && lastLoginMethod === item.provider}
|
|
308
315
|
key={item.provider}
|
|
309
316
|
title={LOGIN_PROVIDER_NAME[item.provider]}
|
|
310
317
|
icon={
|
|
@@ -2,17 +2,20 @@ import { Box, Tooltip, Typography, useTheme } from '@mui/material';
|
|
|
2
2
|
import { Icon } from '@iconify/react';
|
|
3
3
|
import { isValidElement } from 'react';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
|
+
import noop from 'lodash/noop';
|
|
5
6
|
import { mergeSx } from '@arcblock/ux/lib/Util/style';
|
|
6
7
|
import { LOGIN_PROVIDER_ICON_SIZE } from '@arcblock/ux/lib/Util/constant';
|
|
7
8
|
import ArrowRightAltRoundedIcon from '@iconify-icons/material-symbols/arrow-right-alt-rounded';
|
|
8
9
|
|
|
9
10
|
export default function LoginMethodItem({
|
|
11
|
+
isLatest = false,
|
|
10
12
|
title,
|
|
11
13
|
description = null,
|
|
12
14
|
icon,
|
|
13
15
|
iconScale = 0.95,
|
|
14
16
|
slotProps = {},
|
|
15
17
|
mode = 'normal',
|
|
18
|
+
t = noop,
|
|
16
19
|
...rest
|
|
17
20
|
}) {
|
|
18
21
|
const theme = useTheme();
|
|
@@ -23,13 +26,16 @@ export default function LoginMethodItem({
|
|
|
23
26
|
className="arc-login-item"
|
|
24
27
|
sx={mergeSx(
|
|
25
28
|
{
|
|
29
|
+
position: 'relative',
|
|
26
30
|
display: 'flex',
|
|
27
31
|
alignItems: 'center',
|
|
28
32
|
gap: 1,
|
|
29
33
|
cursor: 'pointer',
|
|
30
34
|
p: 1.2,
|
|
31
35
|
borderRadius: 1,
|
|
32
|
-
backgroundColor: 'grey.50',
|
|
36
|
+
backgroundColor: isLatest ? 'grey.100' : 'grey.50',
|
|
37
|
+
border: isLatest ? '1px solid' : 'none',
|
|
38
|
+
borderColor: isLatest ? 'grey.100' : 'transparent',
|
|
33
39
|
textDecoration: 'none',
|
|
34
40
|
transition: 'background-color 0.5s',
|
|
35
41
|
'&:hover, &:active, &.did-connect__choose-item__active': {
|
|
@@ -100,12 +106,21 @@ export default function LoginMethodItem({
|
|
|
100
106
|
</Typography>
|
|
101
107
|
) : null}
|
|
102
108
|
</Box>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
{isLatest ? (
|
|
110
|
+
<Typography
|
|
111
|
+
component="span"
|
|
112
|
+
className="latest-badge"
|
|
113
|
+
style={{ color: theme.palette.text.secondary, fontSize: 11 }}>
|
|
114
|
+
{t('lastUsed')}
|
|
115
|
+
</Typography>
|
|
116
|
+
) : (
|
|
117
|
+
<Icon
|
|
118
|
+
className="other-item-icon"
|
|
119
|
+
icon={ArrowRightAltRoundedIcon}
|
|
120
|
+
fontSize="1.3rem"
|
|
121
|
+
color={theme.palette.primary.main}
|
|
122
|
+
/>
|
|
123
|
+
)}
|
|
109
124
|
</>
|
|
110
125
|
) : null}
|
|
111
126
|
</Box>
|
|
@@ -119,4 +134,6 @@ LoginMethodItem.propTypes = {
|
|
|
119
134
|
iconScale: PropTypes.number,
|
|
120
135
|
slotProps: PropTypes.object,
|
|
121
136
|
mode: PropTypes.oneOf(['mini', 'simple', 'normal']),
|
|
137
|
+
isLatest: PropTypes.bool,
|
|
138
|
+
t: PropTypes.func,
|
|
122
139
|
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
2
|
import { useImperativeHandle, useRef } from 'react';
|
|
3
3
|
import { useMemoizedFn } from 'ahooks';
|
|
4
|
+
import { LOGIN_PROVIDER } from '@arcblock/ux/lib/Util/constant';
|
|
4
5
|
|
|
5
6
|
import PasskeyActions from '../../../Passkey/actions';
|
|
6
7
|
import { getAppId } from '../../../utils';
|
|
7
8
|
import { useStateContext } from '../../contexts/state';
|
|
8
9
|
|
|
9
10
|
export default function PasskeyLoginItem({ ref = null, onSuccess, tokenState, behavior = 'none', ...rest }) {
|
|
10
|
-
const { extraParams } = useStateContext();
|
|
11
|
+
const { extraParams, lastLoginMethod } = useStateContext();
|
|
11
12
|
const passkeyActionRef = useRef(null);
|
|
12
13
|
|
|
13
14
|
const handleSuccess = useMemoizedFn((result) =>
|
|
@@ -36,6 +37,7 @@ export default function PasskeyLoginItem({ ref = null, onSuccess, tokenState, be
|
|
|
36
37
|
<PasskeyActions
|
|
37
38
|
{...rest}
|
|
38
39
|
ref={passkeyActionRef}
|
|
40
|
+
isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.PASSKEY}
|
|
39
41
|
action={tokenState.action}
|
|
40
42
|
behavior={behavior}
|
|
41
43
|
onSuccess={handleSuccess}
|
|
@@ -24,7 +24,7 @@ export default function WalletLoginOptions({
|
|
|
24
24
|
onWebLoginClick,
|
|
25
25
|
onBack,
|
|
26
26
|
}) {
|
|
27
|
-
const { locale } = useStateContext();
|
|
27
|
+
const { t, locale } = useStateContext();
|
|
28
28
|
const browser = useBrowser();
|
|
29
29
|
const isSameProtocol = checkSameProtocol(webWalletUrl);
|
|
30
30
|
const extension = detectWalletExtension();
|
|
@@ -32,7 +32,6 @@ export default function WalletLoginOptions({
|
|
|
32
32
|
const isTablet = useCreation(() => {
|
|
33
33
|
return browser.mobile.tablet || (!browser.mobile.any && window?.navigator?.maxTouchPoints > 0);
|
|
34
34
|
}, [browser.mobile.tablet, browser.mobile.any]);
|
|
35
|
-
|
|
36
35
|
return (
|
|
37
36
|
<>
|
|
38
37
|
{qrcode}
|
|
@@ -67,6 +66,7 @@ export default function WalletLoginOptions({
|
|
|
67
66
|
}}>
|
|
68
67
|
{isTablet ? (
|
|
69
68
|
<MobileLoginItem
|
|
69
|
+
t={t}
|
|
70
70
|
key={LOGIN_PROVIDER.WALLET}
|
|
71
71
|
ref={walletLoginRef}
|
|
72
72
|
tokenState={tokenState}
|
|
@@ -82,6 +82,7 @@ export default function WalletLoginOptions({
|
|
|
82
82
|
<>
|
|
83
83
|
{(isSameProtocol || extension) && (!browser.mobile.any || extension) ? (
|
|
84
84
|
<WebLoginItem
|
|
85
|
+
t={t}
|
|
85
86
|
key={LOGIN_PROVIDER.WALLET}
|
|
86
87
|
ref={webLoginRef}
|
|
87
88
|
tokenState={tokenState}
|