@magic-ext/magic-widget 1.0.0-canary.979.21008432451.0 → 1.0.0-canary.979.21048249937.0
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/dist/cjs/index.js +174 -61
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/MagicWidget.d.ts +2 -1
- package/dist/cjs/types/constants.d.ts +2 -2
- package/dist/cjs/types/context/WidgetConfigContext.d.ts +22 -0
- package/dist/cjs/types/context/index.d.ts +1 -0
- package/dist/cjs/types/hooks/useSiweLogin.d.ts +1 -1
- package/dist/cjs/types/hooks/useWalletConnect.d.ts +2 -2
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/reducer.d.ts +2 -2
- package/dist/cjs/types/types.d.ts +125 -8
- package/dist/cjs/types/views/WalletPendingView.d.ts +2 -2
- package/dist/cjs/types/wagmi/connectors.d.ts +4 -4
- package/dist/es/index.mjs +159 -47
- package/dist/es/index.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
2
|
+
import { MagicWidgetProps } from './types';
|
|
3
|
+
export declare function MagicWidget({ displayMode, isOpen, onClose, closeOnSuccess, closeOnClickOutside, wallets, onSuccess, onError, }: MagicWidgetProps): React.JSX.Element | null;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { OAuthProvider, ProviderMetadata,
|
|
2
|
-
export declare const WALLET_METADATA: Record<
|
|
1
|
+
import { OAuthProvider, ProviderMetadata, ThirdPartyWallet } from './types';
|
|
2
|
+
export declare const WALLET_METADATA: Record<ThirdPartyWallet, ProviderMetadata>;
|
|
3
3
|
export declare const OAUTH_METADATA: Record<OAuthProvider, ProviderMetadata>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { LoginResult, MagicWidgetProps, ThirdPartyWallet } from '../types';
|
|
3
|
+
interface WidgetConfigContextValue {
|
|
4
|
+
/** Third-party wallets to display */
|
|
5
|
+
wallets: ThirdPartyWallet[];
|
|
6
|
+
/** Call when login succeeds */
|
|
7
|
+
handleSuccess: (result: LoginResult) => void;
|
|
8
|
+
/** Call when login fails */
|
|
9
|
+
handleError: (error: Error) => void;
|
|
10
|
+
/** Call to close the widget. Undefined if onClose prop wasn't provided. */
|
|
11
|
+
handleClose?: () => void;
|
|
12
|
+
}
|
|
13
|
+
interface WidgetConfigProviderProps extends MagicWidgetProps {
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export declare function WidgetConfigProvider({ children, wallets, onSuccess, onError, onClose, closeOnSuccess, }: WidgetConfigProviderProps): React.JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* Hook to access the widget configuration
|
|
19
|
+
* @throws Error if used outside of WidgetConfigProvider
|
|
20
|
+
*/
|
|
21
|
+
export declare function useWidgetConfig(): WidgetConfigContextValue;
|
|
22
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ThirdPartyWallet } from '../types';
|
|
2
2
|
export interface UseWalletConnectResult {
|
|
3
3
|
connectWallet: () => Promise<void>;
|
|
4
4
|
isPending: boolean;
|
|
@@ -9,4 +9,4 @@ export interface UseWalletConnectResult {
|
|
|
9
9
|
isConnectedToSelectedProvider: boolean;
|
|
10
10
|
disconnect: () => void;
|
|
11
11
|
}
|
|
12
|
-
export declare function useWalletConnect(provider:
|
|
12
|
+
export declare function useWalletConnect(provider: ThirdPartyWallet): UseWalletConnectResult;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export * from './MagicWidget';
|
|
2
2
|
export * from './extension';
|
|
3
|
+
export { ThirdPartyWallets, OAuthProvider, type ThirdPartyWallet, type DisplayMode, type MagicWidgetProps, type LoginResult, type EmailLoginResult, type OAuthLoginResult, type WalletLoginResult, type OAuthUserInfo, } from './types';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LoginProvider, OAuthProvider,
|
|
1
|
+
import { LoginProvider, OAuthProvider, ThirdPartyWallet } from './types';
|
|
2
2
|
export type View = 'login' | 'otp' | 'additional_providers' | 'wallet_pending' | 'oauth_pending' | 'email_otp_pending' | 'device_verification' | 'mfa_pending' | 'recovery_code' | 'lost_recovery_code' | 'login_success';
|
|
3
3
|
export type EmailLoginStatus = 'idle' | 'sending' | 'otp_sent' | 'verifying_otp' | 'invalid_otp' | 'expired_otp' | 'max_attempts_reached' | 'device_needs_approval' | 'device_verification_sent' | 'device_verification_expired' | 'device_approved' | 'mfa_required' | 'recovery_code' | 'success' | 'mfa_verifying' | 'mfa_invalid' | 'recovery_code_verifying' | 'lost_recovery_code' | 'error';
|
|
4
4
|
export interface WidgetState {
|
|
@@ -59,7 +59,7 @@ export type WidgetAction = {
|
|
|
59
59
|
type: 'GO_TO_ADDITIONAL_PROVIDERS';
|
|
60
60
|
} | {
|
|
61
61
|
type: 'SELECT_WALLET';
|
|
62
|
-
provider:
|
|
62
|
+
provider: ThirdPartyWallet;
|
|
63
63
|
};
|
|
64
64
|
export declare const initialState: WidgetState;
|
|
65
65
|
export declare function widgetReducer(state: WidgetState, action: WidgetAction): WidgetState;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { ComponentType } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Available third-party wallet providers.
|
|
4
|
+
* Use these constants or pass string literals directly: 'metamask', 'coinbase', etc.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ThirdPartyWallets: {
|
|
7
|
+
readonly METAMASK: "metamask";
|
|
8
|
+
readonly WALLETCONNECT: "walletconnect";
|
|
9
|
+
readonly COINBASE: "coinbase";
|
|
10
|
+
readonly PHANTOM: "phantom";
|
|
11
|
+
readonly RABBY: "rabby";
|
|
12
|
+
};
|
|
13
|
+
/** Type representing valid third-party wallet values */
|
|
14
|
+
export type ThirdPartyWallet = (typeof ThirdPartyWallets)[keyof typeof ThirdPartyWallets];
|
|
9
15
|
export interface ProviderMetadata {
|
|
10
16
|
displayName: string;
|
|
11
17
|
Icon: ComponentType<{
|
|
@@ -32,7 +38,7 @@ export declare enum OAuthProvider {
|
|
|
32
38
|
GITLAB = "gitlab",
|
|
33
39
|
TELEGRAM = "telegram"
|
|
34
40
|
}
|
|
35
|
-
export type LoginProvider = OAuthProvider |
|
|
41
|
+
export type LoginProvider = OAuthProvider | ThirdPartyWallet;
|
|
36
42
|
export interface ProviderConfig {
|
|
37
43
|
title: string;
|
|
38
44
|
description: string;
|
|
@@ -42,3 +48,114 @@ export interface ProviderConfig {
|
|
|
42
48
|
className?: string;
|
|
43
49
|
}>;
|
|
44
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* OAuth user information returned from social login
|
|
53
|
+
*/
|
|
54
|
+
export interface OAuthUserInfo {
|
|
55
|
+
/** The OAuth provider used (e.g., 'google', 'apple') */
|
|
56
|
+
provider: string;
|
|
57
|
+
name?: string;
|
|
58
|
+
email?: string;
|
|
59
|
+
picture?: string;
|
|
60
|
+
[key: string]: unknown;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Result returned on successful email login
|
|
64
|
+
*/
|
|
65
|
+
export interface EmailLoginResult {
|
|
66
|
+
method: 'email';
|
|
67
|
+
/** The DID token for authentication */
|
|
68
|
+
didToken: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Result returned on successful OAuth login
|
|
72
|
+
*/
|
|
73
|
+
export interface OAuthLoginResult {
|
|
74
|
+
method: 'oauth';
|
|
75
|
+
/** The DID token for authentication */
|
|
76
|
+
didToken: string;
|
|
77
|
+
/** OAuth provider information */
|
|
78
|
+
oauth: OAuthUserInfo;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Result returned on successful wallet login
|
|
82
|
+
*/
|
|
83
|
+
export interface WalletLoginResult {
|
|
84
|
+
method: 'wallet';
|
|
85
|
+
/** The connected wallet address */
|
|
86
|
+
walletAddress: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Discriminated union of all login result types.
|
|
90
|
+
* Check the `method` property to determine which fields are available.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* onSuccess={(result) => {
|
|
94
|
+
* if (result.method === 'email' || result.method === 'oauth') {
|
|
95
|
+
* sendToBackend(result.didToken);
|
|
96
|
+
* } else {
|
|
97
|
+
* console.log('Wallet:', result.walletAddress);
|
|
98
|
+
* }
|
|
99
|
+
* }}
|
|
100
|
+
*/
|
|
101
|
+
export type LoginResult = EmailLoginResult | OAuthLoginResult | WalletLoginResult;
|
|
102
|
+
/**
|
|
103
|
+
* How the widget is displayed on the page.
|
|
104
|
+
* - 'inline': Rendered in the document flow (default)
|
|
105
|
+
* - 'modal': Positioned as a modal dialog, slightly above center
|
|
106
|
+
*/
|
|
107
|
+
export type DisplayMode = 'inline' | 'modal';
|
|
108
|
+
export interface MagicWidgetProps {
|
|
109
|
+
/**
|
|
110
|
+
* How the widget is displayed on the page. Defaults to 'inline'.
|
|
111
|
+
* - 'inline': Rendered in the document flow
|
|
112
|
+
* - 'modal': Positioned as a modal dialog with backdrop
|
|
113
|
+
* @example displayMode="modal"
|
|
114
|
+
*/
|
|
115
|
+
displayMode?: DisplayMode;
|
|
116
|
+
/**
|
|
117
|
+
* Whether the widget modal is open. Defaults to true.
|
|
118
|
+
* @example isOpen={showLogin}
|
|
119
|
+
*/
|
|
120
|
+
isOpen?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Callback fired when the widget is closed (e.g., user clicks X button).
|
|
123
|
+
* @example onClose={() => setShowLogin(false)}
|
|
124
|
+
*/
|
|
125
|
+
onClose?: () => void;
|
|
126
|
+
/**
|
|
127
|
+
* Automatically call onClose after successful login (with a 2 second delay to show success screen).
|
|
128
|
+
* Defaults to false.
|
|
129
|
+
* @example closeOnSuccess={true}
|
|
130
|
+
*/
|
|
131
|
+
closeOnSuccess?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Close the modal when clicking the backdrop. Only applies when displayMode="modal".
|
|
134
|
+
* Defaults to false.
|
|
135
|
+
* @example closeOnClickOutside={true}
|
|
136
|
+
*/
|
|
137
|
+
closeOnClickOutside?: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Third-party wallets to display. None enabled by default.
|
|
140
|
+
* Accepts constants or string literals: 'metamask', 'walletconnect', 'coinbase', 'phantom', 'rabby'
|
|
141
|
+
* @example wallets={['metamask', 'coinbase']}
|
|
142
|
+
* @example wallets={[ThirdPartyWallets.METAMASK, ThirdPartyWallets.COINBASE]}
|
|
143
|
+
*/
|
|
144
|
+
wallets?: ThirdPartyWallet[];
|
|
145
|
+
/**
|
|
146
|
+
* Callback fired when login succeeds.
|
|
147
|
+
* The result type varies by login method - check `result.method` to determine the shape.
|
|
148
|
+
* @example
|
|
149
|
+
* onSuccess={(result) => {
|
|
150
|
+
* if (result.method === 'email' || result.method === 'oauth') {
|
|
151
|
+
* authenticate(result.didToken);
|
|
152
|
+
* }
|
|
153
|
+
* }}
|
|
154
|
+
*/
|
|
155
|
+
onSuccess?: (result: LoginResult) => void;
|
|
156
|
+
/**
|
|
157
|
+
* Callback fired when login fails
|
|
158
|
+
* @example onError={(error) => console.error(error.message)}
|
|
159
|
+
*/
|
|
160
|
+
onError?: (error: Error) => void;
|
|
161
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { WidgetAction } from '../reducer';
|
|
3
|
-
import {
|
|
3
|
+
import { ThirdPartyWallet } from '../types';
|
|
4
4
|
interface WalletPendingViewProps {
|
|
5
|
-
provider:
|
|
5
|
+
provider: ThirdPartyWallet;
|
|
6
6
|
dispatch: React.Dispatch<WidgetAction>;
|
|
7
7
|
}
|
|
8
8
|
export declare const WalletPendingView: ({ provider, dispatch }: WalletPendingViewProps) => React.JSX.Element;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ThirdPartyWallet } from '../types';
|
|
2
2
|
/**
|
|
3
|
-
* Map
|
|
3
|
+
* Map wallet types to wagmi connector IDs
|
|
4
4
|
*/
|
|
5
|
-
export declare const CONNECTOR_IDS: Record<
|
|
5
|
+
export declare const CONNECTOR_IDS: Record<ThirdPartyWallet, string>;
|
|
6
6
|
/**
|
|
7
7
|
* Alternative names to match connectors by name if ID doesn't match
|
|
8
8
|
*/
|
|
9
|
-
export declare const CONNECTOR_NAME_PATTERNS: Record<
|
|
9
|
+
export declare const CONNECTOR_NAME_PATTERNS: Record<ThirdPartyWallet, string>;
|
package/dist/es/index.mjs
CHANGED
|
@@ -13943,14 +13943,17 @@ const ProviderButton = ({ label, Icon, onPress, hideLabel }) => {
|
|
|
13943
13943
|
!hideLabel && label && (React__default.createElement(M$8, { fontWeight: "medium", styles: { lineHeight: '1.5rem' } }, label)))));
|
|
13944
13944
|
};
|
|
13945
13945
|
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13946
|
+
/**
|
|
13947
|
+
* Available third-party wallet providers.
|
|
13948
|
+
* Use these constants or pass string literals directly: 'metamask', 'coinbase', etc.
|
|
13949
|
+
*/
|
|
13950
|
+
const ThirdPartyWallets = {
|
|
13951
|
+
METAMASK: 'metamask',
|
|
13952
|
+
WALLETCONNECT: 'walletconnect',
|
|
13953
|
+
COINBASE: 'coinbase',
|
|
13954
|
+
PHANTOM: 'phantom',
|
|
13955
|
+
RABBY: 'rabby',
|
|
13956
|
+
};
|
|
13954
13957
|
var RpcErrorMessage;
|
|
13955
13958
|
(function (RpcErrorMessage) {
|
|
13956
13959
|
RpcErrorMessage["MalformedEmail"] = "Invalid params: Please provide a valid email address.";
|
|
@@ -14355,8 +14358,48 @@ class MagicWidgetExtension extends Extension.Internal {
|
|
|
14355
14358
|
}
|
|
14356
14359
|
}
|
|
14357
14360
|
|
|
14361
|
+
const WidgetConfigContext = createContext(null);
|
|
14362
|
+
function WidgetConfigProvider({ children, wallets = [], onSuccess, onError, onClose, closeOnSuccess = false, }) {
|
|
14363
|
+
const handleSuccess = useCallback((result) => {
|
|
14364
|
+
onSuccess?.(result);
|
|
14365
|
+
if (closeOnSuccess && onClose) {
|
|
14366
|
+
// Delay closing so users can see the success screen
|
|
14367
|
+
setTimeout(() => {
|
|
14368
|
+
onClose();
|
|
14369
|
+
}, 2000);
|
|
14370
|
+
}
|
|
14371
|
+
}, [onSuccess, closeOnSuccess, onClose]);
|
|
14372
|
+
const handleError = useCallback((error) => {
|
|
14373
|
+
onError?.(error);
|
|
14374
|
+
}, [onError]);
|
|
14375
|
+
const handleClose = onClose
|
|
14376
|
+
? () => {
|
|
14377
|
+
onClose();
|
|
14378
|
+
}
|
|
14379
|
+
: undefined;
|
|
14380
|
+
const value = {
|
|
14381
|
+
wallets,
|
|
14382
|
+
handleSuccess,
|
|
14383
|
+
handleError,
|
|
14384
|
+
handleClose,
|
|
14385
|
+
};
|
|
14386
|
+
return React__default.createElement(WidgetConfigContext.Provider, { value: value }, children);
|
|
14387
|
+
}
|
|
14388
|
+
/**
|
|
14389
|
+
* Hook to access the widget configuration
|
|
14390
|
+
* @throws Error if used outside of WidgetConfigProvider
|
|
14391
|
+
*/
|
|
14392
|
+
function useWidgetConfig() {
|
|
14393
|
+
const context = useContext(WidgetConfigContext);
|
|
14394
|
+
if (!context) {
|
|
14395
|
+
throw new Error('useWidgetConfig must be used within a WidgetConfigProvider');
|
|
14396
|
+
}
|
|
14397
|
+
return context;
|
|
14398
|
+
}
|
|
14399
|
+
|
|
14358
14400
|
const EmailLoginContext = createContext(null);
|
|
14359
14401
|
function EmailLoginProvider({ children, dispatch }) {
|
|
14402
|
+
const { handleSuccess, handleError } = useWidgetConfig();
|
|
14360
14403
|
// Store the current login handle
|
|
14361
14404
|
const handleRef = useRef(null);
|
|
14362
14405
|
const emailRef = useRef(null);
|
|
@@ -14435,19 +14478,24 @@ function EmailLoginProvider({ children, dispatch }) {
|
|
|
14435
14478
|
.then(didToken => {
|
|
14436
14479
|
if (didToken) {
|
|
14437
14480
|
dispatch({ type: 'LOGIN_SUCCESS' });
|
|
14481
|
+
handleSuccess({ method: 'email', didToken });
|
|
14438
14482
|
}
|
|
14439
14483
|
})
|
|
14440
14484
|
.catch(error => {
|
|
14441
|
-
|
|
14485
|
+
const errorInstance = error instanceof Error ? error : new Error(error?.message || 'Login failed');
|
|
14486
|
+
dispatch({ type: 'LOGIN_ERROR', error: errorInstance.message });
|
|
14487
|
+
handleError(errorInstance);
|
|
14442
14488
|
});
|
|
14443
14489
|
}
|
|
14444
14490
|
catch (error) {
|
|
14491
|
+
const errorInstance = error instanceof Error ? error : new Error('Failed to start login');
|
|
14445
14492
|
dispatch({
|
|
14446
14493
|
type: 'LOGIN_ERROR',
|
|
14447
|
-
error:
|
|
14494
|
+
error: errorInstance.message,
|
|
14448
14495
|
});
|
|
14496
|
+
handleError(errorInstance);
|
|
14449
14497
|
}
|
|
14450
|
-
}, [dispatch]);
|
|
14498
|
+
}, [dispatch, handleSuccess, handleError]);
|
|
14451
14499
|
/**
|
|
14452
14500
|
* Submit OTP code for verification
|
|
14453
14501
|
*/
|
|
@@ -14596,10 +14644,7 @@ const SocialProviders = ({ providers, onPress, dispatch }) => {
|
|
|
14596
14644
|
};
|
|
14597
14645
|
|
|
14598
14646
|
function WidgetHeader({ showHeaderText = true, onPressBack }) {
|
|
14599
|
-
const handleClose = ()
|
|
14600
|
-
// TODO: Need to determine what this behavior should be/if it should exist at all
|
|
14601
|
-
console.log('Close widget');
|
|
14602
|
-
};
|
|
14647
|
+
const { handleClose } = useWidgetConfig();
|
|
14603
14648
|
return (React__default.createElement(u$3, { position: "relative" },
|
|
14604
14649
|
!!onPressBack && (React__default.createElement(u$3.LeftAction, null,
|
|
14605
14650
|
React__default.createElement(Q$2, { size: "sm", variant: "neutral", onPress: onPressBack },
|
|
@@ -14607,19 +14652,19 @@ function WidgetHeader({ showHeaderText = true, onPressBack }) {
|
|
|
14607
14652
|
React__default.createElement(s$6, null))))),
|
|
14608
14653
|
showHeaderText && (React__default.createElement(u$3.Content, null,
|
|
14609
14654
|
React__default.createElement(M$8, { size: "sm", fontColor: "text.tertiary" }, "Log in or sign up"))),
|
|
14610
|
-
React__default.createElement(u$3.RightAction, null,
|
|
14655
|
+
handleClose && (React__default.createElement(u$3.RightAction, null,
|
|
14611
14656
|
React__default.createElement(Q$2, { size: "sm", variant: "neutral", onPress: handleClose },
|
|
14612
14657
|
React__default.createElement(Q$2.TrailingIcon, null,
|
|
14613
|
-
React__default.createElement(c$a, null))))));
|
|
14658
|
+
React__default.createElement(c$a, null)))))));
|
|
14614
14659
|
}
|
|
14615
14660
|
|
|
14616
14661
|
const LoginView = ({ dispatch }) => {
|
|
14617
14662
|
const config = getExtensionInstance().getConfig();
|
|
14663
|
+
const { wallets } = useWidgetConfig();
|
|
14618
14664
|
const { primary, social } = config?.authProviders ?? {};
|
|
14619
14665
|
const hasEmailProvider = primary?.includes('email');
|
|
14620
14666
|
const socialProviders = social?.map(provider => provider) ?? [];
|
|
14621
|
-
const
|
|
14622
|
-
const showDivider = socialProviders.length > 0 && enabledWalletProviders.length > 0;
|
|
14667
|
+
const showDivider = (hasEmailProvider || socialProviders.length > 0) && wallets.length > 0;
|
|
14623
14668
|
const handleProviderSelect = (provider) => {
|
|
14624
14669
|
dispatch({ type: 'SELECT_WALLET', provider });
|
|
14625
14670
|
};
|
|
@@ -14637,7 +14682,7 @@ const LoginView = ({ dispatch }) => {
|
|
|
14637
14682
|
React__default.createElement(Divider, { color: "surface.quaternary" }),
|
|
14638
14683
|
React__default.createElement(M$8, { "aria-label": "or", fontColor: "text.tertiary" }, "or"),
|
|
14639
14684
|
React__default.createElement(Divider, { color: "surface.quaternary" }))),
|
|
14640
|
-
|
|
14685
|
+
wallets.length > 0 && (React__default.createElement(Flex, { gap: 2, w: "full", direction: showDivider ? 'row' : 'column', justify: "center" }, wallets.map(provider => (React__default.createElement(ProviderButton, { key: provider, hideLabel: wallets.length > 1 && showDivider, label: WALLET_METADATA[provider].displayName, Icon: WALLET_METADATA[provider].Icon, onPress: () => handleProviderSelect(provider) })))))))));
|
|
14641
14686
|
};
|
|
14642
14687
|
|
|
14643
14688
|
function getProviderConfig(provider) {
|
|
@@ -14659,7 +14704,7 @@ function getProviderConfig(provider) {
|
|
|
14659
14704
|
}
|
|
14660
14705
|
|
|
14661
14706
|
/**
|
|
14662
|
-
* Map
|
|
14707
|
+
* Map wallet types to wagmi connector IDs
|
|
14663
14708
|
*/
|
|
14664
14709
|
const CONNECTOR_IDS = {
|
|
14665
14710
|
[ThirdPartyWallets.METAMASK]: 'metaMaskSDK',
|
|
@@ -14747,15 +14792,16 @@ function useWalletConnect(provider) {
|
|
|
14747
14792
|
function useSiweLogin() {
|
|
14748
14793
|
const { signMessageAsync } = useSignMessage();
|
|
14749
14794
|
const connectedChainId = useChainId();
|
|
14795
|
+
const { handleSuccess, handleError } = useWidgetConfig();
|
|
14750
14796
|
const [isLoading, setIsLoading] = useState(false);
|
|
14751
14797
|
const [error, setError] = useState(null);
|
|
14752
14798
|
const [isSuccess, setIsSuccess] = useState(false);
|
|
14753
|
-
const [
|
|
14799
|
+
const [walletAddress, setWalletAddress] = useState(null);
|
|
14754
14800
|
const performSiweLogin = useCallback(async (address, chainId) => {
|
|
14755
14801
|
setIsLoading(true);
|
|
14756
14802
|
setError(null);
|
|
14757
14803
|
setIsSuccess(false);
|
|
14758
|
-
|
|
14804
|
+
setWalletAddress(null);
|
|
14759
14805
|
try {
|
|
14760
14806
|
const extension = getExtensionInstance();
|
|
14761
14807
|
const effectiveChainId = chainId || connectedChainId || 1;
|
|
@@ -14767,28 +14813,30 @@ function useSiweLogin() {
|
|
|
14767
14813
|
// Step 2: Sign the message with the connected wallet
|
|
14768
14814
|
const signature = await signMessageAsync({ message });
|
|
14769
14815
|
// Step 3: Send the signed message to Magic backend for verification
|
|
14770
|
-
|
|
14816
|
+
await extension.login({ message, signature });
|
|
14771
14817
|
// Step 4: Set up the connected state for 3rd party wallet RPC routing
|
|
14772
14818
|
// This enables signing requests to be routed through the connected wallet
|
|
14773
14819
|
extension.setConnectedState(address, effectiveChainId);
|
|
14774
14820
|
setIsSuccess(true);
|
|
14775
|
-
|
|
14821
|
+
setWalletAddress(address);
|
|
14776
14822
|
setIsLoading(false);
|
|
14777
|
-
|
|
14823
|
+
handleSuccess({ method: 'wallet', walletAddress: address });
|
|
14824
|
+
return address;
|
|
14778
14825
|
}
|
|
14779
14826
|
catch (err) {
|
|
14780
14827
|
const errorInstance = err instanceof Error ? err : new Error('SIWE login failed');
|
|
14781
14828
|
setError(errorInstance);
|
|
14782
14829
|
setIsLoading(false);
|
|
14830
|
+
handleError(errorInstance);
|
|
14783
14831
|
throw errorInstance;
|
|
14784
14832
|
}
|
|
14785
|
-
}, [signMessageAsync, connectedChainId]);
|
|
14833
|
+
}, [signMessageAsync, connectedChainId, handleSuccess, handleError]);
|
|
14786
14834
|
return {
|
|
14787
14835
|
performSiweLogin,
|
|
14788
14836
|
isLoading,
|
|
14789
14837
|
error,
|
|
14790
14838
|
isSuccess,
|
|
14791
|
-
|
|
14839
|
+
walletAddress,
|
|
14792
14840
|
};
|
|
14793
14841
|
}
|
|
14794
14842
|
|
|
@@ -14800,7 +14848,7 @@ const centeredIconClass = css({
|
|
|
14800
14848
|
});
|
|
14801
14849
|
const Pending = ({ onPressBack, title, description, Icon, isPending, errorMessage }) => {
|
|
14802
14850
|
return (React__default.createElement(React__default.Fragment, null,
|
|
14803
|
-
React__default.createElement(WidgetHeader, { onPressBack: onPressBack, showHeaderText: false }),
|
|
14851
|
+
React__default.createElement(WidgetHeader, { onPressBack: isPending ? onPressBack : undefined, showHeaderText: false }),
|
|
14804
14852
|
React__default.createElement(VStack, { gap: 6, pt: 4 },
|
|
14805
14853
|
React__default.createElement(Box, { position: "relative", h: 20, w: 20 },
|
|
14806
14854
|
isPending && React__default.createElement(d$m, { size: 80, strokeWidth: 8, neutral: true, progress: 40 }),
|
|
@@ -15043,6 +15091,7 @@ function widgetReducer(state, action) {
|
|
|
15043
15091
|
}
|
|
15044
15092
|
|
|
15045
15093
|
function useOAuthLogin() {
|
|
15094
|
+
const { handleSuccess, handleError } = useWidgetConfig();
|
|
15046
15095
|
const [isLoading, setIsLoading] = useState(false);
|
|
15047
15096
|
const [error, setError] = useState(null);
|
|
15048
15097
|
const [isSuccess, setIsSuccess] = useState(false);
|
|
@@ -15058,15 +15107,26 @@ function useOAuthLogin() {
|
|
|
15058
15107
|
setIsSuccess(true);
|
|
15059
15108
|
setResult(oauthResult);
|
|
15060
15109
|
setIsLoading(false);
|
|
15110
|
+
handleSuccess({
|
|
15111
|
+
method: 'oauth',
|
|
15112
|
+
didToken: oauthResult.magic.idToken,
|
|
15113
|
+
oauth: {
|
|
15114
|
+
provider: oauthResult.oauth.provider,
|
|
15115
|
+
name: oauthResult.oauth.userInfo.name,
|
|
15116
|
+
email: oauthResult.oauth.userInfo.email,
|
|
15117
|
+
picture: oauthResult.oauth.userInfo.picture,
|
|
15118
|
+
},
|
|
15119
|
+
});
|
|
15061
15120
|
return oauthResult;
|
|
15062
15121
|
}
|
|
15063
15122
|
catch (err) {
|
|
15064
15123
|
const errorInstance = err instanceof Error ? err : new Error('OAuth login failed');
|
|
15065
15124
|
setError(errorInstance);
|
|
15066
15125
|
setIsLoading(false);
|
|
15126
|
+
handleError(errorInstance);
|
|
15067
15127
|
throw errorInstance;
|
|
15068
15128
|
}
|
|
15069
|
-
}, []);
|
|
15129
|
+
}, [handleSuccess, handleError]);
|
|
15070
15130
|
return {
|
|
15071
15131
|
performOAuthLogin,
|
|
15072
15132
|
isLoading,
|
|
@@ -15351,30 +15411,82 @@ function WidgetContent({ state, dispatch }) {
|
|
|
15351
15411
|
renderView(),
|
|
15352
15412
|
React__default.createElement(c$5, null)))));
|
|
15353
15413
|
}
|
|
15354
|
-
//
|
|
15355
|
-
|
|
15414
|
+
// Styles for modal mode
|
|
15415
|
+
const modalBackdropStyles = {
|
|
15416
|
+
position: 'fixed',
|
|
15417
|
+
top: 0,
|
|
15418
|
+
left: 0,
|
|
15419
|
+
right: 0,
|
|
15420
|
+
bottom: 0,
|
|
15421
|
+
backdropFilter: 'blur(0.375rem)',
|
|
15422
|
+
WebkitBackdropFilter: 'blur(0.375rem)', // Safari support
|
|
15423
|
+
display: 'flex',
|
|
15424
|
+
alignItems: 'flex-start',
|
|
15425
|
+
justifyContent: 'center',
|
|
15426
|
+
paddingTop: '15vh', // Slightly above center
|
|
15427
|
+
zIndex: 9999,
|
|
15428
|
+
};
|
|
15429
|
+
const modalContentStyles = {
|
|
15430
|
+
position: 'relative',
|
|
15431
|
+
};
|
|
15432
|
+
// Main widget component
|
|
15433
|
+
function MagicWidget({ displayMode = 'inline', isOpen = true, onClose, closeOnSuccess = false, closeOnClickOutside = false, wallets = [], onSuccess, onError, }) {
|
|
15356
15434
|
const [state, dispatch] = useReducer(widgetReducer, initialState);
|
|
15357
|
-
|
|
15435
|
+
// Check if config is already cached to avoid unnecessary loading state
|
|
15436
|
+
const [isConfigLoading, setIsConfigLoading] = useState(() => {
|
|
15437
|
+
return getExtensionInstance().getConfig() === null;
|
|
15438
|
+
});
|
|
15358
15439
|
useEffect(() => {
|
|
15359
15440
|
injectCSS();
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
|
|
15363
|
-
|
|
15364
|
-
|
|
15365
|
-
|
|
15366
|
-
|
|
15367
|
-
|
|
15441
|
+
// Only fetch if not already cached
|
|
15442
|
+
if (isConfigLoading) {
|
|
15443
|
+
getExtensionInstance()
|
|
15444
|
+
.fetchConfig()
|
|
15445
|
+
.then(() => setIsConfigLoading(false))
|
|
15446
|
+
.catch(err => {
|
|
15447
|
+
console.error('Failed to fetch config:', err);
|
|
15448
|
+
setIsConfigLoading(false); // Still show widget on error
|
|
15449
|
+
});
|
|
15450
|
+
}
|
|
15451
|
+
}, [isConfigLoading]);
|
|
15452
|
+
// Reset to login view when modal is opened
|
|
15453
|
+
useEffect(() => {
|
|
15454
|
+
if (isOpen) {
|
|
15455
|
+
dispatch({ type: 'GO_TO_LOGIN' });
|
|
15456
|
+
}
|
|
15457
|
+
}, [isOpen]);
|
|
15458
|
+
if (!isOpen) {
|
|
15459
|
+
return null;
|
|
15460
|
+
}
|
|
15461
|
+
const isModal = displayMode === 'modal';
|
|
15462
|
+
// Handle backdrop click for closeOnClickOutside
|
|
15463
|
+
const handleBackdropClick = (e) => {
|
|
15464
|
+
// Only close if clicking the backdrop itself, not the content
|
|
15465
|
+
if (closeOnClickOutside && e.target === e.currentTarget && onClose) {
|
|
15466
|
+
onClose();
|
|
15467
|
+
}
|
|
15468
|
+
};
|
|
15368
15469
|
if (isConfigLoading) {
|
|
15369
|
-
|
|
15470
|
+
const loadingContent = (React__default.createElement(r$3, null,
|
|
15370
15471
|
React__default.createElement(VStack, { alignItems: "center", justifyContent: "center", height: "300px" },
|
|
15371
15472
|
React__default.createElement(d$m, null))));
|
|
15473
|
+
if (isModal) {
|
|
15474
|
+
return (React__default.createElement("div", { style: modalBackdropStyles, onClick: handleBackdropClick },
|
|
15475
|
+
React__default.createElement("div", { style: modalContentStyles }, loadingContent)));
|
|
15476
|
+
}
|
|
15477
|
+
return loadingContent;
|
|
15478
|
+
}
|
|
15479
|
+
const widgetContent = (React__default.createElement(WidgetConfigProvider, { wallets: wallets, onSuccess: onSuccess, onError: onError, onClose: onClose, closeOnSuccess: closeOnSuccess },
|
|
15480
|
+
React__default.createElement(WagmiProvider, { config: wagmiConfig },
|
|
15481
|
+
React__default.createElement(QueryClientProvider, { client: queryClient },
|
|
15482
|
+
React__default.createElement("div", { id: "magic-widget-container" },
|
|
15483
|
+
React__default.createElement(WidgetContent, { state: state, dispatch: dispatch }))))));
|
|
15484
|
+
if (isModal) {
|
|
15485
|
+
return (React__default.createElement("div", { style: modalBackdropStyles, onClick: handleBackdropClick },
|
|
15486
|
+
React__default.createElement("div", { style: modalContentStyles }, widgetContent)));
|
|
15372
15487
|
}
|
|
15373
|
-
return
|
|
15374
|
-
React__default.createElement(QueryClientProvider, { client: queryClient },
|
|
15375
|
-
React__default.createElement("div", { id: "magic-widget-container" },
|
|
15376
|
-
React__default.createElement(WidgetContent, { state: state, dispatch: dispatch })))));
|
|
15488
|
+
return widgetContent;
|
|
15377
15489
|
}
|
|
15378
15490
|
|
|
15379
|
-
export { MAGIC_WIDGET_PROVIDER, MagicWidget, MagicWidgetExtension, getExtensionInstance };
|
|
15491
|
+
export { MAGIC_WIDGET_PROVIDER, MagicWidget, MagicWidgetExtension, OAuthProvider, ThirdPartyWallets, getExtensionInstance };
|
|
15380
15492
|
//# sourceMappingURL=index.mjs.map
|