@abstraxn/signer-react 2.1.2 → 2.1.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
CHANGED
|
@@ -5,7 +5,12 @@ 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.1.
|
|
8
|
+
## [2.1.3] - 2026-03-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Turnkey code 16 (session expired)** – When the backend returns a 401 with Turnkey error code 16 (PUBLIC_KEY_NOT_FOUND, e.g. stamping key not found in organization), the SDK now treats it as session expired instead of surfacing a long `NetworkError` message. The user is logged out, the context error is set to "Session expired", and callers receive a simple "Session expired" error. Detection uses Turnkey’s `code === 16` in the error payload (from the API response or from the parsed message). Applied in `@abstraxn/signer-core` (all authenticated API catch blocks) and in the React provider for `signTransactionViaAPI`, `signSolanaTransactionViaAPI`, `signTypedTxViaAPI`, and `signAndSendTransaction`.
|
|
13
|
+
|
|
9
14
|
## [2.1.1] - 2026-03-05
|
|
10
15
|
## [2.1.0] - 2026-03-05
|
|
11
16
|
|
|
@@ -1582,6 +1582,28 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1582
1582
|
}, 200);
|
|
1583
1583
|
}
|
|
1584
1584
|
}, [isExternalWalletConnected, externalWalletsEnabled, wagmiDisconnect, wagmiAccount?.connector]);
|
|
1585
|
+
// Detect Turnkey code 16 (PUBLIC_KEY_NOT_FOUND) / session expired (backend returns 401 with code 16)
|
|
1586
|
+
// Handles both AuthenticationError('Session expired') and NetworkError wrapping the Turnkey payload
|
|
1587
|
+
const isSessionExpiredError = (err) => {
|
|
1588
|
+
if (err instanceof AuthenticationError && err.message === "Session expired")
|
|
1589
|
+
return true;
|
|
1590
|
+
if (err instanceof Error && typeof err.message === "string") {
|
|
1591
|
+
try {
|
|
1592
|
+
// Message may be "Network error: Turnkey API error: 401 - {\"code\":16, ...}" or raw JSON
|
|
1593
|
+
const inner = err.message.match(/\{[\s\S]*\}/)?.[0];
|
|
1594
|
+
const parsed = inner ? JSON.parse(inner) : null;
|
|
1595
|
+
return parsed != null && parsed.code === 16;
|
|
1596
|
+
}
|
|
1597
|
+
catch {
|
|
1598
|
+
return false;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
return false;
|
|
1602
|
+
};
|
|
1603
|
+
const handleSessionExpired = useCallback(async () => {
|
|
1604
|
+
setError(new Error("Session expired"));
|
|
1605
|
+
await disconnect();
|
|
1606
|
+
}, [disconnect]);
|
|
1585
1607
|
// Hide onboarding UI
|
|
1586
1608
|
const hideOnboarding = useCallback(() => {
|
|
1587
1609
|
setError(null); // Clear any previous errors
|
|
@@ -1848,6 +1870,10 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1848
1870
|
return await walletRef.current.signTransactionViaAPI(unsignedTransaction, fromAddress);
|
|
1849
1871
|
}
|
|
1850
1872
|
catch (err) {
|
|
1873
|
+
if (isSessionExpiredError(err)) {
|
|
1874
|
+
await handleSessionExpired();
|
|
1875
|
+
throw new Error("Session expired");
|
|
1876
|
+
}
|
|
1851
1877
|
const error = err instanceof Error ? err : new Error("Failed to sign transaction");
|
|
1852
1878
|
setError(error);
|
|
1853
1879
|
throw error;
|
|
@@ -1855,7 +1881,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1855
1881
|
finally {
|
|
1856
1882
|
setLoading(false);
|
|
1857
1883
|
}
|
|
1858
|
-
}, []);
|
|
1884
|
+
}, [handleSessionExpired]);
|
|
1859
1885
|
// Sign Solana transaction via API (returns signed transaction)
|
|
1860
1886
|
const signSolanaTransactionViaAPI = useCallback(async (unsignedTransaction, fromAddress) => {
|
|
1861
1887
|
if (!walletRef.current)
|
|
@@ -1870,6 +1896,10 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1870
1896
|
return await walletAny.signSolanaTransactionViaAPI(unsignedTransaction, fromAddress);
|
|
1871
1897
|
}
|
|
1872
1898
|
catch (err) {
|
|
1899
|
+
if (isSessionExpiredError(err)) {
|
|
1900
|
+
await handleSessionExpired();
|
|
1901
|
+
throw new Error("Session expired");
|
|
1902
|
+
}
|
|
1873
1903
|
const error = err instanceof Error ? err : new Error("Failed to sign Solana transaction");
|
|
1874
1904
|
setError(error);
|
|
1875
1905
|
throw error;
|
|
@@ -1877,7 +1907,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1877
1907
|
finally {
|
|
1878
1908
|
setLoading(false);
|
|
1879
1909
|
}
|
|
1880
|
-
}, []);
|
|
1910
|
+
}, [handleSessionExpired]);
|
|
1881
1911
|
// Sign typed data / raw payload via API (same flow as signTransactionViaAPI, payload: from, unsignedTransaction, encoding, hashFunction)
|
|
1882
1912
|
const signTypedTxViaAPI = useCallback(async (fromAddress, unsignedTransaction, encoding, hashFunction) => {
|
|
1883
1913
|
if (!walletRef.current)
|
|
@@ -1888,6 +1918,10 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1888
1918
|
return await walletRef.current.signTypedTxViaAPI(fromAddress, unsignedTransaction, encoding, hashFunction);
|
|
1889
1919
|
}
|
|
1890
1920
|
catch (err) {
|
|
1921
|
+
if (isSessionExpiredError(err)) {
|
|
1922
|
+
await handleSessionExpired();
|
|
1923
|
+
throw new Error("Session expired");
|
|
1924
|
+
}
|
|
1891
1925
|
const error = err instanceof Error ? err : new Error("Failed to sign typed payload");
|
|
1892
1926
|
setError(error);
|
|
1893
1927
|
throw error;
|
|
@@ -1895,7 +1929,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1895
1929
|
finally {
|
|
1896
1930
|
setLoading(false);
|
|
1897
1931
|
}
|
|
1898
|
-
}, []);
|
|
1932
|
+
}, [handleSessionExpired]);
|
|
1899
1933
|
// Sign and send transaction using backend API
|
|
1900
1934
|
const signAndSendTransaction = useCallback(async (unsignedTransaction, fromAddress, rpcUrl) => {
|
|
1901
1935
|
if (!walletRef.current)
|
|
@@ -1906,6 +1940,10 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1906
1940
|
return await walletRef.current.signAndSendTransaction(unsignedTransaction, fromAddress, rpcUrl);
|
|
1907
1941
|
}
|
|
1908
1942
|
catch (err) {
|
|
1943
|
+
if (isSessionExpiredError(err)) {
|
|
1944
|
+
await handleSessionExpired();
|
|
1945
|
+
throw new Error("Session expired");
|
|
1946
|
+
}
|
|
1909
1947
|
const error = err instanceof Error
|
|
1910
1948
|
? err
|
|
1911
1949
|
: new Error("Failed to sign and send transaction");
|
|
@@ -1915,7 +1953,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1915
1953
|
finally {
|
|
1916
1954
|
setLoading(false);
|
|
1917
1955
|
}
|
|
1918
|
-
}, []);
|
|
1956
|
+
}, [handleSessionExpired]);
|
|
1919
1957
|
// Login with email OTP (initiate OTP)
|
|
1920
1958
|
const loginWithOTP = useCallback(async (email) => {
|
|
1921
1959
|
if (!walletRef.current)
|