@avalabs/avacloud-waas-react 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @avalabs/avacloud-waas-react
2
2
 
3
- Official React SDK for AvaCloud Authentication and wallet integration. This library provides a seamless way to integrate AvaCloud authentication and wallet functionality into your React applications.
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
  [![npm version](https://img.shields.io/npm/v/@avalabs/avacloud-waas-react.svg)](https://www.npmjs.com/package/@avalabs/avacloud-waas-react)
6
6
  [![License](https://img.shields.io/npm/l/@avalabs/avacloud-waas-react.svg)](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 authentication hooks and components in your application:
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 authentication context.
72
+ The main provider component that wraps your application and provides wallet context.
73
73
 
74
74
  ```tsx
75
75
  <AvaCloudWalletProvider
76
- authServiceUrl="https://auth.avacloud.io"
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
- | `authServiceUrl` | `string` | URL of the AvaCloud authentication service |
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 authentication state and methods.
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 will be used to fetch the organization configuration from the AvaCloud API, which includes the mapping to the appropriate Cubist organization ID used for wallet operations.
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 a Cubist organization ID as specified in the configuration
285
- 3. Use the mapped ID for Cubist authentication and wallet operations
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 Cubist wallets.
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: string;
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: Record<string, unknown> | null;
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: string;
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: Record<string, unknown> | null;
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
@@ -90,6 +90,7 @@ var AUTH0_STORAGE_KEYS = {
90
90
  EXPIRES_AT: "auth0.expires_at"
91
91
  };
92
92
  var CUBIST_USER_ID_KEY = "cubist_user_id";
93
+ var ORG_CONFIG_CACHE_KEY = "avacloud-org-config-cache";
93
94
 
94
95
  // src/hooks/usePostMessage.ts
95
96
  function usePostMessage({
@@ -115,6 +116,30 @@ function usePostMessage({
115
116
  });
116
117
  const hasRequestedOidcRef = (0, import_react.useRef)(false);
117
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]);
118
143
  const sendMessage = (0, import_react.useCallback)((message) => {
119
144
  if (iframe == null ? void 0 : iframe.contentWindow) {
120
145
  try {
@@ -211,6 +236,19 @@ function usePostMessage({
211
236
  if (event.data.orgConfig && onOrgConfigUpdate) {
212
237
  console.log("Received organization config:", event.data.orgConfig);
213
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
+ }
214
252
  }
215
253
  if (!hasRequestedOidcRef.current) {
216
254
  setIsLoading(false);
@@ -253,7 +291,9 @@ function usePostMessage({
253
291
  setIsLoading,
254
292
  setUser,
255
293
  sendMessage,
256
- cubistClient
294
+ cubistClient,
295
+ orgId,
296
+ environment
257
297
  ]);
258
298
  (0, import_react.useEffect)(() => {
259
299
  if (isIframeReady && (iframe == null ? void 0 : iframe.contentWindow)) {
@@ -299,11 +339,70 @@ function PoweredByAvaCloud() {
299
339
 
300
340
  // src/components/SignInContent.tsx
301
341
  var import_jsx_runtime2 = require("react/jsx-runtime");
302
- function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
342
+ function SignInContent({
343
+ onEmailLogin,
344
+ onProviderLogin,
345
+ error,
346
+ isSubmitting,
347
+ socialLogins = ["google", "x", "apple"]
348
+ }) {
303
349
  const [email, setEmail] = (0, import_react2.useState)("");
304
350
  const [password, setPassword] = (0, import_react2.useState)("");
305
351
  const [isPasswordStep, setIsPasswordStep] = (0, import_react2.useState)(false);
306
- const theme = (0, import_core_k2_components2.useTheme)();
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
+ };
307
406
  const handleEmailSubmit = (e) => {
308
407
  e.preventDefault();
309
408
  if (!email) return;
@@ -319,7 +418,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
319
418
  };
320
419
  const titleTypography = {
321
420
  alignSelf: "stretch",
322
- color: (theme2) => theme2.palette.mode === "dark" ? "#FFFFFF" : "rgba(0, 0, 0, 0.80)",
421
+ color: (theme) => theme.palette.mode === "dark" ? "#FFFFFF" : "rgba(0, 0, 0, 0.80)",
323
422
  fontFamily: "Inter",
324
423
  fontSize: "16px",
325
424
  fontStyle: "normal",
@@ -344,7 +443,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
344
443
  helperText: error,
345
444
  sx: {
346
445
  "& .MuiOutlinedInput-root": {
347
- backgroundColor: (theme2) => theme2.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
446
+ backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
348
447
  }
349
448
  }
350
449
  }
@@ -478,80 +577,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
478
577
  }
479
578
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { gap: 3, children: [
480
579
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.Typography, { variant: "h6", sx: titleTypography, children: "Sign in with" }),
481
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core_k2_components2.Stack, { direction: "row", spacing: 3, sx: { justifyContent: "center" }, children: [
482
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
483
- import_core_k2_components2.IconButton,
484
- {
485
- color: "default",
486
- variant: "contained",
487
- onClick: () => onProviderLogin("google-oauth2"),
488
- disabled: isSubmitting,
489
- sx: {
490
- display: "flex",
491
- padding: "16px",
492
- alignItems: "center",
493
- gap: "8px",
494
- borderRadius: "8px",
495
- background: "rgba(0, 0, 0, 0.02)",
496
- boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
497
- width: 72,
498
- height: 72,
499
- "&:hover": {
500
- background: "rgba(0, 0, 0, 0.04)"
501
- }
502
- },
503
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.GoogleColorIcon, { sx: { width: 24, height: 24 } })
504
- }
505
- ),
506
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
507
- import_core_k2_components2.IconButton,
508
- {
509
- color: "default",
510
- variant: "contained",
511
- onClick: () => onProviderLogin("twitter"),
512
- disabled: isSubmitting,
513
- sx: {
514
- display: "flex",
515
- padding: "16px",
516
- alignItems: "center",
517
- gap: "8px",
518
- borderRadius: "8px",
519
- background: "rgba(0, 0, 0, 0.02)",
520
- boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
521
- width: 72,
522
- height: 72,
523
- "&:hover": {
524
- background: "rgba(0, 0, 0, 0.04)"
525
- }
526
- },
527
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.XTwitterIcon, { sx: { width: 24, height: 24 } })
528
- }
529
- ),
530
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
531
- import_core_k2_components2.IconButton,
532
- {
533
- color: "default",
534
- variant: "contained",
535
- onClick: () => onProviderLogin("apple"),
536
- disabled: isSubmitting,
537
- sx: {
538
- display: "flex",
539
- padding: "16px",
540
- alignItems: "center",
541
- gap: "8px",
542
- borderRadius: "8px",
543
- background: "rgba(0, 0, 0, 0.02)",
544
- boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
545
- width: 72,
546
- height: 72,
547
- "&:hover": {
548
- background: "rgba(0, 0, 0, 0.04)"
549
- }
550
- },
551
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core_k2_components2.AppleIcon, { sx: { width: 24, height: 24 } })
552
- }
553
- )
554
- ] }),
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)) }),
555
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" }) }),
556
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: [
557
583
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -568,7 +594,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
568
594
  helperText: error,
569
595
  sx: {
570
596
  "& .MuiOutlinedInput-root": {
571
- backgroundColor: (theme2) => theme2.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
597
+ backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
572
598
  }
573
599
  }
574
600
  }
@@ -671,9 +697,11 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
671
697
  // src/components/Modal.tsx
672
698
  var import_jsx_runtime3 = require("react/jsx-runtime");
673
699
  function LoginModal({ open, onClose }) {
674
- const { iframe } = useAvaCloudWallet();
700
+ var _a;
701
+ const { iframe, orgConfig } = useAvaCloudWallet();
675
702
  const [isSubmitting, setIsSubmitting] = (0, import_react3.useState)(false);
676
703
  const [error, setError] = (0, import_react3.useState)("");
704
+ const socialLogins = (_a = orgConfig == null ? void 0 : orgConfig.adminPortalSettings) == null ? void 0 : _a.socialLogins;
677
705
  (0, import_react3.useEffect)(() => {
678
706
  const handleMessage = (event) => {
679
707
  if (event.data.type === "ERROR") {
@@ -688,11 +716,11 @@ function LoginModal({ open, onClose }) {
688
716
  return () => window.removeEventListener("message", handleMessage);
689
717
  }, [onClose]);
690
718
  const handleProviderLogin = (provider) => {
691
- var _a;
719
+ var _a2;
692
720
  setError("");
693
721
  if (iframe) {
694
722
  console.log(`Sending LOGIN_REQUEST to auth service iframe with ${provider} connection`);
695
- (_a = iframe.contentWindow) == null ? void 0 : _a.postMessage({
723
+ (_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({
696
724
  type: "LOGIN_REQUEST",
697
725
  connection: provider
698
726
  }, "*");
@@ -703,12 +731,12 @@ function LoginModal({ open, onClose }) {
703
731
  }
704
732
  };
705
733
  const handleEmailLogin = (email, password) => {
706
- var _a;
734
+ var _a2;
707
735
  setError("");
708
736
  setIsSubmitting(true);
709
737
  if (iframe) {
710
738
  console.log("Sending email/password LOGIN_REQUEST to auth service iframe");
711
- (_a = iframe.contentWindow) == null ? void 0 : _a.postMessage({
739
+ (_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({
712
740
  type: "LOGIN_REQUEST",
713
741
  email,
714
742
  password
@@ -792,7 +820,8 @@ function LoginModal({ open, onClose }) {
792
820
  onEmailLogin: handleEmailLogin,
793
821
  onProviderLogin: handleProviderLogin,
794
822
  error,
795
- isSubmitting
823
+ isSubmitting,
824
+ socialLogins
796
825
  }
797
826
  ) })
798
827
  ]
@@ -1452,11 +1481,15 @@ function AvaCloudWalletProvider({
1452
1481
  localStorage.removeItem(AUTH0_STORAGE_KEYS.ID_TOKEN);
1453
1482
  localStorage.removeItem(AUTH0_STORAGE_KEYS.EXPIRES_AT);
1454
1483
  localStorage.removeItem(CUBIST_USER_ID_KEY);
1484
+ if (orgId) {
1485
+ const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`;
1486
+ localStorage.removeItem(cachedConfigKey);
1487
+ }
1455
1488
  sessionStorage.removeItem(OIDC_TOKEN_KEY);
1456
1489
  setCubistClient(null);
1457
1490
  setCubistError(null);
1458
1491
  setPendingOidcToken(null);
1459
- }, [sendMessage]);
1492
+ }, [sendMessage, orgId, environment]);
1460
1493
  const addAccount = (0, import_react9.useCallback)(async (accountIndex) => {
1461
1494
  console.log("[addAccount] Called with accountIndex:", accountIndex);
1462
1495
  if (!isAuthenticated || !user || !wallet.mnemonicId) {
@@ -2343,7 +2376,8 @@ function SendFormView({
2343
2376
  value: recipient,
2344
2377
  onChange: (e) => handleRecipientChange(e.target.value),
2345
2378
  error: !!error || !!addressError,
2346
- helperText: addressError
2379
+ helperText: !selectedToken ? "Select a token first" : addressError,
2380
+ disabled: !selectedToken
2347
2381
  }
2348
2382
  )
2349
2383
  ] }),
@@ -2362,7 +2396,8 @@ function SendFormView({
2362
2396
  placeholder: "0.00",
2363
2397
  value: amount,
2364
2398
  onChange: handleAmountChange,
2365
- error: !!error
2399
+ error: !!error,
2400
+ disabled: !selectedToken
2366
2401
  }
2367
2402
  )
2368
2403
  ] }),
@@ -2679,6 +2714,14 @@ function SendView({ onBack, onViewStateChange, selectedToken: initialToken }) {
2679
2714
  const [selectedToken, setSelectedToken] = (0, import_react13.useState)(initialToken);
2680
2715
  const { transfer, transferERC20, error, isLoading, txHash, viewState, reset, actualBaseFee, actualPriorityFee, actualTotalFee } = useTransferTokens();
2681
2716
  const { data: blockchainInfo } = useBlockchain((chainId == null ? void 0 : chainId.toString()) || "");
2717
+ const { wallet } = useAvaCloudWallet();
2718
+ const { data: tokenBalancesResponse } = useERC20Balances((wallet == null ? void 0 : wallet.address) || void 0, chainId == null ? void 0 : chainId.toString());
2719
+ const tokenBalances = tokenBalancesResponse;
2720
+ (0, import_react13.useEffect)(() => {
2721
+ if (!selectedToken && (tokenBalances == null ? void 0 : tokenBalances.nativeTokenBalance)) {
2722
+ setSelectedToken(tokenBalances.nativeTokenBalance);
2723
+ }
2724
+ }, [selectedToken, tokenBalances]);
2682
2725
  (0, import_react13.useEffect)(() => {
2683
2726
  onViewStateChange == null ? void 0 : onViewStateChange(viewState);
2684
2727
  }, [viewState, onViewStateChange]);
@@ -2772,6 +2815,8 @@ function ReceiveView(_props) {
2772
2815
  const { wallet } = useAvaCloudWallet();
2773
2816
  const { chainId } = useChainId();
2774
2817
  const [_copied, setCopied] = (0, import_react15.useState)(false);
2818
+ const theme = (0, import_core_k2_components10.useTheme)();
2819
+ const { isDarkMode } = useThemeMode();
2775
2820
  if (!wallet.address) {
2776
2821
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_core_k2_components10.Box, { sx: { p: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_core_k2_components10.Typography, { color: "text.secondary", children: "No wallet address available" }) });
2777
2822
  }
@@ -2793,7 +2838,7 @@ function ReceiveView(_props) {
2793
2838
  import_core_k2_components10.Typography,
2794
2839
  {
2795
2840
  sx: {
2796
- color: "#000",
2841
+ color: "text.primary",
2797
2842
  fontSize: "14px",
2798
2843
  fontWeight: 500,
2799
2844
  lineHeight: "20px"
@@ -2814,7 +2859,7 @@ function ReceiveView(_props) {
2814
2859
  flex: 1,
2815
2860
  fontFamily: "monospace",
2816
2861
  fontSize: "14px",
2817
- color: "#000",
2862
+ color: "text.primary",
2818
2863
  overflow: "hidden",
2819
2864
  textOverflow: "ellipsis"
2820
2865
  },
@@ -2830,16 +2875,18 @@ function ReceiveView(_props) {
2830
2875
  width: "100%",
2831
2876
  aspectRatio: "1",
2832
2877
  p: 2,
2833
- background: "#FFF",
2878
+ background: isDarkMode ? theme.palette.background.paper : "#FFF",
2834
2879
  borderRadius: "8px",
2835
- border: "1px solid rgba(0, 0, 0, 0.12)"
2880
+ border: `1px solid ${isDarkMode ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.12)"}`
2836
2881
  }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2837
2882
  import_qrcode.QRCodeSVG,
2838
2883
  {
2839
2884
  value: wallet.address ? `ethereum:${wallet.address}@${chainId}` : "",
2840
2885
  level: "H",
2841
2886
  includeMargin: false,
2842
- size: 200
2887
+ size: 200,
2888
+ bgColor: isDarkMode ? theme.palette.background.paper : "#FFFFFF",
2889
+ fgColor: isDarkMode ? "#FFFFFF" : "#000000"
2843
2890
  }
2844
2891
  ) }),
2845
2892
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_core_k2_components10.Box, { sx: { mt: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PoweredByAvaCloud, {}) })
package/dist/index.mjs CHANGED
@@ -44,6 +44,7 @@ var AUTH0_STORAGE_KEYS = {
44
44
  EXPIRES_AT: "auth0.expires_at"
45
45
  };
46
46
  var CUBIST_USER_ID_KEY = "cubist_user_id";
47
+ var ORG_CONFIG_CACHE_KEY = "avacloud-org-config-cache";
47
48
 
48
49
  // src/hooks/usePostMessage.ts
49
50
  function usePostMessage({
@@ -69,6 +70,30 @@ function usePostMessage({
69
70
  });
70
71
  const hasRequestedOidcRef = useRef(false);
71
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]);
72
97
  const sendMessage = useCallback((message) => {
73
98
  if (iframe == null ? void 0 : iframe.contentWindow) {
74
99
  try {
@@ -165,6 +190,19 @@ function usePostMessage({
165
190
  if (event.data.orgConfig && onOrgConfigUpdate) {
166
191
  console.log("Received organization config:", event.data.orgConfig);
167
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
+ }
168
206
  }
169
207
  if (!hasRequestedOidcRef.current) {
170
208
  setIsLoading(false);
@@ -207,7 +245,9 @@ function usePostMessage({
207
245
  setIsLoading,
208
246
  setUser,
209
247
  sendMessage,
210
- cubistClient
248
+ cubistClient,
249
+ orgId,
250
+ environment
211
251
  ]);
212
252
  useEffect(() => {
213
253
  if (isIframeReady && (iframe == null ? void 0 : iframe.contentWindow)) {
@@ -236,7 +276,7 @@ import { Dialog, DialogContent, IconButton as IconButton2, Stack as Stack3, XIco
236
276
 
237
277
  // src/components/SignInContent.tsx
238
278
  import { useState } from "react";
239
- import { Button, TextField, Typography as Typography2, Stack as Stack2, IconButton, Divider, GoogleColorIcon, AppleIcon, XTwitterIcon, useTheme } from "@avalabs/core-k2-components";
279
+ import { Button, TextField, Typography as Typography2, Stack as Stack2, IconButton, Divider, GoogleIcon, AppleIcon, XTwitterIcon, FacebookIcon } from "@avalabs/core-k2-components";
240
280
 
241
281
  // src/components/PoweredByAvaCloud.tsx
242
282
  import { Stack, Typography, AvaCloudConnectIcon } from "@avalabs/core-k2-components";
@@ -253,11 +293,70 @@ function PoweredByAvaCloud() {
253
293
 
254
294
  // src/components/SignInContent.tsx
255
295
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
256
- function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
296
+ function SignInContent({
297
+ onEmailLogin,
298
+ onProviderLogin,
299
+ error,
300
+ isSubmitting,
301
+ socialLogins = ["google", "x", "apple"]
302
+ }) {
257
303
  const [email, setEmail] = useState("");
258
304
  const [password, setPassword] = useState("");
259
305
  const [isPasswordStep, setIsPasswordStep] = useState(false);
260
- const theme = useTheme();
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
+ };
261
360
  const handleEmailSubmit = (e) => {
262
361
  e.preventDefault();
263
362
  if (!email) return;
@@ -273,7 +372,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
273
372
  };
274
373
  const titleTypography = {
275
374
  alignSelf: "stretch",
276
- color: (theme2) => theme2.palette.mode === "dark" ? "#FFFFFF" : "rgba(0, 0, 0, 0.80)",
375
+ color: (theme) => theme.palette.mode === "dark" ? "#FFFFFF" : "rgba(0, 0, 0, 0.80)",
277
376
  fontFamily: "Inter",
278
377
  fontSize: "16px",
279
378
  fontStyle: "normal",
@@ -298,7 +397,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
298
397
  helperText: error,
299
398
  sx: {
300
399
  "& .MuiOutlinedInput-root": {
301
- backgroundColor: (theme2) => theme2.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
400
+ backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
302
401
  }
303
402
  }
304
403
  }
@@ -432,80 +531,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
432
531
  }
433
532
  return /* @__PURE__ */ jsxs2(Stack2, { gap: 3, children: [
434
533
  /* @__PURE__ */ jsx2(Typography2, { variant: "h6", sx: titleTypography, children: "Sign in with" }),
435
- /* @__PURE__ */ jsxs2(Stack2, { direction: "row", spacing: 3, sx: { justifyContent: "center" }, children: [
436
- /* @__PURE__ */ jsx2(
437
- IconButton,
438
- {
439
- color: "default",
440
- variant: "contained",
441
- onClick: () => onProviderLogin("google-oauth2"),
442
- disabled: isSubmitting,
443
- sx: {
444
- display: "flex",
445
- padding: "16px",
446
- alignItems: "center",
447
- gap: "8px",
448
- borderRadius: "8px",
449
- background: "rgba(0, 0, 0, 0.02)",
450
- boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
451
- width: 72,
452
- height: 72,
453
- "&:hover": {
454
- background: "rgba(0, 0, 0, 0.04)"
455
- }
456
- },
457
- children: /* @__PURE__ */ jsx2(GoogleColorIcon, { sx: { width: 24, height: 24 } })
458
- }
459
- ),
460
- /* @__PURE__ */ jsx2(
461
- IconButton,
462
- {
463
- color: "default",
464
- variant: "contained",
465
- onClick: () => onProviderLogin("twitter"),
466
- disabled: isSubmitting,
467
- sx: {
468
- display: "flex",
469
- padding: "16px",
470
- alignItems: "center",
471
- gap: "8px",
472
- borderRadius: "8px",
473
- background: "rgba(0, 0, 0, 0.02)",
474
- boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
475
- width: 72,
476
- height: 72,
477
- "&:hover": {
478
- background: "rgba(0, 0, 0, 0.04)"
479
- }
480
- },
481
- children: /* @__PURE__ */ jsx2(XTwitterIcon, { sx: { width: 24, height: 24 } })
482
- }
483
- ),
484
- /* @__PURE__ */ jsx2(
485
- IconButton,
486
- {
487
- color: "default",
488
- variant: "contained",
489
- onClick: () => onProviderLogin("apple"),
490
- disabled: isSubmitting,
491
- sx: {
492
- display: "flex",
493
- padding: "16px",
494
- alignItems: "center",
495
- gap: "8px",
496
- borderRadius: "8px",
497
- background: "rgba(0, 0, 0, 0.02)",
498
- boxShadow: "2px 1px 4px 0px rgba(0, 0, 0, 0.20)",
499
- width: 72,
500
- height: 72,
501
- "&:hover": {
502
- background: "rgba(0, 0, 0, 0.04)"
503
- }
504
- },
505
- children: /* @__PURE__ */ jsx2(AppleIcon, { sx: { width: 24, height: 24 } })
506
- }
507
- )
508
- ] }),
534
+ /* @__PURE__ */ jsx2(Stack2, { direction: "row", spacing: 3, sx: { justifyContent: "center" }, children: socialLogins.map((loginType) => renderSocialLoginButton(loginType)) }),
509
535
  /* @__PURE__ */ jsx2(Divider, { children: /* @__PURE__ */ jsx2(Typography2, { variant: "body2", color: "text.secondary", children: "or" }) }),
510
536
  /* @__PURE__ */ jsx2("form", { onSubmit: handleEmailSubmit, children: /* @__PURE__ */ jsxs2(Stack2, { gap: 2, children: [
511
537
  /* @__PURE__ */ jsx2(
@@ -522,7 +548,7 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
522
548
  helperText: error,
523
549
  sx: {
524
550
  "& .MuiOutlinedInput-root": {
525
- backgroundColor: (theme2) => theme2.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
551
+ backgroundColor: (theme) => theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.05)" : "grey.50"
526
552
  }
527
553
  }
528
554
  }
@@ -625,9 +651,11 @@ function SignInContent({ onEmailLogin, onProviderLogin, error, isSubmitting }) {
625
651
  // src/components/Modal.tsx
626
652
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
627
653
  function LoginModal({ open, onClose }) {
628
- const { iframe } = useAvaCloudWallet();
654
+ var _a;
655
+ const { iframe, orgConfig } = useAvaCloudWallet();
629
656
  const [isSubmitting, setIsSubmitting] = useState2(false);
630
657
  const [error, setError] = useState2("");
658
+ const socialLogins = (_a = orgConfig == null ? void 0 : orgConfig.adminPortalSettings) == null ? void 0 : _a.socialLogins;
631
659
  useEffect2(() => {
632
660
  const handleMessage = (event) => {
633
661
  if (event.data.type === "ERROR") {
@@ -642,11 +670,11 @@ function LoginModal({ open, onClose }) {
642
670
  return () => window.removeEventListener("message", handleMessage);
643
671
  }, [onClose]);
644
672
  const handleProviderLogin = (provider) => {
645
- var _a;
673
+ var _a2;
646
674
  setError("");
647
675
  if (iframe) {
648
676
  console.log(`Sending LOGIN_REQUEST to auth service iframe with ${provider} connection`);
649
- (_a = iframe.contentWindow) == null ? void 0 : _a.postMessage({
677
+ (_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({
650
678
  type: "LOGIN_REQUEST",
651
679
  connection: provider
652
680
  }, "*");
@@ -657,12 +685,12 @@ function LoginModal({ open, onClose }) {
657
685
  }
658
686
  };
659
687
  const handleEmailLogin = (email, password) => {
660
- var _a;
688
+ var _a2;
661
689
  setError("");
662
690
  setIsSubmitting(true);
663
691
  if (iframe) {
664
692
  console.log("Sending email/password LOGIN_REQUEST to auth service iframe");
665
- (_a = iframe.contentWindow) == null ? void 0 : _a.postMessage({
693
+ (_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage({
666
694
  type: "LOGIN_REQUEST",
667
695
  email,
668
696
  password
@@ -746,7 +774,8 @@ function LoginModal({ open, onClose }) {
746
774
  onEmailLogin: handleEmailLogin,
747
775
  onProviderLogin: handleProviderLogin,
748
776
  error,
749
- isSubmitting
777
+ isSubmitting,
778
+ socialLogins
750
779
  }
751
780
  ) })
752
781
  ]
@@ -1406,11 +1435,15 @@ function AvaCloudWalletProvider({
1406
1435
  localStorage.removeItem(AUTH0_STORAGE_KEYS.ID_TOKEN);
1407
1436
  localStorage.removeItem(AUTH0_STORAGE_KEYS.EXPIRES_AT);
1408
1437
  localStorage.removeItem(CUBIST_USER_ID_KEY);
1438
+ if (orgId) {
1439
+ const cachedConfigKey = `${ORG_CONFIG_CACHE_KEY}-${orgId}-${environment}`;
1440
+ localStorage.removeItem(cachedConfigKey);
1441
+ }
1409
1442
  sessionStorage.removeItem(OIDC_TOKEN_KEY);
1410
1443
  setCubistClient(null);
1411
1444
  setCubistError(null);
1412
1445
  setPendingOidcToken(null);
1413
- }, [sendMessage]);
1446
+ }, [sendMessage, orgId, environment]);
1414
1447
  const addAccount = useCallback5(async (accountIndex) => {
1415
1448
  console.log("[addAccount] Called with accountIndex:", accountIndex);
1416
1449
  if (!isAuthenticated || !user || !wallet.mnemonicId) {
@@ -1571,7 +1604,7 @@ import {
1571
1604
  IconButton as IconButton9,
1572
1605
  CopyIcon as CopyIcon5,
1573
1606
  AvaCloudIcon as AvaCloudIcon2,
1574
- useTheme as useTheme4
1607
+ useTheme as useTheme5
1575
1608
  } from "@avalabs/core-k2-components";
1576
1609
 
1577
1610
  // src/components/WalletCard.tsx
@@ -1581,7 +1614,7 @@ import {
1581
1614
  Box as Box10,
1582
1615
  IconButton as IconButton8,
1583
1616
  CopyIcon as CopyIcon4,
1584
- useTheme as useTheme3,
1617
+ useTheme as useTheme4,
1585
1618
  CircularProgress as CircularProgress2,
1586
1619
  AvaCloudIcon,
1587
1620
  Dialog as Dialog4,
@@ -2337,7 +2370,8 @@ function SendFormView({
2337
2370
  value: recipient,
2338
2371
  onChange: (e) => handleRecipientChange(e.target.value),
2339
2372
  error: !!error || !!addressError,
2340
- helperText: addressError
2373
+ helperText: !selectedToken ? "Select a token first" : addressError,
2374
+ disabled: !selectedToken
2341
2375
  }
2342
2376
  )
2343
2377
  ] }),
@@ -2356,7 +2390,8 @@ function SendFormView({
2356
2390
  placeholder: "0.00",
2357
2391
  value: amount,
2358
2392
  onChange: handleAmountChange,
2359
- error: !!error
2393
+ error: !!error,
2394
+ disabled: !selectedToken
2360
2395
  }
2361
2396
  )
2362
2397
  ] }),
@@ -2673,6 +2708,14 @@ function SendView({ onBack, onViewStateChange, selectedToken: initialToken }) {
2673
2708
  const [selectedToken, setSelectedToken] = useState11(initialToken);
2674
2709
  const { transfer, transferERC20, error, isLoading, txHash, viewState, reset, actualBaseFee, actualPriorityFee, actualTotalFee } = useTransferTokens();
2675
2710
  const { data: blockchainInfo } = useBlockchain((chainId == null ? void 0 : chainId.toString()) || "");
2711
+ const { wallet } = useAvaCloudWallet();
2712
+ const { data: tokenBalancesResponse } = useERC20Balances((wallet == null ? void 0 : wallet.address) || void 0, chainId == null ? void 0 : chainId.toString());
2713
+ const tokenBalances = tokenBalancesResponse;
2714
+ useEffect6(() => {
2715
+ if (!selectedToken && (tokenBalances == null ? void 0 : tokenBalances.nativeTokenBalance)) {
2716
+ setSelectedToken(tokenBalances.nativeTokenBalance);
2717
+ }
2718
+ }, [selectedToken, tokenBalances]);
2676
2719
  useEffect6(() => {
2677
2720
  onViewStateChange == null ? void 0 : onViewStateChange(viewState);
2678
2721
  }, [viewState, onViewStateChange]);
@@ -2764,13 +2807,16 @@ import {
2764
2807
  Box as Box4,
2765
2808
  Typography as Typography5,
2766
2809
  IconButton as IconButton4,
2767
- CopyIcon
2810
+ CopyIcon,
2811
+ useTheme as useTheme2
2768
2812
  } from "@avalabs/core-k2-components";
2769
2813
  import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
2770
2814
  function ReceiveView(_props) {
2771
2815
  const { wallet } = useAvaCloudWallet();
2772
2816
  const { chainId } = useChainId();
2773
2817
  const [_copied, setCopied] = useState12(false);
2818
+ const theme = useTheme2();
2819
+ const { isDarkMode } = useThemeMode();
2774
2820
  if (!wallet.address) {
2775
2821
  return /* @__PURE__ */ jsx12(Box4, { sx: { p: 2 }, children: /* @__PURE__ */ jsx12(Typography5, { color: "text.secondary", children: "No wallet address available" }) });
2776
2822
  }
@@ -2792,7 +2838,7 @@ function ReceiveView(_props) {
2792
2838
  Typography5,
2793
2839
  {
2794
2840
  sx: {
2795
- color: "#000",
2841
+ color: "text.primary",
2796
2842
  fontSize: "14px",
2797
2843
  fontWeight: 500,
2798
2844
  lineHeight: "20px"
@@ -2813,7 +2859,7 @@ function ReceiveView(_props) {
2813
2859
  flex: 1,
2814
2860
  fontFamily: "monospace",
2815
2861
  fontSize: "14px",
2816
- color: "#000",
2862
+ color: "text.primary",
2817
2863
  overflow: "hidden",
2818
2864
  textOverflow: "ellipsis"
2819
2865
  },
@@ -2829,16 +2875,18 @@ function ReceiveView(_props) {
2829
2875
  width: "100%",
2830
2876
  aspectRatio: "1",
2831
2877
  p: 2,
2832
- background: "#FFF",
2878
+ background: isDarkMode ? theme.palette.background.paper : "#FFF",
2833
2879
  borderRadius: "8px",
2834
- border: "1px solid rgba(0, 0, 0, 0.12)"
2880
+ border: `1px solid ${isDarkMode ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.12)"}`
2835
2881
  }, children: /* @__PURE__ */ jsx12(
2836
2882
  QRCodeSVG,
2837
2883
  {
2838
2884
  value: wallet.address ? `ethereum:${wallet.address}@${chainId}` : "",
2839
2885
  level: "H",
2840
2886
  includeMargin: false,
2841
- size: 200
2887
+ size: 200,
2888
+ bgColor: isDarkMode ? theme.palette.background.paper : "#FFFFFF",
2889
+ fgColor: isDarkMode ? "#FFFFFF" : "#000000"
2842
2890
  }
2843
2891
  ) }),
2844
2892
  /* @__PURE__ */ jsx12(Box4, { sx: { mt: "auto" }, children: /* @__PURE__ */ jsx12(PoweredByAvaCloud, {}) })
@@ -2961,7 +3009,7 @@ import {
2961
3009
  Box as Box8,
2962
3010
  Tabs,
2963
3011
  Tab,
2964
- useTheme as useTheme2
3012
+ useTheme as useTheme3
2965
3013
  } from "@avalabs/core-k2-components";
2966
3014
 
2967
3015
  // src/components/FungibleList.tsx
@@ -3357,7 +3405,7 @@ function NonFungibleList() {
3357
3405
  import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
3358
3406
  function TokensView({ onSend }) {
3359
3407
  const [activeTab, setActiveTab] = useState14("tokens");
3360
- const theme = useTheme2();
3408
+ const theme = useTheme3();
3361
3409
  const handleCopyAddress = (address) => {
3362
3410
  navigator.clipboard.writeText(address);
3363
3411
  };
@@ -3598,7 +3646,7 @@ function WalletCard({ onClose }) {
3598
3646
  const { balance, isLoadingBalance, currencySymbol, blockchain } = useGlacier();
3599
3647
  const [currentView, setCurrentView] = useState15("main");
3600
3648
  const [selectedToken, setSelectedToken] = useState15();
3601
- const theme = useTheme3();
3649
+ const theme = useTheme4();
3602
3650
  if (!isAuthenticated || !user) return null;
3603
3651
  const handleCopy = (e) => {
3604
3652
  e.stopPropagation();
@@ -3790,7 +3838,7 @@ function WalletButton({
3790
3838
  }) {
3791
3839
  const { isLoading, isAuthenticated, wallet } = useAvaCloudWallet();
3792
3840
  const [isModalOpen, setIsModalOpen] = useState16(false);
3793
- const theme = useTheme4();
3841
+ const theme = useTheme5();
3794
3842
  const { isDarkMode } = useThemeMode();
3795
3843
  const handleOpen = () => setIsModalOpen(true);
3796
3844
  const handleClose = () => setIsModalOpen(false);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avalabs/avacloud-waas-react",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
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",
@@ -51,7 +52,7 @@
51
52
  "homepage": "https://github.com/ava-labs/avacloud-auth-react#readme",
52
53
  "author": "Ava Labs, Inc.",
53
54
  "scripts": {
54
- "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/",
55
56
  "dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react",
56
57
  "lint": "eslint \"src/**/*.ts*\"",
57
58
  "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
Binary file