@abstraxn/signer-react 2.2.1 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js +31 -88
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js.map +1 -1
- package/dist/src/components/AbstraxnProvider/useWalletInitialization.js +6 -3
- package/dist/src/components/AbstraxnProvider/useWalletInitialization.js.map +1 -1
- package/dist/src/components/AbstraxnProvider/utils.js +1 -12
- package/dist/src/components/AbstraxnProvider/utils.js.map +1 -1
- package/dist/src/components/OnboardingUI/OnboardingUIReact.js +13 -32
- package/dist/src/components/OnboardingUI/OnboardingUIReact.js.map +1 -1
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.d.ts +1 -0
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.js +31 -45
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.js.map +1 -1
- package/dist/src/components/OnboardingUI/components/EmailForm.js +10 -1
- package/dist/src/components/OnboardingUI/components/EmailForm.js.map +1 -1
- package/dist/src/components/OnboardingUI/components/MfaForm.js +10 -3
- package/dist/src/components/OnboardingUI/components/MfaForm.js.map +1 -1
- package/dist/src/components/OnboardingUI/components/OtpForm.js +11 -4
- package/dist/src/components/OnboardingUI/components/OtpForm.js.map +1 -1
- package/dist/src/components/OnboardingUI/hooks/useAuthMethods.js +6 -3
- package/dist/src/components/OnboardingUI/hooks/useAuthMethods.js.map +1 -1
- package/dist/src/components/OnboardingUI/hooks/useOnboarding.js +2 -2
- package/dist/src/components/OnboardingUI/hooks/useOnboarding.js.map +1 -1
- package/dist/src/components/WalletModal/components/ManageWalletModal.js +105 -126
- package/dist/src/components/WalletModal/components/ManageWalletModal.js.map +1 -1
- package/dist/src/hooks.d.ts +59 -1
- package/dist/src/hooks.js +200 -0
- package/dist/src/hooks.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.2.3] - 2026-03-24
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **API key in header** - Changed API key handling to send the API key in request headers.
|
|
13
|
+
- **Social login API flow** - Changed social login flow to call API directly instead of redirecting.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **MFA hooks (enable/disable)** – Added `useEnableMfa` and `useDisableMfa` as state-machine hooks for MFA setup and disable flows with cleaner, minimal APIs.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **MFA enable endpoint payload** – Removed transaction API/sign-payload dependency from MFA enable flow so `mfa/enable` is called directly without transaction payload requirements.
|
|
22
|
+
|
|
23
|
+
### Other changes
|
|
24
|
+
|
|
25
|
+
- **Cookie-based refresh flow** - Updated session refresh handling to call `/auth/refresh` without a refresh token body and rely on backend HttpOnly cookie rotation, while keeping access token updates in SDK state.
|
|
26
|
+
- **OAuth callback query handling** - Updated callback/onboarding URL parsing to consume `success`, `loginCode`, `loginCodeExpiresIn`, optional `mfaRequired`, and `error`.
|
|
27
|
+
|
|
28
|
+
## [2.2.2] - 2026-03-20
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **Onboarding error text formatting** – Removed forced curly-brace wrapping from onboarding error messages (email, OTP, MFA, and generic error states) in both React and Web onboarding UIs.
|
|
33
|
+
- **MFA/setup and onboarding error prefixes** – Normalized displayed error text to remove leading `Network error:` so users see direct backend messages (for example, `Invalid TOTP code`).
|
|
34
|
+
- **MFA enable API contract update** – Updated MFA enable flow to call `mfa/enable` without transaction-sign payload fields, matching the backend contract where the endpoint now accepts no request payload.
|
|
35
|
+
|
|
8
36
|
## [2.2.1] - 2026-03-20
|
|
9
37
|
|
|
10
38
|
### Changed
|
|
@@ -649,7 +649,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
649
649
|
// Clear OAuth callback params from URL so app shows connected state without refresh
|
|
650
650
|
if (typeof window !== "undefined") {
|
|
651
651
|
const url = new URL(window.location.href);
|
|
652
|
-
const keys = ["success", "mfaRequired", "
|
|
652
|
+
const keys = ["success", "mfaRequired", "loginCode", "loginCodeExpiresIn", "turnkeyPublicKey", "error", "provider", "authProvider"];
|
|
653
653
|
keys.forEach((k) => url.searchParams.delete(k));
|
|
654
654
|
window.history.replaceState({}, document.title, url.pathname + url.search);
|
|
655
655
|
}
|
|
@@ -683,7 +683,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
683
683
|
url.searchParams.delete("state");
|
|
684
684
|
url.searchParams.delete("error");
|
|
685
685
|
url.searchParams.delete("success");
|
|
686
|
-
url.searchParams.delete("
|
|
686
|
+
url.searchParams.delete("loginCode");
|
|
687
687
|
url.searchParams.delete("provider");
|
|
688
688
|
url.searchParams.delete("authProvider");
|
|
689
689
|
window.history.replaceState({}, document.title, url.toString());
|
|
@@ -712,7 +712,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
712
712
|
url.searchParams.delete("state");
|
|
713
713
|
url.searchParams.delete("error");
|
|
714
714
|
url.searchParams.delete("success");
|
|
715
|
-
url.searchParams.delete("
|
|
715
|
+
url.searchParams.delete("loginCode");
|
|
716
716
|
url.searchParams.delete("provider");
|
|
717
717
|
url.searchParams.delete("authProvider");
|
|
718
718
|
window.history.replaceState({}, document.title, url.toString());
|
|
@@ -741,7 +741,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
741
741
|
url.searchParams.delete("state");
|
|
742
742
|
url.searchParams.delete("error");
|
|
743
743
|
url.searchParams.delete("success");
|
|
744
|
-
url.searchParams.delete("
|
|
744
|
+
url.searchParams.delete("loginCode");
|
|
745
745
|
url.searchParams.delete("provider");
|
|
746
746
|
url.searchParams.delete("authProvider");
|
|
747
747
|
window.history.replaceState({}, document.title, url.toString());
|
|
@@ -887,25 +887,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
887
887
|
const hasAuthParams = (params) => params.get("success") === "true" ||
|
|
888
888
|
params.get("error") ||
|
|
889
889
|
params.get("code") ||
|
|
890
|
-
params.get("
|
|
891
|
-
const getAuthProviderFromToken = (token) => {
|
|
892
|
-
try {
|
|
893
|
-
const base64Url = token.split(".")[1];
|
|
894
|
-
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
895
|
-
const jsonPayload = decodeURIComponent(window
|
|
896
|
-
.atob(base64)
|
|
897
|
-
.split("")
|
|
898
|
-
.map(function (c) {
|
|
899
|
-
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
900
|
-
})
|
|
901
|
-
.join(""));
|
|
902
|
-
const payload = JSON.parse(jsonPayload);
|
|
903
|
-
return (payload.authProvider || payload.provider || "").toLowerCase();
|
|
904
|
-
}
|
|
905
|
-
catch (e) {
|
|
906
|
-
return null;
|
|
907
|
-
}
|
|
908
|
-
};
|
|
890
|
+
params.get("loginCode");
|
|
909
891
|
const matchesProvider = (provider, params) => {
|
|
910
892
|
const providerParam = (params.get("provider") ||
|
|
911
893
|
params.get("authProvider") ||
|
|
@@ -917,17 +899,6 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
917
899
|
}
|
|
918
900
|
return providerParam === provider;
|
|
919
901
|
}
|
|
920
|
-
// Check accessToken for provider
|
|
921
|
-
const accessToken = params.get("accessToken");
|
|
922
|
-
if (accessToken) {
|
|
923
|
-
const tokenProvider = getAuthProviderFromToken(accessToken);
|
|
924
|
-
if (tokenProvider) {
|
|
925
|
-
if (provider === "twitter") {
|
|
926
|
-
return tokenProvider === "twitter" || tokenProvider === "x";
|
|
927
|
-
}
|
|
928
|
-
return tokenProvider === provider;
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
902
|
if (provider === "twitter") {
|
|
932
903
|
return path.includes("/twitter") || path.includes("/x");
|
|
933
904
|
}
|
|
@@ -1821,6 +1792,21 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1821
1792
|
setError(new Error("Session expired"));
|
|
1822
1793
|
await disconnect();
|
|
1823
1794
|
}, [disconnect]);
|
|
1795
|
+
const withSessionGuard = useCallback(async (action, fallbackMessage = "Operation failed") => {
|
|
1796
|
+
try {
|
|
1797
|
+
return await action();
|
|
1798
|
+
}
|
|
1799
|
+
catch (err) {
|
|
1800
|
+
const alreadyConnected = Boolean(walletRef.current?.isConnected || isConnected);
|
|
1801
|
+
if (alreadyConnected && isSessionExpiredError(err)) {
|
|
1802
|
+
await handleSessionExpired();
|
|
1803
|
+
throw new Error("Session expired");
|
|
1804
|
+
}
|
|
1805
|
+
const error = err instanceof Error ? err : new Error(fallbackMessage);
|
|
1806
|
+
setError(error);
|
|
1807
|
+
throw error;
|
|
1808
|
+
}
|
|
1809
|
+
}, [handleSessionExpired, isConnected]);
|
|
1824
1810
|
// Hide onboarding UI
|
|
1825
1811
|
const hideOnboarding = useCallback(() => {
|
|
1826
1812
|
setError(null); // Clear any previous errors
|
|
@@ -2084,21 +2070,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2084
2070
|
setLoading(true);
|
|
2085
2071
|
setError(null);
|
|
2086
2072
|
try {
|
|
2087
|
-
return await walletRef.current.signTransactionViaAPI(unsignedTransaction, fromAddress);
|
|
2088
|
-
}
|
|
2089
|
-
catch (err) {
|
|
2090
|
-
if (isSessionExpiredError(err)) {
|
|
2091
|
-
await handleSessionExpired();
|
|
2092
|
-
throw new Error("Session expired");
|
|
2093
|
-
}
|
|
2094
|
-
const error = err instanceof Error ? err : new Error("Failed to sign transaction");
|
|
2095
|
-
setError(error);
|
|
2096
|
-
throw error;
|
|
2073
|
+
return await withSessionGuard(() => walletRef.current.signTransactionViaAPI(unsignedTransaction, fromAddress), "Failed to sign transaction");
|
|
2097
2074
|
}
|
|
2098
2075
|
finally {
|
|
2099
2076
|
setLoading(false);
|
|
2100
2077
|
}
|
|
2101
|
-
}, [
|
|
2078
|
+
}, [withSessionGuard]);
|
|
2102
2079
|
// Sign Solana transaction via API (returns signed transaction)
|
|
2103
2080
|
const signSolanaTransactionViaAPI = useCallback(async (unsignedTransaction, fromAddress) => {
|
|
2104
2081
|
if (!walletRef.current)
|
|
@@ -2110,21 +2087,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2110
2087
|
if (typeof walletAny.signSolanaTransactionViaAPI !== "function") {
|
|
2111
2088
|
throw new Error("Solana transaction signing is not supported by this wallet");
|
|
2112
2089
|
}
|
|
2113
|
-
return await walletAny.signSolanaTransactionViaAPI(unsignedTransaction, fromAddress);
|
|
2114
|
-
}
|
|
2115
|
-
catch (err) {
|
|
2116
|
-
if (isSessionExpiredError(err)) {
|
|
2117
|
-
await handleSessionExpired();
|
|
2118
|
-
throw new Error("Session expired");
|
|
2119
|
-
}
|
|
2120
|
-
const error = err instanceof Error ? err : new Error("Failed to sign Solana transaction");
|
|
2121
|
-
setError(error);
|
|
2122
|
-
throw error;
|
|
2090
|
+
return await withSessionGuard(() => walletAny.signSolanaTransactionViaAPI(unsignedTransaction, fromAddress), "Failed to sign Solana transaction");
|
|
2123
2091
|
}
|
|
2124
2092
|
finally {
|
|
2125
2093
|
setLoading(false);
|
|
2126
2094
|
}
|
|
2127
|
-
}, [
|
|
2095
|
+
}, [withSessionGuard]);
|
|
2128
2096
|
// Sign typed data / raw payload via API (same flow as signTransactionViaAPI, payload: from, unsignedTransaction, encoding, hashFunction)
|
|
2129
2097
|
const signTypedTxViaAPI = useCallback(async (fromAddress, unsignedTransaction, encoding, hashFunction) => {
|
|
2130
2098
|
if (!walletRef.current)
|
|
@@ -2132,21 +2100,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2132
2100
|
setLoading(true);
|
|
2133
2101
|
setError(null);
|
|
2134
2102
|
try {
|
|
2135
|
-
return await walletRef.current.signTypedTxViaAPI(fromAddress, unsignedTransaction, encoding, hashFunction);
|
|
2136
|
-
}
|
|
2137
|
-
catch (err) {
|
|
2138
|
-
if (isSessionExpiredError(err)) {
|
|
2139
|
-
await handleSessionExpired();
|
|
2140
|
-
throw new Error("Session expired");
|
|
2141
|
-
}
|
|
2142
|
-
const error = err instanceof Error ? err : new Error("Failed to sign typed payload");
|
|
2143
|
-
setError(error);
|
|
2144
|
-
throw error;
|
|
2103
|
+
return await withSessionGuard(() => walletRef.current.signTypedTxViaAPI(fromAddress, unsignedTransaction, encoding, hashFunction), "Failed to sign typed payload");
|
|
2145
2104
|
}
|
|
2146
2105
|
finally {
|
|
2147
2106
|
setLoading(false);
|
|
2148
2107
|
}
|
|
2149
|
-
}, [
|
|
2108
|
+
}, [withSessionGuard]);
|
|
2150
2109
|
// Sign and send transaction using backend API
|
|
2151
2110
|
const signAndSendTransaction = useCallback(async (unsignedTransaction, fromAddress, rpcUrl) => {
|
|
2152
2111
|
if (!walletRef.current)
|
|
@@ -2154,23 +2113,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2154
2113
|
setLoading(true);
|
|
2155
2114
|
setError(null);
|
|
2156
2115
|
try {
|
|
2157
|
-
return await walletRef.current.signAndSendTransaction(unsignedTransaction, fromAddress, rpcUrl);
|
|
2158
|
-
}
|
|
2159
|
-
catch (err) {
|
|
2160
|
-
if (isSessionExpiredError(err)) {
|
|
2161
|
-
await handleSessionExpired();
|
|
2162
|
-
throw new Error("Session expired");
|
|
2163
|
-
}
|
|
2164
|
-
const error = err instanceof Error
|
|
2165
|
-
? err
|
|
2166
|
-
: new Error("Failed to sign and send transaction");
|
|
2167
|
-
setError(error);
|
|
2168
|
-
throw error;
|
|
2116
|
+
return await withSessionGuard(() => walletRef.current.signAndSendTransaction(unsignedTransaction, fromAddress, rpcUrl), "Failed to sign and send transaction");
|
|
2169
2117
|
}
|
|
2170
2118
|
finally {
|
|
2171
2119
|
setLoading(false);
|
|
2172
2120
|
}
|
|
2173
|
-
}, [
|
|
2121
|
+
}, [withSessionGuard]);
|
|
2174
2122
|
// Login with email OTP (initiate OTP)
|
|
2175
2123
|
const loginWithOTP = useCallback(async (email) => {
|
|
2176
2124
|
if (!walletRef.current)
|
|
@@ -2328,7 +2276,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2328
2276
|
setLoading(true);
|
|
2329
2277
|
setError(null);
|
|
2330
2278
|
try {
|
|
2331
|
-
const whoamiInfo = await walletRef.current.refreshWhoami();
|
|
2279
|
+
const whoamiInfo = await withSessionGuard(() => walletRef.current.refreshWhoami(), "Failed to refresh whoami");
|
|
2332
2280
|
if (whoamiInfo) {
|
|
2333
2281
|
setWhoami(whoamiInfo);
|
|
2334
2282
|
// Update address if available in whoami response
|
|
@@ -2338,15 +2286,10 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2338
2286
|
}
|
|
2339
2287
|
return whoamiInfo;
|
|
2340
2288
|
}
|
|
2341
|
-
catch (err) {
|
|
2342
|
-
const error = err instanceof Error ? err : new Error("Failed to refresh whoami");
|
|
2343
|
-
setError(error);
|
|
2344
|
-
throw error;
|
|
2345
|
-
}
|
|
2346
2289
|
finally {
|
|
2347
2290
|
setLoading(false);
|
|
2348
2291
|
}
|
|
2349
|
-
}, [isExternalWalletConnected]);
|
|
2292
|
+
}, [isExternalWalletConnected, withSessionGuard]);
|
|
2350
2293
|
const getSupportedAuthMethods = useCallback(async () => {
|
|
2351
2294
|
if (!walletRef.current?.isConnected) {
|
|
2352
2295
|
throw new Error("Wallet not connected");
|
|
@@ -3489,7 +3432,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3489
3432
|
// Clear OAuth callback params from URL so app shows connected state without refresh
|
|
3490
3433
|
if (typeof window !== "undefined") {
|
|
3491
3434
|
const url = new URL(window.location.href);
|
|
3492
|
-
const keys = ["success", "mfaRequired", "
|
|
3435
|
+
const keys = ["success", "mfaRequired", "loginCode", "loginCodeExpiresIn", "turnkeyPublicKey", "error", "provider", "authProvider"];
|
|
3493
3436
|
keys.forEach((k) => url.searchParams.delete(k));
|
|
3494
3437
|
window.history.replaceState({}, document.title, url.pathname + url.search);
|
|
3495
3438
|
}
|