@dynamic-labs/utils 3.0.0-alpha.13 → 3.0.0-alpha.14
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 +37 -0
- package/package.json +3 -3
- package/src/errors/WalletAddressMismatchError.cjs +17 -0
- package/src/errors/WalletAddressMismatchError.d.ts +11 -0
- package/src/errors/WalletAddressMismatchError.js +13 -0
- package/src/errors/index.d.ts +1 -0
- package/src/handleMobileWalletRedirect/handleMobileWalletRedirect.cjs +3 -0
- package/src/handleMobileWalletRedirect/handleMobileWalletRedirect.js +3 -0
- package/src/index.cjs +6 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +3 -0
- package/src/retryableFn.cjs +3 -0
- package/src/retryableFn.js +3 -0
- package/src/services/Oauth2Service/Oauth2Service.cjs +34 -0
- package/src/services/Oauth2Service/Oauth2Service.d.ts +30 -0
- package/src/services/Oauth2Service/Oauth2Service.js +30 -0
- package/src/services/Oauth2Service/createWindowOauth2Service/createWindowOauth2Service.cjs +170 -0
- package/src/services/Oauth2Service/createWindowOauth2Service/createWindowOauth2Service.d.ts +2 -0
- package/src/services/Oauth2Service/createWindowOauth2Service/createWindowOauth2Service.js +166 -0
- package/src/services/Oauth2Service/createWindowOauth2Service/index.d.ts +1 -0
- package/src/services/Oauth2Service/index.d.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,41 @@
|
|
|
1
1
|
|
|
2
|
+
## [3.0.0-alpha.14](https://github.com/dynamic-labs/DynamicAuth/compare/v3.0.0-alpha.13...v3.0.0-alpha.14) (2024-07-09)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### ⚠ BREAKING CHANGES
|
|
6
|
+
|
|
7
|
+
* remove setPrimaryWallet in favor of useSwitchWallet (#6212)
|
|
8
|
+
* move getBalance method to wallet so it can be fetched for any wallet not just the active one (#6200)
|
|
9
|
+
* make Wallet a class instead of just a type (#6094)
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add @dynamic-labs/solana-extension ([#6140](https://github.com/dynamic-labs/DynamicAuth/issues/6140)) ([c0e2a06](https://github.com/dynamic-labs/DynamicAuth/commit/c0e2a067dd83163094b58a15696df8654da47c65))
|
|
14
|
+
* add solana support for multi-asset ([#6222](https://github.com/dynamic-labs/DynamicAuth/issues/6222)) ([9660d79](https://github.com/dynamic-labs/DynamicAuth/commit/9660d7962f1fb01011d68397bb367fdfc5335ca9))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* allow closing re-connect wallet modal ([#6250](https://github.com/dynamic-labs/DynamicAuth/issues/6250)) ([55ba25b](https://github.com/dynamic-labs/DynamicAuth/commit/55ba25bd3e907629aaa26e788885bfa38f8fe350))
|
|
20
|
+
* move getBalance method to wallet so it can be fetched for any wallet not just the active one ([#6200](https://github.com/dynamic-labs/DynamicAuth/issues/6200)) ([ee94773](https://github.com/dynamic-labs/DynamicAuth/commit/ee94773df9b31462a325666760fcf1fc70dec68a))
|
|
21
|
+
* move getNameService method to wallet so name service data can be fetched for any wallet ([#6205](https://github.com/dynamic-labs/DynamicAuth/issues/6205)) ([6671ae9](https://github.com/dynamic-labs/DynamicAuth/commit/6671ae92532ffc1889e24519e75f47d336ac0da6))
|
|
22
|
+
* relax phone number length validation ([#6226](https://github.com/dynamic-labs/DynamicAuth/issues/6226)) ([f0969b4](https://github.com/dynamic-labs/DynamicAuth/commit/f0969b4fbdafde07125cddecb16b4bfd011ea65e))
|
|
23
|
+
* sdkHasLoaded flipping back to false with otp ([#6242](https://github.com/dynamic-labs/DynamicAuth/issues/6242)) ([32ad9dd](https://github.com/dynamic-labs/DynamicAuth/commit/32ad9dd2dae7775f494506773fb343fe1a249c65))
|
|
24
|
+
* send transaction demo undefined address/value ([#6248](https://github.com/dynamic-labs/DynamicAuth/issues/6248)) ([036a511](https://github.com/dynamic-labs/DynamicAuth/commit/036a511fb848ef461edd9b7a5d79d478b0f1cf23))
|
|
25
|
+
* set last active account on accountChange request ([#6218](https://github.com/dynamic-labs/DynamicAuth/issues/6218)) ([05797d2](https://github.com/dynamic-labs/DynamicAuth/commit/05797d292aab8b4de02555594d4d1bbd4c9543eb))
|
|
26
|
+
* show ledger toggle when linking wallet ([#6202](https://github.com/dynamic-labs/DynamicAuth/issues/6202)) ([a449c0b](https://github.com/dynamic-labs/DynamicAuth/commit/a449c0bfc4e3a75ccd7084b930c48fbd6c14f691))
|
|
27
|
+
* show user wallet in profile view on single wallet mode even if it's not primary ([#6187](https://github.com/dynamic-labs/DynamicAuth/issues/6187)) ([ffaaeb2](https://github.com/dynamic-labs/DynamicAuth/commit/ffaaeb2c6cbb2868a381d85451ae5574024156bb))
|
|
28
|
+
* stop auto-switching to connected secondary wallet if primary wallet is not connected ([#6196](https://github.com/dynamic-labs/DynamicAuth/issues/6196)) ([4e8bcd2](https://github.com/dynamic-labs/DynamicAuth/commit/4e8bcd2d02d3fca54a0ed29c45b386ae99266b84))
|
|
29
|
+
* stop coinbase and solflare popups when secondary ([#6225](https://github.com/dynamic-labs/DynamicAuth/issues/6225)) ([7e9c104](https://github.com/dynamic-labs/DynamicAuth/commit/7e9c1049a09c9fd513c9a2a746d6baac916f1bf4))
|
|
30
|
+
* stop sending double sign request on network switch ([e325709](https://github.com/dynamic-labs/DynamicAuth/commit/e325709bb5d2d1331fe16cc705398fc7b1cc292a))
|
|
31
|
+
* tunrkey solana signer accept uint8array message ([#6137](https://github.com/dynamic-labs/DynamicAuth/issues/6137)) ([70f89ce](https://github.com/dynamic-labs/DynamicAuth/commit/70f89ce0dafa4c99b318c9c5adce59083cd6d284))
|
|
32
|
+
* update formatting of phantom bitcoin publickey ([#6210](https://github.com/dynamic-labs/DynamicAuth/issues/6210)) ([f58cea9](https://github.com/dynamic-labs/DynamicAuth/commit/f58cea99333fd7c6af8f56f637ee32f1f7ce8d76))
|
|
33
|
+
* use white color in farcaster qr code when in dark mode ([#6245](https://github.com/dynamic-labs/DynamicAuth/issues/6245)) ([a91958d](https://github.com/dynamic-labs/DynamicAuth/commit/a91958d8773be138da8f54791c4c67866257bbad))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
* make Wallet a class instead of just a type ([#6094](https://github.com/dynamic-labs/DynamicAuth/issues/6094)) ([6dc4672](https://github.com/dynamic-labs/DynamicAuth/commit/6dc4672951cfadc22a6c569e74eae3485bd472f3))
|
|
37
|
+
* remove setPrimaryWallet in favor of useSwitchWallet ([#6212](https://github.com/dynamic-labs/DynamicAuth/issues/6212)) ([de125e1](https://github.com/dynamic-labs/DynamicAuth/commit/de125e1ebbc20507e4ec07f337f5f5fd13aabcbe))
|
|
38
|
+
|
|
2
39
|
## [3.0.0-alpha.13](https://github.com/dynamic-labs/DynamicAuth/compare/v3.0.0-alpha.12...v3.0.0-alpha.13) (2024-06-27)
|
|
3
40
|
|
|
4
41
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/utils",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.14",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/dynamic-labs/dynamic-auth.git",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@dynamic-labs/sdk-api-core": "0.0.470",
|
|
30
30
|
"tldts": "6.0.16",
|
|
31
|
-
"@dynamic-labs/logger": "3.0.0-alpha.
|
|
32
|
-
"@dynamic-labs/types": "3.0.0-alpha.
|
|
31
|
+
"@dynamic-labs/logger": "3.0.0-alpha.14",
|
|
32
|
+
"@dynamic-labs/types": "3.0.0-alpha.14",
|
|
33
33
|
"buffer": "6.0.3",
|
|
34
34
|
"stream": "0.0.2"
|
|
35
35
|
},
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var DynamicError = require('./DynamicError.cjs');
|
|
7
|
+
|
|
8
|
+
class WalletAddressMismatchError extends DynamicError.DynamicError {
|
|
9
|
+
constructor(message, { activeAddress, expectedAddress, walletName, }) {
|
|
10
|
+
super(message, 'wallet_address_mismatch_error');
|
|
11
|
+
this.expectedAddress = expectedAddress;
|
|
12
|
+
this.activeAddress = activeAddress;
|
|
13
|
+
this.walletName = walletName;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.WalletAddressMismatchError = WalletAddressMismatchError;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DynamicError } from './DynamicError';
|
|
2
|
+
export declare class WalletAddressMismatchError extends DynamicError {
|
|
3
|
+
expectedAddress: string | undefined;
|
|
4
|
+
activeAddress: string | undefined;
|
|
5
|
+
walletName: string | undefined;
|
|
6
|
+
constructor(message: string, { activeAddress, expectedAddress, walletName, }: {
|
|
7
|
+
activeAddress?: string;
|
|
8
|
+
expectedAddress?: string;
|
|
9
|
+
walletName?: string;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { DynamicError } from './DynamicError.js';
|
|
3
|
+
|
|
4
|
+
class WalletAddressMismatchError extends DynamicError {
|
|
5
|
+
constructor(message, { activeAddress, expectedAddress, walletName, }) {
|
|
6
|
+
super(message, 'wallet_address_mismatch_error');
|
|
7
|
+
this.expectedAddress = expectedAddress;
|
|
8
|
+
this.activeAddress = activeAddress;
|
|
9
|
+
this.walletName = walletName;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { WalletAddressMismatchError };
|
package/src/errors/index.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ var isMobile = require('../isMobile.cjs');
|
|
|
10
10
|
require('../../_virtual/_tslib.cjs');
|
|
11
11
|
require('../bufferPolyfill.cjs');
|
|
12
12
|
require('tldts');
|
|
13
|
+
require('../services/Oauth2Service/Oauth2Service.cjs');
|
|
14
|
+
require('@dynamic-labs/types');
|
|
15
|
+
require('@dynamic-labs/sdk-api-core');
|
|
13
16
|
|
|
14
17
|
const handleMobileWalletRedirect = ({ nativeLink, universalLink, }) => {
|
|
15
18
|
const url = encodeURIComponent(window.location.toString());
|
|
@@ -6,6 +6,9 @@ import { isSamsungBrowser } from '../isMobile.js';
|
|
|
6
6
|
import '../../_virtual/_tslib.js';
|
|
7
7
|
import '../bufferPolyfill.js';
|
|
8
8
|
import 'tldts';
|
|
9
|
+
import '../services/Oauth2Service/Oauth2Service.js';
|
|
10
|
+
import '@dynamic-labs/types';
|
|
11
|
+
import '@dynamic-labs/sdk-api-core';
|
|
9
12
|
|
|
10
13
|
const handleMobileWalletRedirect = ({ nativeLink, universalLink, }) => {
|
|
11
14
|
const url = encodeURIComponent(window.location.toString());
|
package/src/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ var AccessBlockedError = require('./errors/AccessBlockedError.cjs');
|
|
|
36
36
|
var EmbeddedWalletException = require('./errors/EmbeddedWalletException.cjs');
|
|
37
37
|
var MfaInvalidOtpError = require('./errors/MfaInvalidOtpError.cjs');
|
|
38
38
|
var ExternalAuthError = require('./errors/ExternalAuthError.cjs');
|
|
39
|
+
var WalletAddressMismatchError = require('./errors/WalletAddressMismatchError.cjs');
|
|
39
40
|
var CancellablePromise = require('./CancellablePromise/CancellablePromise.cjs');
|
|
40
41
|
var isFunction = require('./isFunction/isFunction.cjs');
|
|
41
42
|
var isMobile = require('./isMobile.cjs');
|
|
@@ -60,6 +61,8 @@ var runSafe = require('./runSafe/runSafe.cjs');
|
|
|
60
61
|
var PlatformService = require('./services/PlatformService/PlatformService.cjs');
|
|
61
62
|
var createBrowserPlatformService = require('./services/PlatformService/createBrowserPlatformService/createBrowserPlatformService.cjs');
|
|
62
63
|
var FetchService = require('./services/FetchService/FetchService.cjs');
|
|
64
|
+
var Oauth2Service = require('./services/Oauth2Service/Oauth2Service.cjs');
|
|
65
|
+
var createWindowOauth2Service = require('./services/Oauth2Service/createWindowOauth2Service/createWindowOauth2Service.cjs');
|
|
63
66
|
var template = require('./template/template.cjs');
|
|
64
67
|
var get = require('./get/get.cjs');
|
|
65
68
|
var hexToString = require('./hexToString/hexToString.cjs');
|
|
@@ -100,6 +103,7 @@ exports.AccessBlockedError = AccessBlockedError.AccessBlockedError;
|
|
|
100
103
|
exports.EmbeddedWalletException = EmbeddedWalletException.EmbeddedWalletException;
|
|
101
104
|
exports.MfaInvalidOtpError = MfaInvalidOtpError.MfaInvalidOtpError;
|
|
102
105
|
exports.ExternalAuthError = ExternalAuthError.ExternalAuthError;
|
|
106
|
+
exports.WalletAddressMismatchError = WalletAddressMismatchError.WalletAddressMismatchError;
|
|
103
107
|
exports.CancellablePromise = CancellablePromise.CancellablePromise;
|
|
104
108
|
exports.isFunction = isFunction.isFunction;
|
|
105
109
|
exports.getAndroidVersion = isMobile.getAndroidVersion;
|
|
@@ -137,6 +141,8 @@ exports.runSafe = runSafe.runSafe;
|
|
|
137
141
|
exports.PlatformService = PlatformService.PlatformService;
|
|
138
142
|
exports.createBrowserPlatformService = createBrowserPlatformService.createBrowserPlatformService;
|
|
139
143
|
exports.FetchService = FetchService.FetchService;
|
|
144
|
+
exports.Oauth2Service = Oauth2Service.Oauth2Service;
|
|
145
|
+
exports.createWindowOauth2Service = createWindowOauth2Service.createWindowOauth2Service;
|
|
140
146
|
exports.template = template.template;
|
|
141
147
|
exports.get = get.get;
|
|
142
148
|
exports.hexToString = hexToString.hexToString;
|
package/src/index.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export * from './eip6963';
|
|
|
24
24
|
export { runSafe } from './runSafe';
|
|
25
25
|
export { PlatformService, createBrowserPlatformService, type IPlatformService, } from './services/PlatformService';
|
|
26
26
|
export { FetchService } from './services/FetchService';
|
|
27
|
+
export { Oauth2Service, type GetOauthCodeError, type GetOauthCodeProps, type IOauth2Service, createWindowOauth2Service, } from './services/Oauth2Service';
|
|
27
28
|
export { template } from './template';
|
|
28
29
|
export { get } from './get';
|
|
29
30
|
export { hexToString } from './hexToString';
|
package/src/index.js
CHANGED
|
@@ -32,6 +32,7 @@ export { AccessBlockedError } from './errors/AccessBlockedError.js';
|
|
|
32
32
|
export { EmbeddedWalletException } from './errors/EmbeddedWalletException.js';
|
|
33
33
|
export { MfaInvalidOtpError } from './errors/MfaInvalidOtpError.js';
|
|
34
34
|
export { ExternalAuthError } from './errors/ExternalAuthError.js';
|
|
35
|
+
export { WalletAddressMismatchError } from './errors/WalletAddressMismatchError.js';
|
|
35
36
|
export { CancellablePromise } from './CancellablePromise/CancellablePromise.js';
|
|
36
37
|
export { isFunction } from './isFunction/isFunction.js';
|
|
37
38
|
export { getAndroidVersion, isAndroid, isIOS, isIPad, isIPhone, isIPhone8OrEarlier, isLegacySafari, isMobile, isSamsungBrowser, isWindows } from './isMobile.js';
|
|
@@ -56,6 +57,8 @@ export { runSafe } from './runSafe/runSafe.js';
|
|
|
56
57
|
export { PlatformService } from './services/PlatformService/PlatformService.js';
|
|
57
58
|
export { createBrowserPlatformService } from './services/PlatformService/createBrowserPlatformService/createBrowserPlatformService.js';
|
|
58
59
|
export { FetchService } from './services/FetchService/FetchService.js';
|
|
60
|
+
export { Oauth2Service } from './services/Oauth2Service/Oauth2Service.js';
|
|
61
|
+
export { createWindowOauth2Service } from './services/Oauth2Service/createWindowOauth2Service/createWindowOauth2Service.js';
|
|
59
62
|
export { template } from './template/template.js';
|
|
60
63
|
export { get } from './get/get.js';
|
|
61
64
|
export { hexToString } from './hexToString/hexToString.js';
|
package/src/retryableFn.cjs
CHANGED
|
@@ -10,6 +10,9 @@ require('./logger/logger.cjs');
|
|
|
10
10
|
require('./bufferPolyfill.cjs');
|
|
11
11
|
var sleep = require('./sleep/sleep.cjs');
|
|
12
12
|
require('tldts');
|
|
13
|
+
require('./services/Oauth2Service/Oauth2Service.cjs');
|
|
14
|
+
require('@dynamic-labs/types');
|
|
15
|
+
require('@dynamic-labs/sdk-api-core');
|
|
13
16
|
|
|
14
17
|
const FALLBACK_UNDEFINED = 'FALLBACK_UNDEFINED';
|
|
15
18
|
const retryableFn = (fn_1, ...args_1) => _tslib.__awaiter(void 0, [fn_1, ...args_1], void 0, function* (fn, options = {}) {
|
package/src/retryableFn.js
CHANGED
|
@@ -6,6 +6,9 @@ import './logger/logger.js';
|
|
|
6
6
|
import './bufferPolyfill.js';
|
|
7
7
|
import { sleep } from './sleep/sleep.js';
|
|
8
8
|
import 'tldts';
|
|
9
|
+
import './services/Oauth2Service/Oauth2Service.js';
|
|
10
|
+
import '@dynamic-labs/types';
|
|
11
|
+
import '@dynamic-labs/sdk-api-core';
|
|
9
12
|
|
|
10
13
|
const FALLBACK_UNDEFINED = 'FALLBACK_UNDEFINED';
|
|
11
14
|
const retryableFn = (fn_1, ...args_1) => __awaiter(void 0, [fn_1, ...args_1], void 0, function* (fn, options = {}) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var types = require('@dynamic-labs/types');
|
|
7
|
+
var createWindowOauth2Service = require('./createWindowOauth2Service/createWindowOauth2Service.cjs');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Class implementing the fetch service with a configurable fetch implementation.
|
|
11
|
+
*/
|
|
12
|
+
class Oauth2Service {
|
|
13
|
+
static get implementation() {
|
|
14
|
+
if (!Oauth2Service._implementation) {
|
|
15
|
+
return createWindowOauth2Service.createWindowOauth2Service();
|
|
16
|
+
}
|
|
17
|
+
return Oauth2Service._implementation;
|
|
18
|
+
}
|
|
19
|
+
static setImplementation(implementation) {
|
|
20
|
+
Oauth2Service._implementation = implementation;
|
|
21
|
+
}
|
|
22
|
+
static get getOauthCode() {
|
|
23
|
+
return Oauth2Service.implementation.getOauthCode;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
Oauth2Service.isGetOauthCodeError = (error) => error === 'user-cancelled' ||
|
|
28
|
+
(typeof error === 'object' &&
|
|
29
|
+
'code' in error &&
|
|
30
|
+
Object.values(types.SocialOAuthErrorCode).includes(error.code) &&
|
|
31
|
+
'message' in error &&
|
|
32
|
+
typeof error.message === 'string');
|
|
33
|
+
|
|
34
|
+
exports.Oauth2Service = Oauth2Service;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { OauthResultResponse, Provider, ProviderEnum } from '@dynamic-labs/sdk-api-core';
|
|
2
|
+
import { SocialOAuthErrorCode } from '@dynamic-labs/types';
|
|
3
|
+
export type GetOauthCodeProps = {
|
|
4
|
+
provider: ProviderEnum;
|
|
5
|
+
apiProvider: Provider | undefined;
|
|
6
|
+
setIsProcessing: (value: boolean) => void;
|
|
7
|
+
onSettled?: VoidFunction;
|
|
8
|
+
getOAuthResultFromApi: () => Promise<OauthResultResponse | undefined>;
|
|
9
|
+
state: string;
|
|
10
|
+
oauthLoginUrl: URL;
|
|
11
|
+
sessionTimeout: number;
|
|
12
|
+
isMobile?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type IOauth2Service = {
|
|
15
|
+
getOauthCode: (props: GetOauthCodeProps) => Promise<string>;
|
|
16
|
+
};
|
|
17
|
+
export type GetOauthCodeError = 'user-cancelled' | {
|
|
18
|
+
code: SocialOAuthErrorCode;
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Class implementing the fetch service with a configurable fetch implementation.
|
|
23
|
+
*/
|
|
24
|
+
export declare class Oauth2Service {
|
|
25
|
+
static _implementation: IOauth2Service;
|
|
26
|
+
static get implementation(): IOauth2Service;
|
|
27
|
+
static setImplementation(implementation: IOauth2Service): void;
|
|
28
|
+
static get getOauthCode(): (props: GetOauthCodeProps) => Promise<string>;
|
|
29
|
+
static isGetOauthCodeError: (error: any) => error is GetOauthCodeError;
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { SocialOAuthErrorCode } from '@dynamic-labs/types';
|
|
3
|
+
import { createWindowOauth2Service } from './createWindowOauth2Service/createWindowOauth2Service.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Class implementing the fetch service with a configurable fetch implementation.
|
|
7
|
+
*/
|
|
8
|
+
class Oauth2Service {
|
|
9
|
+
static get implementation() {
|
|
10
|
+
if (!Oauth2Service._implementation) {
|
|
11
|
+
return createWindowOauth2Service();
|
|
12
|
+
}
|
|
13
|
+
return Oauth2Service._implementation;
|
|
14
|
+
}
|
|
15
|
+
static setImplementation(implementation) {
|
|
16
|
+
Oauth2Service._implementation = implementation;
|
|
17
|
+
}
|
|
18
|
+
static get getOauthCode() {
|
|
19
|
+
return Oauth2Service.implementation.getOauthCode;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
Oauth2Service.isGetOauthCodeError = (error) => error === 'user-cancelled' ||
|
|
24
|
+
(typeof error === 'object' &&
|
|
25
|
+
'code' in error &&
|
|
26
|
+
Object.values(SocialOAuthErrorCode).includes(error.code) &&
|
|
27
|
+
'message' in error &&
|
|
28
|
+
typeof error.message === 'string');
|
|
29
|
+
|
|
30
|
+
export { Oauth2Service };
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var _tslib = require('../../../../_virtual/_tslib.cjs');
|
|
7
|
+
var types = require('@dynamic-labs/types');
|
|
8
|
+
var sdkApiCore = require('@dynamic-labs/sdk-api-core');
|
|
9
|
+
var logger = require('../../../logger/logger.cjs');
|
|
10
|
+
|
|
11
|
+
const providersWithoutWindowOpenerReference = ['twitter'];
|
|
12
|
+
let authWindowInterval;
|
|
13
|
+
const createWindowOauth2Service = () => ({
|
|
14
|
+
getOauthCode: ({ apiProvider, provider, setIsProcessing, state, oauthLoginUrl, getOAuthResultFromApi, sessionTimeout, isMobile, onSettled, }) => new Promise((resolve, _reject) => {
|
|
15
|
+
// When we catch this error we assume it follows this type, so we must enforce it
|
|
16
|
+
// here to ensure the assumption is correct
|
|
17
|
+
const typedReject = (params) => _reject(params);
|
|
18
|
+
// Clear any potential pending timeouts and intervals
|
|
19
|
+
clearInterval(authWindowInterval);
|
|
20
|
+
const providersWaitingOauthMessage = {};
|
|
21
|
+
let shouldPool = false;
|
|
22
|
+
const authWindow = window.open('', '_blank', 'width=500,height=600');
|
|
23
|
+
const clearListeners = () => {
|
|
24
|
+
window.removeEventListener('message', handleWindowMessage);
|
|
25
|
+
providersWaitingOauthMessage[provider] = false;
|
|
26
|
+
};
|
|
27
|
+
const handleWindowMessage = (event) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
const message = event.data;
|
|
29
|
+
if (!(apiProvider === null || apiProvider === void 0 ? void 0 : apiProvider.redirectUrl)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
let expectedOrigin = window.location.origin;
|
|
33
|
+
if (!providersWithoutWindowOpenerReference.includes(provider)) {
|
|
34
|
+
try {
|
|
35
|
+
const redirectUri = new URL(apiProvider.redirectUrl);
|
|
36
|
+
expectedOrigin = redirectUri.origin;
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
logger.logger.error('Failed to parse social provider redirect url', {
|
|
40
|
+
error: e,
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if ((message === null || message === void 0 ? void 0 : message.type) === 'origin_check' && authWindow) {
|
|
46
|
+
logger.logger.debug('Origin check message received. Sending response now.', {
|
|
47
|
+
data: message,
|
|
48
|
+
expectedOrigin,
|
|
49
|
+
});
|
|
50
|
+
authWindow.postMessage('origin_check_response', expectedOrigin);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const isAuthorizationMessage = (message === null || message === void 0 ? void 0 : message.type) === 'authorization_response';
|
|
54
|
+
if (isAuthorizationMessage) {
|
|
55
|
+
logger.logger.debug('Message received', { data: message });
|
|
56
|
+
}
|
|
57
|
+
const isExpectedOrigin = event.origin === expectedOrigin;
|
|
58
|
+
const isValidMessage = isAuthorizationMessage &&
|
|
59
|
+
(message === null || message === void 0 ? void 0 : message.provider) === provider &&
|
|
60
|
+
isExpectedOrigin;
|
|
61
|
+
// don't process invalid messages for provider
|
|
62
|
+
if (!isValidMessage) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
setIsProcessing(true);
|
|
66
|
+
if (!providersWaitingOauthMessage[provider]) {
|
|
67
|
+
typedReject({
|
|
68
|
+
code: types.SocialOAuthErrorCode.SESSION_TIMEOUT,
|
|
69
|
+
message: `Connecting ${provider} account session timeout.`,
|
|
70
|
+
});
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
clearListeners();
|
|
74
|
+
const { code, error, state: authState } = message;
|
|
75
|
+
if (error && error !== 'undefined') {
|
|
76
|
+
typedReject({
|
|
77
|
+
code: types.SocialOAuthErrorCode.OAUTH_ERROR,
|
|
78
|
+
message: `Failed to connect ${provider} social account: ${error}`,
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// check that the state we receive from message is the same state we calculated earlier
|
|
83
|
+
// this could be an attack
|
|
84
|
+
// this state check is used only by providers with an open window opener reference (eg, not twitter)
|
|
85
|
+
if (!providersWithoutWindowOpenerReference.includes(provider) &&
|
|
86
|
+
state !== authState) {
|
|
87
|
+
typedReject({
|
|
88
|
+
code: types.SocialOAuthErrorCode.OAUTH_ERROR,
|
|
89
|
+
message: `Failed to connect ${provider} social account: Invalid random state`,
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!code) {
|
|
94
|
+
typedReject({
|
|
95
|
+
code: types.SocialOAuthErrorCode.NO_AUTH_CODE,
|
|
96
|
+
message: `Failed to connect ${provider} social account: no authorization code`,
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
resolve(code);
|
|
101
|
+
setIsProcessing(false);
|
|
102
|
+
});
|
|
103
|
+
if (!providersWaitingOauthMessage[provider]) {
|
|
104
|
+
window.addEventListener('message', handleWindowMessage);
|
|
105
|
+
providersWaitingOauthMessage[provider] = true;
|
|
106
|
+
}
|
|
107
|
+
authWindow === null || authWindow === void 0 ? void 0 : authWindow.location.assign(oauthLoginUrl);
|
|
108
|
+
if (!providersWithoutWindowOpenerReference.includes(provider)) {
|
|
109
|
+
// For provider that support window.opener, we need to clear all states/listeners when the window is closed
|
|
110
|
+
authWindowInterval = setInterval(() => {
|
|
111
|
+
if (!(authWindow === null || authWindow === void 0 ? void 0 : authWindow.closed))
|
|
112
|
+
return;
|
|
113
|
+
clearInterval(authWindowInterval);
|
|
114
|
+
setIsProcessing(false);
|
|
115
|
+
// user didn't complete oauth
|
|
116
|
+
if (providersWaitingOauthMessage[provider])
|
|
117
|
+
typedReject('user-cancelled');
|
|
118
|
+
}, 2000);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// For provider that don't support window.opener, we need to use a timeout to pool the oauth result
|
|
122
|
+
// If we don't get a valid result in {async sessionTimeout} ms, we'll assume the user closed the window
|
|
123
|
+
// and we'll clear all states/listeners
|
|
124
|
+
const poolOauthResult = () => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
125
|
+
if (!shouldPool)
|
|
126
|
+
return;
|
|
127
|
+
const result = yield getOAuthResultFromApi();
|
|
128
|
+
if (!shouldPool)
|
|
129
|
+
return;
|
|
130
|
+
if ((result === null || result === void 0 ? void 0 : result.status) !== sdkApiCore.OauthResultStatus.Completed) {
|
|
131
|
+
authWindowInterval = setTimeout(() => {
|
|
132
|
+
poolOauthResult();
|
|
133
|
+
}, 1000);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
shouldPool = false;
|
|
137
|
+
const authMessage = {
|
|
138
|
+
code: result === null || result === void 0 ? void 0 : result.code,
|
|
139
|
+
error: result === null || result === void 0 ? void 0 : result.error,
|
|
140
|
+
provider,
|
|
141
|
+
type: 'authorization_response',
|
|
142
|
+
};
|
|
143
|
+
window.postMessage(authMessage, '*');
|
|
144
|
+
});
|
|
145
|
+
// start pooling oauth result
|
|
146
|
+
shouldPool = true;
|
|
147
|
+
poolOauthResult();
|
|
148
|
+
// if this is mobile, set a longer timeout to allow the user to login to the provider in the browser
|
|
149
|
+
let authWindowTimeout = sessionTimeout;
|
|
150
|
+
if (isMobile) {
|
|
151
|
+
authWindowTimeout = authWindowTimeout * 3;
|
|
152
|
+
}
|
|
153
|
+
authWindowInterval = setTimeout(() => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
154
|
+
shouldPool = false;
|
|
155
|
+
// clear all states/listeners, assuming user closed the window before completing oauth
|
|
156
|
+
if (providersWaitingOauthMessage[provider]) {
|
|
157
|
+
clearListeners();
|
|
158
|
+
typedReject({
|
|
159
|
+
code: types.SocialOAuthErrorCode.OAUTH_WINDOW_TIMEOUT,
|
|
160
|
+
message: `Connecting ${provider} account window timeout.`,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
setIsProcessing(false);
|
|
164
|
+
onSettled === null || onSettled === void 0 ? void 0 : onSettled();
|
|
165
|
+
}), authWindowTimeout);
|
|
166
|
+
}
|
|
167
|
+
}),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
exports.createWindowOauth2Service = createWindowOauth2Service;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../_virtual/_tslib.js';
|
|
3
|
+
import { SocialOAuthErrorCode } from '@dynamic-labs/types';
|
|
4
|
+
import { OauthResultStatus } from '@dynamic-labs/sdk-api-core';
|
|
5
|
+
import { logger } from '../../../logger/logger.js';
|
|
6
|
+
|
|
7
|
+
const providersWithoutWindowOpenerReference = ['twitter'];
|
|
8
|
+
let authWindowInterval;
|
|
9
|
+
const createWindowOauth2Service = () => ({
|
|
10
|
+
getOauthCode: ({ apiProvider, provider, setIsProcessing, state, oauthLoginUrl, getOAuthResultFromApi, sessionTimeout, isMobile, onSettled, }) => new Promise((resolve, _reject) => {
|
|
11
|
+
// When we catch this error we assume it follows this type, so we must enforce it
|
|
12
|
+
// here to ensure the assumption is correct
|
|
13
|
+
const typedReject = (params) => _reject(params);
|
|
14
|
+
// Clear any potential pending timeouts and intervals
|
|
15
|
+
clearInterval(authWindowInterval);
|
|
16
|
+
const providersWaitingOauthMessage = {};
|
|
17
|
+
let shouldPool = false;
|
|
18
|
+
const authWindow = window.open('', '_blank', 'width=500,height=600');
|
|
19
|
+
const clearListeners = () => {
|
|
20
|
+
window.removeEventListener('message', handleWindowMessage);
|
|
21
|
+
providersWaitingOauthMessage[provider] = false;
|
|
22
|
+
};
|
|
23
|
+
const handleWindowMessage = (event) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
const message = event.data;
|
|
25
|
+
if (!(apiProvider === null || apiProvider === void 0 ? void 0 : apiProvider.redirectUrl)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
let expectedOrigin = window.location.origin;
|
|
29
|
+
if (!providersWithoutWindowOpenerReference.includes(provider)) {
|
|
30
|
+
try {
|
|
31
|
+
const redirectUri = new URL(apiProvider.redirectUrl);
|
|
32
|
+
expectedOrigin = redirectUri.origin;
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
logger.error('Failed to parse social provider redirect url', {
|
|
36
|
+
error: e,
|
|
37
|
+
});
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if ((message === null || message === void 0 ? void 0 : message.type) === 'origin_check' && authWindow) {
|
|
42
|
+
logger.debug('Origin check message received. Sending response now.', {
|
|
43
|
+
data: message,
|
|
44
|
+
expectedOrigin,
|
|
45
|
+
});
|
|
46
|
+
authWindow.postMessage('origin_check_response', expectedOrigin);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const isAuthorizationMessage = (message === null || message === void 0 ? void 0 : message.type) === 'authorization_response';
|
|
50
|
+
if (isAuthorizationMessage) {
|
|
51
|
+
logger.debug('Message received', { data: message });
|
|
52
|
+
}
|
|
53
|
+
const isExpectedOrigin = event.origin === expectedOrigin;
|
|
54
|
+
const isValidMessage = isAuthorizationMessage &&
|
|
55
|
+
(message === null || message === void 0 ? void 0 : message.provider) === provider &&
|
|
56
|
+
isExpectedOrigin;
|
|
57
|
+
// don't process invalid messages for provider
|
|
58
|
+
if (!isValidMessage) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
setIsProcessing(true);
|
|
62
|
+
if (!providersWaitingOauthMessage[provider]) {
|
|
63
|
+
typedReject({
|
|
64
|
+
code: SocialOAuthErrorCode.SESSION_TIMEOUT,
|
|
65
|
+
message: `Connecting ${provider} account session timeout.`,
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
clearListeners();
|
|
70
|
+
const { code, error, state: authState } = message;
|
|
71
|
+
if (error && error !== 'undefined') {
|
|
72
|
+
typedReject({
|
|
73
|
+
code: SocialOAuthErrorCode.OAUTH_ERROR,
|
|
74
|
+
message: `Failed to connect ${provider} social account: ${error}`,
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// check that the state we receive from message is the same state we calculated earlier
|
|
79
|
+
// this could be an attack
|
|
80
|
+
// this state check is used only by providers with an open window opener reference (eg, not twitter)
|
|
81
|
+
if (!providersWithoutWindowOpenerReference.includes(provider) &&
|
|
82
|
+
state !== authState) {
|
|
83
|
+
typedReject({
|
|
84
|
+
code: SocialOAuthErrorCode.OAUTH_ERROR,
|
|
85
|
+
message: `Failed to connect ${provider} social account: Invalid random state`,
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (!code) {
|
|
90
|
+
typedReject({
|
|
91
|
+
code: SocialOAuthErrorCode.NO_AUTH_CODE,
|
|
92
|
+
message: `Failed to connect ${provider} social account: no authorization code`,
|
|
93
|
+
});
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
resolve(code);
|
|
97
|
+
setIsProcessing(false);
|
|
98
|
+
});
|
|
99
|
+
if (!providersWaitingOauthMessage[provider]) {
|
|
100
|
+
window.addEventListener('message', handleWindowMessage);
|
|
101
|
+
providersWaitingOauthMessage[provider] = true;
|
|
102
|
+
}
|
|
103
|
+
authWindow === null || authWindow === void 0 ? void 0 : authWindow.location.assign(oauthLoginUrl);
|
|
104
|
+
if (!providersWithoutWindowOpenerReference.includes(provider)) {
|
|
105
|
+
// For provider that support window.opener, we need to clear all states/listeners when the window is closed
|
|
106
|
+
authWindowInterval = setInterval(() => {
|
|
107
|
+
if (!(authWindow === null || authWindow === void 0 ? void 0 : authWindow.closed))
|
|
108
|
+
return;
|
|
109
|
+
clearInterval(authWindowInterval);
|
|
110
|
+
setIsProcessing(false);
|
|
111
|
+
// user didn't complete oauth
|
|
112
|
+
if (providersWaitingOauthMessage[provider])
|
|
113
|
+
typedReject('user-cancelled');
|
|
114
|
+
}, 2000);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// For provider that don't support window.opener, we need to use a timeout to pool the oauth result
|
|
118
|
+
// If we don't get a valid result in {async sessionTimeout} ms, we'll assume the user closed the window
|
|
119
|
+
// and we'll clear all states/listeners
|
|
120
|
+
const poolOauthResult = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
121
|
+
if (!shouldPool)
|
|
122
|
+
return;
|
|
123
|
+
const result = yield getOAuthResultFromApi();
|
|
124
|
+
if (!shouldPool)
|
|
125
|
+
return;
|
|
126
|
+
if ((result === null || result === void 0 ? void 0 : result.status) !== OauthResultStatus.Completed) {
|
|
127
|
+
authWindowInterval = setTimeout(() => {
|
|
128
|
+
poolOauthResult();
|
|
129
|
+
}, 1000);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
shouldPool = false;
|
|
133
|
+
const authMessage = {
|
|
134
|
+
code: result === null || result === void 0 ? void 0 : result.code,
|
|
135
|
+
error: result === null || result === void 0 ? void 0 : result.error,
|
|
136
|
+
provider,
|
|
137
|
+
type: 'authorization_response',
|
|
138
|
+
};
|
|
139
|
+
window.postMessage(authMessage, '*');
|
|
140
|
+
});
|
|
141
|
+
// start pooling oauth result
|
|
142
|
+
shouldPool = true;
|
|
143
|
+
poolOauthResult();
|
|
144
|
+
// if this is mobile, set a longer timeout to allow the user to login to the provider in the browser
|
|
145
|
+
let authWindowTimeout = sessionTimeout;
|
|
146
|
+
if (isMobile) {
|
|
147
|
+
authWindowTimeout = authWindowTimeout * 3;
|
|
148
|
+
}
|
|
149
|
+
authWindowInterval = setTimeout(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
150
|
+
shouldPool = false;
|
|
151
|
+
// clear all states/listeners, assuming user closed the window before completing oauth
|
|
152
|
+
if (providersWaitingOauthMessage[provider]) {
|
|
153
|
+
clearListeners();
|
|
154
|
+
typedReject({
|
|
155
|
+
code: SocialOAuthErrorCode.OAUTH_WINDOW_TIMEOUT,
|
|
156
|
+
message: `Connecting ${provider} account window timeout.`,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
setIsProcessing(false);
|
|
160
|
+
onSettled === null || onSettled === void 0 ? void 0 : onSettled();
|
|
161
|
+
}), authWindowTimeout);
|
|
162
|
+
}
|
|
163
|
+
}),
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
export { createWindowOauth2Service };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createWindowOauth2Service';
|