@dynamic-labs/sdk-react-core 0.18.100-viem.2 → 0.18.100-viem.4
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/CHANGELOG.md +19 -0
- package/package.cjs +2 -2
- package/package.js +2 -2
- package/package.json +9 -9
- package/src/index.cjs +2 -0
- package/src/index.js +1 -0
- package/src/lib/context/DynamicContext/DynamicContext.cjs +2 -1
- package/src/lib/context/DynamicContext/DynamicContext.js +2 -1
- package/src/lib/data/api.cjs +17 -1
- package/src/lib/data/api.d.ts +2 -1
- package/src/lib/data/api.js +17 -2
- package/src/lib/styles/index.shadow.cjs +1 -1
- package/src/lib/styles/index.shadow.js +1 -1
- package/src/lib/utils/functions/digestSHA256/digestSHA256.cjs +11 -0
- package/src/lib/utils/functions/digestSHA256/digestSHA256.d.ts +1 -0
- package/src/lib/utils/functions/digestSHA256/digestSHA256.js +7 -0
- package/src/lib/utils/functions/digestSHA256/index.d.ts +1 -0
- package/src/lib/utils/functions/encodeBase64URL/encodeBase64URL.cjs +14 -0
- package/src/lib/utils/functions/encodeBase64URL/encodeBase64URL.d.ts +1 -0
- package/src/lib/utils/functions/encodeBase64URL/encodeBase64URL.js +10 -0
- package/src/lib/utils/functions/encodeBase64URL/index.d.ts +1 -0
- package/src/lib/utils/functions/getRedirectURIOrigin/getRedirectURIOrigin.cjs +33 -0
- package/src/lib/utils/functions/getRedirectURIOrigin/getRedirectURIOrigin.d.ts +1 -0
- package/src/lib/utils/functions/getRedirectURIOrigin/getRedirectURIOrigin.js +29 -0
- package/src/lib/utils/functions/getRedirectURIOrigin/index.d.ts +1 -0
- package/src/lib/utils/functions/index.d.ts +5 -0
- package/src/lib/utils/functions/randomString/index.d.ts +1 -0
- package/src/lib/utils/functions/randomString/randomString.cjs +14 -0
- package/src/lib/utils/functions/randomString/randomString.d.ts +1 -0
- package/src/lib/utils/functions/randomString/randomString.js +10 -0
- package/src/lib/utils/functions/stringifyURIQuery/index.d.ts +1 -0
- package/src/lib/utils/functions/stringifyURIQuery/stringifyURIQuery.cjs +13 -0
- package/src/lib/utils/functions/stringifyURIQuery/stringifyURIQuery.d.ts +1 -0
- package/src/lib/utils/functions/stringifyURIQuery/stringifyURIQuery.js +9 -0
- package/src/lib/utils/hooks/useConnectedWalletsNetworkValidation/useConnectedWalletsNetworkValidation.cjs +7 -6
- package/src/lib/utils/hooks/useConnectedWalletsNetworkValidation/useConnectedWalletsNetworkValidation.js +7 -6
- package/src/lib/utils/hooks/useSocialAccounts/useSocialAccounts.cjs +90 -23
- package/src/lib/utils/hooks/useSocialAccounts/useSocialAccounts.js +92 -25
- package/src/lib/views/NetworkNotSupported/NetworkNotSupported.cjs +3 -2
- package/src/lib/views/NetworkNotSupported/NetworkNotSupported.js +3 -2
- package/src/lib/views/NetworkNotSupportedSwitchManual/NetworkNotSupportedSwitchManual.cjs +3 -2
- package/src/lib/views/NetworkNotSupportedSwitchManual/NetworkNotSupportedSwitchManual.js +3 -2
- package/src/lib/widgets/DynamicWidget/hooks/useFetchCurrency/useFetchCurrency.cjs +4 -1
- package/src/lib/widgets/DynamicWidget/hooks/useFetchCurrency/useFetchCurrency.js +4 -1
- package/src/lib/widgets/OAuthIFrameContainer/OAuthIFrameContainer.cjs +13 -0
- package/src/lib/widgets/OAuthIFrameContainer/OAuthIFrameContainer.d.ts +2 -0
- package/src/lib/widgets/OAuthIFrameContainer/OAuthIFrameContainer.js +9 -0
- package/src/lib/widgets/OAuthIFrameContainer/index.d.ts +1 -0
- package/src/lib/widgets/index.d.ts +1 -0
|
@@ -22,7 +22,7 @@ var isProgrammableNetworkSwitchSupported = require('../../functions/isProgrammab
|
|
|
22
22
|
|
|
23
23
|
const useConnectedWalletsNetworkValidation = () => {
|
|
24
24
|
const { connectedWallets, selectedWalletConnector, setSelectedWalletConnector, setShowAuthFlow, showAuthFlow, walletsToConnectByChain, isBridgeFlow, } = useInternalDynamicContext.useInternalDynamicContext();
|
|
25
|
-
const {
|
|
25
|
+
const { setView } = ViewContext.useViewContext();
|
|
26
26
|
React.useEffect(() => {
|
|
27
27
|
if (!isBridgeFlow) {
|
|
28
28
|
return;
|
|
@@ -53,16 +53,17 @@ const useConnectedWalletsNetworkValidation = () => {
|
|
|
53
53
|
}
|
|
54
54
|
setView(networkNotSupportedView);
|
|
55
55
|
}
|
|
56
|
+
// we need it to remove 'showAuthFlow' property. we don't want to react to it,
|
|
57
|
+
// because closing modal on network switch causes it to re-open
|
|
58
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
56
59
|
}, [
|
|
57
|
-
isBridgeFlow,
|
|
58
60
|
connectedWallets,
|
|
59
|
-
|
|
61
|
+
isBridgeFlow,
|
|
60
62
|
selectedWalletConnector,
|
|
61
|
-
walletsToConnectByChain,
|
|
62
|
-
showAuthFlow,
|
|
63
|
-
setView,
|
|
64
63
|
setSelectedWalletConnector,
|
|
65
64
|
setShowAuthFlow,
|
|
65
|
+
setView,
|
|
66
|
+
walletsToConnectByChain,
|
|
66
67
|
]);
|
|
67
68
|
};
|
|
68
69
|
|
|
@@ -18,7 +18,7 @@ import { isProgrammableNetworkSwitchSupported } from '../../functions/isProgramm
|
|
|
18
18
|
|
|
19
19
|
const useConnectedWalletsNetworkValidation = () => {
|
|
20
20
|
const { connectedWallets, selectedWalletConnector, setSelectedWalletConnector, setShowAuthFlow, showAuthFlow, walletsToConnectByChain, isBridgeFlow, } = useInternalDynamicContext();
|
|
21
|
-
const {
|
|
21
|
+
const { setView } = useViewContext();
|
|
22
22
|
useEffect(() => {
|
|
23
23
|
if (!isBridgeFlow) {
|
|
24
24
|
return;
|
|
@@ -49,16 +49,17 @@ const useConnectedWalletsNetworkValidation = () => {
|
|
|
49
49
|
}
|
|
50
50
|
setView(networkNotSupportedView);
|
|
51
51
|
}
|
|
52
|
+
// we need it to remove 'showAuthFlow' property. we don't want to react to it,
|
|
53
|
+
// because closing modal on network switch causes it to re-open
|
|
54
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
52
55
|
}, [
|
|
53
|
-
isBridgeFlow,
|
|
54
56
|
connectedWallets,
|
|
55
|
-
|
|
57
|
+
isBridgeFlow,
|
|
56
58
|
selectedWalletConnector,
|
|
57
|
-
walletsToConnectByChain,
|
|
58
|
-
showAuthFlow,
|
|
59
|
-
setView,
|
|
60
59
|
setSelectedWalletConnector,
|
|
61
60
|
setShowAuthFlow,
|
|
61
|
+
setView,
|
|
62
|
+
walletsToConnectByChain,
|
|
62
63
|
]);
|
|
63
64
|
};
|
|
64
65
|
|
|
@@ -23,6 +23,11 @@ require('@dynamic-labs/multi-wallet');
|
|
|
23
23
|
var getAuthToken = require('../../functions/getAuthToken/getAuthToken.cjs');
|
|
24
24
|
var index = require('../../functions/getEnabledOAuthProviders/index.cjs');
|
|
25
25
|
var isSocialKycEnabled = require('../../functions/isSocialKycEnabled/isSocialKycEnabled.cjs');
|
|
26
|
+
var randomString = require('../../functions/randomString/randomString.cjs');
|
|
27
|
+
var stringifyURIQuery = require('../../functions/stringifyURIQuery/stringifyURIQuery.cjs');
|
|
28
|
+
var digestSHA256 = require('../../functions/digestSHA256/digestSHA256.cjs');
|
|
29
|
+
var encodeBase64URL = require('../../functions/encodeBase64URL/encodeBase64URL.cjs');
|
|
30
|
+
var getRedirectURIOrigin = require('../../functions/getRedirectURIOrigin/getRedirectURIOrigin.cjs');
|
|
26
31
|
|
|
27
32
|
const socialProviders = [
|
|
28
33
|
'discord',
|
|
@@ -33,12 +38,16 @@ const socialProviders = [
|
|
|
33
38
|
'twitch',
|
|
34
39
|
'twitter',
|
|
35
40
|
];
|
|
41
|
+
// pkce params are only required for twitter and break if added for other providers, like google
|
|
42
|
+
// so we should only add provider that support pkce to this list
|
|
43
|
+
const providersRequiringPkce = ['twitter', 'github'];
|
|
36
44
|
const useSocialAccounts = () => {
|
|
37
45
|
var _a;
|
|
38
46
|
const { environmentId, user, projectSettings, onboardingOnlyJwt } = useInternalDynamicContext.useInternalDynamicContext();
|
|
39
47
|
const { updateUserProfileByJWT } = useUpdateUserProfileByJWTCallback.useUpdateUserProfileByJWTCallback();
|
|
40
48
|
const [isProcessing, setIsProcessing] = React.useState(false);
|
|
41
49
|
const [error, setError] = React.useState();
|
|
50
|
+
const providersWaitingOauthMessages = React.useRef({});
|
|
42
51
|
const userJwt = (_a = getAuthToken.getAuthToken()) !== null && _a !== void 0 ? _a : onboardingOnlyJwt;
|
|
43
52
|
const oauthProviders = index.getEnabledOAuthProviders(projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers);
|
|
44
53
|
const verifiedOAuthCredentialsMap = React.useMemo(() => {
|
|
@@ -57,6 +66,23 @@ const useSocialAccounts = () => {
|
|
|
57
66
|
setIsProcessing(false);
|
|
58
67
|
setError(message);
|
|
59
68
|
};
|
|
69
|
+
const addOAuthIFrame = (url) => {
|
|
70
|
+
const container = document.getElementById('oauth-iframe-container');
|
|
71
|
+
let oauthIFrame = document.getElementById('oauth-iframe');
|
|
72
|
+
if (!container || oauthIFrame) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
oauthIFrame = document.createElement('iframe');
|
|
76
|
+
oauthIFrame.setAttribute('id', 'oauth-iframe');
|
|
77
|
+
oauthIFrame.setAttribute('src', url);
|
|
78
|
+
container.appendChild(oauthIFrame);
|
|
79
|
+
};
|
|
80
|
+
const removeOAuthIFrame = () => {
|
|
81
|
+
const oauthIFrame = document.getElementById('oauth-iframe');
|
|
82
|
+
if (oauthIFrame) {
|
|
83
|
+
oauthIFrame.remove();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
60
86
|
const checkValidProvider = (provider) => {
|
|
61
87
|
if (!provider) {
|
|
62
88
|
handleError('Provider is required');
|
|
@@ -68,38 +94,63 @@ const useSocialAccounts = () => {
|
|
|
68
94
|
}
|
|
69
95
|
return true;
|
|
70
96
|
};
|
|
71
|
-
const
|
|
72
|
-
setError(undefined);
|
|
73
|
-
setIsProcessing(true);
|
|
97
|
+
const checkValidOAuthLinking = (provider) => {
|
|
74
98
|
if (!isSocialKycEnabled.isSocialKycEnabled(projectSettings)) {
|
|
75
99
|
handleError('Social linking is not enabled on the dashboard');
|
|
76
|
-
return;
|
|
100
|
+
return false;
|
|
77
101
|
}
|
|
78
102
|
if (!checkValidProvider(provider)) {
|
|
79
|
-
return;
|
|
103
|
+
return false;
|
|
80
104
|
}
|
|
81
105
|
const verifiedCredential = verifiedOAuthCredentialsMap[provider];
|
|
82
106
|
if (verifiedCredential) {
|
|
83
107
|
handleError(`Account already linked for provider: ${provider}`);
|
|
84
|
-
return;
|
|
108
|
+
return false;
|
|
85
109
|
}
|
|
86
110
|
const oauthProvider = oauthProviders.find((p) => p.provider === provider);
|
|
87
111
|
if (!oauthProvider) {
|
|
88
112
|
handleError(`Provider is not enabled on the dashboard: ${provider}`);
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
};
|
|
117
|
+
const linkSocialAccount = (provider) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
118
|
+
var _b;
|
|
119
|
+
setError(undefined);
|
|
120
|
+
setIsProcessing(true);
|
|
121
|
+
// invalid linking request
|
|
122
|
+
if (!checkValidOAuthLinking(provider)) {
|
|
89
123
|
return;
|
|
90
124
|
}
|
|
125
|
+
const state = randomString.randomString(8);
|
|
126
|
+
const verifier = randomString.randomString(43);
|
|
91
127
|
const handleAuthWindowMessage = (event) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
128
|
+
const message = event.data;
|
|
129
|
+
const isAuthorizationMessage = (message === null || message === void 0 ? void 0 : message.type) === 'authorization_response';
|
|
130
|
+
if (isAuthorizationMessage) {
|
|
131
|
+
logger.logger.debug('Message received', { data: message });
|
|
132
|
+
}
|
|
133
|
+
const isValidMessage = isAuthorizationMessage && (message === null || message === void 0 ? void 0 : message.provider) === provider;
|
|
134
|
+
// don't process imvalid messages for provider
|
|
135
|
+
if (!isValidMessage) {
|
|
136
|
+
return;
|
|
95
137
|
}
|
|
96
|
-
|
|
97
|
-
|
|
138
|
+
removeOAuthIFrame();
|
|
139
|
+
window.removeEventListener('message', handleAuthWindowMessage);
|
|
140
|
+
providersWaitingOauthMessages.current = Object.assign(Object.assign({}, providersWaitingOauthMessages.current), { [provider]: false });
|
|
141
|
+
const { code, error } = message;
|
|
142
|
+
if (error && error !== 'undefined') {
|
|
143
|
+
handleError(`Failed to link ${provider} social account: ${error}`);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (!code) {
|
|
147
|
+
handleError(`Failed to link ${provider} social account: no authorization code`);
|
|
98
148
|
return;
|
|
99
149
|
}
|
|
100
|
-
const { code } = event.data;
|
|
101
150
|
const jwt = yield api.verifyOAuth(environmentId, provider, {
|
|
102
151
|
code,
|
|
152
|
+
codeVerifier: verifier,
|
|
153
|
+
state,
|
|
103
154
|
}, String(userJwt));
|
|
104
155
|
if (!jwt) {
|
|
105
156
|
handleError(`Failed to link social account: ${provider}`);
|
|
@@ -108,18 +159,34 @@ const useSocialAccounts = () => {
|
|
|
108
159
|
yield updateUserProfileByJWT(jwt);
|
|
109
160
|
setIsProcessing(false);
|
|
110
161
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
162
|
+
const loginUrl = yield api.getOauthLoginUrl(environmentId, provider, String(userJwt));
|
|
163
|
+
if (!loginUrl) {
|
|
164
|
+
handleError(`Failed to get login url to link social account: ${provider}`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// we need to use an iframe to be the intermediary in communications between the popup and the sdk
|
|
168
|
+
// because of twitter limitations with accessing the window.opener and BroadcastChannel not working between
|
|
169
|
+
// different origins (our api redirect page and the app where the sdk is running)
|
|
170
|
+
const oauthIFrameUrl = `${getRedirectURIOrigin.getRedirectURIOrigin(loginUrl)}/sdkoauth`;
|
|
171
|
+
addOAuthIFrame(oauthIFrameUrl);
|
|
172
|
+
let oauthLoginUrl = loginUrl;
|
|
173
|
+
if (providersRequiringPkce.includes(provider)) {
|
|
174
|
+
const digest = yield digestSHA256.digestSHA256(verifier);
|
|
175
|
+
const pkceParams = stringifyURIQuery.stringifyURIQuery({
|
|
176
|
+
code_challenge: encodeBase64URL.encodeBase64URL(digest),
|
|
177
|
+
code_challenge_method: 'S256',
|
|
178
|
+
state: state,
|
|
179
|
+
});
|
|
180
|
+
oauthLoginUrl = `${loginUrl}&${pkceParams}`;
|
|
181
|
+
}
|
|
182
|
+
if (!((_b = providersWaitingOauthMessages.current) === null || _b === void 0 ? void 0 : _b[provider])) {
|
|
183
|
+
window.addEventListener('message', handleAuthWindowMessage);
|
|
184
|
+
providersWaitingOauthMessages.current = Object.assign(Object.assign({}, providersWaitingOauthMessages.current), { [provider]: true });
|
|
185
|
+
}
|
|
186
|
+
window.open(oauthLoginUrl, '_blank', 'width=500,height=600');
|
|
120
187
|
});
|
|
121
188
|
const unlinkSocialAccount = (provider) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
122
|
-
var
|
|
189
|
+
var _c;
|
|
123
190
|
setError(undefined);
|
|
124
191
|
setIsProcessing(true);
|
|
125
192
|
if (!checkValidProvider(provider)) {
|
|
@@ -133,7 +200,7 @@ const useSocialAccounts = () => {
|
|
|
133
200
|
try {
|
|
134
201
|
const jwt = yield api.unlinkOAuth({
|
|
135
202
|
environmentId,
|
|
136
|
-
verifiedCrentialId: (
|
|
203
|
+
verifiedCrentialId: (_c = verifiedCredential.id) !== null && _c !== void 0 ? _c : '',
|
|
137
204
|
}, String(userJwt));
|
|
138
205
|
if (!jwt) {
|
|
139
206
|
handleError(`Failed to unlink social account: ${provider} | ${verifiedCredential.id}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __awaiter } from '../../../../../_virtual/_tslib.js';
|
|
2
|
-
import { useState, useMemo } from 'react';
|
|
2
|
+
import { useState, useRef, useMemo } from 'react';
|
|
3
3
|
import { useInternalDynamicContext } from '../../../context/DynamicContext/useInternalDynamicContext.js';
|
|
4
|
-
import { unlinkOAuth, verifyOAuth } from '../../../data/api.js';
|
|
4
|
+
import { getOauthLoginUrl, unlinkOAuth, verifyOAuth } from '../../../data/api.js';
|
|
5
5
|
import { useUpdateUserProfileByJWTCallback } from '../useUpdateUserProfileByJWTCallback/useUpdateUserProfileByJWTCallback.js';
|
|
6
6
|
import '@dynamic-labs/sdk-api';
|
|
7
7
|
import { logger } from '../../../shared/logger.js';
|
|
@@ -19,6 +19,11 @@ import '@dynamic-labs/multi-wallet';
|
|
|
19
19
|
import { getAuthToken } from '../../functions/getAuthToken/getAuthToken.js';
|
|
20
20
|
import { getEnabledOAuthProviders } from '../../functions/getEnabledOAuthProviders/index.js';
|
|
21
21
|
import { isSocialKycEnabled } from '../../functions/isSocialKycEnabled/isSocialKycEnabled.js';
|
|
22
|
+
import { randomString } from '../../functions/randomString/randomString.js';
|
|
23
|
+
import { stringifyURIQuery } from '../../functions/stringifyURIQuery/stringifyURIQuery.js';
|
|
24
|
+
import { digestSHA256 } from '../../functions/digestSHA256/digestSHA256.js';
|
|
25
|
+
import { encodeBase64URL } from '../../functions/encodeBase64URL/encodeBase64URL.js';
|
|
26
|
+
import { getRedirectURIOrigin } from '../../functions/getRedirectURIOrigin/getRedirectURIOrigin.js';
|
|
22
27
|
|
|
23
28
|
const socialProviders = [
|
|
24
29
|
'discord',
|
|
@@ -29,12 +34,16 @@ const socialProviders = [
|
|
|
29
34
|
'twitch',
|
|
30
35
|
'twitter',
|
|
31
36
|
];
|
|
37
|
+
// pkce params are only required for twitter and break if added for other providers, like google
|
|
38
|
+
// so we should only add provider that support pkce to this list
|
|
39
|
+
const providersRequiringPkce = ['twitter', 'github'];
|
|
32
40
|
const useSocialAccounts = () => {
|
|
33
41
|
var _a;
|
|
34
42
|
const { environmentId, user, projectSettings, onboardingOnlyJwt } = useInternalDynamicContext();
|
|
35
43
|
const { updateUserProfileByJWT } = useUpdateUserProfileByJWTCallback();
|
|
36
44
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
37
45
|
const [error, setError] = useState();
|
|
46
|
+
const providersWaitingOauthMessages = useRef({});
|
|
38
47
|
const userJwt = (_a = getAuthToken()) !== null && _a !== void 0 ? _a : onboardingOnlyJwt;
|
|
39
48
|
const oauthProviders = getEnabledOAuthProviders(projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers);
|
|
40
49
|
const verifiedOAuthCredentialsMap = useMemo(() => {
|
|
@@ -53,6 +62,23 @@ const useSocialAccounts = () => {
|
|
|
53
62
|
setIsProcessing(false);
|
|
54
63
|
setError(message);
|
|
55
64
|
};
|
|
65
|
+
const addOAuthIFrame = (url) => {
|
|
66
|
+
const container = document.getElementById('oauth-iframe-container');
|
|
67
|
+
let oauthIFrame = document.getElementById('oauth-iframe');
|
|
68
|
+
if (!container || oauthIFrame) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
oauthIFrame = document.createElement('iframe');
|
|
72
|
+
oauthIFrame.setAttribute('id', 'oauth-iframe');
|
|
73
|
+
oauthIFrame.setAttribute('src', url);
|
|
74
|
+
container.appendChild(oauthIFrame);
|
|
75
|
+
};
|
|
76
|
+
const removeOAuthIFrame = () => {
|
|
77
|
+
const oauthIFrame = document.getElementById('oauth-iframe');
|
|
78
|
+
if (oauthIFrame) {
|
|
79
|
+
oauthIFrame.remove();
|
|
80
|
+
}
|
|
81
|
+
};
|
|
56
82
|
const checkValidProvider = (provider) => {
|
|
57
83
|
if (!provider) {
|
|
58
84
|
handleError('Provider is required');
|
|
@@ -64,38 +90,63 @@ const useSocialAccounts = () => {
|
|
|
64
90
|
}
|
|
65
91
|
return true;
|
|
66
92
|
};
|
|
67
|
-
const
|
|
68
|
-
setError(undefined);
|
|
69
|
-
setIsProcessing(true);
|
|
93
|
+
const checkValidOAuthLinking = (provider) => {
|
|
70
94
|
if (!isSocialKycEnabled(projectSettings)) {
|
|
71
95
|
handleError('Social linking is not enabled on the dashboard');
|
|
72
|
-
return;
|
|
96
|
+
return false;
|
|
73
97
|
}
|
|
74
98
|
if (!checkValidProvider(provider)) {
|
|
75
|
-
return;
|
|
99
|
+
return false;
|
|
76
100
|
}
|
|
77
101
|
const verifiedCredential = verifiedOAuthCredentialsMap[provider];
|
|
78
102
|
if (verifiedCredential) {
|
|
79
103
|
handleError(`Account already linked for provider: ${provider}`);
|
|
80
|
-
return;
|
|
104
|
+
return false;
|
|
81
105
|
}
|
|
82
106
|
const oauthProvider = oauthProviders.find((p) => p.provider === provider);
|
|
83
107
|
if (!oauthProvider) {
|
|
84
108
|
handleError(`Provider is not enabled on the dashboard: ${provider}`);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
};
|
|
113
|
+
const linkSocialAccount = (provider) => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
|
+
var _b;
|
|
115
|
+
setError(undefined);
|
|
116
|
+
setIsProcessing(true);
|
|
117
|
+
// invalid linking request
|
|
118
|
+
if (!checkValidOAuthLinking(provider)) {
|
|
85
119
|
return;
|
|
86
120
|
}
|
|
121
|
+
const state = randomString(8);
|
|
122
|
+
const verifier = randomString(43);
|
|
87
123
|
const handleAuthWindowMessage = (event) => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
124
|
+
const message = event.data;
|
|
125
|
+
const isAuthorizationMessage = (message === null || message === void 0 ? void 0 : message.type) === 'authorization_response';
|
|
126
|
+
if (isAuthorizationMessage) {
|
|
127
|
+
logger.debug('Message received', { data: message });
|
|
128
|
+
}
|
|
129
|
+
const isValidMessage = isAuthorizationMessage && (message === null || message === void 0 ? void 0 : message.provider) === provider;
|
|
130
|
+
// don't process imvalid messages for provider
|
|
131
|
+
if (!isValidMessage) {
|
|
132
|
+
return;
|
|
91
133
|
}
|
|
92
|
-
|
|
93
|
-
|
|
134
|
+
removeOAuthIFrame();
|
|
135
|
+
window.removeEventListener('message', handleAuthWindowMessage);
|
|
136
|
+
providersWaitingOauthMessages.current = Object.assign(Object.assign({}, providersWaitingOauthMessages.current), { [provider]: false });
|
|
137
|
+
const { code, error } = message;
|
|
138
|
+
if (error && error !== 'undefined') {
|
|
139
|
+
handleError(`Failed to link ${provider} social account: ${error}`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (!code) {
|
|
143
|
+
handleError(`Failed to link ${provider} social account: no authorization code`);
|
|
94
144
|
return;
|
|
95
145
|
}
|
|
96
|
-
const { code } = event.data;
|
|
97
146
|
const jwt = yield verifyOAuth(environmentId, provider, {
|
|
98
147
|
code,
|
|
148
|
+
codeVerifier: verifier,
|
|
149
|
+
state,
|
|
99
150
|
}, String(userJwt));
|
|
100
151
|
if (!jwt) {
|
|
101
152
|
handleError(`Failed to link social account: ${provider}`);
|
|
@@ -104,18 +155,34 @@ const useSocialAccounts = () => {
|
|
|
104
155
|
yield updateUserProfileByJWT(jwt);
|
|
105
156
|
setIsProcessing(false);
|
|
106
157
|
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
158
|
+
const loginUrl = yield getOauthLoginUrl(environmentId, provider, String(userJwt));
|
|
159
|
+
if (!loginUrl) {
|
|
160
|
+
handleError(`Failed to get login url to link social account: ${provider}`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// we need to use an iframe to be the intermediary in communications between the popup and the sdk
|
|
164
|
+
// because of twitter limitations with accessing the window.opener and BroadcastChannel not working between
|
|
165
|
+
// different origins (our api redirect page and the app where the sdk is running)
|
|
166
|
+
const oauthIFrameUrl = `${getRedirectURIOrigin(loginUrl)}/sdkoauth`;
|
|
167
|
+
addOAuthIFrame(oauthIFrameUrl);
|
|
168
|
+
let oauthLoginUrl = loginUrl;
|
|
169
|
+
if (providersRequiringPkce.includes(provider)) {
|
|
170
|
+
const digest = yield digestSHA256(verifier);
|
|
171
|
+
const pkceParams = stringifyURIQuery({
|
|
172
|
+
code_challenge: encodeBase64URL(digest),
|
|
173
|
+
code_challenge_method: 'S256',
|
|
174
|
+
state: state,
|
|
175
|
+
});
|
|
176
|
+
oauthLoginUrl = `${loginUrl}&${pkceParams}`;
|
|
177
|
+
}
|
|
178
|
+
if (!((_b = providersWaitingOauthMessages.current) === null || _b === void 0 ? void 0 : _b[provider])) {
|
|
179
|
+
window.addEventListener('message', handleAuthWindowMessage);
|
|
180
|
+
providersWaitingOauthMessages.current = Object.assign(Object.assign({}, providersWaitingOauthMessages.current), { [provider]: true });
|
|
181
|
+
}
|
|
182
|
+
window.open(oauthLoginUrl, '_blank', 'width=500,height=600');
|
|
116
183
|
});
|
|
117
184
|
const unlinkSocialAccount = (provider) => __awaiter(void 0, void 0, void 0, function* () {
|
|
118
|
-
var
|
|
185
|
+
var _c;
|
|
119
186
|
setError(undefined);
|
|
120
187
|
setIsProcessing(true);
|
|
121
188
|
if (!checkValidProvider(provider)) {
|
|
@@ -129,7 +196,7 @@ const useSocialAccounts = () => {
|
|
|
129
196
|
try {
|
|
130
197
|
const jwt = yield unlinkOAuth({
|
|
131
198
|
environmentId,
|
|
132
|
-
verifiedCrentialId: (
|
|
199
|
+
verifiedCrentialId: (_c = verifiedCredential.id) !== null && _c !== void 0 ? _c : '',
|
|
133
200
|
}, String(userJwt));
|
|
134
201
|
if (!jwt) {
|
|
135
202
|
handleError(`Failed to unlink social account: ${provider} | ${verifiedCredential.id}`);
|
|
@@ -53,12 +53,13 @@ var SelectNetworkButton = require('../../components/SelectNetworkButton/SelectNe
|
|
|
53
53
|
var useApplyWalletConnectorNetwork = require('../../utils/hooks/useApplyWalletConnectorNetwork/useApplyWalletConnectorNetwork.cjs');
|
|
54
54
|
|
|
55
55
|
const NetworkNotSupported = () => {
|
|
56
|
-
const { network, onboardingImageUrl, selectedWalletConnector: walletConnector, connectedWallets, primaryWallet, isFullyConnected, setShowAuthFlow, } = useInternalDynamicContext.useInternalDynamicContext();
|
|
56
|
+
const { network, onboardingImageUrl, selectedWalletConnector: walletConnector, connectedWallets, primaryWallet, isFullyConnected, setShowAuthFlow, walletsToConnectByChain, } = useInternalDynamicContext.useInternalDynamicContext();
|
|
57
57
|
// Refresh selectedWalletConnector network when primaryWallet or connectedWallets updates
|
|
58
58
|
const { data: walletConnectorNetwork } = usePromise.usePromise(() => walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.getNetwork(), { deps: [primaryWallet, walletConnector, connectedWallets] });
|
|
59
59
|
const finishConnectAndSign = useConnectAndSign.useConnectAndSign({
|
|
60
60
|
shouldCallCallback: false,
|
|
61
|
-
shouldUpdateWallets: !isFullyConnected
|
|
61
|
+
shouldUpdateWallets: !isFullyConnected ||
|
|
62
|
+
(isFullyConnected && Boolean(walletsToConnectByChain === null || walletsToConnectByChain === void 0 ? void 0 : walletsToConnectByChain.length)),
|
|
62
63
|
});
|
|
63
64
|
const [isNetworkPickerOpen, setIsNetworkPickerOpen] = React.useState(false);
|
|
64
65
|
// Finishes auth flow when wallet switches to proper network
|
|
@@ -49,12 +49,13 @@ import { SelectNetworkButton } from '../../components/SelectNetworkButton/Select
|
|
|
49
49
|
import { useApplyWalletConnectorNetwork } from '../../utils/hooks/useApplyWalletConnectorNetwork/useApplyWalletConnectorNetwork.js';
|
|
50
50
|
|
|
51
51
|
const NetworkNotSupported = () => {
|
|
52
|
-
const { network, onboardingImageUrl, selectedWalletConnector: walletConnector, connectedWallets, primaryWallet, isFullyConnected, setShowAuthFlow, } = useInternalDynamicContext();
|
|
52
|
+
const { network, onboardingImageUrl, selectedWalletConnector: walletConnector, connectedWallets, primaryWallet, isFullyConnected, setShowAuthFlow, walletsToConnectByChain, } = useInternalDynamicContext();
|
|
53
53
|
// Refresh selectedWalletConnector network when primaryWallet or connectedWallets updates
|
|
54
54
|
const { data: walletConnectorNetwork } = usePromise(() => walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.getNetwork(), { deps: [primaryWallet, walletConnector, connectedWallets] });
|
|
55
55
|
const finishConnectAndSign = useConnectAndSign({
|
|
56
56
|
shouldCallCallback: false,
|
|
57
|
-
shouldUpdateWallets: !isFullyConnected
|
|
57
|
+
shouldUpdateWallets: !isFullyConnected ||
|
|
58
|
+
(isFullyConnected && Boolean(walletsToConnectByChain === null || walletsToConnectByChain === void 0 ? void 0 : walletsToConnectByChain.length)),
|
|
58
59
|
});
|
|
59
60
|
const [isNetworkPickerOpen, setIsNetworkPickerOpen] = useState(false);
|
|
60
61
|
// Finishes auth flow when wallet switches to proper network
|
|
@@ -54,14 +54,15 @@ var useApplyWalletConnectorNetwork = require('../../utils/hooks/useApplyWalletCo
|
|
|
54
54
|
// as the wallet does not support programmatic network change.
|
|
55
55
|
const NetworkNotSupportedSwitchManual = () => {
|
|
56
56
|
var _a, _b;
|
|
57
|
-
const { user, selectedWalletConnector: walletConnector, connectedWallets, isFullyConnected, setShowAuthFlow, } = useInternalDynamicContext.useInternalDynamicContext();
|
|
57
|
+
const { user, selectedWalletConnector: walletConnector, connectedWallets, isFullyConnected, setShowAuthFlow, walletsToConnectByChain, } = useInternalDynamicContext.useInternalDynamicContext();
|
|
58
58
|
// Refresh selectedWalletConnector network when primaryWallet or connectedWallets updates
|
|
59
59
|
const { data: walletConnectorNetwork } = usePromise.usePromise(() => walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.getNetwork(), {
|
|
60
60
|
deps: [walletConnector, connectedWallets],
|
|
61
61
|
});
|
|
62
62
|
const finishConnectAndSign = useConnectAndSign.useConnectAndSign({
|
|
63
63
|
shouldCallCallback: false,
|
|
64
|
-
shouldUpdateWallets: !isFullyConnected
|
|
64
|
+
shouldUpdateWallets: !isFullyConnected ||
|
|
65
|
+
(isFullyConnected && Boolean(walletsToConnectByChain === null || walletsToConnectByChain === void 0 ? void 0 : walletsToConnectByChain.length)),
|
|
65
66
|
});
|
|
66
67
|
// Finishes auth flow when wallet switches to proper network
|
|
67
68
|
React.useEffect(() => {
|
|
@@ -50,14 +50,15 @@ import { useApplyWalletConnectorNetwork } from '../../utils/hooks/useApplyWallet
|
|
|
50
50
|
// as the wallet does not support programmatic network change.
|
|
51
51
|
const NetworkNotSupportedSwitchManual = () => {
|
|
52
52
|
var _a, _b;
|
|
53
|
-
const { user, selectedWalletConnector: walletConnector, connectedWallets, isFullyConnected, setShowAuthFlow, } = useInternalDynamicContext();
|
|
53
|
+
const { user, selectedWalletConnector: walletConnector, connectedWallets, isFullyConnected, setShowAuthFlow, walletsToConnectByChain, } = useInternalDynamicContext();
|
|
54
54
|
// Refresh selectedWalletConnector network when primaryWallet or connectedWallets updates
|
|
55
55
|
const { data: walletConnectorNetwork } = usePromise(() => walletConnector === null || walletConnector === void 0 ? void 0 : walletConnector.getNetwork(), {
|
|
56
56
|
deps: [walletConnector, connectedWallets],
|
|
57
57
|
});
|
|
58
58
|
const finishConnectAndSign = useConnectAndSign({
|
|
59
59
|
shouldCallCallback: false,
|
|
60
|
-
shouldUpdateWallets: !isFullyConnected
|
|
60
|
+
shouldUpdateWallets: !isFullyConnected ||
|
|
61
|
+
(isFullyConnected && Boolean(walletsToConnectByChain === null || walletsToConnectByChain === void 0 ? void 0 : walletsToConnectByChain.length)),
|
|
61
62
|
});
|
|
62
63
|
// Finishes auth flow when wallet switches to proper network
|
|
63
64
|
useEffect(() => {
|
|
@@ -18,7 +18,10 @@ const useFetchCurrency = (connector, network) => {
|
|
|
18
18
|
setCurrency(chainInfo === null || chainInfo === void 0 ? void 0 : chainInfo.symbol);
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
const
|
|
21
|
+
const network = connector.connectedChain === 'STARK'
|
|
22
|
+
? 'starknetNetworks'
|
|
23
|
+
: 'evmNetworks';
|
|
24
|
+
const result = (_b = connector[network]) === null || _b === void 0 ? void 0 : _b.find((element) => element.chainId === chainId);
|
|
22
25
|
setCurrency((_d = (_c = result === null || result === void 0 ? void 0 : result.nativeCurrency) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : chainInfo === null || chainInfo === void 0 ? void 0 : chainInfo.symbol);
|
|
23
26
|
return [currency];
|
|
24
27
|
});
|
|
@@ -14,7 +14,10 @@ const useFetchCurrency = (connector, network) => {
|
|
|
14
14
|
setCurrency(chainInfo === null || chainInfo === void 0 ? void 0 : chainInfo.symbol);
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
const
|
|
17
|
+
const network = connector.connectedChain === 'STARK'
|
|
18
|
+
? 'starknetNetworks'
|
|
19
|
+
: 'evmNetworks';
|
|
20
|
+
const result = (_b = connector[network]) === null || _b === void 0 ? void 0 : _b.find((element) => element.chainId === chainId);
|
|
18
21
|
setCurrency((_d = (_c = result === null || result === void 0 ? void 0 : result.nativeCurrency) === null || _c === void 0 ? void 0 : _c.symbol) !== null && _d !== void 0 ? _d : chainInfo === null || chainInfo === void 0 ? void 0 : chainInfo.symbol);
|
|
19
22
|
return [currency];
|
|
20
23
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
// we need to use an iframe to be the intermediary in communications between the oauth popup and the sdk
|
|
8
|
+
// because of twitter limitations with accessing the window.opener and BroadcastChannel not working between
|
|
9
|
+
// different origins (our api redirect page and the app where the sdk is running)
|
|
10
|
+
// https://linear.app/dynamic-labs/issue/GVTY-17/[frontend]-fix-twitter-linking
|
|
11
|
+
const OAuthIFrameContainer = () => (jsxRuntime.jsx("div", { id: 'oauth-iframe-container', "data-testid": 'oauth-iframe-container', style: { height: 0, visibility: 'hidden', width: 0 } }));
|
|
12
|
+
|
|
13
|
+
exports.OAuthIFrameContainer = OAuthIFrameContainer;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// we need to use an iframe to be the intermediary in communications between the oauth popup and the sdk
|
|
4
|
+
// because of twitter limitations with accessing the window.opener and BroadcastChannel not working between
|
|
5
|
+
// different origins (our api redirect page and the app where the sdk is running)
|
|
6
|
+
// https://linear.app/dynamic-labs/issue/GVTY-17/[frontend]-fix-twitter-linking
|
|
7
|
+
const OAuthIFrameContainer = () => (jsx("div", { id: 'oauth-iframe-container', "data-testid": 'oauth-iframe-container', style: { height: 0, visibility: 'hidden', width: 0 } }));
|
|
8
|
+
|
|
9
|
+
export { OAuthIFrameContainer };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { OAuthIFrameContainer } from './OAuthIFrameContainer';
|