@abstraxn/signer-react 3.1.2 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js +12 -7
- package/dist/src/components/AbstraxnProvider/useWalletInitialization.js +10 -5
- package/dist/src/components/OnboardingUI/OnboardingUIReact.js +4 -1
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.js +10 -4
- package/dist/src/components/OnboardingUI/hooks/useAuthMethods.js +10 -0
- package/dist/src/hooks.d.ts +7 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ 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
|
+
## [3.1.4] - 2026-04-06
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Passkey completion via login code (`@abstraxn/signer-core`)** – Passkey signup and login now expect a `loginCode` (and optional `mfaRequired`) from the backend, then exchange it through `POST /auth/exchange` before tokens and user state are finalized. Passkey responses no longer persist access/refresh tokens directly from those calls.
|
|
13
|
+
- **Auth route prefixes** – OTP init/verify and passkey signup/login client paths use `/auth/otp/...` and `/auth/passkey/...` instead of `/login/otp/...` and `/login/passkey/...`.
|
|
14
|
+
- **Passkey login stamp** – The WebAuthn/Turnkey stamp is serialized and sent as a JSON string in the passkey login request, matching the updated API contract.
|
|
15
|
+
- **Passkey signup payload** – `targetPublicKey` is optional when a device public key is not available; session completion merges profile fields from the passkey API response where the JWT omits them (e.g. `isPolicy`, `publicKey`, `authProvider`).
|
|
16
|
+
- **MFA after passkey** – `AbstraxnWallet.loginWithPasskey` / `signupWithPasskey` and the React provider defer `connect()` when MFA is still required; `AuthManager` tracks `pendingSessionAuthMethod: 'passkey'` so post-MFA session setup uses the correct path.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **`PasskeyFlowResult` and onboarding hooks** – `onPasskeySignup` / `onPasskeyLogin` may return `{ mfaRequired: true }`; `onPasskeyPendingMfa` lets UIs jump to the MFA step (`OnboardingUIReact`, `OnboardingUIWeb`, and `useAuthMethods`). `PasskeyFlowResult` is re-exported from `@abstraxn/signer-core`.
|
|
21
|
+
- **Server logout on full disconnect** – When the Abstraxn session disconnect runs, the SDK best-effort calls `POST /auth/logout` with the current access token (external-wallet-only disconnect continues to skip this).
|
|
22
|
+
|
|
8
23
|
## [3.1.2] - 2026-03-27
|
|
9
24
|
|
|
10
25
|
### Changed
|
|
@@ -766,10 +766,13 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
766
766
|
}
|
|
767
767
|
const authManager = walletInstance.getAuthManager();
|
|
768
768
|
const user = await authManager.loginWithPasskey();
|
|
769
|
-
// Set user immediately so onLoginSuccess can access it
|
|
770
769
|
setUser(user);
|
|
771
|
-
|
|
770
|
+
const lastAuthState = authManager.getLastAuthState();
|
|
771
|
+
if (lastAuthState?.mfaRequired === true) {
|
|
772
|
+
return { mfaRequired: true };
|
|
773
|
+
}
|
|
772
774
|
await walletInstance.connect();
|
|
775
|
+
return undefined;
|
|
773
776
|
},
|
|
774
777
|
onPasskeySignup: async () => {
|
|
775
778
|
if (!walletInstance)
|
|
@@ -784,11 +787,13 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
784
787
|
}
|
|
785
788
|
const authManager = walletInstance.getAuthManager();
|
|
786
789
|
const user = await authManager.signupWithPasskey();
|
|
787
|
-
// Clear any previous errors on successful verification
|
|
788
|
-
// setError(null);
|
|
789
790
|
setUser(user);
|
|
790
|
-
|
|
791
|
+
const lastAuthState = authManager.getLastAuthState();
|
|
792
|
+
if (lastAuthState?.mfaRequired === true) {
|
|
793
|
+
return { mfaRequired: true };
|
|
794
|
+
}
|
|
791
795
|
await walletInstance.connect();
|
|
796
|
+
return undefined;
|
|
792
797
|
},
|
|
793
798
|
onLoginSuccess: async (_data) => {
|
|
794
799
|
// Clear any previous errors on successful login
|
|
@@ -1605,7 +1610,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1605
1610
|
setLoading(false);
|
|
1606
1611
|
}
|
|
1607
1612
|
}, [showOnboarding]);
|
|
1608
|
-
//
|
|
1613
|
+
// Full disconnect: when Abstraxn is connected, `wallet.disconnect()` runs and signer-core notifies POST /auth/logout; external-wallet-only flows use `disconnectExternalWallet` instead (no core disconnect).
|
|
1609
1614
|
const disconnect = useCallback(async () => {
|
|
1610
1615
|
setLoading(true);
|
|
1611
1616
|
setDisconnecting(true);
|
|
@@ -2972,7 +2977,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2972
2977
|
wagmiDisconnect,
|
|
2973
2978
|
wagmiAccount?.isConnected,
|
|
2974
2979
|
]);
|
|
2975
|
-
//
|
|
2980
|
+
// External wallet only — does not call AbstraxnWallet.disconnect (no server /auth/logout).
|
|
2976
2981
|
const disconnectExternalWallet = useCallback(async () => {
|
|
2977
2982
|
if (!externalWalletsEnabled || !wagmiDisconnect) {
|
|
2978
2983
|
return;
|
|
@@ -351,10 +351,13 @@ export function useWalletInitialization({ config, walletRef, onboardingRef, otpI
|
|
|
351
351
|
}
|
|
352
352
|
const authManager = walletInstance.getAuthManager();
|
|
353
353
|
const user = await authManager.loginWithPasskey();
|
|
354
|
-
// Set user immediately so onLoginSuccess can access it
|
|
355
354
|
setUser(user);
|
|
356
|
-
|
|
355
|
+
const lastAuthState = authManager.getLastAuthState();
|
|
356
|
+
if (lastAuthState?.mfaRequired === true) {
|
|
357
|
+
return { mfaRequired: true };
|
|
358
|
+
}
|
|
357
359
|
await walletInstance.connect();
|
|
360
|
+
return undefined;
|
|
358
361
|
},
|
|
359
362
|
onPasskeySignup: async () => {
|
|
360
363
|
if (!walletInstance)
|
|
@@ -369,11 +372,13 @@ export function useWalletInitialization({ config, walletRef, onboardingRef, otpI
|
|
|
369
372
|
}
|
|
370
373
|
const authManager = walletInstance.getAuthManager();
|
|
371
374
|
const user = await authManager.signupWithPasskey();
|
|
372
|
-
// Clear any previous errors on successful verification
|
|
373
|
-
// setError(null);
|
|
374
375
|
setUser(user);
|
|
375
|
-
|
|
376
|
+
const lastAuthState = authManager.getLastAuthState();
|
|
377
|
+
if (lastAuthState?.mfaRequired === true) {
|
|
378
|
+
return { mfaRequired: true };
|
|
379
|
+
}
|
|
376
380
|
await walletInstance.connect();
|
|
381
|
+
return undefined;
|
|
377
382
|
},
|
|
378
383
|
onLoginSuccess: async (_data) => {
|
|
379
384
|
// Clear any previous errors on successful login
|
|
@@ -27,7 +27,10 @@ export const OnboardingUIReact = ({ config = {}, modal = false, onClose, externa
|
|
|
27
27
|
const authMethods = config.authMethods || ["otp", "google"];
|
|
28
28
|
const showModalCloseButton = config.showCloseButton === true;
|
|
29
29
|
const onboarding = useOnboarding(config);
|
|
30
|
-
const authMethodsHook = useAuthMethods(
|
|
30
|
+
const authMethodsHook = useAuthMethods({
|
|
31
|
+
...config,
|
|
32
|
+
onPasskeyPendingMfa: config.onPasskeyPendingMfa ?? (() => onboarding.setStep("mfa")),
|
|
33
|
+
});
|
|
31
34
|
const { user, isConnected, whoami, loading: providerLoading, error: providerError, emailForOtp, } = useAbstraxnWallet();
|
|
32
35
|
const [showExternalWallets, setShowExternalWallets] = useState(false);
|
|
33
36
|
const [oauthLoading, setOauthLoading] = useState(false);
|
|
@@ -4286,8 +4286,11 @@ export class OnboardingUIWeb {
|
|
|
4286
4286
|
this.setLoading(true, "passkey");
|
|
4287
4287
|
this.hidePasskeyError();
|
|
4288
4288
|
if (this.config.onPasskeyLogin) {
|
|
4289
|
-
await this.config.onPasskeyLogin();
|
|
4290
|
-
|
|
4289
|
+
const result = await this.config.onPasskeyLogin();
|
|
4290
|
+
if (result && typeof result === "object" && result.mfaRequired === true) {
|
|
4291
|
+
this.showMfaVerificationScreenForOAuth();
|
|
4292
|
+
return;
|
|
4293
|
+
}
|
|
4291
4294
|
if (this.config.onLoginSuccess) {
|
|
4292
4295
|
this.config.onLoginSuccess({ user: null });
|
|
4293
4296
|
}
|
|
@@ -4318,8 +4321,11 @@ export class OnboardingUIWeb {
|
|
|
4318
4321
|
this.setLoading(true, "passkey");
|
|
4319
4322
|
this.hidePasskeyError();
|
|
4320
4323
|
if (this.config.onPasskeySignup) {
|
|
4321
|
-
await this.config.onPasskeySignup();
|
|
4322
|
-
|
|
4324
|
+
const result = await this.config.onPasskeySignup();
|
|
4325
|
+
if (result && typeof result === "object" && result.mfaRequired === true) {
|
|
4326
|
+
this.showMfaVerificationScreenForOAuth();
|
|
4327
|
+
return;
|
|
4328
|
+
}
|
|
4323
4329
|
if (this.config.onLoginSuccess) {
|
|
4324
4330
|
this.config.onLoginSuccess({ user: null });
|
|
4325
4331
|
}
|
|
@@ -192,6 +192,11 @@ export const useAuthMethods = (config) => {
|
|
|
192
192
|
else {
|
|
193
193
|
await wallet.loginWithPasskey();
|
|
194
194
|
}
|
|
195
|
+
const mfaPending = wallet.getAuthManager().getLastAuthState()?.mfaRequired === true;
|
|
196
|
+
if (mfaPending) {
|
|
197
|
+
config?.onPasskeyPendingMfa?.();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
195
200
|
config?.onLoginSuccess?.({});
|
|
196
201
|
}
|
|
197
202
|
catch (err) {
|
|
@@ -225,6 +230,11 @@ export const useAuthMethods = (config) => {
|
|
|
225
230
|
else {
|
|
226
231
|
await wallet.signupWithPasskey();
|
|
227
232
|
}
|
|
233
|
+
const mfaPending = wallet.getAuthManager().getLastAuthState()?.mfaRequired === true;
|
|
234
|
+
if (mfaPending) {
|
|
235
|
+
config?.onPasskeyPendingMfa?.();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
228
238
|
config?.onLoginSuccess?.({});
|
|
229
239
|
}
|
|
230
240
|
catch (err) {
|
package/dist/src/hooks.d.ts
CHANGED
|
@@ -270,6 +270,7 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
270
270
|
request?: (parameters: import("viem").CcipRequestParameters) => Promise<import("viem/_types/utils/ccip").CcipRequestReturnType>;
|
|
271
271
|
} | undefined;
|
|
272
272
|
chain: Chain | undefined;
|
|
273
|
+
dataSuffix?: import("viem").DataSuffix | undefined;
|
|
273
274
|
experimental_blockTag?: import("viem").BlockTag | undefined;
|
|
274
275
|
key: string;
|
|
275
276
|
name: string;
|
|
@@ -452,6 +453,7 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
452
453
|
getChainId: () => Promise<import("viem").GetChainIdReturnType>;
|
|
453
454
|
getCode: (args: import("viem").GetBytecodeParameters) => Promise<import("viem").GetBytecodeReturnType>;
|
|
454
455
|
getContractEvents: <const abi extends Abi | readonly unknown[], eventName extends import("viem").ContractEventName<abi> | undefined = undefined, strict extends boolean | undefined = undefined, fromBlock extends import("viem").BlockNumber | import("viem").BlockTag | undefined = undefined, toBlock extends import("viem").BlockNumber | import("viem").BlockTag | undefined = undefined>(args: import("viem").GetContractEventsParameters<abi, eventName, strict, fromBlock, toBlock>) => Promise<import("viem").GetContractEventsReturnType<abi, eventName, strict, fromBlock, toBlock>>;
|
|
456
|
+
getDelegation: (args: import("viem").GetDelegationParameters) => Promise<import("viem").GetDelegationReturnType>;
|
|
455
457
|
getEip712Domain: (args: import("viem").GetEip712DomainParameters) => Promise<import("viem").GetEip712DomainReturnType>;
|
|
456
458
|
getEnsAddress: (args: import("viem").GetEnsAddressParameters) => Promise<import("viem").GetEnsAddressReturnType>;
|
|
457
459
|
getEnsAvatar: (args: import("viem").GetEnsAvatarParameters) => Promise<import("viem").GetEnsAvatarReturnType>;
|
|
@@ -3877,6 +3879,7 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
3877
3879
|
cacheTime?: undefined;
|
|
3878
3880
|
ccipRead?: undefined;
|
|
3879
3881
|
chain?: undefined;
|
|
3882
|
+
dataSuffix?: undefined;
|
|
3880
3883
|
experimental_blockTag?: undefined;
|
|
3881
3884
|
key?: undefined;
|
|
3882
3885
|
name?: undefined;
|
|
@@ -3926,6 +3929,7 @@ export declare function useWalletClient(chain: any, rpcUrl?: string): {
|
|
|
3926
3929
|
request?: (parameters: import("viem").CcipRequestParameters) => Promise<import("viem/_types/utils/ccip").CcipRequestReturnType>;
|
|
3927
3930
|
} | undefined;
|
|
3928
3931
|
chain: Chain | undefined;
|
|
3932
|
+
dataSuffix?: import("viem").DataSuffix | undefined;
|
|
3929
3933
|
experimental_blockTag?: import("viem").BlockTag | undefined;
|
|
3930
3934
|
key: string;
|
|
3931
3935
|
name: string;
|
|
@@ -8337,6 +8341,7 @@ export declare function useWalletClient(chain: any, rpcUrl?: string): {
|
|
|
8337
8341
|
cacheTime?: undefined;
|
|
8338
8342
|
ccipRead?: undefined;
|
|
8339
8343
|
chain?: undefined;
|
|
8344
|
+
dataSuffix?: undefined;
|
|
8340
8345
|
experimental_blockTag?: undefined;
|
|
8341
8346
|
key?: undefined;
|
|
8342
8347
|
name?: undefined;
|
|
@@ -8863,6 +8868,7 @@ export declare function useExternalWalletClient(): {
|
|
|
8863
8868
|
request?: (parameters: import("viem").CcipRequestParameters) => Promise<import("viem/_types/utils/ccip").CcipRequestReturnType>;
|
|
8864
8869
|
} | undefined;
|
|
8865
8870
|
chain: Chain;
|
|
8871
|
+
dataSuffix?: import("viem").DataSuffix | undefined;
|
|
8866
8872
|
experimental_blockTag?: import("viem").BlockTag | undefined;
|
|
8867
8873
|
key: string;
|
|
8868
8874
|
name: string;
|
|
@@ -13274,6 +13280,7 @@ export declare function useExternalWalletClient(): {
|
|
|
13274
13280
|
cacheTime?: undefined;
|
|
13275
13281
|
ccipRead?: undefined;
|
|
13276
13282
|
chain?: undefined;
|
|
13283
|
+
dataSuffix?: undefined;
|
|
13277
13284
|
experimental_blockTag?: undefined;
|
|
13278
13285
|
key?: undefined;
|
|
13279
13286
|
name?: undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abstraxn/signer-react",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.4",
|
|
4
4
|
"description": "React SDK for Abstraxn Wallet - React components, hooks, and providers for seamless Web3 wallet integration",
|
|
5
5
|
"main": "./dist/src/index.js",
|
|
6
6
|
"module": "./dist/src/index.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@abstraxn/signer-core": "
|
|
43
|
+
"@abstraxn/signer-core": "2.1.2",
|
|
44
44
|
"@solana/wallet-adapter-base": "^0.9.27",
|
|
45
45
|
"@solana/wallet-adapter-react": "^0.15.39",
|
|
46
46
|
"@solana/wallet-adapter-react-ui": "^0.9.39",
|