@avalabs/avacloud-waas-react 1.0.1 → 1.0.3
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/README.md +27 -11
- package/dist/index.d.mts +47 -4
- package/dist/index.d.ts +47 -4
- package/dist/index.js +148 -104
- package/dist/index.mjs +144 -100
- package/dist/public/avacloud.png +0 -0
- package/package.json +5 -5
- package/public/avacloud.png +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @avalabs/avacloud-waas-react
|
|
2
2
|
|
|
3
|
-
Official React SDK for AvaCloud
|
|
3
|
+
Official React SDK for AvaCloud Wallet-as-a-Service (WaaS) integration. This library provides a seamless way to integrate AvaCloud wallet functionality into your React applications.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@avalabs/avacloud-waas-react)
|
|
6
6
|
[](https://github.com/ava-labs/avacloud-waas-react/blob/main/LICENSE)
|
|
@@ -38,7 +38,7 @@ function App() {
|
|
|
38
38
|
}
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
Use the
|
|
41
|
+
Use the wallet hooks and components in your application:
|
|
42
42
|
|
|
43
43
|
```tsx
|
|
44
44
|
import { useAvaCloudWallet, LoginButton, WalletDisplay } from '@avalabs/avacloud-waas-react';
|
|
@@ -69,11 +69,11 @@ function YourComponent() {
|
|
|
69
69
|
|
|
70
70
|
### AvaCloudWalletProvider
|
|
71
71
|
|
|
72
|
-
The main provider component that wraps your application and provides
|
|
72
|
+
The main provider component that wraps your application and provides wallet context.
|
|
73
73
|
|
|
74
74
|
```tsx
|
|
75
75
|
<AvaCloudWalletProvider
|
|
76
|
-
|
|
76
|
+
orgId="your-avacloud-org-id" // Required
|
|
77
77
|
chainId={43113}
|
|
78
78
|
darkMode={false}
|
|
79
79
|
onAuthSuccess={(user) => console.log('Auth success', user)}
|
|
@@ -88,7 +88,8 @@ The main provider component that wraps your application and provides authenticat
|
|
|
88
88
|
|
|
89
89
|
| Prop | Type | Description |
|
|
90
90
|
|------|------|-------------|
|
|
91
|
-
| `
|
|
91
|
+
| `orgId` | `string` | Required AvaCloud organization ID |
|
|
92
|
+
| `authServiceUrl` | `string` | (Optional) URL of the AvaCloud authentication service. Defaults to AvaCloud's production auth service. |
|
|
92
93
|
| `chainId` | `number` | (Optional) EVM chain ID to use (defaults to Avalanche Fuji Testnet - 43113) |
|
|
93
94
|
| `darkMode` | `boolean` | (Optional) Whether to use dark mode for UI components |
|
|
94
95
|
| `onAuthSuccess` | `(user: Auth0User) => void` | (Optional) Callback called when authentication is successful |
|
|
@@ -111,7 +112,7 @@ The main provider component that wraps your application and provides authenticat
|
|
|
111
112
|
|
|
112
113
|
### useAvaCloudWallet
|
|
113
114
|
|
|
114
|
-
The main hook for accessing
|
|
115
|
+
The main hook for accessing wallet state and methods.
|
|
115
116
|
|
|
116
117
|
```tsx
|
|
117
118
|
const {
|
|
@@ -192,6 +193,22 @@ const handleTransfer = async () => {
|
|
|
192
193
|
};
|
|
193
194
|
```
|
|
194
195
|
|
|
196
|
+
### useUserWallets
|
|
197
|
+
|
|
198
|
+
Hook for accessing and managing user wallets.
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
const { wallets, isLoading, error } = useUserWallets();
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### useChainId
|
|
205
|
+
|
|
206
|
+
Hook for accessing and setting the current chain ID.
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
const { chainId, setChainId } = useChainId();
|
|
210
|
+
```
|
|
211
|
+
|
|
195
212
|
## Advanced Usage
|
|
196
213
|
|
|
197
214
|
### Theme Customization
|
|
@@ -261,7 +278,7 @@ MIT © [Ava Labs, Inc.](https://github.com/ava-labs)
|
|
|
261
278
|
|
|
262
279
|
## Using the AvaCloud Organization ID
|
|
263
280
|
|
|
264
|
-
The `AvaCloudWalletProvider` requires an AvaCloud organization ID (`orgId`). This
|
|
281
|
+
The `AvaCloudWalletProvider` requires an AvaCloud organization ID (`orgId`). This is used to fetch the organization configuration from the AvaCloud API, which includes the mapping to the appropriate wallet service organization ID used for wallet operations.
|
|
265
282
|
|
|
266
283
|
```jsx
|
|
267
284
|
import { AvaCloudWalletProvider } from '@avalabs/avacloud-waas-react';
|
|
@@ -269,7 +286,6 @@ import { AvaCloudWalletProvider } from '@avalabs/avacloud-waas-react';
|
|
|
269
286
|
function App() {
|
|
270
287
|
return (
|
|
271
288
|
<AvaCloudWalletProvider
|
|
272
|
-
authServiceUrl="https://ac-auth-service.vercel.app/"
|
|
273
289
|
orgId="your-avacloud-org-id" // Required AvaCloud organization ID
|
|
274
290
|
>
|
|
275
291
|
<YourApp />
|
|
@@ -281,7 +297,7 @@ function App() {
|
|
|
281
297
|
When provided, the `orgId` will be used to:
|
|
282
298
|
|
|
283
299
|
1. Fetch the organization configuration from the AvaCloud API
|
|
284
|
-
2. Map to
|
|
285
|
-
3. Use the mapped ID for
|
|
300
|
+
2. Map to the appropriate wallet service organization ID
|
|
301
|
+
3. Use the mapped ID for wallet operations
|
|
286
302
|
|
|
287
|
-
This enables organizations to have their AvaCloud identity seamlessly map to their
|
|
303
|
+
This enables organizations to have their AvaCloud identity seamlessly map to their WaaS wallets.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _cubist_labs_cubesigner_sdk from '@cubist-labs/cubesigner-sdk';
|
|
3
3
|
import { IdentityProof, CubeSignerClient } from '@cubist-labs/cubesigner-sdk';
|
|
4
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
5
4
|
import { PropsWithChildren, ButtonHTMLAttributes } from 'react';
|
|
6
5
|
import { ButtonProps } from '@avalabs/core-k2-components';
|
|
7
6
|
import { Hex, TransactionRequest, Signature, Hash } from 'viem';
|
|
@@ -64,6 +63,44 @@ interface Auth0User$1 {
|
|
|
64
63
|
[key: string]: unknown;
|
|
65
64
|
}
|
|
66
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Organization configuration types
|
|
68
|
+
*/
|
|
69
|
+
/**
|
|
70
|
+
* Admin portal settings within organization configuration
|
|
71
|
+
*/
|
|
72
|
+
interface AdminPortalSettings {
|
|
73
|
+
/**
|
|
74
|
+
* Array of enabled social login providers
|
|
75
|
+
* Possible values: 'google', 'facebook', 'x', 'twitter', 'apple'
|
|
76
|
+
* Note: Some providers like 'facebook' may be in development and not fully supported
|
|
77
|
+
*/
|
|
78
|
+
socialLogins?: string[];
|
|
79
|
+
[key: string]: unknown;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Organization configuration interface
|
|
83
|
+
*/
|
|
84
|
+
interface OrgConfig {
|
|
85
|
+
/** Primary key of the organization */
|
|
86
|
+
PKey?: string;
|
|
87
|
+
/** Secondary key of the organization */
|
|
88
|
+
SKey?: string;
|
|
89
|
+
/** Organization ID */
|
|
90
|
+
orgID?: string;
|
|
91
|
+
/** Wallet provider organization ID used for Cubist */
|
|
92
|
+
walletProviderOrgID?: string;
|
|
93
|
+
/** Admin portal settings */
|
|
94
|
+
adminPortalSettings?: AdminPortalSettings;
|
|
95
|
+
/** Allowed origins for CORS */
|
|
96
|
+
originAllowlist?: string[];
|
|
97
|
+
/** Timestamp when the config was created */
|
|
98
|
+
createdAt?: number;
|
|
99
|
+
/** Timestamp when the config was last updated */
|
|
100
|
+
updatedAt?: number;
|
|
101
|
+
[key: string]: unknown;
|
|
102
|
+
}
|
|
103
|
+
|
|
67
104
|
/**
|
|
68
105
|
* Authentication message payload structure
|
|
69
106
|
*/
|
|
@@ -114,6 +151,12 @@ declare enum VM {
|
|
|
114
151
|
PVM = "PVM"
|
|
115
152
|
}
|
|
116
153
|
|
|
154
|
+
type QueryClient = {
|
|
155
|
+
invalidateQueries: (options: {
|
|
156
|
+
queryKey: string[];
|
|
157
|
+
}) => void;
|
|
158
|
+
};
|
|
159
|
+
|
|
117
160
|
/**
|
|
118
161
|
* Possible AvaCloud environments
|
|
119
162
|
*/
|
|
@@ -240,7 +283,7 @@ type AuthMessage = IframeReadyMessage | CheckAuthStatusMessage | AuthStatusMessa
|
|
|
240
283
|
*/
|
|
241
284
|
interface AvaCloudWalletProviderProps {
|
|
242
285
|
children: React.ReactNode;
|
|
243
|
-
authServiceUrl
|
|
286
|
+
authServiceUrl?: string;
|
|
244
287
|
orgId: string;
|
|
245
288
|
chainId?: number;
|
|
246
289
|
darkMode?: boolean;
|
|
@@ -257,7 +300,7 @@ interface AvaCloudWalletContextType {
|
|
|
257
300
|
isLoading: boolean;
|
|
258
301
|
user: UserInfo | null;
|
|
259
302
|
wallet: WalletInfo;
|
|
260
|
-
orgConfig:
|
|
303
|
+
orgConfig: OrgConfig | null;
|
|
261
304
|
logout: () => void;
|
|
262
305
|
loginWithCubist: (oidcToken?: string) => Promise<void>;
|
|
263
306
|
cubistClient: CubeSignerClient | null;
|
|
@@ -470,4 +513,4 @@ interface UseUserWalletsResult {
|
|
|
470
513
|
}
|
|
471
514
|
declare function useUserWallets(): UseUserWalletsResult;
|
|
472
515
|
|
|
473
|
-
export { type AddAccountMessage, type Auth0User, type AuthMessage, type AuthMessagePayload, type AuthStateUpdateMessage, type AuthStatusMessage, type AvaCloudEnvironment, type AvaCloudWalletContextType, AvaCloudWalletProvider, type AvaCloudWalletProviderProps, type BaseAuthMessage, type CheckAuthStatusMessage, type CubistWalletInfo, type ErrorMessage, ExportView, type GetOidcMessage, type IframeReadyMessage, LoginButton, type LoginRequestMessage, type LogoutRequestMessage, type MessageType, type ReceiveOidcMessage, ReceiveView, type RegisterMessage, type RegisterPayload, type RegisterSuccessMessage, SendView, ThemeProvider, TokensView, type UserInfo, UserProfile, VM, WalletButton, WalletCard, WalletDisplay, type WalletInfo, type WalletKeysErrorMessage, type WalletKeysUpdateMessage, useAuth, useAvaCloudWallet, useChainId, usePostMessage, useSignMessage, useSignTransaction, useThemeMode, useTransferTokens, useUserWallets };
|
|
516
|
+
export { type AddAccountMessage, type AdminPortalSettings, type Auth0User, type AuthMessage, type AuthMessagePayload, type AuthStateUpdateMessage, type AuthStatusMessage, type AvaCloudEnvironment, type AvaCloudWalletContextType, AvaCloudWalletProvider, type AvaCloudWalletProviderProps, type BaseAuthMessage, type CheckAuthStatusMessage, type CubistWalletInfo, type ErrorMessage, ExportView, type GetOidcMessage, type IframeReadyMessage, LoginButton, type LoginRequestMessage, type LogoutRequestMessage, type MessageType, type OrgConfig, type ReceiveOidcMessage, ReceiveView, type RegisterMessage, type RegisterPayload, type RegisterSuccessMessage, SendView, ThemeProvider, TokensView, type UserInfo, UserProfile, VM, WalletButton, WalletCard, WalletDisplay, type WalletInfo, type WalletKeysErrorMessage, type WalletKeysUpdateMessage, useAuth, useAvaCloudWallet, useChainId, usePostMessage, useSignMessage, useSignTransaction, useThemeMode, useTransferTokens, useUserWallets };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _cubist_labs_cubesigner_sdk from '@cubist-labs/cubesigner-sdk';
|
|
3
3
|
import { IdentityProof, CubeSignerClient } from '@cubist-labs/cubesigner-sdk';
|
|
4
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
5
4
|
import { PropsWithChildren, ButtonHTMLAttributes } from 'react';
|
|
6
5
|
import { ButtonProps } from '@avalabs/core-k2-components';
|
|
7
6
|
import { Hex, TransactionRequest, Signature, Hash } from 'viem';
|
|
@@ -64,6 +63,44 @@ interface Auth0User$1 {
|
|
|
64
63
|
[key: string]: unknown;
|
|
65
64
|
}
|
|
66
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Organization configuration types
|
|
68
|
+
*/
|
|
69
|
+
/**
|
|
70
|
+
* Admin portal settings within organization configuration
|
|
71
|
+
*/
|
|
72
|
+
interface AdminPortalSettings {
|
|
73
|
+
/**
|
|
74
|
+
* Array of enabled social login providers
|
|
75
|
+
* Possible values: 'google', 'facebook', 'x', 'twitter', 'apple'
|
|
76
|
+
* Note: Some providers like 'facebook' may be in development and not fully supported
|
|
77
|
+
*/
|
|
78
|
+
socialLogins?: string[];
|
|
79
|
+
[key: string]: unknown;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Organization configuration interface
|
|
83
|
+
*/
|
|
84
|
+
interface OrgConfig {
|
|
85
|
+
/** Primary key of the organization */
|
|
86
|
+
PKey?: string;
|
|
87
|
+
/** Secondary key of the organization */
|
|
88
|
+
SKey?: string;
|
|
89
|
+
/** Organization ID */
|
|
90
|
+
orgID?: string;
|
|
91
|
+
/** Wallet provider organization ID used for Cubist */
|
|
92
|
+
walletProviderOrgID?: string;
|
|
93
|
+
/** Admin portal settings */
|
|
94
|
+
adminPortalSettings?: AdminPortalSettings;
|
|
95
|
+
/** Allowed origins for CORS */
|
|
96
|
+
originAllowlist?: string[];
|
|
97
|
+
/** Timestamp when the config was created */
|
|
98
|
+
createdAt?: number;
|
|
99
|
+
/** Timestamp when the config was last updated */
|
|
100
|
+
updatedAt?: number;
|
|
101
|
+
[key: string]: unknown;
|
|
102
|
+
}
|
|
103
|
+
|
|
67
104
|
/**
|
|
68
105
|
* Authentication message payload structure
|
|
69
106
|
*/
|
|
@@ -114,6 +151,12 @@ declare enum VM {
|
|
|
114
151
|
PVM = "PVM"
|
|
115
152
|
}
|
|
116
153
|
|
|
154
|
+
type QueryClient = {
|
|
155
|
+
invalidateQueries: (options: {
|
|
156
|
+
queryKey: string[];
|
|
157
|
+
}) => void;
|
|
158
|
+
};
|
|
159
|
+
|
|
117
160
|
/**
|
|
118
161
|
* Possible AvaCloud environments
|
|
119
162
|
*/
|
|
@@ -240,7 +283,7 @@ type AuthMessage = IframeReadyMessage | CheckAuthStatusMessage | AuthStatusMessa
|
|
|
240
283
|
*/
|
|
241
284
|
interface AvaCloudWalletProviderProps {
|
|
242
285
|
children: React.ReactNode;
|
|
243
|
-
authServiceUrl
|
|
286
|
+
authServiceUrl?: string;
|
|
244
287
|
orgId: string;
|
|
245
288
|
chainId?: number;
|
|
246
289
|
darkMode?: boolean;
|
|
@@ -257,7 +300,7 @@ interface AvaCloudWalletContextType {
|
|
|
257
300
|
isLoading: boolean;
|
|
258
301
|
user: UserInfo | null;
|
|
259
302
|
wallet: WalletInfo;
|
|
260
|
-
orgConfig:
|
|
303
|
+
orgConfig: OrgConfig | null;
|
|
261
304
|
logout: () => void;
|
|
262
305
|
loginWithCubist: (oidcToken?: string) => Promise<void>;
|
|
263
306
|
cubistClient: CubeSignerClient | null;
|
|
@@ -470,4 +513,4 @@ interface UseUserWalletsResult {
|
|
|
470
513
|
}
|
|
471
514
|
declare function useUserWallets(): UseUserWalletsResult;
|
|
472
515
|
|
|
473
|
-
export { type AddAccountMessage, type Auth0User, type AuthMessage, type AuthMessagePayload, type AuthStateUpdateMessage, type AuthStatusMessage, type AvaCloudEnvironment, type AvaCloudWalletContextType, AvaCloudWalletProvider, type AvaCloudWalletProviderProps, type BaseAuthMessage, type CheckAuthStatusMessage, type CubistWalletInfo, type ErrorMessage, ExportView, type GetOidcMessage, type IframeReadyMessage, LoginButton, type LoginRequestMessage, type LogoutRequestMessage, type MessageType, type ReceiveOidcMessage, ReceiveView, type RegisterMessage, type RegisterPayload, type RegisterSuccessMessage, SendView, ThemeProvider, TokensView, type UserInfo, UserProfile, VM, WalletButton, WalletCard, WalletDisplay, type WalletInfo, type WalletKeysErrorMessage, type WalletKeysUpdateMessage, useAuth, useAvaCloudWallet, useChainId, usePostMessage, useSignMessage, useSignTransaction, useThemeMode, useTransferTokens, useUserWallets };
|
|
516
|
+
export { type AddAccountMessage, type AdminPortalSettings, type Auth0User, type AuthMessage, type AuthMessagePayload, type AuthStateUpdateMessage, type AuthStatusMessage, type AvaCloudEnvironment, type AvaCloudWalletContextType, AvaCloudWalletProvider, type AvaCloudWalletProviderProps, type BaseAuthMessage, type CheckAuthStatusMessage, type CubistWalletInfo, type ErrorMessage, ExportView, type GetOidcMessage, type IframeReadyMessage, LoginButton, type LoginRequestMessage, type LogoutRequestMessage, type MessageType, type OrgConfig, type ReceiveOidcMessage, ReceiveView, type RegisterMessage, type RegisterPayload, type RegisterSuccessMessage, SendView, ThemeProvider, TokensView, type UserInfo, UserProfile, VM, WalletButton, WalletCard, WalletDisplay, type WalletInfo, type WalletKeysErrorMessage, type WalletKeysUpdateMessage, useAuth, useAvaCloudWallet, useChainId, usePostMessage, useSignMessage, useSignTransaction, useThemeMode, useTransferTokens, useUserWallets };
|
package/dist/index.js
CHANGED
|
@@ -79,7 +79,20 @@ function getDerivationPath(vm, accountIndex) {
|
|
|
79
79
|
|
|
80
80
|
// src/hooks/usePostMessage.ts
|
|
81
81
|
var import_react = require("react");
|
|
82
|
-
|
|
82
|
+
|
|
83
|
+
// src/constants/storage.ts
|
|
84
|
+
var OIDC_TOKEN_KEY = "avacloud-auth-oidc-token";
|
|
85
|
+
var AUTH_TOKENS_KEY = "auth_tokens";
|
|
86
|
+
var AUTH0_STORAGE_KEYS = {
|
|
87
|
+
IS_AUTHENTICATED: "auth0.is.authenticated",
|
|
88
|
+
ACCESS_TOKEN: "auth0.access_token",
|
|
89
|
+
ID_TOKEN: "auth0.id_token",
|
|
90
|
+
EXPIRES_AT: "auth0.expires_at"
|
|
91
|
+
};
|
|
92
|
+
var CUBIST_USER_ID_KEY = "cubist_user_id";
|
|
93
|
+
var ORG_CONFIG_CACHE_KEY = "avacloud-org-config-cache";
|
|
94
|
+
|
|
95
|
+
// src/hooks/usePostMessage.ts
|
|
83
96
|
function usePostMessage({
|
|
84
97
|
authServiceUrl,
|
|
85
98
|
orgId,
|
|
@@ -103,6 +116,30 @@ function usePostMessage({
|
|
|
103
116
|
});
|
|
104
117
|
const hasRequestedOidcRef = (0, import_react.useRef)(false);
|
|
105
118
|
const isHandlingMessageRef = (0, import_react.useRef)(false);
|
|
119
|
+
const hasLoadedCacheRef = (0, import_react.useRef)(false);
|
|
120
|
+
(0, import_react.useEffect)(() => {
|
|
121
|
+
if (orgId && onOrgConfigUpdate && !hasLoadedCacheRef.current) {
|
|
122
|
+
hasLoadedCacheRef.current = true;
|
|
123
|
+
try {
|
|
124
|
+
const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`;
|
|
125
|
+
const cachedConfigJson = localStorage.getItem(cachedConfigKey);
|
|
126
|
+
if (cachedConfigJson) {
|
|
127
|
+
const cachedConfig = JSON.parse(cachedConfigJson);
|
|
128
|
+
const timestamp = cachedConfig._timestamp || 0;
|
|
129
|
+
const isExpired = Date.now() - timestamp > 30 * 60 * 1e3;
|
|
130
|
+
if (!isExpired) {
|
|
131
|
+
const { _timestamp, ...configWithoutTimestamp } = cachedConfig;
|
|
132
|
+
console.log("Using cached org config:", configWithoutTimestamp);
|
|
133
|
+
onOrgConfigUpdate(configWithoutTimestamp);
|
|
134
|
+
} else {
|
|
135
|
+
console.log("Cached org config expired, will fetch fresh data");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error("Error loading cached org config:", error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}, [orgId, environment, onOrgConfigUpdate]);
|
|
106
143
|
const sendMessage = (0, import_react.useCallback)((message) => {
|
|
107
144
|
if (iframe == null ? void 0 : iframe.contentWindow) {
|
|
108
145
|
try {
|
|
@@ -178,9 +215,9 @@ function usePostMessage({
|
|
|
178
215
|
}
|
|
179
216
|
} else {
|
|
180
217
|
setUser(null);
|
|
181
|
-
localStorage.removeItem(
|
|
182
|
-
localStorage.removeItem(
|
|
183
|
-
sessionStorage.removeItem(
|
|
218
|
+
localStorage.removeItem(AUTH_TOKENS_KEY);
|
|
219
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.IS_AUTHENTICATED);
|
|
220
|
+
sessionStorage.removeItem(OIDC_TOKEN_KEY);
|
|
184
221
|
}
|
|
185
222
|
lastAuthStateRef.current = {
|
|
186
223
|
isAuthenticated: newIsAuthenticated,
|
|
@@ -190,7 +227,7 @@ function usePostMessage({
|
|
|
190
227
|
if (newIsAuthenticated && event.data.user) {
|
|
191
228
|
if (!hasRequestedOidcRef.current) {
|
|
192
229
|
if (event.data.tokens) {
|
|
193
|
-
localStorage.setItem(
|
|
230
|
+
localStorage.setItem(AUTH_TOKENS_KEY, JSON.stringify(event.data.tokens));
|
|
194
231
|
}
|
|
195
232
|
onAuthSuccess == null ? void 0 : onAuthSuccess();
|
|
196
233
|
}
|
|
@@ -199,6 +236,19 @@ function usePostMessage({
|
|
|
199
236
|
if (event.data.orgConfig && onOrgConfigUpdate) {
|
|
200
237
|
console.log("Received organization config:", event.data.orgConfig);
|
|
201
238
|
onOrgConfigUpdate(event.data.orgConfig);
|
|
239
|
+
if (orgId) {
|
|
240
|
+
try {
|
|
241
|
+
const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`;
|
|
242
|
+
const configWithTimestamp = {
|
|
243
|
+
...event.data.orgConfig,
|
|
244
|
+
_timestamp: Date.now()
|
|
245
|
+
};
|
|
246
|
+
localStorage.setItem(cachedConfigKey, JSON.stringify(configWithTimestamp));
|
|
247
|
+
console.log("Cached organization config for future use");
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.error("Error caching org config:", error);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
202
252
|
}
|
|
203
253
|
if (!hasRequestedOidcRef.current) {
|
|
204
254
|
setIsLoading(false);
|
|
@@ -209,7 +259,7 @@ function usePostMessage({
|
|
|
209
259
|
console.log("Registration successful:", event.data.payload);
|
|
210
260
|
const userId = (_f = event.data.payload) == null ? void 0 : _f.userId;
|
|
211
261
|
if (userId) {
|
|
212
|
-
localStorage.setItem(
|
|
262
|
+
localStorage.setItem(CUBIST_USER_ID_KEY, userId);
|
|
213
263
|
if (!hasRequestedOidcRef.current) {
|
|
214
264
|
console.log("Registration complete, sending GET_OIDC message");
|
|
215
265
|
hasRequestedOidcRef.current = true;
|
|
@@ -241,7 +291,9 @@ function usePostMessage({
|
|
|
241
291
|
setIsLoading,
|
|
242
292
|
setUser,
|
|
243
293
|
sendMessage,
|
|
244
|
-
cubistClient
|
|
294
|
+
cubistClient,
|
|
295
|
+
orgId,
|
|
296
|
+
environment
|
|
245
297
|
]);
|
|
246
298
|
(0, import_react.useEffect)(() => {
|
|
247
299
|
if (isIframeReady && (iframe == null ? void 0 : iframe.contentWindow)) {
|
|
@@ -287,11 +339,70 @@ function PoweredByAvaCloud() {
|
|
|
287
339
|
|
|
288
340
|
// src/components/SignInContent.tsx
|
|
289
341
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
290
|
-
function SignInContent({
|
|
342
|
+
function SignInContent({
|
|
343
|
+
onEmailLogin,
|
|
344
|
+
onProviderLogin,
|
|
345
|
+
error,
|
|
346
|
+
isSubmitting,
|
|
347
|
+
socialLogins = ["google", "x", "apple"]
|
|
348
|
+
}) {
|
|
291
349
|
const [email, setEmail] = (0, import_react2.useState)("");
|
|
292
350
|
const [password, setPassword] = (0, import_react2.useState)("");
|
|
293
351
|
const [isPasswordStep, setIsPasswordStep] = (0, import_react2.useState)(false);
|
|
294
|
-
const
|
|
352
|
+
const providerConnectionMap = {
|
|
353
|
+
"google": "google-oauth2",
|
|
354
|
+
"x": "twitter",
|
|
355
|
+
"twitter": "twitter",
|
|
356
|
+
"facebook": "facebook",
|
|
357
|
+
"apple": "apple"
|
|
358
|
+
};
|
|
359
|
+
const renderSocialLoginButton = (loginType) => {
|
|
360
|
+
if (!providerConnectionMap[loginType]) return null;
|
|
361
|
+
const connectionName = providerConnectionMap[loginType];
|
|
362
|
+
let LoginIcon;
|
|
363
|
+
switch (loginType) {
|
|
364
|
+
case "google":
|
|
365
|
+
LoginIcon = import_core_k2_components2.GoogleIcon;
|
|
366
|
+
break;
|
|
367
|
+
case "x":
|
|
368
|
+
case "twitter":
|
|
369
|
+
LoginIcon = import_core_k2_components2.XTwitterIcon;
|
|
370
|
+
break;
|
|
371
|
+
case "facebook":
|
|
372
|
+
LoginIcon = import_core_k2_components2.FacebookIcon;
|
|
373
|
+
break;
|
|
374
|
+
case "apple":
|
|
375
|
+
LoginIcon = import_core_k2_components2.AppleIcon;
|
|
376
|
+
break;
|
|
377
|
+
default:
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
381
|
+
import_core_k2_components2.IconButton,
|
|
382
|
+
{
|
|
383
|
+
color: "default",
|
|
384
|
+
variant: "contained",
|
|
385
|
+
onClick: () => onProviderLogin(connectionName),
|
|
386
|
+
disabled: isSubmitting,
|
|
387
|
+
sx: {
|
|
388
|
+
display: "flex",
|
|
389
|
+
padding: "16px",
|
|
390
|
+
alignItems: "center",
|
|
391
|
+
gap: "8px",
|
|
392
|
+
borderRadius: "8px",
|
|
393
|
+
background: "rgba(0, 0, 0, 0.02)",
|
|
394
|
+
boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
|
|
395
|
+
width: 72,
|
|
396
|
+
height: 72,
|
|
397
|
+
"&:hover": {
|
|
398
|
+
background: "rgba(0, 0, 0, 0.04)"
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LoginIcon, { sx: { width: 24, height: 24 } })
|
|
402
|
+
},
|
|
403
|
+
loginType
|
|
404
|
+
);
|
|
405
|
+
};
|
|
295
406
|
const handleEmailSubmit = (e) => {
|
|
296
407
|
e.preventDefault();
|
|
297
408
|
if (!email) return;
|
|
@@ -307,7 +418,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
307
418
|
};
|
|
308
419
|
const titleTypography = {
|
|
309
420
|
alignSelf: "stretch",
|
|
310
|
-
color: (
|
|
421
|
+
color: (theme) => theme.palette.mode === "dark" ? "#FFFFFF" : "rgba(0, 0, 0, 0.80)",
|
|
311
422
|
fontFamily: "Inter",
|
|
312
423
|
fontSize: "16px",
|
|
313
424
|
fontStyle: "normal",
|
|
@@ -332,7 +443,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
332
443
|
helperText: error,
|
|
333
444
|
sx: {
|
|
334
445
|
"& .MuiOutlinedInput-root": {
|
|
335
|
-
backgroundColor: (
|
|
446
|
+
backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
|
|
336
447
|
}
|
|
337
448
|
}
|
|
338
449
|
}
|
|
@@ -466,80 +577,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
466
577
|
}
|
|
467
578
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 3, children: [
|
|
468
579
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Typography, { variant: "h6", sx: titleTypography, children: "Sign in with" }),
|
|
469
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
470
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
471
|
-
import_core_k2_components2.IconButton,
|
|
472
|
-
{
|
|
473
|
-
color: "default",
|
|
474
|
-
variant: "contained",
|
|
475
|
-
onClick: () => onProviderLogin("google-oauth2"),
|
|
476
|
-
disabled: isSubmitting,
|
|
477
|
-
sx: {
|
|
478
|
-
display: "flex",
|
|
479
|
-
padding: "16px",
|
|
480
|
-
alignItems: "center",
|
|
481
|
-
gap: "8px",
|
|
482
|
-
borderRadius: "8px",
|
|
483
|
-
background: "rgba(0, 0, 0, 0.02)",
|
|
484
|
-
boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
|
|
485
|
-
width: 72,
|
|
486
|
-
height: 72,
|
|
487
|
-
"&:hover": {
|
|
488
|
-
background: "rgba(0, 0, 0, 0.04)"
|
|
489
|
-
}
|
|
490
|
-
},
|
|
491
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.GoogleColorIcon, { sx: { width: 24, height: 24 } })
|
|
492
|
-
}
|
|
493
|
-
),
|
|
494
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
495
|
-
import_core_k2_components2.IconButton,
|
|
496
|
-
{
|
|
497
|
-
color: "default",
|
|
498
|
-
variant: "contained",
|
|
499
|
-
onClick: () => onProviderLogin("twitter"),
|
|
500
|
-
disabled: isSubmitting,
|
|
501
|
-
sx: {
|
|
502
|
-
display: "flex",
|
|
503
|
-
padding: "16px",
|
|
504
|
-
alignItems: "center",
|
|
505
|
-
gap: "8px",
|
|
506
|
-
borderRadius: "8px",
|
|
507
|
-
background: "rgba(0, 0, 0, 0.02)",
|
|
508
|
-
boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
|
|
509
|
-
width: 72,
|
|
510
|
-
height: 72,
|
|
511
|
-
"&:hover": {
|
|
512
|
-
background: "rgba(0, 0, 0, 0.04)"
|
|
513
|
-
}
|
|
514
|
-
},
|
|
515
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.XTwitterIcon, { sx: { width: 24, height: 24 } })
|
|
516
|
-
}
|
|
517
|
-
),
|
|
518
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
519
|
-
import_core_k2_components2.IconButton,
|
|
520
|
-
{
|
|
521
|
-
color: "default",
|
|
522
|
-
variant: "contained",
|
|
523
|
-
onClick: () => onProviderLogin("apple"),
|
|
524
|
-
disabled: isSubmitting,
|
|
525
|
-
sx: {
|
|
526
|
-
display: "flex",
|
|
527
|
-
padding: "16px",
|
|
528
|
-
alignItems: "center",
|
|
529
|
-
gap: "8px",
|
|
530
|
-
borderRadius: "8px",
|
|
531
|
-
background: "rgba(0, 0, 0, 0.02)",
|
|
532
|
-
boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
|
|
533
|
-
width: 72,
|
|
534
|
-
height: 72,
|
|
535
|
-
"&:hover": {
|
|
536
|
-
background: "rgba(0, 0, 0, 0.04)"
|
|
537
|
-
}
|
|
538
|
-
},
|
|
539
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.AppleIcon, { sx: { width: 24, height: 24 } })
|
|
540
|
-
}
|
|
541
|
-
)
|
|
542
|
-
] }),
|
|
580
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Stack, { direction: "row", spacing: 3, sx: { justifyContent: "center" }, children: socialLogins.map((loginType) => renderSocialLoginButton(loginType)) }),
|
|
543
581
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Divider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Typography, { variant: "body2", color: "text.secondary", children: "or" }) }),
|
|
544
582
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("form", { onSubmit: handleEmailSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 2, children: [
|
|
545
583
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -556,7 +594,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
556
594
|
helperText: error,
|
|
557
595
|
sx: {
|
|
558
596
|
"& .MuiOutlinedInput-root": {
|
|
559
|
-
backgroundColor: (
|
|
597
|
+
backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
|
|
560
598
|
}
|
|
561
599
|
}
|
|
562
600
|
}
|
|
@@ -659,9 +697,11 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
659
697
|
// src/components/Modal.tsx
|
|
660
698
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
661
699
|
function LoginModal({ open, onClose }) {
|
|
662
|
-
|
|
700
|
+
var _a;
|
|
701
|
+
const { iframe, orgConfig } = useAvaCloudWallet();
|
|
663
702
|
const [isSubmitting, setIsSubmitting] = (0, import_react3.useState)(false);
|
|
664
703
|
const [error, setError] = (0, import_react3.useState)("");
|
|
704
|
+
const socialLogins = (_a = orgConfig == null ? void 0 : orgConfig.adminPortalSettings) == null ? void 0 : _a.socialLogins;
|
|
665
705
|
(0, import_react3.useEffect)(() => {
|
|
666
706
|
const handleMessage = (event) => {
|
|
667
707
|
if (event.data.type === "ERROR") {
|
|
@@ -676,11 +716,11 @@ function LoginModal({ open, onClose }) {
|
|
|
676
716
|
return () => window.removeEventListener("message", handleMessage);
|
|
677
717
|
}, [onClose]);
|
|
678
718
|
const handleProviderLogin = (provider) => {
|
|
679
|
-
var
|
|
719
|
+
var _a2;
|
|
680
720
|
setError("");
|
|
681
721
|
if (iframe) {
|
|
682
722
|
console.log(`Sending LOGIN_REQUEST to auth service iframe with ${provider} connection`);
|
|
683
|
-
(
|
|
723
|
+
(_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({
|
|
684
724
|
type: "LOGIN_REQUEST",
|
|
685
725
|
connection: provider
|
|
686
726
|
}, "*");
|
|
@@ -691,12 +731,12 @@ function LoginModal({ open, onClose }) {
|
|
|
691
731
|
}
|
|
692
732
|
};
|
|
693
733
|
const handleEmailLogin = (email, password) => {
|
|
694
|
-
var
|
|
734
|
+
var _a2;
|
|
695
735
|
setError("");
|
|
696
736
|
setIsSubmitting(true);
|
|
697
737
|
if (iframe) {
|
|
698
738
|
console.log("Sending email/password LOGIN_REQUEST to auth service iframe");
|
|
699
|
-
(
|
|
739
|
+
(_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({
|
|
700
740
|
type: "LOGIN_REQUEST",
|
|
701
741
|
email,
|
|
702
742
|
password
|
|
@@ -780,7 +820,8 @@ function LoginModal({ open, onClose }) {
|
|
|
780
820
|
onEmailLogin: handleEmailLogin,
|
|
781
821
|
onProviderLogin: handleProviderLogin,
|
|
782
822
|
error,
|
|
783
|
-
isSubmitting
|
|
823
|
+
isSubmitting,
|
|
824
|
+
socialLogins
|
|
784
825
|
}
|
|
785
826
|
) })
|
|
786
827
|
]
|
|
@@ -1181,7 +1222,6 @@ function ThemeProvider({ children, darkMode, onDarkModeChange }) {
|
|
|
1181
1222
|
}
|
|
1182
1223
|
|
|
1183
1224
|
// src/AvaCloudWalletProvider.tsx
|
|
1184
|
-
var import_waas_common2 = require("@avacloud/waas-common");
|
|
1185
1225
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1186
1226
|
var AvaCloudWalletContext = (0, import_react9.createContext)(void 0);
|
|
1187
1227
|
var queryClient = new import_react_query2.QueryClient({
|
|
@@ -1284,7 +1324,7 @@ function AvaCloudWalletProvider({
|
|
|
1284
1324
|
accessToken = oidcToken;
|
|
1285
1325
|
} else {
|
|
1286
1326
|
console.log("[loginWithCubist] Attempting to get OIDC token from localStorage.");
|
|
1287
|
-
const tokens = localStorage.getItem(
|
|
1327
|
+
const tokens = localStorage.getItem(AUTH_TOKENS_KEY);
|
|
1288
1328
|
if (!tokens) {
|
|
1289
1329
|
throw new Error("No authentication tokens found in localStorage");
|
|
1290
1330
|
}
|
|
@@ -1340,8 +1380,8 @@ function AvaCloudWalletProvider({
|
|
|
1340
1380
|
}
|
|
1341
1381
|
} catch (error) {
|
|
1342
1382
|
console.error("[loginWithCubist] Error during Cubist session creation/wallet info:", error);
|
|
1343
|
-
localStorage.removeItem(
|
|
1344
|
-
localStorage.removeItem(
|
|
1383
|
+
localStorage.removeItem(AUTH_TOKENS_KEY);
|
|
1384
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.IS_AUTHENTICATED);
|
|
1345
1385
|
setIsAuthenticated(false);
|
|
1346
1386
|
setUser(null);
|
|
1347
1387
|
setCubistClient(null);
|
|
@@ -1435,17 +1475,21 @@ function AvaCloudWalletProvider({
|
|
|
1435
1475
|
setUser(null);
|
|
1436
1476
|
setWallet({ address: null });
|
|
1437
1477
|
setIsAuthenticated(false);
|
|
1438
|
-
localStorage.removeItem(
|
|
1439
|
-
localStorage.removeItem(
|
|
1440
|
-
localStorage.removeItem(
|
|
1441
|
-
localStorage.removeItem(
|
|
1442
|
-
localStorage.removeItem(
|
|
1443
|
-
localStorage.removeItem(
|
|
1444
|
-
|
|
1478
|
+
localStorage.removeItem(AUTH_TOKENS_KEY);
|
|
1479
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.IS_AUTHENTICATED);
|
|
1480
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.ACCESS_TOKEN);
|
|
1481
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.ID_TOKEN);
|
|
1482
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.EXPIRES_AT);
|
|
1483
|
+
localStorage.removeItem(CUBIST_USER_ID_KEY);
|
|
1484
|
+
if (orgId) {
|
|
1485
|
+
const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`;
|
|
1486
|
+
localStorage.removeItem(cachedConfigKey);
|
|
1487
|
+
}
|
|
1488
|
+
sessionStorage.removeItem(OIDC_TOKEN_KEY);
|
|
1445
1489
|
setCubistClient(null);
|
|
1446
1490
|
setCubistError(null);
|
|
1447
1491
|
setPendingOidcToken(null);
|
|
1448
|
-
}, [sendMessage]);
|
|
1492
|
+
}, [sendMessage, orgId, environment]);
|
|
1449
1493
|
const addAccount = (0, import_react9.useCallback)(async (accountIndex) => {
|
|
1450
1494
|
console.log("[addAccount] Called with accountIndex:", accountIndex);
|
|
1451
1495
|
if (!isAuthenticated || !user || !wallet.mnemonicId) {
|
package/dist/index.mjs
CHANGED
|
@@ -33,7 +33,20 @@ function getDerivationPath(vm, accountIndex) {
|
|
|
33
33
|
|
|
34
34
|
// src/hooks/usePostMessage.ts
|
|
35
35
|
import { useCallback, useEffect, useRef } from "react";
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
// src/constants/storage.ts
|
|
38
|
+
var OIDC_TOKEN_KEY = "avacloud-auth-oidc-token";
|
|
39
|
+
var AUTH_TOKENS_KEY = "auth_tokens";
|
|
40
|
+
var AUTH0_STORAGE_KEYS = {
|
|
41
|
+
IS_AUTHENTICATED: "auth0.is.authenticated",
|
|
42
|
+
ACCESS_TOKEN: "auth0.access_token",
|
|
43
|
+
ID_TOKEN: "auth0.id_token",
|
|
44
|
+
EXPIRES_AT: "auth0.expires_at"
|
|
45
|
+
};
|
|
46
|
+
var CUBIST_USER_ID_KEY = "cubist_user_id";
|
|
47
|
+
var ORG_CONFIG_CACHE_KEY = "avacloud-org-config-cache";
|
|
48
|
+
|
|
49
|
+
// src/hooks/usePostMessage.ts
|
|
37
50
|
function usePostMessage({
|
|
38
51
|
authServiceUrl,
|
|
39
52
|
orgId,
|
|
@@ -57,6 +70,30 @@ function usePostMessage({
|
|
|
57
70
|
});
|
|
58
71
|
const hasRequestedOidcRef = useRef(false);
|
|
59
72
|
const isHandlingMessageRef = useRef(false);
|
|
73
|
+
const hasLoadedCacheRef = useRef(false);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (orgId && onOrgConfigUpdate && !hasLoadedCacheRef.current) {
|
|
76
|
+
hasLoadedCacheRef.current = true;
|
|
77
|
+
try {
|
|
78
|
+
const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`;
|
|
79
|
+
const cachedConfigJson = localStorage.getItem(cachedConfigKey);
|
|
80
|
+
if (cachedConfigJson) {
|
|
81
|
+
const cachedConfig = JSON.parse(cachedConfigJson);
|
|
82
|
+
const timestamp = cachedConfig._timestamp || 0;
|
|
83
|
+
const isExpired = Date.now() - timestamp > 30 * 60 * 1e3;
|
|
84
|
+
if (!isExpired) {
|
|
85
|
+
const { _timestamp, ...configWithoutTimestamp } = cachedConfig;
|
|
86
|
+
console.log("Using cached org config:", configWithoutTimestamp);
|
|
87
|
+
onOrgConfigUpdate(configWithoutTimestamp);
|
|
88
|
+
} else {
|
|
89
|
+
console.log("Cached org config expired, will fetch fresh data");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error("Error loading cached org config:", error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}, [orgId, environment, onOrgConfigUpdate]);
|
|
60
97
|
const sendMessage = useCallback((message) => {
|
|
61
98
|
if (iframe == null ? void 0 : iframe.contentWindow) {
|
|
62
99
|
try {
|
|
@@ -153,6 +190,19 @@ function usePostMessage({
|
|
|
153
190
|
if (event.data.orgConfig && onOrgConfigUpdate) {
|
|
154
191
|
console.log("Received organization config:", event.data.orgConfig);
|
|
155
192
|
onOrgConfigUpdate(event.data.orgConfig);
|
|
193
|
+
if (orgId) {
|
|
194
|
+
try {
|
|
195
|
+
const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`;
|
|
196
|
+
const configWithTimestamp = {
|
|
197
|
+
...event.data.orgConfig,
|
|
198
|
+
_timestamp: Date.now()
|
|
199
|
+
};
|
|
200
|
+
localStorage.setItem(cachedConfigKey, JSON.stringify(configWithTimestamp));
|
|
201
|
+
console.log("Cached organization config for future use");
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error("Error caching org config:", error);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
156
206
|
}
|
|
157
207
|
if (!hasRequestedOidcRef.current) {
|
|
158
208
|
setIsLoading(false);
|
|
@@ -195,7 +245,9 @@ function usePostMessage({
|
|
|
195
245
|
setIsLoading,
|
|
196
246
|
setUser,
|
|
197
247
|
sendMessage,
|
|
198
|
-
cubistClient
|
|
248
|
+
cubistClient,
|
|
249
|
+
orgId,
|
|
250
|
+
environment
|
|
199
251
|
]);
|
|
200
252
|
useEffect(() => {
|
|
201
253
|
if (isIframeReady && (iframe == null ? void 0 : iframe.contentWindow)) {
|
|
@@ -224,7 +276,7 @@ import { Dialog, DialogContent, IconButton as IconButton2, Stack as Stack3, XIco
|
|
|
224
276
|
|
|
225
277
|
// src/components/SignInContent.tsx
|
|
226
278
|
import { useState } from "react";
|
|
227
|
-
import { Button, TextField, Typography as Typography2, Stack as Stack2, IconButton, Divider,
|
|
279
|
+
import { Button, TextField, Typography as Typography2, Stack as Stack2, IconButton, Divider, GoogleIcon, AppleIcon, XTwitterIcon, FacebookIcon } from "@avalabs/core-k2-components";
|
|
228
280
|
|
|
229
281
|
// src/components/PoweredByAvaCloud.tsx
|
|
230
282
|
import { Stack, Typography, AvaCloudConnectIcon } from "@avalabs/core-k2-components";
|
|
@@ -241,11 +293,70 @@ function PoweredByAvaCloud() {
|
|
|
241
293
|
|
|
242
294
|
// src/components/SignInContent.tsx
|
|
243
295
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
244
|
-
function SignInContent({
|
|
296
|
+
function SignInContent({
|
|
297
|
+
onEmailLogin,
|
|
298
|
+
onProviderLogin,
|
|
299
|
+
error,
|
|
300
|
+
isSubmitting,
|
|
301
|
+
socialLogins = ["google", "x", "apple"]
|
|
302
|
+
}) {
|
|
245
303
|
const [email, setEmail] = useState("");
|
|
246
304
|
const [password, setPassword] = useState("");
|
|
247
305
|
const [isPasswordStep, setIsPasswordStep] = useState(false);
|
|
248
|
-
const
|
|
306
|
+
const providerConnectionMap = {
|
|
307
|
+
"google": "google-oauth2",
|
|
308
|
+
"x": "twitter",
|
|
309
|
+
"twitter": "twitter",
|
|
310
|
+
"facebook": "facebook",
|
|
311
|
+
"apple": "apple"
|
|
312
|
+
};
|
|
313
|
+
const renderSocialLoginButton = (loginType) => {
|
|
314
|
+
if (!providerConnectionMap[loginType]) return null;
|
|
315
|
+
const connectionName = providerConnectionMap[loginType];
|
|
316
|
+
let LoginIcon;
|
|
317
|
+
switch (loginType) {
|
|
318
|
+
case "google":
|
|
319
|
+
LoginIcon = GoogleIcon;
|
|
320
|
+
break;
|
|
321
|
+
case "x":
|
|
322
|
+
case "twitter":
|
|
323
|
+
LoginIcon = XTwitterIcon;
|
|
324
|
+
break;
|
|
325
|
+
case "facebook":
|
|
326
|
+
LoginIcon = FacebookIcon;
|
|
327
|
+
break;
|
|
328
|
+
case "apple":
|
|
329
|
+
LoginIcon = AppleIcon;
|
|
330
|
+
break;
|
|
331
|
+
default:
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
return /* @__PURE__ */ jsx2(
|
|
335
|
+
IconButton,
|
|
336
|
+
{
|
|
337
|
+
color: "default",
|
|
338
|
+
variant: "contained",
|
|
339
|
+
onClick: () => onProviderLogin(connectionName),
|
|
340
|
+
disabled: isSubmitting,
|
|
341
|
+
sx: {
|
|
342
|
+
display: "flex",
|
|
343
|
+
padding: "16px",
|
|
344
|
+
alignItems: "center",
|
|
345
|
+
gap: "8px",
|
|
346
|
+
borderRadius: "8px",
|
|
347
|
+
background: "rgba(0, 0, 0, 0.02)",
|
|
348
|
+
boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
|
|
349
|
+
width: 72,
|
|
350
|
+
height: 72,
|
|
351
|
+
"&:hover": {
|
|
352
|
+
background: "rgba(0, 0, 0, 0.04)"
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
children: /* @__PURE__ */ jsx2(LoginIcon, { sx: { width: 24, height: 24 } })
|
|
356
|
+
},
|
|
357
|
+
loginType
|
|
358
|
+
);
|
|
359
|
+
};
|
|
249
360
|
const handleEmailSubmit = (e) => {
|
|
250
361
|
e.preventDefault();
|
|
251
362
|
if (!email) return;
|
|
@@ -261,7 +372,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
261
372
|
};
|
|
262
373
|
const titleTypography = {
|
|
263
374
|
alignSelf: "stretch",
|
|
264
|
-
color: (
|
|
375
|
+
color: (theme) => theme.palette.mode === "dark" ? "#FFFFFF" : "rgba(0, 0, 0, 0.80)",
|
|
265
376
|
fontFamily: "Inter",
|
|
266
377
|
fontSize: "16px",
|
|
267
378
|
fontStyle: "normal",
|
|
@@ -286,7 +397,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
286
397
|
helperText: error,
|
|
287
398
|
sx: {
|
|
288
399
|
"& .MuiOutlinedInput-root": {
|
|
289
|
-
backgroundColor: (
|
|
400
|
+
backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
|
|
290
401
|
}
|
|
291
402
|
}
|
|
292
403
|
}
|
|
@@ -420,80 +531,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
420
531
|
}
|
|
421
532
|
return /* @__PURE__ */ jsxs2(Stack2, { gap: 3, children: [
|
|
422
533
|
/* @__PURE__ */ jsx2(Typography2, { variant: "h6", sx: titleTypography, children: "Sign in with" }),
|
|
423
|
-
/* @__PURE__ */
|
|
424
|
-
/* @__PURE__ */ jsx2(
|
|
425
|
-
IconButton,
|
|
426
|
-
{
|
|
427
|
-
color: "default",
|
|
428
|
-
variant: "contained",
|
|
429
|
-
onClick: () => onProviderLogin("google-oauth2"),
|
|
430
|
-
disabled: isSubmitting,
|
|
431
|
-
sx: {
|
|
432
|
-
display: "flex",
|
|
433
|
-
padding: "16px",
|
|
434
|
-
alignItems: "center",
|
|
435
|
-
gap: "8px",
|
|
436
|
-
borderRadius: "8px",
|
|
437
|
-
background: "rgba(0, 0, 0, 0.02)",
|
|
438
|
-
boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
|
|
439
|
-
width: 72,
|
|
440
|
-
height: 72,
|
|
441
|
-
"&:hover": {
|
|
442
|
-
background: "rgba(0, 0, 0, 0.04)"
|
|
443
|
-
}
|
|
444
|
-
},
|
|
445
|
-
children: /* @__PURE__ */ jsx2(GoogleColorIcon, { sx: { width: 24, height: 24 } })
|
|
446
|
-
}
|
|
447
|
-
),
|
|
448
|
-
/* @__PURE__ */ jsx2(
|
|
449
|
-
IconButton,
|
|
450
|
-
{
|
|
451
|
-
color: "default",
|
|
452
|
-
variant: "contained",
|
|
453
|
-
onClick: () => onProviderLogin("twitter"),
|
|
454
|
-
disabled: isSubmitting,
|
|
455
|
-
sx: {
|
|
456
|
-
display: "flex",
|
|
457
|
-
padding: "16px",
|
|
458
|
-
alignItems: "center",
|
|
459
|
-
gap: "8px",
|
|
460
|
-
borderRadius: "8px",
|
|
461
|
-
background: "rgba(0, 0, 0, 0.02)",
|
|
462
|
-
boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
|
|
463
|
-
width: 72,
|
|
464
|
-
height: 72,
|
|
465
|
-
"&:hover": {
|
|
466
|
-
background: "rgba(0, 0, 0, 0.04)"
|
|
467
|
-
}
|
|
468
|
-
},
|
|
469
|
-
children: /* @__PURE__ */ jsx2(XTwitterIcon, { sx: { width: 24, height: 24 } })
|
|
470
|
-
}
|
|
471
|
-
),
|
|
472
|
-
/* @__PURE__ */ jsx2(
|
|
473
|
-
IconButton,
|
|
474
|
-
{
|
|
475
|
-
color: "default",
|
|
476
|
-
variant: "contained",
|
|
477
|
-
onClick: () => onProviderLogin("apple"),
|
|
478
|
-
disabled: isSubmitting,
|
|
479
|
-
sx: {
|
|
480
|
-
display: "flex",
|
|
481
|
-
padding: "16px",
|
|
482
|
-
alignItems: "center",
|
|
483
|
-
gap: "8px",
|
|
484
|
-
borderRadius: "8px",
|
|
485
|
-
background: "rgba(0, 0, 0, 0.02)",
|
|
486
|
-
boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
|
|
487
|
-
width: 72,
|
|
488
|
-
height: 72,
|
|
489
|
-
"&:hover": {
|
|
490
|
-
background: "rgba(0, 0, 0, 0.04)"
|
|
491
|
-
}
|
|
492
|
-
},
|
|
493
|
-
children: /* @__PURE__ */ jsx2(AppleIcon, { sx: { width: 24, height: 24 } })
|
|
494
|
-
}
|
|
495
|
-
)
|
|
496
|
-
] }),
|
|
534
|
+
/* @__PURE__ */ jsx2(Stack2, { direction: "row", spacing: 3, sx: { justifyContent: "center" }, children: socialLogins.map((loginType) => renderSocialLoginButton(loginType)) }),
|
|
497
535
|
/* @__PURE__ */ jsx2(Divider, { children: /* @__PURE__ */ jsx2(Typography2, { variant: "body2", color: "text.secondary", children: "or" }) }),
|
|
498
536
|
/* @__PURE__ */ jsx2("form", { onSubmit: handleEmailSubmit, children: /* @__PURE__ */ jsxs2(Stack2, { gap: 2, children: [
|
|
499
537
|
/* @__PURE__ */ jsx2(
|
|
@@ -510,7 +548,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
510
548
|
helperText: error,
|
|
511
549
|
sx: {
|
|
512
550
|
"& .MuiOutlinedInput-root": {
|
|
513
|
-
backgroundColor: (
|
|
551
|
+
backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
|
|
514
552
|
}
|
|
515
553
|
}
|
|
516
554
|
}
|
|
@@ -613,9 +651,11 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
|
|
|
613
651
|
// src/components/Modal.tsx
|
|
614
652
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
615
653
|
function LoginModal({ open, onClose }) {
|
|
616
|
-
|
|
654
|
+
var _a;
|
|
655
|
+
const { iframe, orgConfig } = useAvaCloudWallet();
|
|
617
656
|
const [isSubmitting, setIsSubmitting] = useState2(false);
|
|
618
657
|
const [error, setError] = useState2("");
|
|
658
|
+
const socialLogins = (_a = orgConfig == null ? void 0 : orgConfig.adminPortalSettings) == null ? void 0 : _a.socialLogins;
|
|
619
659
|
useEffect2(() => {
|
|
620
660
|
const handleMessage = (event) => {
|
|
621
661
|
if (event.data.type === "ERROR") {
|
|
@@ -630,11 +670,11 @@ function LoginModal({ open, onClose }) {
|
|
|
630
670
|
return () => window.removeEventListener("message", handleMessage);
|
|
631
671
|
}, [onClose]);
|
|
632
672
|
const handleProviderLogin = (provider) => {
|
|
633
|
-
var
|
|
673
|
+
var _a2;
|
|
634
674
|
setError("");
|
|
635
675
|
if (iframe) {
|
|
636
676
|
console.log(`Sending LOGIN_REQUEST to auth service iframe with ${provider} connection`);
|
|
637
|
-
(
|
|
677
|
+
(_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({
|
|
638
678
|
type: "LOGIN_REQUEST",
|
|
639
679
|
connection: provider
|
|
640
680
|
}, "*");
|
|
@@ -645,12 +685,12 @@ function LoginModal({ open, onClose }) {
|
|
|
645
685
|
}
|
|
646
686
|
};
|
|
647
687
|
const handleEmailLogin = (email, password) => {
|
|
648
|
-
var
|
|
688
|
+
var _a2;
|
|
649
689
|
setError("");
|
|
650
690
|
setIsSubmitting(true);
|
|
651
691
|
if (iframe) {
|
|
652
692
|
console.log("Sending email/password LOGIN_REQUEST to auth service iframe");
|
|
653
|
-
(
|
|
693
|
+
(_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({
|
|
654
694
|
type: "LOGIN_REQUEST",
|
|
655
695
|
email,
|
|
656
696
|
password
|
|
@@ -734,7 +774,8 @@ function LoginModal({ open, onClose }) {
|
|
|
734
774
|
onEmailLogin: handleEmailLogin,
|
|
735
775
|
onProviderLogin: handleProviderLogin,
|
|
736
776
|
error,
|
|
737
|
-
isSubmitting
|
|
777
|
+
isSubmitting,
|
|
778
|
+
socialLogins
|
|
738
779
|
}
|
|
739
780
|
) })
|
|
740
781
|
]
|
|
@@ -1135,7 +1176,6 @@ function ThemeProvider({ children, darkMode, onDarkModeChange }) {
|
|
|
1135
1176
|
}
|
|
1136
1177
|
|
|
1137
1178
|
// src/AvaCloudWalletProvider.tsx
|
|
1138
|
-
import { AUTH_TOKENS_KEY as AUTH_TOKENS_KEY2, OIDC_TOKEN_KEY as OIDC_TOKEN_KEY2, AUTH0_STORAGE_KEYS as AUTH0_STORAGE_KEYS2, CUBIST_USER_ID_KEY as CUBIST_USER_ID_KEY2 } from "@avacloud/waas-common";
|
|
1139
1179
|
import { Fragment, jsx as jsx7 } from "react/jsx-runtime";
|
|
1140
1180
|
var AvaCloudWalletContext = createContext4(void 0);
|
|
1141
1181
|
var queryClient = new QueryClient({
|
|
@@ -1238,7 +1278,7 @@ function AvaCloudWalletProvider({
|
|
|
1238
1278
|
accessToken = oidcToken;
|
|
1239
1279
|
} else {
|
|
1240
1280
|
console.log("[loginWithCubist] Attempting to get OIDC token from localStorage.");
|
|
1241
|
-
const tokens = localStorage.getItem(
|
|
1281
|
+
const tokens = localStorage.getItem(AUTH_TOKENS_KEY);
|
|
1242
1282
|
if (!tokens) {
|
|
1243
1283
|
throw new Error("No authentication tokens found in localStorage");
|
|
1244
1284
|
}
|
|
@@ -1294,8 +1334,8 @@ function AvaCloudWalletProvider({
|
|
|
1294
1334
|
}
|
|
1295
1335
|
} catch (error) {
|
|
1296
1336
|
console.error("[loginWithCubist] Error during Cubist session creation/wallet info:", error);
|
|
1297
|
-
localStorage.removeItem(
|
|
1298
|
-
localStorage.removeItem(
|
|
1337
|
+
localStorage.removeItem(AUTH_TOKENS_KEY);
|
|
1338
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.IS_AUTHENTICATED);
|
|
1299
1339
|
setIsAuthenticated(false);
|
|
1300
1340
|
setUser(null);
|
|
1301
1341
|
setCubistClient(null);
|
|
@@ -1389,17 +1429,21 @@ function AvaCloudWalletProvider({
|
|
|
1389
1429
|
setUser(null);
|
|
1390
1430
|
setWallet({ address: null });
|
|
1391
1431
|
setIsAuthenticated(false);
|
|
1392
|
-
localStorage.removeItem(
|
|
1393
|
-
localStorage.removeItem(
|
|
1394
|
-
localStorage.removeItem(
|
|
1395
|
-
localStorage.removeItem(
|
|
1396
|
-
localStorage.removeItem(
|
|
1397
|
-
localStorage.removeItem(
|
|
1398
|
-
|
|
1432
|
+
localStorage.removeItem(AUTH_TOKENS_KEY);
|
|
1433
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.IS_AUTHENTICATED);
|
|
1434
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.ACCESS_TOKEN);
|
|
1435
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.ID_TOKEN);
|
|
1436
|
+
localStorage.removeItem(AUTH0_STORAGE_KEYS.EXPIRES_AT);
|
|
1437
|
+
localStorage.removeItem(CUBIST_USER_ID_KEY);
|
|
1438
|
+
if (orgId) {
|
|
1439
|
+
const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`;
|
|
1440
|
+
localStorage.removeItem(cachedConfigKey);
|
|
1441
|
+
}
|
|
1442
|
+
sessionStorage.removeItem(OIDC_TOKEN_KEY);
|
|
1399
1443
|
setCubistClient(null);
|
|
1400
1444
|
setCubistError(null);
|
|
1401
1445
|
setPendingOidcToken(null);
|
|
1402
|
-
}, [sendMessage]);
|
|
1446
|
+
}, [sendMessage, orgId, environment]);
|
|
1403
1447
|
const addAccount = useCallback5(async (accountIndex) => {
|
|
1404
1448
|
console.log("[addAccount] Called with accountIndex:", accountIndex);
|
|
1405
1449
|
if (!isAuthenticated || !user || !wallet.mnemonicId) {
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@avalabs/avacloud-waas-react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "React SDK for AvaCloud Wallet as a Service",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"files": [
|
|
11
|
-
"dist/**"
|
|
11
|
+
"dist/**",
|
|
12
|
+
"public/**"
|
|
12
13
|
],
|
|
13
14
|
"devDependencies": {
|
|
14
15
|
"@iconify/types": "^2.0.0",
|
|
@@ -30,8 +31,7 @@
|
|
|
30
31
|
"@tanstack/react-query": "^5.64.2",
|
|
31
32
|
"lottie-react": "^2.4.0",
|
|
32
33
|
"qrcode.react": "^3.1.0",
|
|
33
|
-
"viem": "^2.5.0"
|
|
34
|
-
"@avacloud/waas-common": "0.1.0"
|
|
34
|
+
"viem": "^2.5.0"
|
|
35
35
|
},
|
|
36
36
|
"keywords": [
|
|
37
37
|
"avalanche",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"homepage": "https://github.com/ava-labs/avacloud-auth-react#readme",
|
|
53
53
|
"author": "Ava Labs, Inc.",
|
|
54
54
|
"scripts": {
|
|
55
|
-
"build": "tsup src/index.ts --format esm,cjs --dts --external react",
|
|
55
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --external react && cp -r public dist/",
|
|
56
56
|
"dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react",
|
|
57
57
|
"lint": "eslint \"src/**/*.ts*\"",
|
|
58
58
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
|
Binary file
|