@b3dotfun/sdk 0.1.2 → 0.1.5
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/dist/cjs/anyspend/react/components/AnySpend.d.ts +7 -1
- package/dist/cjs/anyspend/react/components/AnySpend.js +66 -15
- package/dist/cjs/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +6 -2
- package/dist/cjs/anyspend/react/components/AnySpendCollectorClubPurchase.js +4 -4
- package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.d.ts +6 -0
- package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +185 -50
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +6 -1
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +19 -4
- package/dist/cjs/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +2 -1
- package/dist/cjs/anyspend/react/components/AnySpendStakeUpsideExactIn.js +2 -2
- package/dist/cjs/anyspend/react/components/QRDeposit.d.ts +4 -1
- package/dist/cjs/anyspend/react/components/QRDeposit.js +12 -4
- package/dist/cjs/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/CryptoPaySection.js +7 -5
- package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +4 -3
- package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +7 -6
- package/dist/cjs/anyspend/react/components/common/FeeDetailPanel.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/FeeDetailPanel.js +15 -6
- package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.js +10 -6
- package/dist/cjs/anyspend/react/components/common/OrderDetails.d.ts +3 -0
- package/dist/cjs/anyspend/react/components/common/OrderDetails.js +11 -10
- package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.js +9 -9
- package/dist/cjs/anyspend/react/components/common/OrderHistory.js +2 -1
- package/dist/cjs/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +2 -2
- package/dist/cjs/anyspend/react/components/common/PanelOnrampPayment.d.ts +2 -0
- package/dist/cjs/anyspend/react/components/common/PanelOnrampPayment.js +20 -7
- package/dist/cjs/anyspend/react/components/common/PointsDetailPanel.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/PointsDetailPanel.js +3 -2
- package/dist/cjs/anyspend/react/components/common/RecipientSelection.d.ts +6 -1
- package/dist/cjs/anyspend/react/components/common/RecipientSelection.js +5 -2
- package/dist/cjs/anyspend/react/components/common/TabSection.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/TabSection.js +16 -7
- package/dist/cjs/anyspend/react/components/common/TransferCryptoDetails.d.ts +2 -0
- package/dist/cjs/anyspend/react/components/common/TransferCryptoDetails.js +3 -2
- package/dist/cjs/anyspend/react/components/common/WarningText.d.ts +8 -7
- package/dist/cjs/anyspend/react/components/common/WarningText.js +5 -6
- package/dist/cjs/anyspend/react/components/index.d.ts +1 -0
- package/dist/cjs/anyspend/react/components/types/classes.d.ts +390 -0
- package/dist/cjs/anyspend/react/components/types/classes.js +6 -0
- package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/cjs/anyspend/react/hooks/index.js +1 -0
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +22 -2
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +119 -15
- package/dist/cjs/anyspend/react/hooks/useDirectTransfer.d.ts +17 -0
- package/dist/cjs/anyspend/react/hooks/useDirectTransfer.js +46 -0
- package/dist/cjs/anyspend/react/hooks/useRecipientAddressState.js +1 -1
- package/dist/cjs/anyspend/utils/format.js +12 -2
- package/dist/cjs/global-account/react/components/B3DynamicModal.js +1 -5
- package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +1 -3
- package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.js +1 -2
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +1 -4
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +2 -2
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.native.d.ts +1 -1
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.native.js +1 -1
- package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +1 -4
- package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.js +1 -3
- package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +1 -3
- package/dist/cjs/global-account/react/components/ManageAccount/SettingsContent.js +17 -3
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +19 -152
- package/dist/cjs/global-account/react/components/index.d.ts +0 -1
- package/dist/cjs/global-account/react/components/index.js +3 -6
- package/dist/cjs/global-account/react/hooks/index.d.ts +0 -1
- package/dist/cjs/global-account/react/hooks/index.js +2 -4
- package/dist/cjs/global-account/react/hooks/useAuth.d.ts +2 -3
- package/dist/cjs/global-account/react/hooks/useAuth.js +14 -31
- package/dist/cjs/global-account/react/hooks/useTWAuth.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useTWAuth.js +3 -3
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +8 -19
- package/dist/esm/anyspend/react/components/AnySpend.d.ts +7 -1
- package/dist/esm/anyspend/react/components/AnySpend.js +68 -17
- package/dist/esm/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +6 -2
- package/dist/esm/anyspend/react/components/AnySpendCollectorClubPurchase.js +4 -4
- package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.d.ts +6 -0
- package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +189 -54
- package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +6 -1
- package/dist/esm/anyspend/react/components/AnySpendDeposit.js +19 -4
- package/dist/esm/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +2 -1
- package/dist/esm/anyspend/react/components/AnySpendStakeUpsideExactIn.js +2 -2
- package/dist/esm/anyspend/react/components/QRDeposit.d.ts +4 -1
- package/dist/esm/anyspend/react/components/QRDeposit.js +12 -4
- package/dist/esm/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/CryptoPaySection.js +7 -5
- package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +4 -3
- package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +7 -6
- package/dist/esm/anyspend/react/components/common/FeeDetailPanel.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/FeeDetailPanel.js +15 -6
- package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.js +10 -6
- package/dist/esm/anyspend/react/components/common/OrderDetails.d.ts +3 -0
- package/dist/esm/anyspend/react/components/common/OrderDetails.js +11 -10
- package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.js +9 -9
- package/dist/esm/anyspend/react/components/common/OrderHistory.js +2 -1
- package/dist/esm/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/PanelOnramp.js +2 -2
- package/dist/esm/anyspend/react/components/common/PanelOnrampPayment.d.ts +2 -0
- package/dist/esm/anyspend/react/components/common/PanelOnrampPayment.js +20 -7
- package/dist/esm/anyspend/react/components/common/PointsDetailPanel.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/PointsDetailPanel.js +3 -2
- package/dist/esm/anyspend/react/components/common/RecipientSelection.d.ts +6 -1
- package/dist/esm/anyspend/react/components/common/RecipientSelection.js +5 -2
- package/dist/esm/anyspend/react/components/common/TabSection.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/TabSection.js +16 -7
- package/dist/esm/anyspend/react/components/common/TransferCryptoDetails.d.ts +2 -0
- package/dist/esm/anyspend/react/components/common/TransferCryptoDetails.js +3 -2
- package/dist/esm/anyspend/react/components/common/WarningText.d.ts +8 -7
- package/dist/esm/anyspend/react/components/common/WarningText.js +5 -6
- package/dist/esm/anyspend/react/components/index.d.ts +1 -0
- package/dist/esm/anyspend/react/components/types/classes.d.ts +390 -0
- package/dist/esm/anyspend/react/components/types/classes.js +5 -0
- package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/esm/anyspend/react/hooks/index.js +1 -0
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +22 -2
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +119 -16
- package/dist/esm/anyspend/react/hooks/useDirectTransfer.d.ts +17 -0
- package/dist/esm/anyspend/react/hooks/useDirectTransfer.js +43 -0
- package/dist/esm/anyspend/react/hooks/useRecipientAddressState.js +1 -1
- package/dist/esm/anyspend/utils/format.js +12 -2
- package/dist/esm/global-account/react/components/B3DynamicModal.js +1 -5
- package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +1 -3
- package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.js +1 -2
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +1 -4
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +2 -2
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.native.d.ts +1 -1
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.native.js +1 -1
- package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +1 -4
- package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.js +1 -3
- package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +1 -3
- package/dist/esm/global-account/react/components/ManageAccount/SettingsContent.js +16 -2
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +20 -153
- package/dist/esm/global-account/react/components/index.d.ts +0 -1
- package/dist/esm/global-account/react/components/index.js +0 -2
- package/dist/esm/global-account/react/hooks/index.d.ts +0 -1
- package/dist/esm/global-account/react/hooks/index.js +0 -1
- package/dist/esm/global-account/react/hooks/useAuth.d.ts +2 -3
- package/dist/esm/global-account/react/hooks/useAuth.js +14 -31
- package/dist/esm/global-account/react/hooks/useTWAuth.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useTWAuth.js +3 -3
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +8 -19
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/AnySpend.d.ts +7 -1
- package/dist/types/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +6 -2
- package/dist/types/anyspend/react/components/AnySpendCustomExactIn.d.ts +6 -0
- package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +6 -1
- package/dist/types/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +2 -1
- package/dist/types/anyspend/react/components/QRDeposit.d.ts +4 -1
- package/dist/types/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/CryptoPaymentMethod.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/FeeDetailPanel.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/FiatPaymentMethod.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/OrderDetails.d.ts +3 -0
- package/dist/types/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/types/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/PanelOnrampPayment.d.ts +2 -0
- package/dist/types/anyspend/react/components/common/PointsDetailPanel.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/RecipientSelection.d.ts +6 -1
- package/dist/types/anyspend/react/components/common/TabSection.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/TransferCryptoDetails.d.ts +2 -0
- package/dist/types/anyspend/react/components/common/WarningText.d.ts +8 -7
- package/dist/types/anyspend/react/components/index.d.ts +1 -0
- package/dist/types/anyspend/react/components/types/classes.d.ts +390 -0
- package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +22 -2
- package/dist/types/anyspend/react/hooks/useDirectTransfer.d.ts +17 -0
- package/dist/types/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +1 -3
- package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +1 -4
- package/dist/types/global-account/react/components/B3Provider/B3Provider.native.d.ts +1 -1
- package/dist/types/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +1 -4
- package/dist/types/global-account/react/components/index.d.ts +0 -1
- package/dist/types/global-account/react/hooks/index.d.ts +0 -1
- package/dist/types/global-account/react/hooks/useAuth.d.ts +2 -3
- package/dist/types/global-account/react/hooks/useTWAuth.d.ts +1 -1
- package/dist/types/global-account/react/stores/useModalStore.d.ts +8 -19
- package/package.json +1 -1
- package/src/anyspend/react/components/AnySpend.tsx +164 -36
- package/src/anyspend/react/components/AnySpendCollectorClubPurchase.tsx +11 -6
- package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +278 -69
- package/src/anyspend/react/components/AnySpendDeposit.tsx +176 -52
- package/src/anyspend/react/components/AnySpendStakeUpsideExactIn.tsx +3 -0
- package/src/anyspend/react/components/QRDeposit.tsx +91 -35
- package/src/anyspend/react/components/common/CryptoPaySection.tsx +31 -19
- package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +14 -4
- package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +43 -23
- package/src/anyspend/react/components/common/FeeDetailPanel.tsx +53 -32
- package/src/anyspend/react/components/common/FiatPaymentMethod.tsx +26 -13
- package/src/anyspend/react/components/common/OrderDetails.tsx +20 -9
- package/src/anyspend/react/components/common/OrderDetailsCollapsible.tsx +12 -7
- package/src/anyspend/react/components/common/OrderHistory.tsx +2 -1
- package/src/anyspend/react/components/common/PanelOnramp.tsx +4 -1
- package/src/anyspend/react/components/common/PanelOnrampPayment.tsx +118 -40
- package/src/anyspend/react/components/common/PointsDetailPanel.tsx +28 -14
- package/src/anyspend/react/components/common/RecipientSelection.tsx +20 -5
- package/src/anyspend/react/components/common/TabSection.tsx +21 -12
- package/src/anyspend/react/components/common/TransferCryptoDetails.tsx +12 -4
- package/src/anyspend/react/components/common/WarningText.tsx +10 -10
- package/src/anyspend/react/components/index.ts +16 -0
- package/src/anyspend/react/components/types/classes.ts +476 -0
- package/src/anyspend/react/hooks/index.ts +1 -0
- package/src/anyspend/react/hooks/useAnyspendFlow.ts +141 -17
- package/src/anyspend/react/hooks/useDirectTransfer.ts +67 -0
- package/src/anyspend/react/hooks/useRecipientAddressState.ts +1 -1
- package/src/anyspend/utils/format.ts +13 -2
- package/src/global-account/react/components/B3DynamicModal.tsx +0 -5
- package/src/global-account/react/components/B3Provider/B3ConfigProvider.tsx +0 -4
- package/src/global-account/react/components/B3Provider/B3Provider.native.tsx +1 -1
- package/src/global-account/react/components/B3Provider/B3Provider.tsx +1 -11
- package/src/global-account/react/components/B3Provider/LocalSDKProvider.tsx +0 -6
- package/src/global-account/react/components/B3Provider/RelayKitProviderWrapper.tsx +1 -4
- package/src/global-account/react/components/ManageAccount/SettingsContent.tsx +33 -1
- package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +27 -184
- package/src/global-account/react/components/index.ts +0 -3
- package/src/global-account/react/hooks/index.ts +0 -1
- package/src/global-account/react/hooks/useAuth.ts +14 -31
- package/src/global-account/react/hooks/useTWAuth.tsx +3 -5
- package/src/global-account/react/stores/useModalStore.ts +7 -20
- package/dist/cjs/global-account/react/components/TurnkeyAuthModal.d.ts +0 -8
- package/dist/cjs/global-account/react/components/TurnkeyAuthModal.js +0 -86
- package/dist/cjs/global-account/react/hooks/useTurnkeyAuth.d.ts +0 -20
- package/dist/cjs/global-account/react/hooks/useTurnkeyAuth.js +0 -142
- package/dist/esm/global-account/react/components/TurnkeyAuthModal.d.ts +0 -8
- package/dist/esm/global-account/react/components/TurnkeyAuthModal.js +0 -83
- package/dist/esm/global-account/react/hooks/useTurnkeyAuth.d.ts +0 -20
- package/dist/esm/global-account/react/hooks/useTurnkeyAuth.js +0 -136
- package/dist/types/global-account/react/components/TurnkeyAuthModal.d.ts +0 -8
- package/dist/types/global-account/react/hooks/useTurnkeyAuth.d.ts +0 -20
- package/src/global-account/react/components/TurnkeyAuthModal.tsx +0 -243
- package/src/global-account/react/hooks/useTurnkeyAuth.ts +0 -171
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.useTurnkeyAuth = useTurnkeyAuth;
|
|
7
|
-
const debug_1 = require("../../../shared/utils/debug");
|
|
8
|
-
const react_1 = require("react");
|
|
9
|
-
const app_1 = __importDefault(require("../../app"));
|
|
10
|
-
const components_1 = require("../components");
|
|
11
|
-
const stores_1 = require("../stores");
|
|
12
|
-
const useAuth_1 = require("./useAuth");
|
|
13
|
-
const debug = (0, debug_1.debugB3React)("useTurnkeyAuth");
|
|
14
|
-
/**
|
|
15
|
-
* Hook for Turnkey email-based OTP authentication
|
|
16
|
-
*
|
|
17
|
-
* Usage:
|
|
18
|
-
* 1. Call initiateLogin(email) → User receives OTP email
|
|
19
|
-
* 2. Call verifyOtp(...) → Verifies OTP and authenticates with b3-api
|
|
20
|
-
* 3. User is authenticated, JWT stored in cookies automatically
|
|
21
|
-
*/
|
|
22
|
-
function useTurnkeyAuth() {
|
|
23
|
-
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
24
|
-
const [error, setError] = (0, react_1.useState)(null);
|
|
25
|
-
const setIsAuthenticating = (0, stores_1.useAuthStore)(state => state.setIsAuthenticating);
|
|
26
|
-
const setIsAuthenticated = (0, stores_1.useAuthStore)(state => state.setIsAuthenticated);
|
|
27
|
-
const { partnerId } = (0, components_1.useB3Config)();
|
|
28
|
-
const { authenticate } = (0, useAuth_1.useAuth)();
|
|
29
|
-
/**
|
|
30
|
-
* Step 1: Initiate login with email
|
|
31
|
-
* - Calls backend turnkey-jwt strategy (init action) to create sub-org (if needed) and send OTP
|
|
32
|
-
* - Returns otpId to use in verification step
|
|
33
|
-
*
|
|
34
|
-
* Note: Uses the turnkey-jwt authentication strategy, not the service directly.
|
|
35
|
-
* The turnkey-jwt strategy handles both OTP flow (init/verify) and final authentication.
|
|
36
|
-
*/
|
|
37
|
-
const initiateLogin = (0, react_1.useCallback)(async (email) => {
|
|
38
|
-
setIsLoading(true);
|
|
39
|
-
setError(null);
|
|
40
|
-
setIsAuthenticating(true);
|
|
41
|
-
try {
|
|
42
|
-
debug(`Initiating login for: ${email}`);
|
|
43
|
-
// Use authentication service with turnkey-jwt strategy (init action)
|
|
44
|
-
// userId is resolved from authentication context on the backend (params.user.userId)
|
|
45
|
-
// Backend will get userId from _params.user?.userId if authenticated, or handle unauthenticated case
|
|
46
|
-
// So we only need to send email
|
|
47
|
-
debug(`Calling app.authenticate with turnkey-jwt strategy (init action)`, { email });
|
|
48
|
-
const response = await app_1.default.authenticate({
|
|
49
|
-
strategy: "turnkey-jwt",
|
|
50
|
-
action: "init",
|
|
51
|
-
email,
|
|
52
|
-
});
|
|
53
|
-
// The strategy returns the TurnkeyAuthInitResponse directly
|
|
54
|
-
const data = response;
|
|
55
|
-
debug(`OTP initialized successfully. OtpId: ${data.otpId}`);
|
|
56
|
-
return data;
|
|
57
|
-
}
|
|
58
|
-
catch (err) {
|
|
59
|
-
debug("Error initiating login:", err);
|
|
60
|
-
// Provide more detailed error information
|
|
61
|
-
let errorMessage = "Failed to send OTP email. Please try again.";
|
|
62
|
-
if (err.message) {
|
|
63
|
-
errorMessage = err.message;
|
|
64
|
-
}
|
|
65
|
-
else if (err.name === "TypeError" && err.message?.includes("fetch")) {
|
|
66
|
-
errorMessage = "Network error: Unable to reach the server. Please check your connection and try again.";
|
|
67
|
-
}
|
|
68
|
-
else if (err.code === "ECONNREFUSED" || err.code === "ENOTFOUND") {
|
|
69
|
-
errorMessage = "Connection error: Unable to reach the server. Please check your internet connection.";
|
|
70
|
-
}
|
|
71
|
-
else if (err.response) {
|
|
72
|
-
// FeathersJS error response
|
|
73
|
-
errorMessage = err.response.message || err.message || errorMessage;
|
|
74
|
-
debug("FeathersJS error response:", err.response);
|
|
75
|
-
}
|
|
76
|
-
setError(errorMessage);
|
|
77
|
-
throw err;
|
|
78
|
-
}
|
|
79
|
-
finally {
|
|
80
|
-
setIsLoading(false);
|
|
81
|
-
setIsAuthenticating(false);
|
|
82
|
-
}
|
|
83
|
-
}, [setIsAuthenticating]);
|
|
84
|
-
/**
|
|
85
|
-
* Step 2: Verify OTP and authenticate
|
|
86
|
-
* - Verifies OTP with backend via turnkey-jwt strategy (verify action)
|
|
87
|
-
* - Gets Turnkey session JWT from the verify response
|
|
88
|
-
* - Authenticates with b3-api using "turnkey-jwt" strategy
|
|
89
|
-
* - JWT automatically stored in cookies by SDK
|
|
90
|
-
*/
|
|
91
|
-
const verifyOtp = (0, react_1.useCallback)(async (otpId, otpCode) => {
|
|
92
|
-
setIsLoading(true);
|
|
93
|
-
setError(null);
|
|
94
|
-
setIsAuthenticating(true);
|
|
95
|
-
try {
|
|
96
|
-
debug(`Verifying OTP...`, { otpId });
|
|
97
|
-
// Step 1: Verify OTP with backend using turnkey-jwt strategy (verify action)
|
|
98
|
-
// This returns the Turnkey session JWT
|
|
99
|
-
const response = await app_1.default.authenticate({
|
|
100
|
-
strategy: "turnkey-jwt",
|
|
101
|
-
action: "verify",
|
|
102
|
-
otpId,
|
|
103
|
-
otpCode,
|
|
104
|
-
});
|
|
105
|
-
// The strategy returns the TurnkeyAuthVerifyResponse directly
|
|
106
|
-
const verifyResult = response;
|
|
107
|
-
const { turnkeySessionJwt } = verifyResult;
|
|
108
|
-
debug(`OTP verified! Got Turnkey session JWT. Authenticating with b3-api...`);
|
|
109
|
-
// Step 2: Authenticate with b3-api using Turnkey JWT
|
|
110
|
-
// Use the unified useAuth hook for authentication with "turnkey-jwt" strategy
|
|
111
|
-
const authResult = await authenticate(turnkeySessionJwt, partnerId || "");
|
|
112
|
-
debug(`Successfully authenticated with b3-api!`, authResult);
|
|
113
|
-
// Update auth store to reflect authenticated state
|
|
114
|
-
setIsAuthenticated(true);
|
|
115
|
-
// Return user data
|
|
116
|
-
return {
|
|
117
|
-
user: authResult.user,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
catch (err) {
|
|
121
|
-
debug("Error verifying OTP:", err);
|
|
122
|
-
const errorMessage = err.message || "Failed to verify OTP. Please try again.";
|
|
123
|
-
setError(errorMessage);
|
|
124
|
-
setIsAuthenticated(false);
|
|
125
|
-
throw err;
|
|
126
|
-
}
|
|
127
|
-
finally {
|
|
128
|
-
setIsLoading(false);
|
|
129
|
-
setIsAuthenticating(false);
|
|
130
|
-
}
|
|
131
|
-
}, [partnerId, setIsAuthenticating, setIsAuthenticated, authenticate]);
|
|
132
|
-
const clearError = (0, react_1.useCallback)(() => {
|
|
133
|
-
setError(null);
|
|
134
|
-
}, []);
|
|
135
|
-
return {
|
|
136
|
-
initiateLogin,
|
|
137
|
-
verifyOtp,
|
|
138
|
-
isLoading,
|
|
139
|
-
error,
|
|
140
|
-
clearError,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
interface TurnkeyAuthModalProps {
|
|
2
|
-
onClose: () => void;
|
|
3
|
-
onSuccess: (_user: any) => void;
|
|
4
|
-
initialEmail?: string;
|
|
5
|
-
skipToOtp?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare function TurnkeyAuthModal({ onClose, onSuccess, initialEmail, skipToOtp }: TurnkeyAuthModalProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
-
export {};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState } from "react";
|
|
3
|
-
import { useTurnkeyAuth } from "../hooks/useTurnkeyAuth.js";
|
|
4
|
-
export function TurnkeyAuthModal({ onClose, onSuccess, initialEmail = "", skipToOtp = false }) {
|
|
5
|
-
const [step, setStep] = useState(skipToOtp ? "otp" : "email");
|
|
6
|
-
const [email, setEmail] = useState(initialEmail);
|
|
7
|
-
const [otpCode, setOtpCode] = useState("");
|
|
8
|
-
const [otpId, setOtpId] = useState("");
|
|
9
|
-
const autoSubmitTriggeredRef = useRef(false);
|
|
10
|
-
const { initiateLogin, verifyOtp, isLoading, error, clearError } = useTurnkeyAuth();
|
|
11
|
-
// Update email when initialEmail changes
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
if (initialEmail && initialEmail !== email) {
|
|
14
|
-
setEmail(initialEmail);
|
|
15
|
-
}
|
|
16
|
-
}, [initialEmail, email]);
|
|
17
|
-
// Auto-submit email form if skipToOtp is true - triggers on mount when skipToOtp=true
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (skipToOtp && email && step === "otp" && !otpId && !isLoading && !autoSubmitTriggeredRef.current) {
|
|
20
|
-
autoSubmitTriggeredRef.current = true;
|
|
21
|
-
// Call initiateLogin directly to get OTP
|
|
22
|
-
initiateLogin(email)
|
|
23
|
-
.then(result => {
|
|
24
|
-
setOtpId(result.otpId);
|
|
25
|
-
})
|
|
26
|
-
.catch(err => {
|
|
27
|
-
console.error("Failed to initiate login:", err);
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31
|
-
}, [skipToOtp, email, step, otpId, isLoading]);
|
|
32
|
-
const handleEmailSubmit = async (e) => {
|
|
33
|
-
e.preventDefault();
|
|
34
|
-
try {
|
|
35
|
-
const result = await initiateLogin(email);
|
|
36
|
-
setOtpId(result.otpId);
|
|
37
|
-
setStep("otp");
|
|
38
|
-
}
|
|
39
|
-
catch (err) {
|
|
40
|
-
// Error is handled by the hook
|
|
41
|
-
console.error("Failed to initiate login:", err);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const handleOtpSubmit = async (e) => {
|
|
45
|
-
e.preventDefault();
|
|
46
|
-
try {
|
|
47
|
-
const result = await verifyOtp(otpId, otpCode);
|
|
48
|
-
setStep("success");
|
|
49
|
-
// Auto-close after success and notify parent
|
|
50
|
-
setTimeout(() => {
|
|
51
|
-
onSuccess(result.user);
|
|
52
|
-
handleClose();
|
|
53
|
-
}, 1500);
|
|
54
|
-
}
|
|
55
|
-
catch (err) {
|
|
56
|
-
// Error is handled by the hook
|
|
57
|
-
console.error("Failed to verify OTP:", err);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
const handleClose = () => {
|
|
61
|
-
// Reset state
|
|
62
|
-
setStep("email");
|
|
63
|
-
setEmail("");
|
|
64
|
-
setOtpCode("");
|
|
65
|
-
setOtpId("");
|
|
66
|
-
autoSubmitTriggeredRef.current = false;
|
|
67
|
-
clearError();
|
|
68
|
-
onClose();
|
|
69
|
-
};
|
|
70
|
-
const handleResendOtp = async () => {
|
|
71
|
-
try {
|
|
72
|
-
const result = await initiateLogin(email);
|
|
73
|
-
setOtpId(result.otpId);
|
|
74
|
-
clearError();
|
|
75
|
-
}
|
|
76
|
-
catch (err) {
|
|
77
|
-
console.error("Failed to resend OTP:", err);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
const isTurnkeyPrimary = process.env.NEXT_PUBLIC_TURNKEY_PRIMARY === "true";
|
|
81
|
-
const walletBrand = isTurnkeyPrimary ? "Smart Wallet" : "AnySpend Wallet";
|
|
82
|
-
return (_jsxs("div", { className: "font-neue-montreal p-8", children: [step === "email" && (_jsxs(_Fragment, { children: [_jsxs("h2", { className: "mb-6 text-center text-2xl font-bold text-gray-900 dark:text-white", children: ["Setup your ", walletBrand] }), _jsxs("div", { className: "mb-6 space-y-3 text-center text-sm text-gray-600 dark:text-gray-400", children: [_jsxs("p", { children: [isTurnkeyPrimary ? "We use a secure," : "AnySpend uses a secure,", _jsx("br", {}), "embedded wallet to fund your workflows."] }), _jsxs("p", { children: ["Please provide an email address to secure", _jsx("br", {}), "your wallet."] })] }), _jsxs("form", { onSubmit: handleEmailSubmit, className: "space-y-4", children: [_jsx("div", { children: _jsx("input", { type: "email", placeholder: "email", value: email, onChange: e => setEmail(e.target.value), required: true, disabled: isLoading, className: "w-full rounded-lg border border-gray-300 px-4 py-3 text-center text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20 disabled:cursor-not-allowed disabled:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500" }) }), error && (_jsx("div", { className: "rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400", children: error })), _jsx("button", { type: "submit", disabled: isLoading || !email, className: "w-full rounded-lg bg-blue-600 px-6 py-3 font-semibold text-white transition-all duration-200 hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-gray-300 dark:disabled:bg-gray-700", children: isLoading ? (_jsxs("span", { className: "flex items-center justify-center gap-2", children: [_jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" }), "Sending..."] })) : ("Continue") })] })] })), step === "otp" && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "mb-4 text-center text-2xl font-bold text-gray-900 dark:text-white", children: "2FA Security" }), _jsx("div", { className: "mb-6 space-y-3 text-center text-sm text-gray-600 dark:text-gray-400", children: _jsxs("p", { children: [isTurnkeyPrimary ? "We use a secure," : "AnySpend uses a secure,", _jsx("br", {}), "embedded wallet to fund your workflows.", _jsx("br", {}), "Please provide 2FA code sent to your email."] }) }), _jsxs("form", { onSubmit: handleOtpSubmit, className: "space-y-4", children: [_jsx("div", { children: _jsx("input", { type: "text", placeholder: "Enter code", value: otpCode, onChange: e => setOtpCode(e.target.value.toUpperCase()), required: true, disabled: isLoading, autoFocus: true, className: "w-full rounded-lg border border-gray-300 px-4 py-3 text-center font-mono text-lg uppercase tracking-wider text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20 disabled:cursor-not-allowed disabled:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500", maxLength: 20 }) }), error && (_jsx("div", { className: "rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400", children: error })), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("button", { type: "submit", disabled: isLoading || !otpCode, className: "w-full rounded-lg bg-blue-600 px-6 py-3 font-semibold text-white transition-all duration-200 hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-gray-300 dark:disabled:bg-gray-700", children: isLoading ? (_jsxs("span", { className: "flex items-center justify-center gap-2", children: [_jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" }), "Verifying..."] })) : ("Confirm") }), _jsx("button", { type: "button", onClick: handleResendOtp, disabled: isLoading, className: "text-sm text-blue-600 hover:text-blue-700 hover:underline disabled:cursor-not-allowed disabled:text-gray-400 dark:text-blue-400 dark:hover:text-blue-300", children: "Resend code" })] })] })] })), step === "success" && (_jsxs("div", { className: "text-center", children: [_jsx("div", { className: "mb-6 flex items-center justify-center", children: _jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-full bg-green-100 dark:bg-green-900/20", children: _jsx("svg", { className: "h-8 w-8 text-green-600 dark:text-green-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) }) }), _jsx("h2", { className: "mb-2 text-2xl font-bold text-gray-900 dark:text-white", children: "Successfully Authenticated!" }), _jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: "Redirecting..." })] }))] }));
|
|
83
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { TurnkeyAuthInitResponse } from "@b3dotfun/b3-api";
|
|
2
|
-
interface UseTurnkeyAuthReturn {
|
|
3
|
-
initiateLogin: (_email: string) => Promise<TurnkeyAuthInitResponse>;
|
|
4
|
-
verifyOtp: (_otpId: string, _otpCode: string) => Promise<{
|
|
5
|
-
user: any;
|
|
6
|
-
}>;
|
|
7
|
-
isLoading: boolean;
|
|
8
|
-
error: string | null;
|
|
9
|
-
clearError: () => void;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Hook for Turnkey email-based OTP authentication
|
|
13
|
-
*
|
|
14
|
-
* Usage:
|
|
15
|
-
* 1. Call initiateLogin(email) → User receives OTP email
|
|
16
|
-
* 2. Call verifyOtp(...) → Verifies OTP and authenticates with b3-api
|
|
17
|
-
* 3. User is authenticated, JWT stored in cookies automatically
|
|
18
|
-
*/
|
|
19
|
-
export declare function useTurnkeyAuth(): UseTurnkeyAuthReturn;
|
|
20
|
-
export {};
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { debugB3React } from "../../../shared/utils/debug.js";
|
|
2
|
-
import { useCallback, useState } from "react";
|
|
3
|
-
import app from "../../app.js";
|
|
4
|
-
import { useB3Config } from "../components/index.js";
|
|
5
|
-
import { useAuthStore } from "../stores/index.js";
|
|
6
|
-
import { useAuth } from "./useAuth.js";
|
|
7
|
-
const debug = debugB3React("useTurnkeyAuth");
|
|
8
|
-
/**
|
|
9
|
-
* Hook for Turnkey email-based OTP authentication
|
|
10
|
-
*
|
|
11
|
-
* Usage:
|
|
12
|
-
* 1. Call initiateLogin(email) → User receives OTP email
|
|
13
|
-
* 2. Call verifyOtp(...) → Verifies OTP and authenticates with b3-api
|
|
14
|
-
* 3. User is authenticated, JWT stored in cookies automatically
|
|
15
|
-
*/
|
|
16
|
-
export function useTurnkeyAuth() {
|
|
17
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
18
|
-
const [error, setError] = useState(null);
|
|
19
|
-
const setIsAuthenticating = useAuthStore(state => state.setIsAuthenticating);
|
|
20
|
-
const setIsAuthenticated = useAuthStore(state => state.setIsAuthenticated);
|
|
21
|
-
const { partnerId } = useB3Config();
|
|
22
|
-
const { authenticate } = useAuth();
|
|
23
|
-
/**
|
|
24
|
-
* Step 1: Initiate login with email
|
|
25
|
-
* - Calls backend turnkey-jwt strategy (init action) to create sub-org (if needed) and send OTP
|
|
26
|
-
* - Returns otpId to use in verification step
|
|
27
|
-
*
|
|
28
|
-
* Note: Uses the turnkey-jwt authentication strategy, not the service directly.
|
|
29
|
-
* The turnkey-jwt strategy handles both OTP flow (init/verify) and final authentication.
|
|
30
|
-
*/
|
|
31
|
-
const initiateLogin = useCallback(async (email) => {
|
|
32
|
-
setIsLoading(true);
|
|
33
|
-
setError(null);
|
|
34
|
-
setIsAuthenticating(true);
|
|
35
|
-
try {
|
|
36
|
-
debug(`Initiating login for: ${email}`);
|
|
37
|
-
// Use authentication service with turnkey-jwt strategy (init action)
|
|
38
|
-
// userId is resolved from authentication context on the backend (params.user.userId)
|
|
39
|
-
// Backend will get userId from _params.user?.userId if authenticated, or handle unauthenticated case
|
|
40
|
-
// So we only need to send email
|
|
41
|
-
debug(`Calling app.authenticate with turnkey-jwt strategy (init action)`, { email });
|
|
42
|
-
const response = await app.authenticate({
|
|
43
|
-
strategy: "turnkey-jwt",
|
|
44
|
-
action: "init",
|
|
45
|
-
email,
|
|
46
|
-
});
|
|
47
|
-
// The strategy returns the TurnkeyAuthInitResponse directly
|
|
48
|
-
const data = response;
|
|
49
|
-
debug(`OTP initialized successfully. OtpId: ${data.otpId}`);
|
|
50
|
-
return data;
|
|
51
|
-
}
|
|
52
|
-
catch (err) {
|
|
53
|
-
debug("Error initiating login:", err);
|
|
54
|
-
// Provide more detailed error information
|
|
55
|
-
let errorMessage = "Failed to send OTP email. Please try again.";
|
|
56
|
-
if (err.message) {
|
|
57
|
-
errorMessage = err.message;
|
|
58
|
-
}
|
|
59
|
-
else if (err.name === "TypeError" && err.message?.includes("fetch")) {
|
|
60
|
-
errorMessage = "Network error: Unable to reach the server. Please check your connection and try again.";
|
|
61
|
-
}
|
|
62
|
-
else if (err.code === "ECONNREFUSED" || err.code === "ENOTFOUND") {
|
|
63
|
-
errorMessage = "Connection error: Unable to reach the server. Please check your internet connection.";
|
|
64
|
-
}
|
|
65
|
-
else if (err.response) {
|
|
66
|
-
// FeathersJS error response
|
|
67
|
-
errorMessage = err.response.message || err.message || errorMessage;
|
|
68
|
-
debug("FeathersJS error response:", err.response);
|
|
69
|
-
}
|
|
70
|
-
setError(errorMessage);
|
|
71
|
-
throw err;
|
|
72
|
-
}
|
|
73
|
-
finally {
|
|
74
|
-
setIsLoading(false);
|
|
75
|
-
setIsAuthenticating(false);
|
|
76
|
-
}
|
|
77
|
-
}, [setIsAuthenticating]);
|
|
78
|
-
/**
|
|
79
|
-
* Step 2: Verify OTP and authenticate
|
|
80
|
-
* - Verifies OTP with backend via turnkey-jwt strategy (verify action)
|
|
81
|
-
* - Gets Turnkey session JWT from the verify response
|
|
82
|
-
* - Authenticates with b3-api using "turnkey-jwt" strategy
|
|
83
|
-
* - JWT automatically stored in cookies by SDK
|
|
84
|
-
*/
|
|
85
|
-
const verifyOtp = useCallback(async (otpId, otpCode) => {
|
|
86
|
-
setIsLoading(true);
|
|
87
|
-
setError(null);
|
|
88
|
-
setIsAuthenticating(true);
|
|
89
|
-
try {
|
|
90
|
-
debug(`Verifying OTP...`, { otpId });
|
|
91
|
-
// Step 1: Verify OTP with backend using turnkey-jwt strategy (verify action)
|
|
92
|
-
// This returns the Turnkey session JWT
|
|
93
|
-
const response = await app.authenticate({
|
|
94
|
-
strategy: "turnkey-jwt",
|
|
95
|
-
action: "verify",
|
|
96
|
-
otpId,
|
|
97
|
-
otpCode,
|
|
98
|
-
});
|
|
99
|
-
// The strategy returns the TurnkeyAuthVerifyResponse directly
|
|
100
|
-
const verifyResult = response;
|
|
101
|
-
const { turnkeySessionJwt } = verifyResult;
|
|
102
|
-
debug(`OTP verified! Got Turnkey session JWT. Authenticating with b3-api...`);
|
|
103
|
-
// Step 2: Authenticate with b3-api using Turnkey JWT
|
|
104
|
-
// Use the unified useAuth hook for authentication with "turnkey-jwt" strategy
|
|
105
|
-
const authResult = await authenticate(turnkeySessionJwt, partnerId || "");
|
|
106
|
-
debug(`Successfully authenticated with b3-api!`, authResult);
|
|
107
|
-
// Update auth store to reflect authenticated state
|
|
108
|
-
setIsAuthenticated(true);
|
|
109
|
-
// Return user data
|
|
110
|
-
return {
|
|
111
|
-
user: authResult.user,
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
catch (err) {
|
|
115
|
-
debug("Error verifying OTP:", err);
|
|
116
|
-
const errorMessage = err.message || "Failed to verify OTP. Please try again.";
|
|
117
|
-
setError(errorMessage);
|
|
118
|
-
setIsAuthenticated(false);
|
|
119
|
-
throw err;
|
|
120
|
-
}
|
|
121
|
-
finally {
|
|
122
|
-
setIsLoading(false);
|
|
123
|
-
setIsAuthenticating(false);
|
|
124
|
-
}
|
|
125
|
-
}, [partnerId, setIsAuthenticating, setIsAuthenticated, authenticate]);
|
|
126
|
-
const clearError = useCallback(() => {
|
|
127
|
-
setError(null);
|
|
128
|
-
}, []);
|
|
129
|
-
return {
|
|
130
|
-
initiateLogin,
|
|
131
|
-
verifyOtp,
|
|
132
|
-
isLoading,
|
|
133
|
-
error,
|
|
134
|
-
clearError,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
interface TurnkeyAuthModalProps {
|
|
2
|
-
onClose: () => void;
|
|
3
|
-
onSuccess: (_user: any) => void;
|
|
4
|
-
initialEmail?: string;
|
|
5
|
-
skipToOtp?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare function TurnkeyAuthModal({ onClose, onSuccess, initialEmail, skipToOtp }: TurnkeyAuthModalProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { TurnkeyAuthInitResponse } from "@b3dotfun/b3-api";
|
|
2
|
-
interface UseTurnkeyAuthReturn {
|
|
3
|
-
initiateLogin: (_email: string) => Promise<TurnkeyAuthInitResponse>;
|
|
4
|
-
verifyOtp: (_otpId: string, _otpCode: string) => Promise<{
|
|
5
|
-
user: any;
|
|
6
|
-
}>;
|
|
7
|
-
isLoading: boolean;
|
|
8
|
-
error: string | null;
|
|
9
|
-
clearError: () => void;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Hook for Turnkey email-based OTP authentication
|
|
13
|
-
*
|
|
14
|
-
* Usage:
|
|
15
|
-
* 1. Call initiateLogin(email) → User receives OTP email
|
|
16
|
-
* 2. Call verifyOtp(...) → Verifies OTP and authenticates with b3-api
|
|
17
|
-
* 3. User is authenticated, JWT stored in cookies automatically
|
|
18
|
-
*/
|
|
19
|
-
export declare function useTurnkeyAuth(): UseTurnkeyAuthReturn;
|
|
20
|
-
export {};
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
-
import { useTurnkeyAuth } from "../hooks/useTurnkeyAuth";
|
|
3
|
-
|
|
4
|
-
type ModalStep = "email" | "otp" | "success";
|
|
5
|
-
|
|
6
|
-
interface TurnkeyAuthModalProps {
|
|
7
|
-
onClose: () => void;
|
|
8
|
-
onSuccess: (_user: any) => void;
|
|
9
|
-
initialEmail?: string;
|
|
10
|
-
skipToOtp?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function TurnkeyAuthModal({ onClose, onSuccess, initialEmail = "", skipToOtp = false }: TurnkeyAuthModalProps) {
|
|
14
|
-
const [step, setStep] = useState<ModalStep>(skipToOtp ? "otp" : "email");
|
|
15
|
-
const [email, setEmail] = useState(initialEmail);
|
|
16
|
-
const [otpCode, setOtpCode] = useState("");
|
|
17
|
-
const [otpId, setOtpId] = useState("");
|
|
18
|
-
const autoSubmitTriggeredRef = useRef(false);
|
|
19
|
-
|
|
20
|
-
const { initiateLogin, verifyOtp, isLoading, error, clearError } = useTurnkeyAuth();
|
|
21
|
-
|
|
22
|
-
// Update email when initialEmail changes
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
if (initialEmail && initialEmail !== email) {
|
|
25
|
-
setEmail(initialEmail);
|
|
26
|
-
}
|
|
27
|
-
}, [initialEmail, email]);
|
|
28
|
-
|
|
29
|
-
// Auto-submit email form if skipToOtp is true - triggers on mount when skipToOtp=true
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
if (skipToOtp && email && step === "otp" && !otpId && !isLoading && !autoSubmitTriggeredRef.current) {
|
|
32
|
-
autoSubmitTriggeredRef.current = true;
|
|
33
|
-
// Call initiateLogin directly to get OTP
|
|
34
|
-
initiateLogin(email)
|
|
35
|
-
.then(result => {
|
|
36
|
-
setOtpId(result.otpId);
|
|
37
|
-
})
|
|
38
|
-
.catch(err => {
|
|
39
|
-
console.error("Failed to initiate login:", err);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
43
|
-
}, [skipToOtp, email, step, otpId, isLoading]);
|
|
44
|
-
|
|
45
|
-
const handleEmailSubmit = async (e: React.FormEvent) => {
|
|
46
|
-
e.preventDefault();
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
const result = await initiateLogin(email);
|
|
50
|
-
setOtpId(result.otpId);
|
|
51
|
-
setStep("otp");
|
|
52
|
-
} catch (err) {
|
|
53
|
-
// Error is handled by the hook
|
|
54
|
-
console.error("Failed to initiate login:", err);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const handleOtpSubmit = async (e: React.FormEvent) => {
|
|
59
|
-
e.preventDefault();
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
const result = await verifyOtp(otpId, otpCode);
|
|
63
|
-
setStep("success");
|
|
64
|
-
|
|
65
|
-
// Auto-close after success and notify parent
|
|
66
|
-
setTimeout(() => {
|
|
67
|
-
onSuccess(result.user);
|
|
68
|
-
handleClose();
|
|
69
|
-
}, 1500);
|
|
70
|
-
} catch (err) {
|
|
71
|
-
// Error is handled by the hook
|
|
72
|
-
console.error("Failed to verify OTP:", err);
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const handleClose = () => {
|
|
77
|
-
// Reset state
|
|
78
|
-
setStep("email");
|
|
79
|
-
setEmail("");
|
|
80
|
-
setOtpCode("");
|
|
81
|
-
setOtpId("");
|
|
82
|
-
autoSubmitTriggeredRef.current = false;
|
|
83
|
-
clearError();
|
|
84
|
-
onClose();
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const handleResendOtp = async () => {
|
|
88
|
-
try {
|
|
89
|
-
const result = await initiateLogin(email);
|
|
90
|
-
setOtpId(result.otpId);
|
|
91
|
-
clearError();
|
|
92
|
-
} catch (err) {
|
|
93
|
-
console.error("Failed to resend OTP:", err);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const isTurnkeyPrimary = process.env.NEXT_PUBLIC_TURNKEY_PRIMARY === "true";
|
|
98
|
-
const walletBrand = isTurnkeyPrimary ? "Smart Wallet" : "AnySpend Wallet";
|
|
99
|
-
|
|
100
|
-
return (
|
|
101
|
-
<div className="font-neue-montreal p-8">
|
|
102
|
-
{/* Email Step */}
|
|
103
|
-
{step === "email" && (
|
|
104
|
-
<>
|
|
105
|
-
<h2 className="mb-6 text-center text-2xl font-bold text-gray-900 dark:text-white">
|
|
106
|
-
Setup your {walletBrand}
|
|
107
|
-
</h2>
|
|
108
|
-
<div className="mb-6 space-y-3 text-center text-sm text-gray-600 dark:text-gray-400">
|
|
109
|
-
<p>
|
|
110
|
-
{isTurnkeyPrimary ? "We use a secure," : "AnySpend uses a secure,"}
|
|
111
|
-
<br />
|
|
112
|
-
embedded wallet to fund your workflows.
|
|
113
|
-
</p>
|
|
114
|
-
<p>
|
|
115
|
-
Please provide an email address to secure
|
|
116
|
-
<br />
|
|
117
|
-
your wallet.
|
|
118
|
-
</p>
|
|
119
|
-
</div>
|
|
120
|
-
|
|
121
|
-
<form onSubmit={handleEmailSubmit} className="space-y-4">
|
|
122
|
-
<div>
|
|
123
|
-
<input
|
|
124
|
-
type="email"
|
|
125
|
-
placeholder="email"
|
|
126
|
-
value={email}
|
|
127
|
-
onChange={e => setEmail(e.target.value)}
|
|
128
|
-
required
|
|
129
|
-
disabled={isLoading}
|
|
130
|
-
className="w-full rounded-lg border border-gray-300 px-4 py-3 text-center text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20 disabled:cursor-not-allowed disabled:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
|
|
131
|
-
/>
|
|
132
|
-
</div>
|
|
133
|
-
|
|
134
|
-
{error && (
|
|
135
|
-
<div className="rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400">
|
|
136
|
-
{error}
|
|
137
|
-
</div>
|
|
138
|
-
)}
|
|
139
|
-
|
|
140
|
-
<button
|
|
141
|
-
type="submit"
|
|
142
|
-
disabled={isLoading || !email}
|
|
143
|
-
className="w-full rounded-lg bg-blue-600 px-6 py-3 font-semibold text-white transition-all duration-200 hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-gray-300 dark:disabled:bg-gray-700"
|
|
144
|
-
>
|
|
145
|
-
{isLoading ? (
|
|
146
|
-
<span className="flex items-center justify-center gap-2">
|
|
147
|
-
<div className="h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
|
|
148
|
-
Sending...
|
|
149
|
-
</span>
|
|
150
|
-
) : (
|
|
151
|
-
"Continue"
|
|
152
|
-
)}
|
|
153
|
-
</button>
|
|
154
|
-
</form>
|
|
155
|
-
</>
|
|
156
|
-
)}
|
|
157
|
-
|
|
158
|
-
{/* OTP Step */}
|
|
159
|
-
{step === "otp" && (
|
|
160
|
-
<>
|
|
161
|
-
<h2 className="mb-4 text-center text-2xl font-bold text-gray-900 dark:text-white">2FA Security</h2>
|
|
162
|
-
<div className="mb-6 space-y-3 text-center text-sm text-gray-600 dark:text-gray-400">
|
|
163
|
-
<p>
|
|
164
|
-
{isTurnkeyPrimary ? "We use a secure," : "AnySpend uses a secure,"}
|
|
165
|
-
<br />
|
|
166
|
-
embedded wallet to fund your workflows.
|
|
167
|
-
<br />
|
|
168
|
-
Please provide 2FA code sent to your email.
|
|
169
|
-
</p>
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
<form onSubmit={handleOtpSubmit} className="space-y-4">
|
|
173
|
-
<div>
|
|
174
|
-
<input
|
|
175
|
-
type="text"
|
|
176
|
-
placeholder="Enter code"
|
|
177
|
-
value={otpCode}
|
|
178
|
-
onChange={e => setOtpCode(e.target.value.toUpperCase())}
|
|
179
|
-
required
|
|
180
|
-
disabled={isLoading}
|
|
181
|
-
autoFocus
|
|
182
|
-
className="w-full rounded-lg border border-gray-300 px-4 py-3 text-center font-mono text-lg uppercase tracking-wider text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20 disabled:cursor-not-allowed disabled:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
|
|
183
|
-
maxLength={20}
|
|
184
|
-
/>
|
|
185
|
-
</div>
|
|
186
|
-
|
|
187
|
-
{error && (
|
|
188
|
-
<div className="rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400">
|
|
189
|
-
{error}
|
|
190
|
-
</div>
|
|
191
|
-
)}
|
|
192
|
-
|
|
193
|
-
<div className="flex flex-col gap-2">
|
|
194
|
-
<button
|
|
195
|
-
type="submit"
|
|
196
|
-
disabled={isLoading || !otpCode}
|
|
197
|
-
className="w-full rounded-lg bg-blue-600 px-6 py-3 font-semibold text-white transition-all duration-200 hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-gray-300 dark:disabled:bg-gray-700"
|
|
198
|
-
>
|
|
199
|
-
{isLoading ? (
|
|
200
|
-
<span className="flex items-center justify-center gap-2">
|
|
201
|
-
<div className="h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
|
|
202
|
-
Verifying...
|
|
203
|
-
</span>
|
|
204
|
-
) : (
|
|
205
|
-
"Confirm"
|
|
206
|
-
)}
|
|
207
|
-
</button>
|
|
208
|
-
|
|
209
|
-
<button
|
|
210
|
-
type="button"
|
|
211
|
-
onClick={handleResendOtp}
|
|
212
|
-
disabled={isLoading}
|
|
213
|
-
className="text-sm text-blue-600 hover:text-blue-700 hover:underline disabled:cursor-not-allowed disabled:text-gray-400 dark:text-blue-400 dark:hover:text-blue-300"
|
|
214
|
-
>
|
|
215
|
-
Resend code
|
|
216
|
-
</button>
|
|
217
|
-
</div>
|
|
218
|
-
</form>
|
|
219
|
-
</>
|
|
220
|
-
)}
|
|
221
|
-
|
|
222
|
-
{/* Success Step */}
|
|
223
|
-
{step === "success" && (
|
|
224
|
-
<div className="text-center">
|
|
225
|
-
<div className="mb-6 flex items-center justify-center">
|
|
226
|
-
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-green-100 dark:bg-green-900/20">
|
|
227
|
-
<svg
|
|
228
|
-
className="h-8 w-8 text-green-600 dark:text-green-400"
|
|
229
|
-
fill="none"
|
|
230
|
-
viewBox="0 0 24 24"
|
|
231
|
-
stroke="currentColor"
|
|
232
|
-
>
|
|
233
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
234
|
-
</svg>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
<h2 className="mb-2 text-2xl font-bold text-gray-900 dark:text-white">Successfully Authenticated!</h2>
|
|
238
|
-
<p className="text-sm text-gray-600 dark:text-gray-400">Redirecting...</p>
|
|
239
|
-
</div>
|
|
240
|
-
)}
|
|
241
|
-
</div>
|
|
242
|
-
);
|
|
243
|
-
}
|