@0xkey-io/react-native-wallet-kit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +93 -0
- package/dist/hooks/use-0xkey.d.ts +3 -0
- package/dist/hooks/use-0xkey.d.ts.map +1 -0
- package/dist/hooks/use-0xkey.js +15 -0
- package/dist/hooks/use-0xkey.js.map +1 -0
- package/dist/hooks/use-0xkey.mjs +13 -0
- package/dist/hooks/use-0xkey.mjs.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers/Types.d.ts +275 -0
- package/dist/providers/Types.d.ts.map +1 -0
- package/dist/providers/Types.js +9 -0
- package/dist/providers/Types.js.map +1 -0
- package/dist/providers/Types.mjs +7 -0
- package/dist/providers/Types.mjs.map +1 -0
- package/dist/providers/ZeroXKeyProvider.d.ts +39 -0
- package/dist/providers/ZeroXKeyProvider.d.ts.map +1 -0
- package/dist/providers/ZeroXKeyProvider.js +1846 -0
- package/dist/providers/ZeroXKeyProvider.js.map +1 -0
- package/dist/providers/ZeroXKeyProvider.mjs +1844 -0
- package/dist/providers/ZeroXKeyProvider.mjs.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/tests/oauth-test.d.ts +2 -0
- package/dist/tests/oauth-test.d.ts.map +1 -0
- package/dist/typedoc-entry/index.d.ts +5 -0
- package/dist/typedoc-entry/index.d.ts.map +1 -0
- package/dist/types/base.d.ts +137 -0
- package/dist/types/base.d.ts.map +1 -0
- package/dist/types/base.js +48 -0
- package/dist/types/base.js.map +1 -0
- package/dist/types/base.mjs +48 -0
- package/dist/types/base.mjs.map +1 -0
- package/dist/types/method-types.d.ts +102 -0
- package/dist/types/method-types.d.ts.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/oauth.d.ts +240 -0
- package/dist/utils/oauth.d.ts.map +1 -0
- package/dist/utils/oauth.js +340 -0
- package/dist/utils/oauth.js.map +1 -0
- package/dist/utils/oauth.mjs +319 -0
- package/dist/utils/oauth.mjs.map +1 -0
- package/dist/utils/timers.d.ts +73 -0
- package/dist/utils/timers.d.ts.map +1 -0
- package/dist/utils/timers.js +132 -0
- package/dist/utils/timers.js.map +1 -0
- package/dist/utils/timers.mjs +122 -0
- package/dist/utils/timers.mjs.map +1 -0
- package/dist/utils/utils.d.ts +27 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +37 -0
- package/dist/utils/utils.js.map +1 -0
- package/dist/utils/utils.mjs +33 -0
- package/dist/utils/utils.mjs.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,1846 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var utils = require('../utils/utils.js');
|
|
5
|
+
var timers = require('../utils/timers.js');
|
|
6
|
+
var oauth = require('../utils/oauth.js');
|
|
7
|
+
var core = require('@0xkey-io/core');
|
|
8
|
+
var react = require('react');
|
|
9
|
+
var reactNative = require('react-native');
|
|
10
|
+
var DeviceInfo = require('react-native-device-info');
|
|
11
|
+
var reactNativeInappbrowserReborn = require('react-native-inappbrowser-reborn');
|
|
12
|
+
var sha2 = require('@noble/hashes/sha2');
|
|
13
|
+
var utils$1 = require('@noble/hashes/utils');
|
|
14
|
+
var sdkTypes = require('@0xkey-io/sdk-types');
|
|
15
|
+
var base = require('../types/base.js');
|
|
16
|
+
var Types = require('./Types.js');
|
|
17
|
+
var crypto = require('@0xkey-io/crypto');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Provides ZeroXKey client authentication, session management, wallet operations, and user profile management
|
|
21
|
+
* for the React Native Wallet Kit SDK. This context provider encapsulates all core authentication flows (Passkey, OTP, OAuth),
|
|
22
|
+
* session lifecycle (creation, expiration, refresh), wallet import/export, and user profile updates (email, phone, name).
|
|
23
|
+
*
|
|
24
|
+
* The provider automatically initializes the ZeroXKey client, fetches configuration (including proxy auth config if needed),
|
|
25
|
+
* and synchronizes session and authentication state. It exposes a comprehensive set of methods for authentication flows,
|
|
26
|
+
* wallet management, and user profile operations, as well as UI handlers for modal-driven flows.
|
|
27
|
+
*
|
|
28
|
+
* Features:
|
|
29
|
+
* - Passkey, OTP (Email/SMS), and OAuth (Google, Apple, Facebook, Discord, X) authentication and sign-up flows.
|
|
30
|
+
* - React Native-specific OAuth: opens an in-app browser (Custom Tabs/Safari View Controller) and deep-links back via the configured app scheme.
|
|
31
|
+
* - Session management: creation, expiration scheduling, refresh, and clearing.
|
|
32
|
+
* - Wallet management: fetch, import, export, account management.
|
|
33
|
+
* - User profile management: email, phone, name, OAuth provider, and passkey linking/removal.
|
|
34
|
+
* - Error handling and callback integration for custom error and event responses.
|
|
35
|
+
*
|
|
36
|
+
* Usage:
|
|
37
|
+
* Wrap your application with `ZeroXKeyProvider` to enable authentication and wallet features via context.
|
|
38
|
+
*
|
|
39
|
+
* @param config - The ZeroXKey provider configuration object.
|
|
40
|
+
* @param children - React children to be rendered within the provider.
|
|
41
|
+
* @param callbacks - Optional callbacks for error handling and session events.
|
|
42
|
+
*
|
|
43
|
+
* @returns A React context provider exposing authentication, wallet, and user management methods and state.
|
|
44
|
+
*/
|
|
45
|
+
const ZeroXKeyProvider = ({ config, children, callbacks, }) => {
|
|
46
|
+
const [client, setClient] = react.useState(undefined);
|
|
47
|
+
const [session, setSession] = react.useState(undefined);
|
|
48
|
+
const [masterConfig, setMasterConfig] = react.useState(undefined);
|
|
49
|
+
const [wallets, setWallets] = react.useState([]);
|
|
50
|
+
const [user, setUser] = react.useState(undefined);
|
|
51
|
+
const [clientState, setClientState] = react.useState();
|
|
52
|
+
const [authState, setAuthState] = react.useState(base.AuthState.Unauthenticated);
|
|
53
|
+
const expiryTimeoutsRef = react.useRef({});
|
|
54
|
+
const proxyAuthConfigRef = react.useRef(null);
|
|
55
|
+
const [allSessions, setAllSessions] = react.useState(undefined);
|
|
56
|
+
// if there is no authProxyConfigId or if autoFetchWalletKitConfig is specifically
|
|
57
|
+
// set to false, we don't need to fetch the config
|
|
58
|
+
const shouldFetchWalletKitConfig = config.authProxyConfigId != null &&
|
|
59
|
+
config.authProxyConfigId !== "" &&
|
|
60
|
+
config.autoFetchWalletKitConfig !== false;
|
|
61
|
+
const buildConfig = (proxyAuthConfig) => {
|
|
62
|
+
// Juggle the local overrides with the values set in the dashboard (proxyAuthConfig).
|
|
63
|
+
// Normalize potentially empty string values coming from the app-level config
|
|
64
|
+
const sanitizedAuthProxyUrl = config.authProxyUrl && config.authProxyUrl.trim()
|
|
65
|
+
? config.authProxyUrl
|
|
66
|
+
: undefined;
|
|
67
|
+
// Resolve OTP enablement
|
|
68
|
+
const emailOtpEnabled = config.auth?.otp?.email ??
|
|
69
|
+
proxyAuthConfig?.enabledProviders.includes("email") ??
|
|
70
|
+
false;
|
|
71
|
+
const smsOtpEnabled = config.auth?.otp?.sms ??
|
|
72
|
+
proxyAuthConfig?.enabledProviders.includes("sms") ??
|
|
73
|
+
false;
|
|
74
|
+
// Resolve shared redirect; do NOT attach scheme here. We'll attach in handler on demand.
|
|
75
|
+
const appScheme = config.auth?.oauth?.appScheme ?? undefined;
|
|
76
|
+
const redirectUrl = config.auth?.oauth?.redirectUri ??
|
|
77
|
+
proxyAuthConfig?.oauthRedirectUrl ??
|
|
78
|
+
oauth.ZEROXKEY_OAUTH_REDIRECT_URL;
|
|
79
|
+
// Warn if they are trying to set auth proxy only settings directly
|
|
80
|
+
if (proxyAuthConfig) {
|
|
81
|
+
if (config.auth?.sessionExpirationSeconds) {
|
|
82
|
+
console.warn("ZeroXKey SDK warning. You have set sessionExpirationSeconds directly in the ZeroXKeyProvider. This setting will be ignored because you are using an auth proxy. Please configure session expiration in the ZeroXKey dashboard.");
|
|
83
|
+
}
|
|
84
|
+
if (config.auth?.otp?.alphanumeric !== undefined &&
|
|
85
|
+
shouldFetchWalletKitConfig) {
|
|
86
|
+
console.warn("ZeroXKey SDK warning. You have set otpAlphanumeric directly in the ZeroXKeyProvider. This setting will be ignored because you are using an auth proxy. Please configure OTP settings in the ZeroXKey dashboard.");
|
|
87
|
+
}
|
|
88
|
+
if (config.auth?.otp?.length && shouldFetchWalletKitConfig) {
|
|
89
|
+
console.warn("ZeroXKey SDK warning. You have set otpLength directly in the ZeroXKeyProvider. This setting will be ignored because you are using an auth proxy. Please configure OTP settings in the ZeroXKey dashboard.");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// These are settings that can only be set via the auth proxy config
|
|
93
|
+
const authProxyPrioSettings = {
|
|
94
|
+
sessionExpirationSeconds: proxyAuthConfig?.sessionExpirationSeconds ??
|
|
95
|
+
config.auth?.sessionExpirationSeconds,
|
|
96
|
+
otp: {
|
|
97
|
+
alphanumeric: proxyAuthConfig?.otpAlphanumeric ??
|
|
98
|
+
config.auth?.otp?.alphanumeric ??
|
|
99
|
+
true,
|
|
100
|
+
length: proxyAuthConfig?.otpLength ?? config.auth?.otp?.length ?? "6",
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
...config,
|
|
105
|
+
// Ensure empty strings are not forwarded as URLs
|
|
106
|
+
authProxyUrl: sanitizedAuthProxyUrl,
|
|
107
|
+
// Overrides:
|
|
108
|
+
auth: {
|
|
109
|
+
...config.auth,
|
|
110
|
+
// Proxy-controlled settings
|
|
111
|
+
sessionExpirationSeconds: authProxyPrioSettings.sessionExpirationSeconds,
|
|
112
|
+
otp: {
|
|
113
|
+
...config.auth?.otp,
|
|
114
|
+
// Enablement flags
|
|
115
|
+
email: emailOtpEnabled,
|
|
116
|
+
sms: smsOtpEnabled,
|
|
117
|
+
// Proxy-only settings
|
|
118
|
+
alphanumeric: authProxyPrioSettings.otp.alphanumeric,
|
|
119
|
+
length: authProxyPrioSettings.otp.length,
|
|
120
|
+
},
|
|
121
|
+
// OAuth shared settings
|
|
122
|
+
oauth: {
|
|
123
|
+
...config.auth?.oauth,
|
|
124
|
+
...(appScheme && { appScheme }),
|
|
125
|
+
redirectUri: redirectUrl,
|
|
126
|
+
},
|
|
127
|
+
autoRefreshSession: config.auth?.autoRefreshSession ?? true,
|
|
128
|
+
},
|
|
129
|
+
autoRefreshManagedState: config.autoRefreshManagedState ?? true,
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
const getOauthProviderSettings = (provider) => {
|
|
133
|
+
const oauth$1 = masterConfig?.auth?.oauth;
|
|
134
|
+
const providerConfig = oauth$1 ? oauth$1[provider] : undefined;
|
|
135
|
+
const providerObjectConfig = providerConfig && typeof providerConfig === "object"
|
|
136
|
+
? providerConfig
|
|
137
|
+
: undefined;
|
|
138
|
+
const proxyClientIds = proxyAuthConfigRef.current?.oauthClientIds;
|
|
139
|
+
const clientId = providerObjectConfig?.clientId ??
|
|
140
|
+
(proxyClientIds ? proxyClientIds[provider] : undefined);
|
|
141
|
+
const appScheme = oauth$1?.appScheme;
|
|
142
|
+
// For Discord and X, default to scheme-based deep link if not explicitly provided.
|
|
143
|
+
const redirectUri = providerObjectConfig?.redirectUri ??
|
|
144
|
+
((provider === "discord" || provider === "x") && appScheme
|
|
145
|
+
? `${appScheme}://`
|
|
146
|
+
: (oauth$1?.redirectUri ??
|
|
147
|
+
proxyAuthConfigRef.current?.oauthRedirectUrl ??
|
|
148
|
+
oauth.ZEROXKEY_OAUTH_REDIRECT_URL));
|
|
149
|
+
return { clientId, redirectUri, appScheme };
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Initializes the ZeroXKey client with the provided configuration.
|
|
153
|
+
* This function sets up the client, fetches the proxy auth config if needed,
|
|
154
|
+
* and prepares the client for use in authentication and wallet operations.
|
|
155
|
+
*
|
|
156
|
+
* @internal
|
|
157
|
+
*/
|
|
158
|
+
const initializeClient = async () => {
|
|
159
|
+
if (!masterConfig || client || clientState == base.ClientState.Loading)
|
|
160
|
+
return;
|
|
161
|
+
try {
|
|
162
|
+
setClientState(base.ClientState.Loading);
|
|
163
|
+
const zeroXKeyClient = new core.ZeroXKeyClient({
|
|
164
|
+
apiBaseUrl: masterConfig.apiBaseUrl,
|
|
165
|
+
authProxyUrl: masterConfig.authProxyUrl,
|
|
166
|
+
authProxyConfigId: masterConfig.authProxyConfigId,
|
|
167
|
+
organizationId: masterConfig.organizationId,
|
|
168
|
+
defaultStamperType: masterConfig.defaultStamperType,
|
|
169
|
+
// Define passkey and wallet config here. If we don't pass it into the client, Mr. Client will assume that we don't want to use passkeys/wallets and not create the stamper!
|
|
170
|
+
passkeyConfig: {
|
|
171
|
+
rpId: masterConfig.passkeyConfig?.rpId,
|
|
172
|
+
timeout: masterConfig.passkeyConfig?.timeout || 60000, // 60 seconds
|
|
173
|
+
userVerification: masterConfig.passkeyConfig?.userVerification || "preferred",
|
|
174
|
+
allowCredentials: masterConfig.passkeyConfig?.allowCredentials || [],
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
await zeroXKeyClient.init();
|
|
178
|
+
setClient(zeroXKeyClient);
|
|
179
|
+
// Don't set clientState to ready until we fetch the proxy auth config (See other fetchProxyAuthConfig useEffect)
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
setClientState(base.ClientState.Error);
|
|
183
|
+
if (error instanceof sdkTypes.ZeroXKeyError ||
|
|
184
|
+
error instanceof sdkTypes.ZeroXKeyNetworkError) {
|
|
185
|
+
callbacks?.onError?.(error);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
callbacks?.onError?.(new sdkTypes.ZeroXKeyError(`Failed to initialize ZeroXKey client`, sdkTypes.ZeroXKeyErrorCodes.INITIALIZE_CLIENT_ERROR, error));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* @internal
|
|
194
|
+
* Schedules a session expiration and warning timer for the given session key.
|
|
195
|
+
*
|
|
196
|
+
* - Sets up two timers: one for warning before expiry and one for actual expiry.
|
|
197
|
+
* - Uses capped timeouts under the hood so delays > 24.8 days are safe (see utils/timers.ts).
|
|
198
|
+
*
|
|
199
|
+
* @param params.sessionKey - The key of the session to schedule expiration for.
|
|
200
|
+
* @param params.expiry - The expiration time in seconds since epoch.
|
|
201
|
+
* @throws {ZeroXKeyError} If an error occurs while scheduling the session expiration.
|
|
202
|
+
*/
|
|
203
|
+
async function scheduleSessionExpiration(params) {
|
|
204
|
+
const { sessionKey, expiry } = params;
|
|
205
|
+
try {
|
|
206
|
+
const warnKey = `${sessionKey}-warning`;
|
|
207
|
+
// Replace any prior timers for this session
|
|
208
|
+
timers.clearKey(expiryTimeoutsRef.current, sessionKey);
|
|
209
|
+
timers.clearKey(expiryTimeoutsRef.current, warnKey);
|
|
210
|
+
const now = Date.now();
|
|
211
|
+
const expiryMs = expiry * 1000;
|
|
212
|
+
const timeUntilExpiry = expiryMs - now;
|
|
213
|
+
const beforeExpiry = async () => {
|
|
214
|
+
const activeSession = await getSession();
|
|
215
|
+
if (!activeSession && expiryTimeoutsRef.current[warnKey]) {
|
|
216
|
+
// Keep nudging until session materializes (short 10s timer is fine)
|
|
217
|
+
timers.setTimeoutInMap(expiryTimeoutsRef.current, warnKey, beforeExpiry, 10_000);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const session = await getSession({ sessionKey });
|
|
221
|
+
if (!session)
|
|
222
|
+
return;
|
|
223
|
+
callbacks?.beforeSessionExpiry?.({ sessionKey });
|
|
224
|
+
if (masterConfig?.auth?.autoRefreshSession) {
|
|
225
|
+
await refreshSession({
|
|
226
|
+
expirationSeconds: session.expirationSeconds,
|
|
227
|
+
sessionKey,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
const expireSession = async () => {
|
|
232
|
+
const expiredSession = await getSession({ sessionKey });
|
|
233
|
+
if (!expiredSession)
|
|
234
|
+
return;
|
|
235
|
+
callbacks?.onSessionExpired?.({ sessionKey });
|
|
236
|
+
if ((await getActiveSessionKey()) === sessionKey) {
|
|
237
|
+
setSession(undefined);
|
|
238
|
+
}
|
|
239
|
+
setAllSessions((prev) => {
|
|
240
|
+
if (!prev)
|
|
241
|
+
return prev;
|
|
242
|
+
const next = { ...prev };
|
|
243
|
+
delete next[sessionKey];
|
|
244
|
+
return next;
|
|
245
|
+
});
|
|
246
|
+
await clearSession({ sessionKey });
|
|
247
|
+
// Remove timers for this session
|
|
248
|
+
timers.clearKey(expiryTimeoutsRef.current, sessionKey);
|
|
249
|
+
timers.clearKey(expiryTimeoutsRef.current, warnKey);
|
|
250
|
+
await logout();
|
|
251
|
+
};
|
|
252
|
+
// Already expired → expire immediately
|
|
253
|
+
if (timeUntilExpiry <= 0) {
|
|
254
|
+
await expireSession();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
// Warning timer (if threshold is in the future)
|
|
258
|
+
const warnAt = expiryMs - utils.SESSION_WARNING_THRESHOLD_MS;
|
|
259
|
+
if (warnAt <= now) {
|
|
260
|
+
void beforeExpiry(); // fire-and-forget is fine
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
timers.setCappedTimeoutInMap(expiryTimeoutsRef.current, warnKey, beforeExpiry, warnAt - now);
|
|
264
|
+
}
|
|
265
|
+
// Actual expiry timer (safe for long delays)
|
|
266
|
+
timers.setCappedTimeoutInMap(expiryTimeoutsRef.current, sessionKey, expireSession, timeUntilExpiry);
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
if (error instanceof sdkTypes.ZeroXKeyError ||
|
|
270
|
+
error instanceof sdkTypes.ZeroXKeyNetworkError) {
|
|
271
|
+
callbacks?.onError?.(error);
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
callbacks?.onError?.(new sdkTypes.ZeroXKeyError(`Failed to schedule session expiration for ${sessionKey}`, sdkTypes.ZeroXKeyErrorCodes.SCHEDULE_SESSION_EXPIRY_ERROR, error));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Clears all scheduled session timers (warning + expiry).
|
|
280
|
+
*
|
|
281
|
+
* - Removes all active timers managed by this client.
|
|
282
|
+
* - Useful on re-init or logout to avoid stale timers.
|
|
283
|
+
*
|
|
284
|
+
* @throws {ZeroXKeyError} If an error occurs while clearing the timers.
|
|
285
|
+
*/
|
|
286
|
+
function clearSessionTimeouts(sessionKeys) {
|
|
287
|
+
try {
|
|
288
|
+
if (sessionKeys) {
|
|
289
|
+
timers.clearKeys(expiryTimeoutsRef.current, sessionKeys);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
timers.clearAll(expiryTimeoutsRef.current); // clears & deletes everything
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
if (error instanceof sdkTypes.ZeroXKeyError ||
|
|
297
|
+
error instanceof sdkTypes.ZeroXKeyNetworkError) {
|
|
298
|
+
callbacks?.onError?.(error);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
callbacks?.onError?.(new sdkTypes.ZeroXKeyError("Failed to clear session timeouts", sdkTypes.ZeroXKeyErrorCodes.CLEAR_SESSION_TIMEOUTS_ERROR, error));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Initializes the user sessions by fetching all active sessions and setting up their state.
|
|
307
|
+
* @internal
|
|
308
|
+
*/
|
|
309
|
+
const initializeSessions = async () => {
|
|
310
|
+
setSession(undefined);
|
|
311
|
+
setAllSessions(undefined);
|
|
312
|
+
try {
|
|
313
|
+
const allLocalStorageSessions = await getAllSessions();
|
|
314
|
+
if (!allLocalStorageSessions)
|
|
315
|
+
return;
|
|
316
|
+
await Promise.all(Object.keys(allLocalStorageSessions).map(async (sessionKey) => {
|
|
317
|
+
const s = allLocalStorageSessions?.[sessionKey];
|
|
318
|
+
if (!utils.isValidSession(s)) {
|
|
319
|
+
await clearSession({ sessionKey });
|
|
320
|
+
if (sessionKey === (await getActiveSessionKey())) {
|
|
321
|
+
setSession(undefined);
|
|
322
|
+
}
|
|
323
|
+
delete allLocalStorageSessions[sessionKey];
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
await scheduleSessionExpiration({
|
|
327
|
+
sessionKey,
|
|
328
|
+
expiry: s.expiry,
|
|
329
|
+
});
|
|
330
|
+
}));
|
|
331
|
+
setAllSessions(allLocalStorageSessions || undefined);
|
|
332
|
+
const activeSessionKey = await client?.getActiveSessionKey();
|
|
333
|
+
if (activeSessionKey) {
|
|
334
|
+
if (!allLocalStorageSessions[activeSessionKey]) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
setSession(allLocalStorageSessions[activeSessionKey]);
|
|
338
|
+
await maybeRefreshUser();
|
|
339
|
+
await maybeRefreshWallets();
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
if (error instanceof sdkTypes.ZeroXKeyError ||
|
|
345
|
+
error instanceof sdkTypes.ZeroXKeyNetworkError) {
|
|
346
|
+
callbacks?.onError?.(error);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
callbacks?.onError?.(new sdkTypes.ZeroXKeyError(`Failed to initialize sessions`, sdkTypes.ZeroXKeyErrorCodes.INITIALIZE_SESSION_ERROR, error));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
/**
|
|
354
|
+
* @internal
|
|
355
|
+
* Handles the post-authentication flow.
|
|
356
|
+
*
|
|
357
|
+
* - This function is called after a successful authentication (login or sign-up) via any supported method (Passkey, Wallet, OTP, OAuth).
|
|
358
|
+
* - It fetches the active session and all sessions, updates the session state, and schedules session expiration and warning timeouts.
|
|
359
|
+
* - It also refreshes the user's wallets and profile information to ensure the provider state is up to date.
|
|
360
|
+
* - This function is used internally after all authentication flows to synchronize state and trigger any necessary callbacks.
|
|
361
|
+
*
|
|
362
|
+
* @returns A void promise.
|
|
363
|
+
* @throws {ZeroXKeyError} If the client is not initialized or if there is an error during the process.
|
|
364
|
+
*/
|
|
365
|
+
const handlePostAuth = async (params) => {
|
|
366
|
+
const { method, action, identifier } = params;
|
|
367
|
+
try {
|
|
368
|
+
const sessionKey = await getActiveSessionKey();
|
|
369
|
+
const session = await getSession({
|
|
370
|
+
...(sessionKey && { sessionKey }),
|
|
371
|
+
});
|
|
372
|
+
if (session && sessionKey)
|
|
373
|
+
await scheduleSessionExpiration({
|
|
374
|
+
sessionKey,
|
|
375
|
+
expiry: session.expiry,
|
|
376
|
+
});
|
|
377
|
+
const allSessions = await client.getAllSessions();
|
|
378
|
+
setSession(session);
|
|
379
|
+
setAllSessions(allSessions);
|
|
380
|
+
await maybeRefreshWallets();
|
|
381
|
+
await maybeRefreshUser();
|
|
382
|
+
callbacks?.onAuthenticationSuccess?.({
|
|
383
|
+
session,
|
|
384
|
+
method,
|
|
385
|
+
action,
|
|
386
|
+
identifier,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
if (error instanceof sdkTypes.ZeroXKeyError ||
|
|
391
|
+
error instanceof sdkTypes.ZeroXKeyNetworkError) {
|
|
392
|
+
callbacks?.onError?.(error);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
callbacks?.onError?.(new sdkTypes.ZeroXKeyError(`Failed to handle post-authentication`, sdkTypes.ZeroXKeyErrorCodes.HANDLE_POST_AUTH_ERROR, error));
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
/**
|
|
400
|
+
* @internal
|
|
401
|
+
* Handles the post-logout flow.
|
|
402
|
+
*
|
|
403
|
+
* - This function is called after a successful logout or session clear.
|
|
404
|
+
* - It clears all scheduled session expiration and warning timeouts associated to the session key to prevent memory leaks.
|
|
405
|
+
* - It resets the session state, removes user data from memory, the logged out session from all sessions state, and clears the wallets list.
|
|
406
|
+
* - This ensures that all sensitive information is removed from the provider state after logout.
|
|
407
|
+
* - Called internally after logout or when all sessions are cleared.
|
|
408
|
+
*
|
|
409
|
+
* @returns void
|
|
410
|
+
* @throws {ZeroXKeyError} If there is an error during the post-logout process.
|
|
411
|
+
*/
|
|
412
|
+
const handlePostLogout = (sessionKey) => {
|
|
413
|
+
try {
|
|
414
|
+
clearSessionTimeouts(sessionKey ? [sessionKey, `${sessionKey}-warning`] : undefined);
|
|
415
|
+
setAllSessions((prev) => {
|
|
416
|
+
if (!prev)
|
|
417
|
+
return prev;
|
|
418
|
+
if (sessionKey) {
|
|
419
|
+
const next = { ...prev };
|
|
420
|
+
delete next[sessionKey];
|
|
421
|
+
return next;
|
|
422
|
+
}
|
|
423
|
+
return {};
|
|
424
|
+
});
|
|
425
|
+
setSession(undefined);
|
|
426
|
+
setUser(undefined);
|
|
427
|
+
setWallets([]);
|
|
428
|
+
}
|
|
429
|
+
catch (error) {
|
|
430
|
+
callbacks?.onError?.(new sdkTypes.ZeroXKeyError(`Failed to initialize sessions`, sdkTypes.ZeroXKeyErrorCodes.HANDLE_POST_LOGOUT_ERROR, error));
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
const createPasskey = react.useCallback(async (params) => {
|
|
434
|
+
if (!client) {
|
|
435
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
436
|
+
}
|
|
437
|
+
return utils.withZeroXKeyErrorHandling(() => client.createPasskey({ ...params }), () => logout(), callbacks, "Failed to create passkey");
|
|
438
|
+
}, [client, callbacks]);
|
|
439
|
+
const createHttpClient = react.useCallback((params) => {
|
|
440
|
+
if (!client) {
|
|
441
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
442
|
+
}
|
|
443
|
+
return client.createHttpClient(params);
|
|
444
|
+
}, [client]);
|
|
445
|
+
const logout = react.useCallback(async (params) => {
|
|
446
|
+
if (!client) {
|
|
447
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
448
|
+
}
|
|
449
|
+
await utils.withZeroXKeyErrorHandling(async () => {
|
|
450
|
+
// If no sessionKey is provided, we try to get the active one.
|
|
451
|
+
let sessionKey = params?.sessionKey;
|
|
452
|
+
if (!sessionKey)
|
|
453
|
+
sessionKey = await getActiveSessionKey();
|
|
454
|
+
await client.logout(params);
|
|
455
|
+
// We only handle post logout if the sessionKey is defined since that means we actually logged out of a session.
|
|
456
|
+
if (sessionKey)
|
|
457
|
+
handlePostLogout(sessionKey);
|
|
458
|
+
}, () => logout(), callbacks, "Failed to logout");
|
|
459
|
+
return;
|
|
460
|
+
}, [client, callbacks]);
|
|
461
|
+
const loginWithPasskey = react.useCallback(async (params) => {
|
|
462
|
+
if (!client) {
|
|
463
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
464
|
+
}
|
|
465
|
+
const expirationSeconds = params?.expirationSeconds ??
|
|
466
|
+
masterConfig?.auth?.sessionExpirationSeconds ??
|
|
467
|
+
core.DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
|
|
468
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.loginWithPasskey({ ...params, expirationSeconds }), () => logout(), callbacks, "Failed to login with passkey");
|
|
469
|
+
if (res) {
|
|
470
|
+
await handlePostAuth({
|
|
471
|
+
method: base.AuthMethod.Passkey,
|
|
472
|
+
action: sdkTypes.AuthAction.LOGIN,
|
|
473
|
+
identifier: res.credentialId,
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
return res;
|
|
477
|
+
}, [client, callbacks]);
|
|
478
|
+
const signUpWithPasskey = react.useCallback(async (params) => {
|
|
479
|
+
if (!client) {
|
|
480
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
481
|
+
}
|
|
482
|
+
if (!masterConfig) {
|
|
483
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
484
|
+
}
|
|
485
|
+
// If createSubOrgParams is not provided, use the default from masterConfig
|
|
486
|
+
let createSubOrgParams = params?.createSubOrgParams ??
|
|
487
|
+
masterConfig.auth?.createSuborgParams?.passkeyAuth;
|
|
488
|
+
params =
|
|
489
|
+
createSubOrgParams !== undefined
|
|
490
|
+
? { ...params, createSubOrgParams }
|
|
491
|
+
: { ...params };
|
|
492
|
+
const expirationSeconds = params.expirationSeconds ??
|
|
493
|
+
masterConfig?.auth?.sessionExpirationSeconds ??
|
|
494
|
+
core.DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
|
|
495
|
+
const websiteName = reactNative.Platform.OS === "web" && typeof window !== "undefined"
|
|
496
|
+
? window.location.hostname
|
|
497
|
+
: DeviceInfo.getApplicationName() ||
|
|
498
|
+
DeviceInfo.getBundleId() ||
|
|
499
|
+
"mobile-app";
|
|
500
|
+
const timestamp = new Date().toLocaleDateString() +
|
|
501
|
+
"-" +
|
|
502
|
+
new Date().toLocaleTimeString([], {
|
|
503
|
+
hour: "2-digit",
|
|
504
|
+
minute: "2-digit",
|
|
505
|
+
});
|
|
506
|
+
// We allow passkeyName to be passed in thru the provider or thru the params of this function directly.
|
|
507
|
+
// This is because signUpWithPasskey will create a new passkey using that name.
|
|
508
|
+
// Any extra authenticators will be created after the first one. (see core implementation)
|
|
509
|
+
const passkeyName = params?.passkeyDisplayName ??
|
|
510
|
+
masterConfig.auth?.createSuborgParams?.passkeyAuth?.passkeyName ??
|
|
511
|
+
`${websiteName}-${timestamp}`;
|
|
512
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.signUpWithPasskey({
|
|
513
|
+
...params,
|
|
514
|
+
passkeyDisplayName: passkeyName,
|
|
515
|
+
expirationSeconds,
|
|
516
|
+
}), () => logout(), callbacks, "Failed to sign up with passkey");
|
|
517
|
+
if (res) {
|
|
518
|
+
await handlePostAuth({
|
|
519
|
+
method: base.AuthMethod.Passkey,
|
|
520
|
+
action: sdkTypes.AuthAction.SIGNUP,
|
|
521
|
+
identifier: res.credentialId,
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
return res;
|
|
525
|
+
}, [client, callbacks]);
|
|
526
|
+
const initOtp = react.useCallback(async (params) => {
|
|
527
|
+
if (!client) {
|
|
528
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
529
|
+
}
|
|
530
|
+
return utils.withZeroXKeyErrorHandling(() => client.initOtp(params), () => logout(), callbacks, "Failed to initialize OTP");
|
|
531
|
+
}, [client, callbacks]);
|
|
532
|
+
const verifyOtp = react.useCallback(async (params) => {
|
|
533
|
+
if (!client) {
|
|
534
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
535
|
+
}
|
|
536
|
+
return utils.withZeroXKeyErrorHandling(() => client.verifyOtp(params), () => logout(), callbacks, "Failed to verify OTP");
|
|
537
|
+
}, [client, callbacks]);
|
|
538
|
+
const loginWithOtp = react.useCallback(async (params) => {
|
|
539
|
+
if (!client) {
|
|
540
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
541
|
+
}
|
|
542
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.loginWithOtp(params), () => logout(), callbacks, "Failed to login with OTP");
|
|
543
|
+
if (res) {
|
|
544
|
+
await handlePostAuth({
|
|
545
|
+
method: base.AuthMethod.Otp,
|
|
546
|
+
action: sdkTypes.AuthAction.LOGIN,
|
|
547
|
+
identifier: params.verificationToken,
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
return res;
|
|
551
|
+
}, [client, callbacks]);
|
|
552
|
+
const signUpWithOtp = react.useCallback(async (params) => {
|
|
553
|
+
if (!client) {
|
|
554
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
555
|
+
}
|
|
556
|
+
if (!masterConfig) {
|
|
557
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
558
|
+
}
|
|
559
|
+
// If createSubOrgParams is not provided, use the default from masterConfig
|
|
560
|
+
let createSubOrgParams = params.createSubOrgParams;
|
|
561
|
+
if (!createSubOrgParams && masterConfig?.auth?.createSuborgParams) {
|
|
562
|
+
if (params.otpType === core.OtpType.Email) {
|
|
563
|
+
createSubOrgParams =
|
|
564
|
+
masterConfig.auth.createSuborgParams.emailOtpAuth;
|
|
565
|
+
}
|
|
566
|
+
else if (params.otpType === core.OtpType.Sms) {
|
|
567
|
+
createSubOrgParams = masterConfig.auth.createSuborgParams.smsOtpAuth;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
params =
|
|
571
|
+
createSubOrgParams !== undefined
|
|
572
|
+
? { ...params, createSubOrgParams }
|
|
573
|
+
: { ...params };
|
|
574
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.signUpWithOtp(params), () => logout(), callbacks, "Failed to sign up with OTP");
|
|
575
|
+
if (res) {
|
|
576
|
+
await handlePostAuth({
|
|
577
|
+
method: base.AuthMethod.Otp,
|
|
578
|
+
action: sdkTypes.AuthAction.SIGNUP,
|
|
579
|
+
identifier: params.verificationToken,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
return res;
|
|
583
|
+
}, [client, callbacks, masterConfig]);
|
|
584
|
+
const completeOtp = react.useCallback(async (params) => {
|
|
585
|
+
if (!client) {
|
|
586
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
587
|
+
}
|
|
588
|
+
if (!masterConfig) {
|
|
589
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
590
|
+
}
|
|
591
|
+
// If createSubOrgParams is not provided, use the default from masterConfig
|
|
592
|
+
let createSubOrgParams = params.createSubOrgParams;
|
|
593
|
+
if (!createSubOrgParams && masterConfig?.auth?.createSuborgParams) {
|
|
594
|
+
if (params.otpType === core.OtpType.Email) {
|
|
595
|
+
createSubOrgParams =
|
|
596
|
+
masterConfig.auth.createSuborgParams.emailOtpAuth;
|
|
597
|
+
}
|
|
598
|
+
else if (params.otpType === core.OtpType.Sms) {
|
|
599
|
+
createSubOrgParams = masterConfig.auth.createSuborgParams.smsOtpAuth;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
params =
|
|
603
|
+
createSubOrgParams !== undefined
|
|
604
|
+
? { ...params, createSubOrgParams }
|
|
605
|
+
: { ...params };
|
|
606
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.completeOtp(params), () => logout(), callbacks, "Failed to complete OTP");
|
|
607
|
+
if (res) {
|
|
608
|
+
await handlePostAuth({
|
|
609
|
+
method: base.AuthMethod.Otp,
|
|
610
|
+
action: res.action,
|
|
611
|
+
identifier: res.verificationToken,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
return res;
|
|
615
|
+
}, [client, callbacks, masterConfig]);
|
|
616
|
+
const loginWithOauth = react.useCallback(async (params) => {
|
|
617
|
+
if (!client) {
|
|
618
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
619
|
+
}
|
|
620
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.loginWithOauth(params), () => logout(), callbacks, "Failed to login with OAuth");
|
|
621
|
+
if (res) {
|
|
622
|
+
await handlePostAuth({
|
|
623
|
+
method: base.AuthMethod.Oauth,
|
|
624
|
+
action: sdkTypes.AuthAction.LOGIN,
|
|
625
|
+
identifier: params.oidcToken,
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
return res;
|
|
629
|
+
}, [client, callbacks]);
|
|
630
|
+
const signUpWithOauth = react.useCallback(async (params) => {
|
|
631
|
+
if (!client) {
|
|
632
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
633
|
+
}
|
|
634
|
+
if (!masterConfig) {
|
|
635
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
636
|
+
}
|
|
637
|
+
// If createSubOrgParams is not provided, use the default from masterConfig
|
|
638
|
+
let createSubOrgParams = params.createSubOrgParams ??
|
|
639
|
+
masterConfig.auth?.createSuborgParams?.oauth;
|
|
640
|
+
params =
|
|
641
|
+
createSubOrgParams !== undefined
|
|
642
|
+
? { ...params, createSubOrgParams }
|
|
643
|
+
: { ...params };
|
|
644
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.signUpWithOauth(params), () => logout(), callbacks, "Failed to sign up with OAuth");
|
|
645
|
+
if (res) {
|
|
646
|
+
await handlePostAuth({
|
|
647
|
+
method: base.AuthMethod.Oauth,
|
|
648
|
+
action: sdkTypes.AuthAction.SIGNUP,
|
|
649
|
+
identifier: params.oidcToken,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
return res;
|
|
653
|
+
}, [client, callbacks, masterConfig]);
|
|
654
|
+
const completeOauth = react.useCallback(async (params) => {
|
|
655
|
+
if (!client) {
|
|
656
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
657
|
+
}
|
|
658
|
+
if (!masterConfig) {
|
|
659
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
660
|
+
}
|
|
661
|
+
// If createSubOrgParams is not provided, use the default from masterConfig
|
|
662
|
+
const createSubOrgParams = params.createSubOrgParams ??
|
|
663
|
+
masterConfig.auth?.createSuborgParams?.oauth;
|
|
664
|
+
params =
|
|
665
|
+
createSubOrgParams !== undefined
|
|
666
|
+
? { ...params, createSubOrgParams }
|
|
667
|
+
: { ...params };
|
|
668
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.completeOauth(params), () => logout(), callbacks, "Failed to complete OAuth");
|
|
669
|
+
if (res) {
|
|
670
|
+
await handlePostAuth({
|
|
671
|
+
method: base.AuthMethod.Oauth,
|
|
672
|
+
action: res.action,
|
|
673
|
+
identifier: params.oidcToken,
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
return res;
|
|
677
|
+
}, [client, callbacks, masterConfig]);
|
|
678
|
+
const fetchWallets = react.useCallback(async (params) => {
|
|
679
|
+
if (!client) {
|
|
680
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
681
|
+
}
|
|
682
|
+
return utils.withZeroXKeyErrorHandling(() => client.fetchWallets(params), () => logout(), callbacks, "Failed to fetch wallets");
|
|
683
|
+
}, [client, callbacks]);
|
|
684
|
+
const fetchWalletAccounts = react.useCallback(async (params) => {
|
|
685
|
+
if (!client) {
|
|
686
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
687
|
+
}
|
|
688
|
+
return utils.withZeroXKeyErrorHandling(() => client.fetchWalletAccounts(params), () => logout(), callbacks, "Failed to fetch wallet accounts");
|
|
689
|
+
}, [client, callbacks]);
|
|
690
|
+
const fetchPrivateKeys = react.useCallback(async (params) => {
|
|
691
|
+
if (!client) {
|
|
692
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
693
|
+
}
|
|
694
|
+
return utils.withZeroXKeyErrorHandling(() => client.fetchPrivateKeys(params), () => logout(), callbacks, "Failed to fetch private keys");
|
|
695
|
+
}, [client, callbacks]);
|
|
696
|
+
const fetchBootProofForAppProof = react.useCallback(async (params) => {
|
|
697
|
+
if (!client)
|
|
698
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
699
|
+
return utils.withZeroXKeyErrorHandling(() => client.fetchBootProofForAppProof(params), () => logout(), callbacks, "Failed to fetch or create delegated access user");
|
|
700
|
+
}, [client, callbacks]);
|
|
701
|
+
const signMessage = react.useCallback(async (params) => {
|
|
702
|
+
if (!client)
|
|
703
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
704
|
+
return utils.withZeroXKeyErrorHandling(() => client.signMessage(params), () => logout(), callbacks, "Failed to sign message");
|
|
705
|
+
}, [client, callbacks]);
|
|
706
|
+
const signTransaction = react.useCallback(async (params) => {
|
|
707
|
+
if (!client)
|
|
708
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
709
|
+
return utils.withZeroXKeyErrorHandling(() => client.signTransaction(params), () => logout(), callbacks, "Failed to sign transaction");
|
|
710
|
+
}, [client, callbacks]);
|
|
711
|
+
const solSendTransaction = react.useCallback(async (params) => {
|
|
712
|
+
if (!client)
|
|
713
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
714
|
+
return utils.withZeroXKeyErrorHandling(() => client.solSendTransaction(params), () => logout(), callbacks, "Failed to send sol transaction");
|
|
715
|
+
}, [client, callbacks]);
|
|
716
|
+
const ethSendTransaction = react.useCallback(async (params) => {
|
|
717
|
+
if (!client)
|
|
718
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
719
|
+
return utils.withZeroXKeyErrorHandling(() => client.ethSendTransaction(params), () => logout(), callbacks, "Failed to send eth transaction");
|
|
720
|
+
}, [client, callbacks]);
|
|
721
|
+
const ethSendErc20Transfer = react.useCallback(async (params) => {
|
|
722
|
+
if (!client)
|
|
723
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
724
|
+
return utils.withZeroXKeyErrorHandling(() => client.ethSendErc20Transfer(params), () => logout(), callbacks, "Failed to send ERC20 transfer");
|
|
725
|
+
}, [client, callbacks]);
|
|
726
|
+
const signAndSendTransaction = react.useCallback(async (params) => {
|
|
727
|
+
if (!client)
|
|
728
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
729
|
+
return utils.withZeroXKeyErrorHandling(() => client.signAndSendTransaction(params), () => logout(), callbacks, "Failed to sign and send raw transaction");
|
|
730
|
+
}, [client, callbacks, logout]);
|
|
731
|
+
const pollTransactionStatus = react.useCallback(async (params) => {
|
|
732
|
+
if (!client)
|
|
733
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
734
|
+
return utils.withZeroXKeyErrorHandling(() => client.pollTransactionStatus(params), () => logout(), callbacks, "Failed to poll transaction status");
|
|
735
|
+
}, [client, callbacks]);
|
|
736
|
+
const fetchUser = react.useCallback(async (params) => {
|
|
737
|
+
if (!client)
|
|
738
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
739
|
+
return utils.withZeroXKeyErrorHandling(() => client.fetchUser(params), () => logout(), callbacks, "Failed to fetch user");
|
|
740
|
+
}, [client, callbacks]);
|
|
741
|
+
const fetchOrCreateP256ApiKeyUser = react.useCallback(async (params) => {
|
|
742
|
+
if (!client)
|
|
743
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
744
|
+
return utils.withZeroXKeyErrorHandling(() => client.fetchOrCreateP256ApiKeyUser(params), () => logout(), callbacks, "Failed to fetch or create delegated access user");
|
|
745
|
+
}, [client, callbacks]);
|
|
746
|
+
const fetchOrCreatePolicies = react.useCallback(async (params) => {
|
|
747
|
+
if (!client)
|
|
748
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
749
|
+
return utils.withZeroXKeyErrorHandling(() => client.fetchOrCreatePolicies(params), () => logout(), callbacks, "Failed to fetch or create delegated access user");
|
|
750
|
+
}, [client, callbacks]);
|
|
751
|
+
const updateUserEmail = react.useCallback(async (params) => {
|
|
752
|
+
if (!client)
|
|
753
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
754
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.updateUserEmail(params), () => logout(), callbacks, "Failed to update user email");
|
|
755
|
+
if (res)
|
|
756
|
+
await maybeRefreshUser({
|
|
757
|
+
stampWith: params?.stampWith,
|
|
758
|
+
...(params?.organizationId && {
|
|
759
|
+
organizationId: params.organizationId,
|
|
760
|
+
}),
|
|
761
|
+
...(params?.userId && { userId: params.userId }),
|
|
762
|
+
});
|
|
763
|
+
return res;
|
|
764
|
+
}, [client, callbacks]);
|
|
765
|
+
const removeUserEmail = react.useCallback(async (params) => {
|
|
766
|
+
if (!client)
|
|
767
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
768
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.removeUserEmail(params), () => logout(), callbacks, "Failed to remove user email");
|
|
769
|
+
if (res)
|
|
770
|
+
await maybeRefreshUser({
|
|
771
|
+
stampWith: params?.stampWith,
|
|
772
|
+
...(params?.organizationId && {
|
|
773
|
+
organizationId: params.organizationId,
|
|
774
|
+
}),
|
|
775
|
+
...(params?.userId && { userId: params.userId }),
|
|
776
|
+
});
|
|
777
|
+
return res;
|
|
778
|
+
}, [client, callbacks]);
|
|
779
|
+
const updateUserPhoneNumber = react.useCallback(async (params) => {
|
|
780
|
+
if (!client)
|
|
781
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
782
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.updateUserPhoneNumber(params), () => logout(), callbacks, "Failed to update user phone number");
|
|
783
|
+
if (res)
|
|
784
|
+
await maybeRefreshUser({
|
|
785
|
+
stampWith: params?.stampWith,
|
|
786
|
+
...(params?.organizationId && {
|
|
787
|
+
organizationId: params.organizationId,
|
|
788
|
+
}),
|
|
789
|
+
...(params?.userId && { userId: params.userId }),
|
|
790
|
+
});
|
|
791
|
+
return res;
|
|
792
|
+
}, [client, callbacks]);
|
|
793
|
+
const removeUserPhoneNumber = react.useCallback(async (params) => {
|
|
794
|
+
if (!client)
|
|
795
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
796
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.removeUserPhoneNumber(params), () => logout(), callbacks, "Failed to remove user phone number");
|
|
797
|
+
if (res)
|
|
798
|
+
await maybeRefreshUser({
|
|
799
|
+
stampWith: params?.stampWith,
|
|
800
|
+
...(params?.organizationId && {
|
|
801
|
+
organizationId: params.organizationId,
|
|
802
|
+
}),
|
|
803
|
+
...(params?.userId && { userId: params.userId }),
|
|
804
|
+
});
|
|
805
|
+
return res;
|
|
806
|
+
}, [client, callbacks]);
|
|
807
|
+
const updateUserName = react.useCallback(async (params) => {
|
|
808
|
+
if (!client)
|
|
809
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
810
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.updateUserName(params), () => logout(), callbacks, "Failed to update user name");
|
|
811
|
+
if (res)
|
|
812
|
+
await maybeRefreshUser({
|
|
813
|
+
stampWith: params?.stampWith,
|
|
814
|
+
...(params?.organizationId && {
|
|
815
|
+
organizationId: params.organizationId,
|
|
816
|
+
}),
|
|
817
|
+
...(params?.userId && { userId: params.userId }),
|
|
818
|
+
});
|
|
819
|
+
return res;
|
|
820
|
+
}, [client, callbacks]);
|
|
821
|
+
const addOauthProvider = react.useCallback(async (params) => {
|
|
822
|
+
if (!client)
|
|
823
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
824
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.addOauthProvider(params), () => logout(), callbacks, "Failed to add OAuth provider");
|
|
825
|
+
if (res)
|
|
826
|
+
await maybeRefreshUser({
|
|
827
|
+
stampWith: params?.stampWith,
|
|
828
|
+
...(params?.organizationId && {
|
|
829
|
+
organizationId: params.organizationId,
|
|
830
|
+
}),
|
|
831
|
+
...(params?.userId && { userId: params.userId }),
|
|
832
|
+
});
|
|
833
|
+
return res;
|
|
834
|
+
}, [client, callbacks]);
|
|
835
|
+
const removeOauthProviders = react.useCallback(async (params) => {
|
|
836
|
+
if (!client)
|
|
837
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
838
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.removeOauthProviders(params), () => logout(), callbacks, "Failed to remove OAuth providers");
|
|
839
|
+
if (res)
|
|
840
|
+
await maybeRefreshUser({
|
|
841
|
+
stampWith: params?.stampWith,
|
|
842
|
+
...(params?.organizationId && {
|
|
843
|
+
organizationId: params.organizationId,
|
|
844
|
+
}),
|
|
845
|
+
...(params?.userId && { userId: params.userId }),
|
|
846
|
+
});
|
|
847
|
+
return res;
|
|
848
|
+
}, [client, callbacks]);
|
|
849
|
+
const addPasskey = react.useCallback(async (params) => {
|
|
850
|
+
if (!client)
|
|
851
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
852
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.addPasskey(params), () => logout(), callbacks, "Failed to add passkey");
|
|
853
|
+
if (res)
|
|
854
|
+
await maybeRefreshUser({
|
|
855
|
+
stampWith: params?.stampWith,
|
|
856
|
+
...(params?.organizationId && {
|
|
857
|
+
organizationId: params.organizationId,
|
|
858
|
+
}),
|
|
859
|
+
...(params?.userId && { userId: params.userId }),
|
|
860
|
+
});
|
|
861
|
+
return res;
|
|
862
|
+
}, [client, callbacks]);
|
|
863
|
+
const removePasskeys = react.useCallback(async (params) => {
|
|
864
|
+
if (!client)
|
|
865
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
866
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.removePasskeys(params), () => logout(), callbacks, "Failed to remove passkeys");
|
|
867
|
+
if (res)
|
|
868
|
+
await maybeRefreshUser({
|
|
869
|
+
stampWith: params?.stampWith,
|
|
870
|
+
...(params?.organizationId && {
|
|
871
|
+
organizationId: params.organizationId,
|
|
872
|
+
}),
|
|
873
|
+
...(params?.userId && { userId: params.userId }),
|
|
874
|
+
});
|
|
875
|
+
return res;
|
|
876
|
+
}, [client, callbacks]);
|
|
877
|
+
const createWallet = react.useCallback(async (params) => {
|
|
878
|
+
if (!client)
|
|
879
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
880
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.createWallet(params), () => logout(), callbacks, "Failed to create wallet");
|
|
881
|
+
const s = await getSession();
|
|
882
|
+
if (res && s)
|
|
883
|
+
await maybeRefreshWallets({
|
|
884
|
+
stampWith: params?.stampWith,
|
|
885
|
+
...(params?.organizationId && {
|
|
886
|
+
organizationId: params.organizationId,
|
|
887
|
+
}),
|
|
888
|
+
});
|
|
889
|
+
return res;
|
|
890
|
+
}, [client, session, callbacks]);
|
|
891
|
+
const createWalletAccounts = react.useCallback(async (params) => {
|
|
892
|
+
if (!client)
|
|
893
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
894
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.createWalletAccounts(params), () => logout(), callbacks, "Failed to create wallet accounts");
|
|
895
|
+
const s = await getSession();
|
|
896
|
+
if (res && s)
|
|
897
|
+
await maybeRefreshWallets({
|
|
898
|
+
stampWith: params?.stampWith,
|
|
899
|
+
...(params?.organizationId && {
|
|
900
|
+
organizationId: params.organizationId,
|
|
901
|
+
}),
|
|
902
|
+
});
|
|
903
|
+
return res;
|
|
904
|
+
}, [client, session, callbacks]);
|
|
905
|
+
const exportWallet = react.useCallback(async (params) => {
|
|
906
|
+
if (!client)
|
|
907
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
908
|
+
// Default: decrypt unless explicitly disabled
|
|
909
|
+
const shouldDecrypt = params?.decrypt !== false;
|
|
910
|
+
if (!shouldDecrypt) {
|
|
911
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.exportWallet({
|
|
912
|
+
walletId: params.walletId,
|
|
913
|
+
targetPublicKey: params.targetPublicKey,
|
|
914
|
+
...(params.organizationId && {
|
|
915
|
+
organizationId: params.organizationId,
|
|
916
|
+
}),
|
|
917
|
+
...(params.stampWith && { stampWith: params.stampWith }),
|
|
918
|
+
}), () => logout(), callbacks, "Failed to export wallet");
|
|
919
|
+
const s = await getSession();
|
|
920
|
+
if (res && s)
|
|
921
|
+
await maybeRefreshWallets({
|
|
922
|
+
stampWith: params?.stampWith,
|
|
923
|
+
...(params?.organizationId && {
|
|
924
|
+
organizationId: params.organizationId,
|
|
925
|
+
}),
|
|
926
|
+
});
|
|
927
|
+
return res;
|
|
928
|
+
}
|
|
929
|
+
// Decrypting path: generate P-256 keypair, export, then decrypt to mnemonic
|
|
930
|
+
try {
|
|
931
|
+
const { privateKey, publicKeyUncompressed } = crypto.generateP256KeyPair();
|
|
932
|
+
const targetPublicKey = publicKeyUncompressed;
|
|
933
|
+
const exportParams = {
|
|
934
|
+
walletId: params.walletId,
|
|
935
|
+
targetPublicKey,
|
|
936
|
+
...(params.organizationId && {
|
|
937
|
+
organizationId: params.organizationId,
|
|
938
|
+
}),
|
|
939
|
+
...(params.stampWith && { stampWith: params.stampWith }),
|
|
940
|
+
};
|
|
941
|
+
const bundle = await utils.withZeroXKeyErrorHandling(() => client.exportWallet(exportParams), () => logout(), callbacks, "Failed to export wallet");
|
|
942
|
+
const session = await getSession();
|
|
943
|
+
const orgId = session?.organizationId;
|
|
944
|
+
if (!orgId) {
|
|
945
|
+
throw new sdkTypes.ZeroXKeyError("Missing organizationId in session for decryption", sdkTypes.ZeroXKeyErrorCodes.INVALID_REQUEST);
|
|
946
|
+
}
|
|
947
|
+
const mnemonic = await crypto.decryptExportBundle({
|
|
948
|
+
exportBundle: bundle,
|
|
949
|
+
embeddedKey: privateKey,
|
|
950
|
+
organizationId: orgId,
|
|
951
|
+
returnMnemonic: true,
|
|
952
|
+
keyFormat: "HEXADECIMAL",
|
|
953
|
+
});
|
|
954
|
+
return mnemonic;
|
|
955
|
+
}
|
|
956
|
+
catch (error) {
|
|
957
|
+
throw error;
|
|
958
|
+
}
|
|
959
|
+
}, [client, session, callbacks]);
|
|
960
|
+
const exportPrivateKey = react.useCallback(async (params) => {
|
|
961
|
+
if (!client)
|
|
962
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
963
|
+
const shouldDecrypt = params?.decrypt !== false;
|
|
964
|
+
if (!shouldDecrypt) {
|
|
965
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.exportPrivateKey({
|
|
966
|
+
privateKeyId: params.privateKeyId,
|
|
967
|
+
targetPublicKey: params.targetPublicKey,
|
|
968
|
+
...(params.organizationId && {
|
|
969
|
+
organizationId: params.organizationId,
|
|
970
|
+
}),
|
|
971
|
+
...(params.stampWith && { stampWith: params.stampWith }),
|
|
972
|
+
}), () => logout(), callbacks, "Failed to export private key");
|
|
973
|
+
return res;
|
|
974
|
+
}
|
|
975
|
+
try {
|
|
976
|
+
const { privateKey, publicKeyUncompressed } = crypto.generateP256KeyPair();
|
|
977
|
+
const targetPublicKey = publicKeyUncompressed;
|
|
978
|
+
const exportParams = {
|
|
979
|
+
privateKeyId: params.privateKeyId,
|
|
980
|
+
targetPublicKey,
|
|
981
|
+
...(params.organizationId && {
|
|
982
|
+
organizationId: params.organizationId,
|
|
983
|
+
}),
|
|
984
|
+
...(params.stampWith && { stampWith: params.stampWith }),
|
|
985
|
+
};
|
|
986
|
+
const bundle = await utils.withZeroXKeyErrorHandling(() => client.exportPrivateKey(exportParams), () => logout(), callbacks, "Failed to export private key");
|
|
987
|
+
const session = await getSession();
|
|
988
|
+
const orgId = session?.organizationId;
|
|
989
|
+
if (!orgId) {
|
|
990
|
+
throw new sdkTypes.ZeroXKeyError("Missing organizationId in session for decryption", sdkTypes.ZeroXKeyErrorCodes.INVALID_REQUEST);
|
|
991
|
+
}
|
|
992
|
+
const rawPrivateKey = await crypto.decryptExportBundle({
|
|
993
|
+
exportBundle: bundle,
|
|
994
|
+
embeddedKey: privateKey,
|
|
995
|
+
organizationId: orgId,
|
|
996
|
+
returnMnemonic: false,
|
|
997
|
+
keyFormat: "HEXADECIMAL",
|
|
998
|
+
});
|
|
999
|
+
return rawPrivateKey;
|
|
1000
|
+
}
|
|
1001
|
+
catch (error) {
|
|
1002
|
+
throw error;
|
|
1003
|
+
}
|
|
1004
|
+
}, [client, callbacks]);
|
|
1005
|
+
const exportWalletAccount = react.useCallback(async (params) => {
|
|
1006
|
+
if (!client)
|
|
1007
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1008
|
+
const shouldDecrypt = params?.decrypt !== false;
|
|
1009
|
+
if (!shouldDecrypt) {
|
|
1010
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.exportWalletAccount({
|
|
1011
|
+
address: params.address,
|
|
1012
|
+
targetPublicKey: params.targetPublicKey,
|
|
1013
|
+
...(params.organizationId && {
|
|
1014
|
+
organizationId: params.organizationId,
|
|
1015
|
+
}),
|
|
1016
|
+
...(params.stampWith && { stampWith: params.stampWith }),
|
|
1017
|
+
}), () => logout(), callbacks, "Failed to export wallet accounts");
|
|
1018
|
+
return res;
|
|
1019
|
+
}
|
|
1020
|
+
try {
|
|
1021
|
+
const { privateKey, publicKeyUncompressed } = crypto.generateP256KeyPair();
|
|
1022
|
+
const targetPublicKey = publicKeyUncompressed;
|
|
1023
|
+
const exportParams = {
|
|
1024
|
+
address: params.address,
|
|
1025
|
+
targetPublicKey,
|
|
1026
|
+
...(params.organizationId && {
|
|
1027
|
+
organizationId: params.organizationId,
|
|
1028
|
+
}),
|
|
1029
|
+
...(params.stampWith && { stampWith: params.stampWith }),
|
|
1030
|
+
};
|
|
1031
|
+
const bundle = await utils.withZeroXKeyErrorHandling(() => client.exportWalletAccount(exportParams), () => logout(), callbacks, "Failed to export wallet accounts");
|
|
1032
|
+
const session = await getSession();
|
|
1033
|
+
const orgId = session?.organizationId;
|
|
1034
|
+
if (!orgId) {
|
|
1035
|
+
throw new sdkTypes.ZeroXKeyError("Missing organizationId in session for decryption", sdkTypes.ZeroXKeyErrorCodes.INVALID_REQUEST);
|
|
1036
|
+
}
|
|
1037
|
+
const decryptedKey = await crypto.decryptExportBundle({
|
|
1038
|
+
exportBundle: bundle,
|
|
1039
|
+
embeddedKey: privateKey,
|
|
1040
|
+
organizationId: orgId,
|
|
1041
|
+
returnMnemonic: false,
|
|
1042
|
+
keyFormat: "HEXADECIMAL",
|
|
1043
|
+
});
|
|
1044
|
+
return decryptedKey;
|
|
1045
|
+
}
|
|
1046
|
+
catch (error) {
|
|
1047
|
+
throw error;
|
|
1048
|
+
}
|
|
1049
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1050
|
+
const importWallet = react.useCallback(async (params) => {
|
|
1051
|
+
if (!client)
|
|
1052
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1053
|
+
const { mnemonic, walletName, accounts, organizationId, userId, stampWith, } = params;
|
|
1054
|
+
// Resolve org/user from params or current session
|
|
1055
|
+
const currentSession = await getSession();
|
|
1056
|
+
const effectiveOrgId = organizationId ?? currentSession?.organizationId;
|
|
1057
|
+
const effectiveUserId = userId ?? currentSession?.userId;
|
|
1058
|
+
if (!effectiveOrgId || !effectiveUserId) {
|
|
1059
|
+
throw new sdkTypes.ZeroXKeyError("Missing organizationId or userId for wallet import", sdkTypes.ZeroXKeyErrorCodes.INVALID_REQUEST);
|
|
1060
|
+
}
|
|
1061
|
+
// Step 1: init import to obtain importBundle
|
|
1062
|
+
const initRes = await utils.withZeroXKeyErrorHandling(() => client.httpClient?.initImportWallet({
|
|
1063
|
+
organizationId: effectiveOrgId,
|
|
1064
|
+
userId: effectiveUserId,
|
|
1065
|
+
}, stampWith), () => logout(), callbacks, "Failed to init wallet import");
|
|
1066
|
+
const importBundle = initRes?.importBundle;
|
|
1067
|
+
if (!importBundle) {
|
|
1068
|
+
throw new sdkTypes.ZeroXKeyError("Failed to retrieve import bundle", sdkTypes.ZeroXKeyErrorCodes.IMPORT_WALLET_ERROR);
|
|
1069
|
+
}
|
|
1070
|
+
// Step 2: encrypt mnemonic to encryptedBundle
|
|
1071
|
+
const encryptedBundle = await crypto.encryptWalletToBundle({
|
|
1072
|
+
mnemonic,
|
|
1073
|
+
importBundle,
|
|
1074
|
+
userId: effectiveUserId,
|
|
1075
|
+
organizationId: effectiveOrgId,
|
|
1076
|
+
});
|
|
1077
|
+
// Step 3: call importWallet with encrypted bundle
|
|
1078
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.importWallet({
|
|
1079
|
+
encryptedBundle,
|
|
1080
|
+
walletName,
|
|
1081
|
+
...(accounts && { accounts }),
|
|
1082
|
+
organizationId: effectiveOrgId,
|
|
1083
|
+
userId: effectiveUserId,
|
|
1084
|
+
...(stampWith && { stampWith }),
|
|
1085
|
+
}), () => logout(), callbacks, "Failed to import wallet");
|
|
1086
|
+
// Refresh state after import
|
|
1087
|
+
if (res)
|
|
1088
|
+
await maybeRefreshWallets({
|
|
1089
|
+
...(stampWith && { stampWith }),
|
|
1090
|
+
organizationId: effectiveOrgId,
|
|
1091
|
+
userId: effectiveUserId,
|
|
1092
|
+
});
|
|
1093
|
+
return res;
|
|
1094
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1095
|
+
const importPrivateKey = react.useCallback(async (params) => {
|
|
1096
|
+
if (!client)
|
|
1097
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1098
|
+
const { privateKey, privateKeyName, addressFormats, curve, keyFormat = "HEXADECIMAL", organizationId, userId, stampWith, } = params;
|
|
1099
|
+
// Resolve org/user
|
|
1100
|
+
const currentSession = await getSession();
|
|
1101
|
+
const effectiveOrgId = organizationId ?? currentSession?.organizationId;
|
|
1102
|
+
const effectiveUserId = userId ?? currentSession?.userId;
|
|
1103
|
+
if (!effectiveOrgId || !effectiveUserId) {
|
|
1104
|
+
throw new sdkTypes.ZeroXKeyError("Missing organizationId or userId for private key import", sdkTypes.ZeroXKeyErrorCodes.INVALID_REQUEST);
|
|
1105
|
+
}
|
|
1106
|
+
// Init import to get bundle
|
|
1107
|
+
const initRes = await utils.withZeroXKeyErrorHandling(() => client.httpClient?.initImportPrivateKey({
|
|
1108
|
+
organizationId: effectiveOrgId,
|
|
1109
|
+
userId: effectiveUserId,
|
|
1110
|
+
}, stampWith), () => logout(), callbacks, "Failed to init private key import");
|
|
1111
|
+
const importBundle = initRes?.importBundle;
|
|
1112
|
+
if (!importBundle) {
|
|
1113
|
+
throw new sdkTypes.ZeroXKeyError("Failed to retrieve import bundle", sdkTypes.ZeroXKeyErrorCodes.IMPORT_WALLET_ERROR);
|
|
1114
|
+
}
|
|
1115
|
+
// Encrypt provided private key to bundle
|
|
1116
|
+
const encryptedBundle = await crypto.encryptPrivateKeyToBundle({
|
|
1117
|
+
privateKey,
|
|
1118
|
+
keyFormat,
|
|
1119
|
+
importBundle,
|
|
1120
|
+
userId: effectiveUserId,
|
|
1121
|
+
organizationId: effectiveOrgId,
|
|
1122
|
+
});
|
|
1123
|
+
// Import
|
|
1124
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.importPrivateKey({
|
|
1125
|
+
encryptedBundle,
|
|
1126
|
+
privateKeyName,
|
|
1127
|
+
addressFormats,
|
|
1128
|
+
curve: curve ?? "CURVE_SECP256K1",
|
|
1129
|
+
organizationId: effectiveOrgId,
|
|
1130
|
+
userId: effectiveUserId,
|
|
1131
|
+
...(stampWith && { stampWith }),
|
|
1132
|
+
}), () => logout(), callbacks, "Failed to import private key");
|
|
1133
|
+
return res;
|
|
1134
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1135
|
+
const deleteSubOrganization = react.useCallback(async (params) => {
|
|
1136
|
+
if (!client)
|
|
1137
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1138
|
+
return utils.withZeroXKeyErrorHandling(() => client.deleteSubOrganization(params), () => logout(), callbacks, "Failed to delete sub-organization");
|
|
1139
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1140
|
+
const storeSession = react.useCallback(async (params) => {
|
|
1141
|
+
if (!client)
|
|
1142
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1143
|
+
await utils.withZeroXKeyErrorHandling(() => client.storeSession(params), () => logout(), callbacks, "Failed to store session");
|
|
1144
|
+
const sessionKey = await getActiveSessionKey();
|
|
1145
|
+
const session = await getSession({
|
|
1146
|
+
...(sessionKey && { sessionKey }),
|
|
1147
|
+
});
|
|
1148
|
+
if (session && sessionKey)
|
|
1149
|
+
await scheduleSessionExpiration({ sessionKey, expiry: session.expiry });
|
|
1150
|
+
const allSessions = await getAllSessions();
|
|
1151
|
+
setSession(session);
|
|
1152
|
+
setAllSessions(allSessions);
|
|
1153
|
+
await maybeRefreshWallets();
|
|
1154
|
+
await maybeRefreshUser();
|
|
1155
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1156
|
+
const clearSession = react.useCallback(async (params) => {
|
|
1157
|
+
if (!client)
|
|
1158
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1159
|
+
await utils.withZeroXKeyErrorHandling(async () => client.clearSession(params), () => logout(), callbacks, "Failed to clear session");
|
|
1160
|
+
const sessionKey = params?.sessionKey ?? (await getActiveSessionKey());
|
|
1161
|
+
if (!sessionKey)
|
|
1162
|
+
return;
|
|
1163
|
+
if (!params?.sessionKey) {
|
|
1164
|
+
setSession(undefined);
|
|
1165
|
+
}
|
|
1166
|
+
clearSessionTimeouts([sessionKey]);
|
|
1167
|
+
// clear only the cleared session from allSessions
|
|
1168
|
+
const newAllSessions = { ...allSessions };
|
|
1169
|
+
if (newAllSessions) {
|
|
1170
|
+
delete newAllSessions[sessionKey];
|
|
1171
|
+
}
|
|
1172
|
+
setAllSessions(newAllSessions);
|
|
1173
|
+
return;
|
|
1174
|
+
}, [client, callbacks, session, user, masterConfig]);
|
|
1175
|
+
const clearAllSessions = react.useCallback(async () => {
|
|
1176
|
+
if (!client)
|
|
1177
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1178
|
+
setSession(undefined);
|
|
1179
|
+
setAllSessions(undefined);
|
|
1180
|
+
clearSessionTimeouts();
|
|
1181
|
+
return await utils.withZeroXKeyErrorHandling(() => client.clearAllSessions(), () => logout(), callbacks, "Failed to clear all sessions");
|
|
1182
|
+
}, [client, callbacks, session, user, masterConfig]);
|
|
1183
|
+
const refreshSession = react.useCallback(async (params) => {
|
|
1184
|
+
if (!client) {
|
|
1185
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1186
|
+
}
|
|
1187
|
+
const activeSessionKey = await client.getActiveSessionKey();
|
|
1188
|
+
if (!activeSessionKey) {
|
|
1189
|
+
throw new sdkTypes.ZeroXKeyError("No active session found.", sdkTypes.ZeroXKeyErrorCodes.NO_SESSION_FOUND);
|
|
1190
|
+
}
|
|
1191
|
+
const sessionKey = params?.sessionKey ?? activeSessionKey;
|
|
1192
|
+
const res = await utils.withZeroXKeyErrorHandling(() => client.refreshSession({ ...params }), () => logout(), callbacks, "Failed to refresh session");
|
|
1193
|
+
const session = await getSession({ sessionKey });
|
|
1194
|
+
if (session && sessionKey) {
|
|
1195
|
+
await scheduleSessionExpiration({
|
|
1196
|
+
sessionKey,
|
|
1197
|
+
expiry: session.expiry,
|
|
1198
|
+
...(params?.expirationSeconds && {
|
|
1199
|
+
expirationSeconds: params?.expirationSeconds,
|
|
1200
|
+
}),
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
const allSessions = await getAllSessions();
|
|
1204
|
+
setSession(session);
|
|
1205
|
+
setAllSessions(allSessions);
|
|
1206
|
+
return res;
|
|
1207
|
+
}, [client, callbacks, scheduleSessionExpiration, session, user, masterConfig]);
|
|
1208
|
+
const getSession = react.useCallback(async (params) => {
|
|
1209
|
+
if (!client)
|
|
1210
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1211
|
+
return utils.withZeroXKeyErrorHandling(() => client.getSession(params), () => logout(), callbacks, "Failed to get session");
|
|
1212
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1213
|
+
const getAllSessions = react.useCallback(async () => {
|
|
1214
|
+
if (!client)
|
|
1215
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1216
|
+
return utils.withZeroXKeyErrorHandling(() => client.getAllSessions(), () => logout(), callbacks, "Failed to get all sessions");
|
|
1217
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1218
|
+
const setActiveSession = react.useCallback(async (params) => {
|
|
1219
|
+
if (!client)
|
|
1220
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1221
|
+
const session = await utils.withZeroXKeyErrorHandling(() => client.getSession({ sessionKey: params.sessionKey }), () => logout(), callbacks, "Failed to get session");
|
|
1222
|
+
const s = await getSession();
|
|
1223
|
+
if (!s) {
|
|
1224
|
+
throw new sdkTypes.ZeroXKeyError("Session not found.", sdkTypes.ZeroXKeyErrorCodes.NOT_FOUND);
|
|
1225
|
+
}
|
|
1226
|
+
await utils.withZeroXKeyErrorHandling(() => client.setActiveSession(params), () => logout(), callbacks, "Failed to set active session");
|
|
1227
|
+
setSession(session);
|
|
1228
|
+
await utils.withZeroXKeyErrorHandling(async () => {
|
|
1229
|
+
await maybeRefreshWallets();
|
|
1230
|
+
await maybeRefreshUser();
|
|
1231
|
+
}, () => logout(), callbacks, "Failed to refresh data after setting active session");
|
|
1232
|
+
return;
|
|
1233
|
+
}, [client, callbacks, session, user, masterConfig]);
|
|
1234
|
+
const getActiveSessionKey = react.useCallback(async () => {
|
|
1235
|
+
if (!client)
|
|
1236
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1237
|
+
return utils.withZeroXKeyErrorHandling(() => client.getActiveSessionKey(), () => logout(), callbacks, "Failed to get active session key");
|
|
1238
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1239
|
+
const clearUnusedKeyPairs = react.useCallback(async () => {
|
|
1240
|
+
if (!client)
|
|
1241
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1242
|
+
return utils.withZeroXKeyErrorHandling(() => client.clearUnusedKeyPairs(), () => logout(), callbacks, "Failed to clear unused key pairs");
|
|
1243
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1244
|
+
const createApiKeyPair = react.useCallback(async (params) => {
|
|
1245
|
+
if (!client)
|
|
1246
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1247
|
+
return utils.withZeroXKeyErrorHandling(() => client.createApiKeyPair(params), () => logout(), callbacks, "Failed to create API key pair");
|
|
1248
|
+
}, [client, callbacks, session, user, masterConfig]);
|
|
1249
|
+
const getProxyAuthConfig = react.useCallback(async () => {
|
|
1250
|
+
if (!client)
|
|
1251
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1252
|
+
return utils.withZeroXKeyErrorHandling(() => client.getProxyAuthConfig(), () => logout(), callbacks, "Failed to get proxy auth config");
|
|
1253
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1254
|
+
const verifyAppProofs = react.useCallback(async (params) => {
|
|
1255
|
+
if (!client)
|
|
1256
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1257
|
+
return utils.withZeroXKeyErrorHandling(() => client.verifyAppProofs(params), () => logout(), callbacks, "Failed to verify app proofs");
|
|
1258
|
+
}, [client, callbacks]);
|
|
1259
|
+
const refreshUser = react.useCallback(async (params) => {
|
|
1260
|
+
const { stampWith, organizationId, userId } = params || {};
|
|
1261
|
+
if (!client)
|
|
1262
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1263
|
+
const user = await utils.withZeroXKeyErrorHandling(() => fetchUser({
|
|
1264
|
+
stampWith,
|
|
1265
|
+
...(organizationId && { organizationId }),
|
|
1266
|
+
...(userId && { userId }),
|
|
1267
|
+
}), () => logout(), callbacks, "Failed to refresh user");
|
|
1268
|
+
if (user) {
|
|
1269
|
+
setUser(user);
|
|
1270
|
+
}
|
|
1271
|
+
}, [client, callbacks, fetchUser, session, user]);
|
|
1272
|
+
/**
|
|
1273
|
+
* @internal
|
|
1274
|
+
* Auto-refresh user only if enabled in config. This is only used internally.
|
|
1275
|
+
*
|
|
1276
|
+
* @param params.organizationId - organization ID to specify the sub-organization (defaults to the current session's organizationId).
|
|
1277
|
+
* @param params.userId - user ID to fetch specific user details (defaults to the current session's userId).
|
|
1278
|
+
* @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1279
|
+
* @returns A promise that resolves when the user is refreshed, or does nothing if auto-refresh is disabled
|
|
1280
|
+
*/
|
|
1281
|
+
const maybeRefreshUser = react.useCallback(async (params) => {
|
|
1282
|
+
if (!masterConfig?.autoRefreshManagedState)
|
|
1283
|
+
return;
|
|
1284
|
+
return refreshUser(params);
|
|
1285
|
+
}, [masterConfig, refreshUser]);
|
|
1286
|
+
const refreshWallets = react.useCallback(async (params) => {
|
|
1287
|
+
const { stampWith, organizationId, userId } = params || {};
|
|
1288
|
+
if (!client)
|
|
1289
|
+
throw new sdkTypes.ZeroXKeyError("Client is not initialized.", sdkTypes.ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1290
|
+
const wallets = await utils.withZeroXKeyErrorHandling(() => fetchWallets({
|
|
1291
|
+
stampWith,
|
|
1292
|
+
...(organizationId && { organizationId }),
|
|
1293
|
+
...(userId && { userId }),
|
|
1294
|
+
}), () => logout(), callbacks, "Failed to refresh wallets");
|
|
1295
|
+
if (wallets) {
|
|
1296
|
+
setWallets(wallets);
|
|
1297
|
+
}
|
|
1298
|
+
return wallets;
|
|
1299
|
+
}, [client, callbacks, fetchWallets, session, user]);
|
|
1300
|
+
/**
|
|
1301
|
+
* @internal
|
|
1302
|
+
* Auto-refresh wallets only if enabled in config. This is only used internally.
|
|
1303
|
+
*
|
|
1304
|
+
* @param params.organizationId - organization ID to specify the sub-organization (defaults to the current session's organizationId).
|
|
1305
|
+
* @param params.userId - user ID to fetch specific user details (defaults to the current session's userId).
|
|
1306
|
+
* @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
|
|
1307
|
+
* @returns A promise that resolves to an array of wallets, or an empty array if auto-refresh is disabled
|
|
1308
|
+
*/
|
|
1309
|
+
const maybeRefreshWallets = react.useCallback(async (params) => {
|
|
1310
|
+
if (!masterConfig?.autoRefreshManagedState)
|
|
1311
|
+
return [];
|
|
1312
|
+
return refreshWallets(params);
|
|
1313
|
+
}, [masterConfig, refreshWallets]);
|
|
1314
|
+
const handleDiscordOauth = react.useCallback(async (params) => {
|
|
1315
|
+
const { additionalState: additionalParameters } = params || {};
|
|
1316
|
+
const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(sdkTypes.OAuthProviders.DISCORD);
|
|
1317
|
+
try {
|
|
1318
|
+
if (!masterConfig) {
|
|
1319
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1320
|
+
}
|
|
1321
|
+
if (!clientId) {
|
|
1322
|
+
throw new sdkTypes.ZeroXKeyError("Discord Client ID is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1323
|
+
}
|
|
1324
|
+
if (!redirectUri) {
|
|
1325
|
+
throw new sdkTypes.ZeroXKeyError("OAuth Redirect URI is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1326
|
+
}
|
|
1327
|
+
if (!scheme) {
|
|
1328
|
+
throw new sdkTypes.ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1329
|
+
}
|
|
1330
|
+
// Create key pair and generate nonce
|
|
1331
|
+
const publicKey = await createApiKeyPair();
|
|
1332
|
+
if (!publicKey) {
|
|
1333
|
+
throw new sdkTypes.ZeroXKeyError("Failed to create public key for OAuth.", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1334
|
+
}
|
|
1335
|
+
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
1336
|
+
// Generate PKCE challenge pair and store verifier
|
|
1337
|
+
const { verifier, codeChallenge } = await oauth.generateChallengePair();
|
|
1338
|
+
await oauth.storePKCEVerifier(sdkTypes.OAuthProviders.DISCORD, verifier);
|
|
1339
|
+
// Build OAuth URL (direct Discord URL, not proxy)
|
|
1340
|
+
const discordAuthUrl = oauth.buildOAuthUrl({
|
|
1341
|
+
provider: sdkTypes.OAuthProviders.DISCORD,
|
|
1342
|
+
clientId,
|
|
1343
|
+
redirectUri,
|
|
1344
|
+
publicKey,
|
|
1345
|
+
nonce,
|
|
1346
|
+
codeChallenge,
|
|
1347
|
+
additionalState: additionalParameters,
|
|
1348
|
+
useOauthProxyOrigin: false,
|
|
1349
|
+
});
|
|
1350
|
+
if (!(await reactNativeInappbrowserReborn.InAppBrowser.isAvailable())) {
|
|
1351
|
+
throw new sdkTypes.ZeroXKeyError("InAppBrowser is not available", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1352
|
+
}
|
|
1353
|
+
const result = await reactNativeInappbrowserReborn.InAppBrowser.openAuth(discordAuthUrl, scheme, {
|
|
1354
|
+
dismissButtonStyle: "cancel",
|
|
1355
|
+
animated: true,
|
|
1356
|
+
modalPresentationStyle: "fullScreen",
|
|
1357
|
+
modalTransitionStyle: "coverVertical",
|
|
1358
|
+
modalEnabled: true,
|
|
1359
|
+
enableBarCollapsing: false,
|
|
1360
|
+
showTitle: true,
|
|
1361
|
+
enableUrlBarHiding: true,
|
|
1362
|
+
enableDefaultShare: true,
|
|
1363
|
+
});
|
|
1364
|
+
if (!result || result.type !== "success" || !result.url) {
|
|
1365
|
+
throw new sdkTypes.ZeroXKeyError("OAuth flow did not complete successfully", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1366
|
+
}
|
|
1367
|
+
// Parse the deep link result
|
|
1368
|
+
const parsed = oauth.parseInAppBrowserResult(result.url);
|
|
1369
|
+
if (!parsed.authCode) {
|
|
1370
|
+
throw new sdkTypes.ZeroXKeyError("Missing authorization code from Discord OAuth", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1371
|
+
}
|
|
1372
|
+
// Handle PKCE flow: exchange code for token and complete
|
|
1373
|
+
await oauth.handlePKCEFlow({
|
|
1374
|
+
provider: sdkTypes.OAuthProviders.DISCORD,
|
|
1375
|
+
publicKey,
|
|
1376
|
+
authCode: parsed.authCode,
|
|
1377
|
+
...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
|
|
1378
|
+
...(callbacks && { callbacks }),
|
|
1379
|
+
completeOauth,
|
|
1380
|
+
exchangeCodeForToken: async (codeVerifier) => {
|
|
1381
|
+
const resp = await client?.httpClient?.proxyOAuth2Authenticate({
|
|
1382
|
+
provider: "OAUTH2_PROVIDER_DISCORD",
|
|
1383
|
+
authCode: parsed.authCode,
|
|
1384
|
+
redirectUri,
|
|
1385
|
+
codeVerifier,
|
|
1386
|
+
clientId,
|
|
1387
|
+
nonce,
|
|
1388
|
+
});
|
|
1389
|
+
const oidcToken = resp?.oidcToken;
|
|
1390
|
+
if (!oidcToken) {
|
|
1391
|
+
throw new sdkTypes.ZeroXKeyError("Missing oidcToken from OAuth exchange", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1392
|
+
}
|
|
1393
|
+
return oidcToken;
|
|
1394
|
+
},
|
|
1395
|
+
});
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
catch (error) {
|
|
1399
|
+
throw error;
|
|
1400
|
+
}
|
|
1401
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1402
|
+
const handleXOauth = react.useCallback(async (params) => {
|
|
1403
|
+
const { additionalState: additionalParameters } = params || {};
|
|
1404
|
+
const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(sdkTypes.OAuthProviders.X);
|
|
1405
|
+
try {
|
|
1406
|
+
if (!masterConfig) {
|
|
1407
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1408
|
+
}
|
|
1409
|
+
if (!clientId) {
|
|
1410
|
+
throw new sdkTypes.ZeroXKeyError("Twitter Client ID is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1411
|
+
}
|
|
1412
|
+
if (!redirectUri) {
|
|
1413
|
+
throw new sdkTypes.ZeroXKeyError("OAuth Redirect URI is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1414
|
+
}
|
|
1415
|
+
if (!scheme) {
|
|
1416
|
+
throw new sdkTypes.ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1417
|
+
}
|
|
1418
|
+
const publicKey = await createApiKeyPair();
|
|
1419
|
+
if (!publicKey) {
|
|
1420
|
+
throw new sdkTypes.ZeroXKeyError("Failed to create public key for OAuth.", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1421
|
+
}
|
|
1422
|
+
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
1423
|
+
// Generate PKCE challenge pair and store verifier
|
|
1424
|
+
const { verifier, codeChallenge } = await oauth.generateChallengePair();
|
|
1425
|
+
await oauth.storePKCEVerifier(sdkTypes.OAuthProviders.X, verifier);
|
|
1426
|
+
// Build OAuth URL (direct X/Twitter URL, not proxy)
|
|
1427
|
+
const twitterAuthUrl = oauth.buildOAuthUrl({
|
|
1428
|
+
provider: sdkTypes.OAuthProviders.X,
|
|
1429
|
+
clientId,
|
|
1430
|
+
redirectUri,
|
|
1431
|
+
publicKey,
|
|
1432
|
+
nonce,
|
|
1433
|
+
codeChallenge,
|
|
1434
|
+
additionalState: additionalParameters,
|
|
1435
|
+
useOauthProxyOrigin: false,
|
|
1436
|
+
});
|
|
1437
|
+
if (!(await reactNativeInappbrowserReborn.InAppBrowser.isAvailable())) {
|
|
1438
|
+
throw new sdkTypes.ZeroXKeyError("InAppBrowser is not available", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1439
|
+
}
|
|
1440
|
+
const result = await reactNativeInappbrowserReborn.InAppBrowser.openAuth(twitterAuthUrl, scheme, {
|
|
1441
|
+
dismissButtonStyle: "cancel",
|
|
1442
|
+
animated: true,
|
|
1443
|
+
modalPresentationStyle: "fullScreen",
|
|
1444
|
+
modalTransitionStyle: "coverVertical",
|
|
1445
|
+
modalEnabled: true,
|
|
1446
|
+
enableBarCollapsing: false,
|
|
1447
|
+
showTitle: true,
|
|
1448
|
+
enableUrlBarHiding: true,
|
|
1449
|
+
enableDefaultShare: true,
|
|
1450
|
+
});
|
|
1451
|
+
if (!result || result.type !== "success" || !result.url) {
|
|
1452
|
+
throw new sdkTypes.ZeroXKeyError("OAuth flow did not complete successfully", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1453
|
+
}
|
|
1454
|
+
// Parse the deep link result
|
|
1455
|
+
const parsed = oauth.parseInAppBrowserResult(result.url);
|
|
1456
|
+
if (!parsed.authCode) {
|
|
1457
|
+
throw new sdkTypes.ZeroXKeyError("Missing authorization code from Twitter OAuth", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1458
|
+
}
|
|
1459
|
+
// Handle PKCE flow: exchange code for token and complete
|
|
1460
|
+
await oauth.handlePKCEFlow({
|
|
1461
|
+
provider: sdkTypes.OAuthProviders.X,
|
|
1462
|
+
publicKey,
|
|
1463
|
+
authCode: parsed.authCode,
|
|
1464
|
+
...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
|
|
1465
|
+
...(callbacks && { callbacks }),
|
|
1466
|
+
completeOauth,
|
|
1467
|
+
exchangeCodeForToken: async (codeVerifier) => {
|
|
1468
|
+
const resp = await client?.httpClient?.proxyOAuth2Authenticate({
|
|
1469
|
+
provider: "OAUTH2_PROVIDER_X",
|
|
1470
|
+
authCode: parsed.authCode,
|
|
1471
|
+
redirectUri,
|
|
1472
|
+
codeVerifier,
|
|
1473
|
+
clientId,
|
|
1474
|
+
nonce,
|
|
1475
|
+
});
|
|
1476
|
+
const oidcToken = resp?.oidcToken;
|
|
1477
|
+
if (!oidcToken) {
|
|
1478
|
+
throw new sdkTypes.ZeroXKeyError("Missing oidcToken from OAuth exchange", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1479
|
+
}
|
|
1480
|
+
return oidcToken;
|
|
1481
|
+
},
|
|
1482
|
+
});
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
catch (error) {
|
|
1486
|
+
throw error;
|
|
1487
|
+
}
|
|
1488
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1489
|
+
const handleGoogleOauth = react.useCallback(async (params) => {
|
|
1490
|
+
const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(sdkTypes.OAuthProviders.GOOGLE);
|
|
1491
|
+
try {
|
|
1492
|
+
if (!masterConfig) {
|
|
1493
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1494
|
+
}
|
|
1495
|
+
if (!clientId) {
|
|
1496
|
+
throw new sdkTypes.ZeroXKeyError("Google Client ID is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1497
|
+
}
|
|
1498
|
+
if (!redirectUri) {
|
|
1499
|
+
throw new sdkTypes.ZeroXKeyError("OAuth Redirect URI is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1500
|
+
}
|
|
1501
|
+
if (!scheme) {
|
|
1502
|
+
throw new sdkTypes.ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1503
|
+
}
|
|
1504
|
+
const finalRedirectUri = `${redirectUri}?scheme=${encodeURIComponent(scheme)}`;
|
|
1505
|
+
// Create key pair and generate nonce
|
|
1506
|
+
const publicKey = await createApiKeyPair();
|
|
1507
|
+
if (!publicKey) {
|
|
1508
|
+
throw new sdkTypes.ZeroXKeyError("Failed to create public key for OAuth.", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1509
|
+
}
|
|
1510
|
+
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
1511
|
+
// Build OAuth URL using ZeroXKey OAuth proxy
|
|
1512
|
+
const oauthUrl = oauth.buildOAuthUrl({
|
|
1513
|
+
provider: sdkTypes.OAuthProviders.GOOGLE,
|
|
1514
|
+
clientId,
|
|
1515
|
+
redirectUri: finalRedirectUri,
|
|
1516
|
+
publicKey,
|
|
1517
|
+
nonce,
|
|
1518
|
+
useOauthProxyOrigin: true,
|
|
1519
|
+
});
|
|
1520
|
+
if (!(await reactNativeInappbrowserReborn.InAppBrowser.isAvailable())) {
|
|
1521
|
+
throw new sdkTypes.ZeroXKeyError("InAppBrowser is not available", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1522
|
+
}
|
|
1523
|
+
const result = await reactNativeInappbrowserReborn.InAppBrowser.openAuth(oauthUrl, scheme, {
|
|
1524
|
+
dismissButtonStyle: "cancel",
|
|
1525
|
+
animated: true,
|
|
1526
|
+
modalPresentationStyle: "fullScreen",
|
|
1527
|
+
modalTransitionStyle: "coverVertical",
|
|
1528
|
+
modalEnabled: true,
|
|
1529
|
+
enableBarCollapsing: false,
|
|
1530
|
+
showTitle: true,
|
|
1531
|
+
enableUrlBarHiding: true,
|
|
1532
|
+
enableDefaultShare: true,
|
|
1533
|
+
});
|
|
1534
|
+
if (!result || result.type !== "success" || !result.url) {
|
|
1535
|
+
throw new sdkTypes.ZeroXKeyError("OAuth flow did not complete successfully", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1536
|
+
}
|
|
1537
|
+
// Parse the deep link result
|
|
1538
|
+
const parsed = oauth.parseInAppBrowserResult(result.url);
|
|
1539
|
+
if (!parsed.idToken) {
|
|
1540
|
+
throw new sdkTypes.ZeroXKeyError("oidcToken not found in the response", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1541
|
+
}
|
|
1542
|
+
// Complete OAuth flow
|
|
1543
|
+
await oauth.completeOAuthFlow({
|
|
1544
|
+
provider: sdkTypes.OAuthProviders.GOOGLE,
|
|
1545
|
+
publicKey,
|
|
1546
|
+
oidcToken: parsed.idToken,
|
|
1547
|
+
...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
|
|
1548
|
+
...(callbacks && { callbacks }),
|
|
1549
|
+
completeOauth,
|
|
1550
|
+
});
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
catch (error) {
|
|
1554
|
+
throw error;
|
|
1555
|
+
}
|
|
1556
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1557
|
+
const handleAppleOauth = react.useCallback(async (params) => {
|
|
1558
|
+
const { additionalState: additionalParameters } = params || {};
|
|
1559
|
+
const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(sdkTypes.OAuthProviders.APPLE);
|
|
1560
|
+
try {
|
|
1561
|
+
if (!masterConfig) {
|
|
1562
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1563
|
+
}
|
|
1564
|
+
if (!clientId) {
|
|
1565
|
+
throw new sdkTypes.ZeroXKeyError("Apple Client ID is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1566
|
+
}
|
|
1567
|
+
if (!redirectUri) {
|
|
1568
|
+
throw new sdkTypes.ZeroXKeyError("OAuth Redirect URI is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1569
|
+
}
|
|
1570
|
+
if (!scheme) {
|
|
1571
|
+
throw new sdkTypes.ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1572
|
+
}
|
|
1573
|
+
const finalRedirectUri = `${redirectUri}?scheme=${encodeURIComponent(scheme)}`;
|
|
1574
|
+
// Create key pair and generate nonce
|
|
1575
|
+
const publicKey = await createApiKeyPair();
|
|
1576
|
+
if (!publicKey) {
|
|
1577
|
+
throw new sdkTypes.ZeroXKeyError("Failed to create public key for OAuth.", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1578
|
+
}
|
|
1579
|
+
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
1580
|
+
// Build OAuth URL using ZeroXKey OAuth proxy
|
|
1581
|
+
const oauthUrl = oauth.buildOAuthUrl({
|
|
1582
|
+
provider: sdkTypes.OAuthProviders.APPLE,
|
|
1583
|
+
clientId,
|
|
1584
|
+
redirectUri: finalRedirectUri,
|
|
1585
|
+
publicKey,
|
|
1586
|
+
nonce,
|
|
1587
|
+
additionalState: additionalParameters,
|
|
1588
|
+
useOauthProxyOrigin: true,
|
|
1589
|
+
});
|
|
1590
|
+
if (!(await reactNativeInappbrowserReborn.InAppBrowser.isAvailable())) {
|
|
1591
|
+
throw new sdkTypes.ZeroXKeyError("InAppBrowser is not available", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1592
|
+
}
|
|
1593
|
+
const result = await reactNativeInappbrowserReborn.InAppBrowser.openAuth(oauthUrl, scheme, {
|
|
1594
|
+
dismissButtonStyle: "cancel",
|
|
1595
|
+
animated: true,
|
|
1596
|
+
modalPresentationStyle: "fullScreen",
|
|
1597
|
+
modalTransitionStyle: "coverVertical",
|
|
1598
|
+
modalEnabled: true,
|
|
1599
|
+
enableBarCollapsing: false,
|
|
1600
|
+
showTitle: true,
|
|
1601
|
+
enableUrlBarHiding: true,
|
|
1602
|
+
enableDefaultShare: true,
|
|
1603
|
+
});
|
|
1604
|
+
if (!result || result.type !== "success" || !result.url) {
|
|
1605
|
+
throw new sdkTypes.ZeroXKeyError("OAuth flow did not complete successfully", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1606
|
+
}
|
|
1607
|
+
// Parse the deep link result
|
|
1608
|
+
const parsed = oauth.parseInAppBrowserResult(result.url);
|
|
1609
|
+
if (!parsed.idToken) {
|
|
1610
|
+
throw new sdkTypes.ZeroXKeyError("oidcToken not found in the response", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1611
|
+
}
|
|
1612
|
+
// Complete OAuth flow
|
|
1613
|
+
await oauth.completeOAuthFlow({
|
|
1614
|
+
provider: sdkTypes.OAuthProviders.APPLE,
|
|
1615
|
+
publicKey,
|
|
1616
|
+
oidcToken: parsed.idToken,
|
|
1617
|
+
...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
|
|
1618
|
+
...(callbacks && { callbacks }),
|
|
1619
|
+
completeOauth,
|
|
1620
|
+
});
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
catch (error) {
|
|
1624
|
+
throw error;
|
|
1625
|
+
}
|
|
1626
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1627
|
+
const handleFacebookOauth = react.useCallback(async (params) => {
|
|
1628
|
+
const { additionalState: additionalParameters } = params || {};
|
|
1629
|
+
const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(sdkTypes.OAuthProviders.FACEBOOK);
|
|
1630
|
+
try {
|
|
1631
|
+
if (!masterConfig) {
|
|
1632
|
+
throw new sdkTypes.ZeroXKeyError("Config is not ready yet!", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1633
|
+
}
|
|
1634
|
+
if (!clientId) {
|
|
1635
|
+
throw new sdkTypes.ZeroXKeyError("Facebook Client ID is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1636
|
+
}
|
|
1637
|
+
if (!redirectUri) {
|
|
1638
|
+
throw new sdkTypes.ZeroXKeyError("OAuth Redirect URI is not configured.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1639
|
+
}
|
|
1640
|
+
if (!scheme) {
|
|
1641
|
+
throw new sdkTypes.ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1642
|
+
}
|
|
1643
|
+
const finalRedirectUri = `${redirectUri}?scheme=${encodeURIComponent(scheme)}`;
|
|
1644
|
+
// Create key pair and generate nonce
|
|
1645
|
+
const publicKey = await createApiKeyPair();
|
|
1646
|
+
if (!publicKey) {
|
|
1647
|
+
throw new sdkTypes.ZeroXKeyError("Failed to create public key for OAuth.", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1648
|
+
}
|
|
1649
|
+
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
1650
|
+
// Generate PKCE challenge pair and store verifier
|
|
1651
|
+
const { verifier, codeChallenge } = await oauth.generateChallengePair();
|
|
1652
|
+
await oauth.storePKCEVerifier(sdkTypes.OAuthProviders.FACEBOOK, verifier);
|
|
1653
|
+
// Build OAuth URL using ZeroXKey OAuth proxy
|
|
1654
|
+
const oauthUrl = oauth.buildOAuthUrl({
|
|
1655
|
+
provider: sdkTypes.OAuthProviders.FACEBOOK,
|
|
1656
|
+
clientId,
|
|
1657
|
+
redirectUri: finalRedirectUri,
|
|
1658
|
+
publicKey,
|
|
1659
|
+
nonce,
|
|
1660
|
+
codeChallenge,
|
|
1661
|
+
additionalState: additionalParameters,
|
|
1662
|
+
useOauthProxyOrigin: true,
|
|
1663
|
+
});
|
|
1664
|
+
if (!(await reactNativeInappbrowserReborn.InAppBrowser.isAvailable())) {
|
|
1665
|
+
throw new sdkTypes.ZeroXKeyError("InAppBrowser is not available", sdkTypes.ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
|
|
1666
|
+
}
|
|
1667
|
+
const result = await reactNativeInappbrowserReborn.InAppBrowser.openAuth(oauthUrl, scheme, {
|
|
1668
|
+
dismissButtonStyle: "cancel",
|
|
1669
|
+
animated: true,
|
|
1670
|
+
modalPresentationStyle: "fullScreen",
|
|
1671
|
+
modalTransitionStyle: "coverVertical",
|
|
1672
|
+
modalEnabled: true,
|
|
1673
|
+
enableBarCollapsing: false,
|
|
1674
|
+
showTitle: true,
|
|
1675
|
+
enableUrlBarHiding: true,
|
|
1676
|
+
enableDefaultShare: true,
|
|
1677
|
+
});
|
|
1678
|
+
if (!result || result.type !== "success" || !result.url) {
|
|
1679
|
+
throw new sdkTypes.ZeroXKeyError("OAuth flow did not complete successfully", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1680
|
+
}
|
|
1681
|
+
// Parse the deep link result
|
|
1682
|
+
const parsed = oauth.parseInAppBrowserResult(result.url);
|
|
1683
|
+
if (!parsed.authCode) {
|
|
1684
|
+
throw new sdkTypes.ZeroXKeyError("Missing authorization code from Facebook OAuth", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1685
|
+
}
|
|
1686
|
+
// Handle PKCE flow: exchange code for token and complete
|
|
1687
|
+
await oauth.handlePKCEFlow({
|
|
1688
|
+
provider: sdkTypes.OAuthProviders.FACEBOOK,
|
|
1689
|
+
publicKey,
|
|
1690
|
+
authCode: parsed.authCode,
|
|
1691
|
+
...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
|
|
1692
|
+
...(callbacks && { callbacks }),
|
|
1693
|
+
completeOauth,
|
|
1694
|
+
exchangeCodeForToken: async (codeVerifier) => {
|
|
1695
|
+
const tokenData = await oauth.exchangeCodeForToken(clientId, finalRedirectUri, parsed.authCode, codeVerifier);
|
|
1696
|
+
const idToken = tokenData?.id_token;
|
|
1697
|
+
if (!idToken) {
|
|
1698
|
+
throw new sdkTypes.ZeroXKeyError("Missing oidcToken from OAuth exchange", sdkTypes.ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
|
|
1699
|
+
}
|
|
1700
|
+
return idToken;
|
|
1701
|
+
},
|
|
1702
|
+
});
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
catch (error) {
|
|
1706
|
+
throw error;
|
|
1707
|
+
}
|
|
1708
|
+
}, [client, callbacks, masterConfig, session, user]);
|
|
1709
|
+
react.useEffect(() => {
|
|
1710
|
+
if (proxyAuthConfigRef.current)
|
|
1711
|
+
return;
|
|
1712
|
+
// Only fetch the proxy auth config once. Use that to build the master config.
|
|
1713
|
+
const fetchProxyAuthConfig = async () => {
|
|
1714
|
+
try {
|
|
1715
|
+
let proxyAuthConfig;
|
|
1716
|
+
if (shouldFetchWalletKitConfig) {
|
|
1717
|
+
// Only fetch the proxy auth config if we have an authProxyId and the autoFetchWalletKitConfig param is enabled or not passed in.
|
|
1718
|
+
const sanitizedAuthProxyUrl = config.authProxyUrl && config.authProxyUrl.trim()
|
|
1719
|
+
? config.authProxyUrl
|
|
1720
|
+
: undefined;
|
|
1721
|
+
proxyAuthConfig = await core.getAuthProxyConfig(config.authProxyConfigId, // Can assert safely. See shouldFetchWalletKitConfig definition.
|
|
1722
|
+
sanitizedAuthProxyUrl);
|
|
1723
|
+
proxyAuthConfigRef.current = proxyAuthConfig;
|
|
1724
|
+
}
|
|
1725
|
+
setMasterConfig(buildConfig(proxyAuthConfig));
|
|
1726
|
+
}
|
|
1727
|
+
catch {
|
|
1728
|
+
setClientState(base.ClientState.Error);
|
|
1729
|
+
}
|
|
1730
|
+
};
|
|
1731
|
+
fetchProxyAuthConfig();
|
|
1732
|
+
}, []);
|
|
1733
|
+
react.useEffect(() => {
|
|
1734
|
+
// Start the client initialization process once we have the master config.
|
|
1735
|
+
if (!masterConfig)
|
|
1736
|
+
return;
|
|
1737
|
+
initializeClient();
|
|
1738
|
+
}, [masterConfig]);
|
|
1739
|
+
react.useEffect(() => {
|
|
1740
|
+
// Handle changes to the passed in config prop -- update the master config
|
|
1741
|
+
// Rebuild the master config with the updated config and stored proxyAuthConfig
|
|
1742
|
+
// If we don't have a stored proxyAuthConfig and we need to fetch it, we wait until that fetch is done in the other useEffect.
|
|
1743
|
+
// If shouldFetchWalletKitConfig is false, we'll never have a proxyAuthConfig to build the master config with, so this useEffect should always run.
|
|
1744
|
+
if (!proxyAuthConfigRef.current && shouldFetchWalletKitConfig)
|
|
1745
|
+
return;
|
|
1746
|
+
setMasterConfig(buildConfig(proxyAuthConfigRef.current ?? undefined));
|
|
1747
|
+
}, [config, proxyAuthConfigRef.current]);
|
|
1748
|
+
react.useEffect(() => {
|
|
1749
|
+
// authState must be consistent with session state. We found during testing that there are cases where the session and authState can be out of sync in very rare edge cases.
|
|
1750
|
+
// This will ensure that they are always in sync and remove the need to setAuthState manually in other places.
|
|
1751
|
+
if (session && utils.isValidSession(session)) {
|
|
1752
|
+
setAuthState(base.AuthState.Authenticated);
|
|
1753
|
+
}
|
|
1754
|
+
else {
|
|
1755
|
+
setAuthState(base.AuthState.Unauthenticated);
|
|
1756
|
+
}
|
|
1757
|
+
}, [session]);
|
|
1758
|
+
react.useEffect(() => {
|
|
1759
|
+
// After client and config are ready, initialize sessions then mark client ready.
|
|
1760
|
+
if (!client || !masterConfig)
|
|
1761
|
+
return;
|
|
1762
|
+
clearSessionTimeouts();
|
|
1763
|
+
initializeSessions().finally(() => {
|
|
1764
|
+
setClientState(base.ClientState.Ready);
|
|
1765
|
+
});
|
|
1766
|
+
return () => {
|
|
1767
|
+
clearSessionTimeouts();
|
|
1768
|
+
};
|
|
1769
|
+
}, [client]);
|
|
1770
|
+
return (jsxRuntime.jsx(Types.ClientContext.Provider, { value: {
|
|
1771
|
+
session,
|
|
1772
|
+
allSessions,
|
|
1773
|
+
clientState,
|
|
1774
|
+
authState,
|
|
1775
|
+
user,
|
|
1776
|
+
wallets,
|
|
1777
|
+
config: masterConfig,
|
|
1778
|
+
httpClient: client?.httpClient,
|
|
1779
|
+
createHttpClient,
|
|
1780
|
+
createPasskey,
|
|
1781
|
+
logout,
|
|
1782
|
+
loginWithPasskey,
|
|
1783
|
+
signUpWithPasskey,
|
|
1784
|
+
initOtp,
|
|
1785
|
+
verifyOtp,
|
|
1786
|
+
loginWithOtp,
|
|
1787
|
+
signUpWithOtp,
|
|
1788
|
+
completeOtp,
|
|
1789
|
+
loginWithOauth,
|
|
1790
|
+
signUpWithOauth,
|
|
1791
|
+
completeOauth,
|
|
1792
|
+
fetchWallets,
|
|
1793
|
+
fetchWalletAccounts,
|
|
1794
|
+
fetchPrivateKeys,
|
|
1795
|
+
verifyAppProofs,
|
|
1796
|
+
refreshWallets,
|
|
1797
|
+
signMessage,
|
|
1798
|
+
signTransaction,
|
|
1799
|
+
signAndSendTransaction,
|
|
1800
|
+
ethSendTransaction,
|
|
1801
|
+
ethSendErc20Transfer,
|
|
1802
|
+
solSendTransaction,
|
|
1803
|
+
pollTransactionStatus,
|
|
1804
|
+
fetchUser,
|
|
1805
|
+
fetchOrCreateP256ApiKeyUser,
|
|
1806
|
+
fetchOrCreatePolicies,
|
|
1807
|
+
refreshUser,
|
|
1808
|
+
updateUserEmail,
|
|
1809
|
+
removeUserEmail,
|
|
1810
|
+
updateUserPhoneNumber,
|
|
1811
|
+
removeUserPhoneNumber,
|
|
1812
|
+
updateUserName,
|
|
1813
|
+
addOauthProvider,
|
|
1814
|
+
removeOauthProviders,
|
|
1815
|
+
addPasskey,
|
|
1816
|
+
removePasskeys,
|
|
1817
|
+
createWallet,
|
|
1818
|
+
createWalletAccounts,
|
|
1819
|
+
exportWallet,
|
|
1820
|
+
exportPrivateKey,
|
|
1821
|
+
exportWalletAccount,
|
|
1822
|
+
importWallet,
|
|
1823
|
+
importPrivateKey,
|
|
1824
|
+
deleteSubOrganization,
|
|
1825
|
+
storeSession,
|
|
1826
|
+
clearSession,
|
|
1827
|
+
clearAllSessions,
|
|
1828
|
+
refreshSession,
|
|
1829
|
+
getSession,
|
|
1830
|
+
getAllSessions,
|
|
1831
|
+
setActiveSession,
|
|
1832
|
+
clearUnusedKeyPairs,
|
|
1833
|
+
getActiveSessionKey,
|
|
1834
|
+
createApiKeyPair,
|
|
1835
|
+
getProxyAuthConfig,
|
|
1836
|
+
handleGoogleOauth,
|
|
1837
|
+
handleXOauth,
|
|
1838
|
+
handleDiscordOauth,
|
|
1839
|
+
handleAppleOauth,
|
|
1840
|
+
handleFacebookOauth,
|
|
1841
|
+
fetchBootProofForAppProof,
|
|
1842
|
+
}, children: children }));
|
|
1843
|
+
};
|
|
1844
|
+
|
|
1845
|
+
exports.ZeroXKeyProvider = ZeroXKeyProvider;
|
|
1846
|
+
//# sourceMappingURL=ZeroXKeyProvider.js.map
|