@cedros/login-react 0.0.1
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 +21 -0
- package/README.md +1183 -0
- package/dist/EmailRegisterForm-D_uCEdX9.cjs +1 -0
- package/dist/EmailRegisterForm-D_uCEdX9.cjs.map +1 -0
- package/dist/EmailRegisterForm-m3rX3A6X.js +2923 -0
- package/dist/EmailRegisterForm-m3rX3A6X.js.map +1 -0
- package/dist/ErrorMessage-Bm1j5mBT.js +2042 -0
- package/dist/ErrorMessage-Bm1j5mBT.js.map +1 -0
- package/dist/ErrorMessage-CntMyn93.cjs +1 -0
- package/dist/ErrorMessage-CntMyn93.cjs.map +1 -0
- package/dist/GoogleLoginButton-CJNJ-THo.cjs +1 -0
- package/dist/GoogleLoginButton-CJNJ-THo.cjs.map +1 -0
- package/dist/GoogleLoginButton-CvDoOc-0.js +227 -0
- package/dist/GoogleLoginButton-CvDoOc-0.js.map +1 -0
- package/dist/SolanaLoginButton-BlSgPW50.cjs +1 -0
- package/dist/SolanaLoginButton-BlSgPW50.cjs.map +1 -0
- package/dist/SolanaLoginButton-h32xN2PQ.js +261 -0
- package/dist/SolanaLoginButton-h32xN2PQ.js.map +1 -0
- package/dist/assets/argon2Worker-Bi5TuQvD.js +1 -0
- package/dist/assets/argon2Worker-Bi5TuQvD.js.map +1 -0
- package/dist/components/LoginButton.d.ts +23 -0
- package/dist/components/LoginForm.d.ts +9 -0
- package/dist/components/LoginModal.d.ts +9 -0
- package/dist/components/admin/AdminUserDetail.d.ts +21 -0
- package/dist/components/admin/AdminUserList.d.ts +25 -0
- package/dist/components/admin/CedrosAdminDashboard.d.ts +48 -0
- package/dist/components/admin/SystemSettings.d.ts +19 -0
- package/dist/components/apple/AppleLoginButton.d.ts +29 -0
- package/dist/components/deposit/CreditBalance.d.ts +19 -0
- package/dist/components/deposit/DepositFlow.d.ts +118 -0
- package/dist/components/deposit/FeeConfigDisplay.d.ts +15 -0
- package/dist/components/deposit/History.d.ts +21 -0
- package/dist/components/deposit/TieredAmountSlider.d.ts +19 -0
- package/dist/components/deposit/TokenSelector.d.ts +23 -0
- package/dist/components/deposit/admin/AdminDepositList.d.ts +21 -0
- package/dist/components/deposit/admin/AdminDepositStats.d.ts +15 -0
- package/dist/components/deposit/admin/AdminPrivacyPeriodDeposits.d.ts +19 -0
- package/dist/components/deposit/admin/AdminWithdrawalHistory.d.ts +19 -0
- package/dist/components/deposit/admin/AdminWithdrawalQueue.d.ts +23 -0
- package/dist/components/deposit/admin/PrivacySystemStatus.d.ts +15 -0
- package/dist/components/deposit/admin/index.d.ts +17 -0
- package/dist/components/deposit/index.d.ts +12 -0
- package/dist/components/deposit/tierUtils.d.ts +8 -0
- package/dist/components/deposit/tokens.d.ts +19 -0
- package/dist/components/email/EmailLoginForm.d.ts +11 -0
- package/dist/components/email/EmailRegisterForm.d.ts +14 -0
- package/dist/components/email/ForgotPasswordForm.d.ts +17 -0
- package/dist/components/email/PasswordInput.d.ts +14 -0
- package/dist/components/email/ResetPasswordForm.d.ts +22 -0
- package/dist/components/google/GoogleLoginButton.d.ts +12 -0
- package/dist/components/invites/InviteForm.d.ts +38 -0
- package/dist/components/invites/InviteList.d.ts +40 -0
- package/dist/components/members/MemberList.d.ts +47 -0
- package/dist/components/org/CreateOrgForm.d.ts +7 -0
- package/dist/components/org/OrgAvatar.d.ts +7 -0
- package/dist/components/org/OrgListView.d.ts +9 -0
- package/dist/components/org/OrgSelector.d.ts +51 -0
- package/dist/components/org/OrgSwitcher.d.ts +47 -0
- package/dist/components/org/icons.d.ts +8 -0
- package/dist/components/sessions/SessionList.d.ts +33 -0
- package/dist/components/shared/ErrorBoundary.d.ts +38 -0
- package/dist/components/shared/ErrorMessage.d.ts +14 -0
- package/dist/components/shared/LoadingSpinner.d.ts +16 -0
- package/dist/components/solana/SolanaLoginButton.d.ts +49 -0
- package/dist/components/templates/FullPageLayout.d.ts +40 -0
- package/dist/components/templates/SplitPageLayout.d.ts +44 -0
- package/dist/components/templates/index.d.ts +4 -0
- package/dist/components/totp/OtpInput.d.ts +32 -0
- package/dist/components/totp/QrCode.d.ts +21 -0
- package/dist/components/totp/TotpSettings.d.ts +38 -0
- package/dist/components/totp/TotpSetup.d.ts +23 -0
- package/dist/components/totp/TotpVerify.d.ts +25 -0
- package/dist/components/totp/index.d.ts +10 -0
- package/dist/components/wallet/CapabilityWarning.d.ts +11 -0
- package/dist/components/wallet/PasskeyPrompt.d.ts +34 -0
- package/dist/components/wallet/RecoveryPhraseDisplay.d.ts +18 -0
- package/dist/components/wallet/RecoveryPhraseInput.d.ts +21 -0
- package/dist/components/wallet/WalletAddressRow.d.ts +10 -0
- package/dist/components/wallet/WalletEnrollment.d.ts +15 -0
- package/dist/components/wallet/WalletManager.d.ts +9 -0
- package/dist/components/wallet/WalletRecovery.d.ts +19 -0
- package/dist/components/wallet/WalletStatus.d.ts +28 -0
- package/dist/components/wallet/WalletUnlock.d.ts +23 -0
- package/dist/components/wallet/index.d.ts +23 -0
- package/dist/components/webauthn/PasskeyLoginButton.d.ts +8 -0
- package/dist/context/CedrosLoginContext.d.ts +24 -0
- package/dist/context/CedrosLoginProvider.d.ts +17 -0
- package/dist/context/EmbeddedWalletExposure.d.ts +19 -0
- package/dist/context/useCedrosLogin.d.ts +12 -0
- package/dist/crypto/aesGcm.d.ts +89 -0
- package/dist/crypto/argon2.d.ts +65 -0
- package/dist/crypto/argon2Worker.d.ts +1 -0
- package/dist/crypto/argon2WorkerClient.d.ts +28 -0
- package/dist/crypto/bip39.d.ts +106 -0
- package/dist/crypto/capabilities.d.ts +35 -0
- package/dist/crypto/entropy.d.ts +56 -0
- package/dist/crypto/hkdf.d.ts +38 -0
- package/dist/crypto/index.d.ts +30 -0
- package/dist/crypto/secureWipe.d.ts +90 -0
- package/dist/crypto/shamir.d.ts +52 -0
- package/dist/crypto/solanaKeypair.d.ts +63 -0
- package/dist/crypto/types.d.ts +134 -0
- package/dist/crypto/webauthnPrf.d.ts +118 -0
- package/dist/email-only.cjs +1 -0
- package/dist/email-only.cjs.map +1 -0
- package/dist/email-only.d.ts +16 -0
- package/dist/email-only.js +15 -0
- package/dist/email-only.js.map +1 -0
- package/dist/google-only.cjs +1 -0
- package/dist/google-only.cjs.map +1 -0
- package/dist/google-only.d.ts +13 -0
- package/dist/google-only.js +11 -0
- package/dist/google-only.js.map +1 -0
- package/dist/hooks/useAdminDeposits.d.ts +10 -0
- package/dist/hooks/useAdminUsers.d.ts +28 -0
- package/dist/hooks/useAppleAuth.d.ts +52 -0
- package/dist/hooks/useAuth.d.ts +34 -0
- package/dist/hooks/useAuthSession.d.ts +19 -0
- package/dist/hooks/useAuthorize.d.ts +62 -0
- package/dist/hooks/useCredits.d.ts +11 -0
- package/dist/hooks/useDeposit.d.ts +16 -0
- package/dist/hooks/useEmailAuth.d.ts +60 -0
- package/dist/hooks/useGoogleAuth.d.ts +67 -0
- package/dist/hooks/useInstantLink.d.ts +42 -0
- package/dist/hooks/useInvites.d.ts +57 -0
- package/dist/hooks/useMembers.d.ts +52 -0
- package/dist/hooks/useOrgs.d.ts +49 -0
- package/dist/hooks/usePasswordReset.d.ts +32 -0
- package/dist/hooks/usePendingRecovery.d.ts +34 -0
- package/dist/hooks/useRateLimiter.d.ts +58 -0
- package/dist/hooks/useSessions.d.ts +45 -0
- package/dist/hooks/useSolanaAuth.d.ts +30 -0
- package/dist/hooks/useSystemSettings.d.ts +47 -0
- package/dist/hooks/useThemeManager.d.ts +11 -0
- package/dist/hooks/useTotp.d.ts +52 -0
- package/dist/hooks/useTotpVerify.d.ts +38 -0
- package/dist/hooks/useTransactionSigning.d.ts +45 -0
- package/dist/hooks/useWallet.d.ts +10 -0
- package/dist/hooks/useWalletDiscovery.d.ts +24 -0
- package/dist/hooks/useWalletEnrollment.d.ts +9 -0
- package/dist/hooks/useWalletMaterial.d.ts +10 -0
- package/dist/hooks/useWalletRecovery.d.ts +9 -0
- package/dist/hooks/useWalletSigning.d.ts +31 -0
- package/dist/hooks/useWebAuthn.d.ts +25 -0
- package/dist/i18n/I18nProvider.d.ts +16 -0
- package/dist/i18n/context.d.ts +6 -0
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/translations.d.ts +66 -0
- package/dist/i18n/useI18n.d.ts +9 -0
- package/dist/index.cjs +2061 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.js +14910 -0
- package/dist/index.js.map +1 -0
- package/dist/login-react.css +1 -0
- package/dist/solana-only.cjs +1 -0
- package/dist/solana-only.cjs.map +1 -0
- package/dist/solana-only.d.ts +13 -0
- package/dist/solana-only.js +11 -0
- package/dist/solana-only.js.map +1 -0
- package/dist/style.cjs +1 -0
- package/dist/style.cjs.map +1 -0
- package/dist/style.js +1 -0
- package/dist/style.js.map +1 -0
- package/dist/types/adminUser.d.ts +112 -0
- package/dist/types/auth.d.ts +122 -0
- package/dist/types/config.d.ts +266 -0
- package/dist/types/deposit.d.ts +488 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/invite.d.ts +71 -0
- package/dist/types/member.d.ts +45 -0
- package/dist/types/org.d.ts +101 -0
- package/dist/types/session.d.ts +28 -0
- package/dist/types/systemSettings.d.ts +81 -0
- package/dist/types/totp.d.ts +52 -0
- package/dist/types/wallet.d.ts +309 -0
- package/dist/utils/adminUserApi.d.ts +51 -0
- package/dist/utils/apiClient.d.ts +78 -0
- package/dist/utils/cryptoShim.d.ts +17 -0
- package/dist/utils/csrf.d.ts +1 -0
- package/dist/utils/deviceDetection.d.ts +17 -0
- package/dist/utils/embeddedWallet.d.ts +75 -0
- package/dist/utils/inviteApi.d.ts +31 -0
- package/dist/utils/memberApi.d.ts +23 -0
- package/dist/utils/orgApi.d.ts +36 -0
- package/dist/utils/sanitization.d.ts +66 -0
- package/dist/utils/sessionApi.d.ts +16 -0
- package/dist/utils/silentWalletEnroll.d.ts +41 -0
- package/dist/utils/systemSettingsApi.d.ts +18 -0
- package/dist/utils/tabSync.d.ts +46 -0
- package/dist/utils/tokenManager.d.ts +107 -0
- package/dist/utils/unlockCredential.d.ts +5 -0
- package/dist/utils/validation.d.ts +48 -0
- package/dist/utils/walletDetection.d.ts +23 -0
- package/dist/utils/webauthnJson.d.ts +21 -0
- package/dist/validation-BeXIfuHB.cjs +1 -0
- package/dist/validation-BeXIfuHB.cjs.map +1 -0
- package/dist/validation-BebL7hMF.js +56 -0
- package/dist/validation-BebL7hMF.js.map +1 -0
- package/package.json +109 -0
package/README.md
ADDED
|
@@ -0,0 +1,1183 @@
|
|
|
1
|
+
# @cedros/login-react
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@cedros/login-react)
|
|
4
|
+
[](https://www.npmjs.com/package/@cedros/login-react)
|
|
5
|
+
[](https://github.com/conorholds/cedros-login/blob/main/ui/LICENSE)
|
|
6
|
+
|
|
7
|
+
> **Warning: Development Preview**
|
|
8
|
+
>
|
|
9
|
+
> This package is in early development (v0.0.x) and is **not ready for production use**. APIs may change without notice. Use at your own risk.
|
|
10
|
+
|
|
11
|
+
React component library for authentication with email/password, Google OAuth, Apple Sign In, Solana wallet, instant links, and multi-tenancy support.
|
|
12
|
+
Supports embedded Solana wallets through SSS and private deposits and account credits through Privacy Cash.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @cedros/login-react
|
|
18
|
+
# or
|
|
19
|
+
yarn add @cedros/login-react
|
|
20
|
+
# or
|
|
21
|
+
pnpm add @cedros/login-react
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Optional: Solana Wallet Support
|
|
25
|
+
|
|
26
|
+
For Solana wallet authentication, install the wallet adapter packages:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @solana/wallet-adapter-base @solana/wallet-adapter-react @solana/wallet-adapter-react-ui @solana/wallet-adapter-wallets @solana/web3.js
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { CedrosLoginProvider, LoginButton, useCedrosLogin } from '@cedros/login-react';
|
|
36
|
+
import '@cedros/login-react/style.css';
|
|
37
|
+
|
|
38
|
+
function App() {
|
|
39
|
+
return (
|
|
40
|
+
<CedrosLoginProvider
|
|
41
|
+
config={{
|
|
42
|
+
serverUrl: 'http://localhost:8080',
|
|
43
|
+
features: {
|
|
44
|
+
email: true,
|
|
45
|
+
google: true,
|
|
46
|
+
apple: true,
|
|
47
|
+
solana: true,
|
|
48
|
+
},
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
<AuthStatus />
|
|
52
|
+
</CedrosLoginProvider>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function AuthStatus() {
|
|
57
|
+
const { user, isAuthenticated, logout } = useCedrosLogin();
|
|
58
|
+
|
|
59
|
+
if (!isAuthenticated) {
|
|
60
|
+
return <LoginButton />;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div>
|
|
65
|
+
<p>Welcome, {user?.name || user?.email}</p>
|
|
66
|
+
<button onClick={logout}>Logout</button>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Features
|
|
73
|
+
|
|
74
|
+
- **Multiple Auth Methods**: Email/password, Google OAuth, Apple Sign In, Solana wallet, instant links, WebAuthn/Passkeys
|
|
75
|
+
- **WebAuthn/Passkeys**: Passwordless login with TouchID, FaceID, Windows Hello, or security keys
|
|
76
|
+
- **Username-less Login**: Discoverable credentials allow login without entering email first
|
|
77
|
+
- **Multi-Tenancy**: Organization management, member invites, role-based access
|
|
78
|
+
- **Session Management**: View and revoke active sessions
|
|
79
|
+
- **Credential Management**: View and manage all authentication methods
|
|
80
|
+
- **MFA Support**: TOTP two-factor authentication with QR setup, recovery codes, and verification
|
|
81
|
+
- **i18n Ready**: Built-in translations with customization support
|
|
82
|
+
- **Theming**: Light/dark mode with CSS variable customization
|
|
83
|
+
- **TypeScript**: Full type definitions included
|
|
84
|
+
- **Tree-Shakeable**: Import only what you need
|
|
85
|
+
|
|
86
|
+
## Components
|
|
87
|
+
|
|
88
|
+
### Authentication
|
|
89
|
+
|
|
90
|
+
| Component | Description |
|
|
91
|
+
|-----------|-------------|
|
|
92
|
+
| `LoginButton` | Button that opens the login modal |
|
|
93
|
+
| `LoginModal` | Full authentication modal with all methods |
|
|
94
|
+
| `LoginForm` | Standalone login form |
|
|
95
|
+
| `EmailLoginForm` | Email/password login form |
|
|
96
|
+
| `EmailRegisterForm` | Registration form with password validation |
|
|
97
|
+
| `GoogleLoginButton` | Google sign-in button |
|
|
98
|
+
| `AppleLoginButton` | Apple Sign In button |
|
|
99
|
+
| `SolanaLoginButton` | Solana wallet connect button |
|
|
100
|
+
| `PasswordInput` | Password field with visibility toggle and strength meter |
|
|
101
|
+
| `ForgotPasswordForm` | Password reset request form |
|
|
102
|
+
| `ResetPasswordForm` | Password reset form with token |
|
|
103
|
+
| `PasskeyPrompt` | WebAuthn passkey registration/authentication prompt |
|
|
104
|
+
|
|
105
|
+
### WebAuthn / Passkeys
|
|
106
|
+
|
|
107
|
+
| Component | Description |
|
|
108
|
+
|-----------|-------------|
|
|
109
|
+
| `PasskeyPrompt` | Modal for passkey registration or authentication |
|
|
110
|
+
| `PasskeyList` | List registered passkeys with management options |
|
|
111
|
+
|
|
112
|
+
### Embedded Wallet (Server-Side Signing)
|
|
113
|
+
|
|
114
|
+
| Component | Description |
|
|
115
|
+
|-----------|-------------|
|
|
116
|
+
| `WalletEnrollment` | Full enrollment flow with auth method selection |
|
|
117
|
+
| `WalletStatus` | Shows wallet state (not enrolled/locked/unlocked) |
|
|
118
|
+
| `WalletAddressRow` | Wallet address display with copy + explorer link |
|
|
119
|
+
| `WalletUnlock` | Unlock prompt for session-based signing |
|
|
120
|
+
| `WalletManager` | Orchestrates status/enroll/unlock/recover in one flow |
|
|
121
|
+
| `RecoveryPhraseDisplay` | Shows 24-word phrase with copy/confirm |
|
|
122
|
+
| `RecoveryPhraseInput` | Input for recovery phrase entry |
|
|
123
|
+
| `CapabilityWarning` | Browser capability check (WebCrypto, etc.) |
|
|
124
|
+
|
|
125
|
+
### Organizations
|
|
126
|
+
|
|
127
|
+
| Component | Description |
|
|
128
|
+
|-----------|-------------|
|
|
129
|
+
| `OrgSelector` | Dropdown to select active organization |
|
|
130
|
+
| `OrgSwitcher` | Modal to switch organizations or create new ones |
|
|
131
|
+
|
|
132
|
+
### Members & Invites
|
|
133
|
+
|
|
134
|
+
| Component | Description |
|
|
135
|
+
|-----------|-------------|
|
|
136
|
+
| `MemberList` | List org members with role management |
|
|
137
|
+
| `InviteForm` | Form to invite new members by email |
|
|
138
|
+
| `InviteList` | List and manage pending invites |
|
|
139
|
+
|
|
140
|
+
### Sessions
|
|
141
|
+
|
|
142
|
+
| Component | Description |
|
|
143
|
+
|-----------|-------------|
|
|
144
|
+
| `SessionList` | List active sessions with revoke option |
|
|
145
|
+
|
|
146
|
+
### Two-Factor Authentication (TOTP)
|
|
147
|
+
|
|
148
|
+
| Component | Description |
|
|
149
|
+
|-----------|-------------|
|
|
150
|
+
| `TotpSettings` | Settings panel to enable/disable 2FA, regenerate recovery codes |
|
|
151
|
+
| `TotpSetup` | Step-by-step wizard for setting up TOTP |
|
|
152
|
+
| `TotpVerify` | Verification prompt during login |
|
|
153
|
+
| `OtpInput` | 6-digit code input component |
|
|
154
|
+
|
|
155
|
+
### Privacy Cash (Deposits & Credits)
|
|
156
|
+
|
|
157
|
+
| Component | Description |
|
|
158
|
+
|-----------|-------------|
|
|
159
|
+
| `DepositForm` | Create new privacy deposits (amount input, wallet signing) |
|
|
160
|
+
| `CreditBalance` | Display current SOL credit balance |
|
|
161
|
+
| `CreditHistory` | Transaction history (deposits, spends) with pagination |
|
|
162
|
+
| `DepositStatus` | Single deposit status card with progress indicator |
|
|
163
|
+
| `DepositList` | User's deposit history with status filtering |
|
|
164
|
+
|
|
165
|
+
### Privacy Cash Admin (System Admin Only)
|
|
166
|
+
|
|
167
|
+
| Component | Description |
|
|
168
|
+
|-----------|-------------|
|
|
169
|
+
| `AdminDepositStats` | Aggregate statistics (totals, pending, withdrawn, failed) |
|
|
170
|
+
| `AdminDepositList` | All deposits across users with status filtering |
|
|
171
|
+
| `AdminWithdrawalQueue` | Deposits ready for withdrawal processing |
|
|
172
|
+
| `PrivacyCashAdminPanel` | Combined tabbed admin interface |
|
|
173
|
+
|
|
174
|
+
### Credentials
|
|
175
|
+
|
|
176
|
+
| Component | Description |
|
|
177
|
+
|-----------|-------------|
|
|
178
|
+
| `CredentialList` | List all authentication methods (passwords, passkeys, OAuth) |
|
|
179
|
+
| `CredentialCard` | Individual credential display with management options |
|
|
180
|
+
|
|
181
|
+
### Admin
|
|
182
|
+
|
|
183
|
+
| Component | Description |
|
|
184
|
+
|-----------|-------------|
|
|
185
|
+
| `AdminPanel` | Admin dashboard with tabs for members, invites, sessions, system settings |
|
|
186
|
+
| `SystemSettings` | System settings editor (privacy, withdrawal, rate limits) - system admin only |
|
|
187
|
+
|
|
188
|
+
### Shared
|
|
189
|
+
|
|
190
|
+
| Component | Description |
|
|
191
|
+
|-----------|-------------|
|
|
192
|
+
| `LoadingSpinner` | Loading indicator |
|
|
193
|
+
| `ErrorMessage` | Error display component |
|
|
194
|
+
|
|
195
|
+
### LoginButton Customization
|
|
196
|
+
|
|
197
|
+
The `LoginButton` component shows a "Sign in" button when logged out, and a user menu with dropdown when authenticated. You can customize the dropdown menu items:
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
import { LoginButton, LoginModal } from '@cedros/login-react';
|
|
201
|
+
|
|
202
|
+
function Navbar() {
|
|
203
|
+
return (
|
|
204
|
+
<nav>
|
|
205
|
+
<LoginButton
|
|
206
|
+
menuItems={[
|
|
207
|
+
{
|
|
208
|
+
label: 'Account settings',
|
|
209
|
+
onClick: () => navigate('/settings'),
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
label: 'Billing',
|
|
213
|
+
onClick: () => navigate('/billing'),
|
|
214
|
+
},
|
|
215
|
+
]}
|
|
216
|
+
/>
|
|
217
|
+
<LoginModal />
|
|
218
|
+
</nav>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Props:**
|
|
224
|
+
|
|
225
|
+
| Prop | Type | Default | Description |
|
|
226
|
+
|------|------|---------|-------------|
|
|
227
|
+
| `variant` | `'default' \| 'outline' \| 'ghost'` | `'default'` | Button style variant |
|
|
228
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
|
|
229
|
+
| `menuItems` | `MenuItemConfig[]` | `[]` | Custom menu items above "Sign out" |
|
|
230
|
+
| `hideSignOut` | `boolean` | `false` | Hide the default "Sign out" item |
|
|
231
|
+
| `className` | `string` | `''` | Additional CSS classes |
|
|
232
|
+
| `children` | `ReactNode` | `'Sign in'` | Custom button text (logged out state) |
|
|
233
|
+
|
|
234
|
+
**MenuItemConfig:**
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
interface MenuItemConfig {
|
|
238
|
+
label: string; // Display text
|
|
239
|
+
onClick: () => void; // Click handler
|
|
240
|
+
icon?: ReactNode; // Optional icon element
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Dark navbar styling:**
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
// Use the built-in dark navbar class
|
|
248
|
+
<LoginButton className="cedros-button-dark-navbar" />
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Hooks
|
|
252
|
+
|
|
253
|
+
### Authentication
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
// Main authentication hook
|
|
257
|
+
const {
|
|
258
|
+
user, // Current user or null
|
|
259
|
+
isAuthenticated, // Boolean auth status
|
|
260
|
+
isLoading, // Loading state
|
|
261
|
+
login, // Login function
|
|
262
|
+
register, // Registration function
|
|
263
|
+
logout, // Logout function
|
|
264
|
+
refreshToken, // Refresh access token
|
|
265
|
+
} = useCedrosLogin();
|
|
266
|
+
|
|
267
|
+
// Email-specific auth
|
|
268
|
+
const {
|
|
269
|
+
login,
|
|
270
|
+
register,
|
|
271
|
+
isLoading,
|
|
272
|
+
error,
|
|
273
|
+
} = useEmailAuth();
|
|
274
|
+
|
|
275
|
+
// Google OAuth
|
|
276
|
+
const {
|
|
277
|
+
login,
|
|
278
|
+
isLoading,
|
|
279
|
+
error,
|
|
280
|
+
} = useGoogleAuth();
|
|
281
|
+
|
|
282
|
+
// Solana wallet
|
|
283
|
+
const {
|
|
284
|
+
login,
|
|
285
|
+
challenge,
|
|
286
|
+
isLoading,
|
|
287
|
+
error,
|
|
288
|
+
} = useSolanaAuth();
|
|
289
|
+
|
|
290
|
+
// Apple Sign In
|
|
291
|
+
const {
|
|
292
|
+
login,
|
|
293
|
+
isLoading,
|
|
294
|
+
error,
|
|
295
|
+
} = useAppleAuth();
|
|
296
|
+
|
|
297
|
+
// WebAuthn / Passkeys
|
|
298
|
+
const {
|
|
299
|
+
registerPasskey, // Start passkey registration
|
|
300
|
+
authenticatePasskey, // Start passkey authentication
|
|
301
|
+
isSupported, // Browser supports WebAuthn
|
|
302
|
+
isLoading,
|
|
303
|
+
error,
|
|
304
|
+
} = useWebAuthn();
|
|
305
|
+
|
|
306
|
+
// Password reset
|
|
307
|
+
const {
|
|
308
|
+
requestReset, // Send password reset email
|
|
309
|
+
resetPassword, // Reset with token
|
|
310
|
+
isLoading,
|
|
311
|
+
error,
|
|
312
|
+
} = usePasswordReset();
|
|
313
|
+
|
|
314
|
+
// TOTP / Two-Factor Authentication
|
|
315
|
+
const {
|
|
316
|
+
status, // { enabled: boolean, recoveryCodesRemaining: number } or null
|
|
317
|
+
isLoading,
|
|
318
|
+
error,
|
|
319
|
+
getStatus, // Fetch current 2FA status
|
|
320
|
+
beginSetup, // Initiate setup (returns otpauthUri + secret + recovery codes)
|
|
321
|
+
enableTotp, // Enable with verification code
|
|
322
|
+
disableTotp, // Disable with password confirmation
|
|
323
|
+
regenerateBackupCodes, // Get new recovery codes (requires TOTP code)
|
|
324
|
+
clearError,
|
|
325
|
+
} = useTotp();
|
|
326
|
+
|
|
327
|
+
// TOTP Verification (during login)
|
|
328
|
+
const {
|
|
329
|
+
verifyTotp, // Complete login MFA (submit TOTP code or recovery code)
|
|
330
|
+
isLoading,
|
|
331
|
+
error,
|
|
332
|
+
} = useTotpVerify();
|
|
333
|
+
|
|
334
|
+
// Wallet status and capabilities
|
|
335
|
+
const {
|
|
336
|
+
status, // 'not_enrolled' | 'enrolled_locked' | 'enrolled_unlocked'
|
|
337
|
+
solanaPubkey, // Base58 public key (if enrolled)
|
|
338
|
+
authMethod, // 'password' | 'passkey'
|
|
339
|
+
hasExternalWallet, // User logged in with Solana wallet (not SSS)
|
|
340
|
+
isUnlocked, // Whether SSS wallet is unlocked
|
|
341
|
+
capabilities, // Browser capability check
|
|
342
|
+
refresh, // Refresh wallet status
|
|
343
|
+
error,
|
|
344
|
+
} = useWallet();
|
|
345
|
+
|
|
346
|
+
// Wallet enrollment
|
|
347
|
+
const {
|
|
348
|
+
startEnrollment, // Begin enrollment flow
|
|
349
|
+
completeEnrollment, // Finish with shares
|
|
350
|
+
isLoading,
|
|
351
|
+
error,
|
|
352
|
+
} = useWalletEnrollment();
|
|
353
|
+
|
|
354
|
+
// Wallet material API (low-level operations)
|
|
355
|
+
const {
|
|
356
|
+
getMaterial, // Get wallet material
|
|
357
|
+
getStatus, // Get wallet status
|
|
358
|
+
enroll, // Enroll new wallet
|
|
359
|
+
signTransaction, // Sign transaction
|
|
360
|
+
unlock, // Unlock for session-based signing (returns { unlocked, ttlSeconds })
|
|
361
|
+
lock, // Lock wallet (clear cached key)
|
|
362
|
+
rotateUserSecret, // Re-encrypt Share A with new credential
|
|
363
|
+
isLoading,
|
|
364
|
+
error,
|
|
365
|
+
} = useWalletMaterial();
|
|
366
|
+
|
|
367
|
+
// Wallet signing (high-level)
|
|
368
|
+
const {
|
|
369
|
+
signTransaction, // Sign transaction (prompts for credential if needed)
|
|
370
|
+
isSigning,
|
|
371
|
+
error,
|
|
372
|
+
} = useWalletSigning();
|
|
373
|
+
|
|
374
|
+
// Unified transaction signing (routes to external or SSS wallet)
|
|
375
|
+
const {
|
|
376
|
+
signTransaction, // Auto-routes to correct wallet type
|
|
377
|
+
signingMethod, // 'external' | 'sss' | 'none'
|
|
378
|
+
canSign, // Whether user can sign transactions
|
|
379
|
+
publicKey, // Solana public key
|
|
380
|
+
hasExternalWallet,
|
|
381
|
+
hasSssWallet,
|
|
382
|
+
isSssUnlocked,
|
|
383
|
+
isSigning,
|
|
384
|
+
error,
|
|
385
|
+
} = useTransactionSigning({
|
|
386
|
+
// For external wallet users, provide adapter callback
|
|
387
|
+
onExternalSign: (tx) => walletAdapter.signTransaction(tx),
|
|
388
|
+
});
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Organizations
|
|
392
|
+
|
|
393
|
+
```tsx
|
|
394
|
+
const {
|
|
395
|
+
orgs, // List of user's organizations
|
|
396
|
+
activeOrg, // Currently selected organization
|
|
397
|
+
isLoading,
|
|
398
|
+
error,
|
|
399
|
+
createOrg, // Create new organization
|
|
400
|
+
updateOrg, // Update organization details
|
|
401
|
+
deleteOrg, // Delete organization
|
|
402
|
+
switchOrg, // Switch active organization
|
|
403
|
+
refetch, // Refresh org list
|
|
404
|
+
} = useOrgs();
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Members
|
|
408
|
+
|
|
409
|
+
```tsx
|
|
410
|
+
const {
|
|
411
|
+
members, // List of organization members
|
|
412
|
+
isLoading,
|
|
413
|
+
error,
|
|
414
|
+
updateRole, // Change member's role
|
|
415
|
+
removeMember, // Remove member from org
|
|
416
|
+
refetch,
|
|
417
|
+
} = useMembers(orgId);
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Invites
|
|
421
|
+
|
|
422
|
+
```tsx
|
|
423
|
+
const {
|
|
424
|
+
invites, // List of pending invites
|
|
425
|
+
isLoading,
|
|
426
|
+
error,
|
|
427
|
+
createInvite, // Send new invite
|
|
428
|
+
cancelInvite, // Cancel pending invite
|
|
429
|
+
resendInvite, // Resend invite email
|
|
430
|
+
acceptInvite, // Accept invite (by invitee)
|
|
431
|
+
refetch,
|
|
432
|
+
} = useInvites(orgId);
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Sessions
|
|
436
|
+
|
|
437
|
+
```tsx
|
|
438
|
+
const {
|
|
439
|
+
sessions, // List of active sessions
|
|
440
|
+
isLoading,
|
|
441
|
+
error,
|
|
442
|
+
revokeAll, // Revoke all sessions (logout everywhere)
|
|
443
|
+
refetch,
|
|
444
|
+
} = useSessions();
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Privacy Cash (Deposits & Credits)
|
|
448
|
+
|
|
449
|
+
```tsx
|
|
450
|
+
// User deposit operations
|
|
451
|
+
const {
|
|
452
|
+
deposit, // Execute a deposit (returns DepositResponse)
|
|
453
|
+
getStatus, // Get deposit status by session ID
|
|
454
|
+
getConfig, // Get deposit configuration (min amount, etc.)
|
|
455
|
+
listDeposits, // List user's deposits with pagination
|
|
456
|
+
isLoading,
|
|
457
|
+
error,
|
|
458
|
+
clearError,
|
|
459
|
+
} = useDeposit();
|
|
460
|
+
|
|
461
|
+
// User credit operations
|
|
462
|
+
const {
|
|
463
|
+
getBalance, // Get SOL credit balance
|
|
464
|
+
getAllBalances, // Get all currency balances
|
|
465
|
+
getHistory, // Get transaction history with pagination
|
|
466
|
+
isLoading,
|
|
467
|
+
error,
|
|
468
|
+
clearError,
|
|
469
|
+
} = useCredits();
|
|
470
|
+
|
|
471
|
+
// Admin operations (requires system admin privileges)
|
|
472
|
+
const {
|
|
473
|
+
listDeposits, // List all deposits across users
|
|
474
|
+
getStats, // Get aggregate statistics
|
|
475
|
+
listPendingWithdrawals, // List deposits ready for withdrawal
|
|
476
|
+
processWithdrawal, // Process single withdrawal (with optional force for early)
|
|
477
|
+
processAllWithdrawals, // Process all ready withdrawals
|
|
478
|
+
isLoading,
|
|
479
|
+
error,
|
|
480
|
+
clearError,
|
|
481
|
+
} = useAdminDeposits();
|
|
482
|
+
|
|
483
|
+
// System settings (requires system admin privileges)
|
|
484
|
+
const {
|
|
485
|
+
settings, // Settings grouped by category { privacy: [...], withdrawal: [...], rate_limit: [...] }
|
|
486
|
+
isLoading,
|
|
487
|
+
isUpdating,
|
|
488
|
+
error,
|
|
489
|
+
fetchSettings, // Refresh settings from server
|
|
490
|
+
updateSettings, // Update multiple settings: [{ key, value }, ...]
|
|
491
|
+
getValue, // Get single setting value by key
|
|
492
|
+
} = useSystemSettings();
|
|
493
|
+
|
|
494
|
+
// Process a single withdrawal
|
|
495
|
+
const result = await processWithdrawal(sessionId, { force: false });
|
|
496
|
+
// result: { success, sessionId, txSignature?, error?, earlyWithdrawal }
|
|
497
|
+
|
|
498
|
+
// Force early withdrawal (before privacy period - shows warning in UI)
|
|
499
|
+
const result = await processWithdrawal(sessionId, { force: true });
|
|
500
|
+
|
|
501
|
+
// Process all ready withdrawals (past privacy period only)
|
|
502
|
+
const batchResult = await processAllWithdrawals();
|
|
503
|
+
// batchResult: { totalProcessed, totalSucceeded, totalFailed, results }
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Credentials
|
|
507
|
+
|
|
508
|
+
```tsx
|
|
509
|
+
const {
|
|
510
|
+
credentials, // List of all auth methods (password, passkeys, OAuth)
|
|
511
|
+
isLoading,
|
|
512
|
+
error,
|
|
513
|
+
updateCredential, // Update credential label
|
|
514
|
+
unlinkCredential, // Remove credential (if not last one)
|
|
515
|
+
refetch,
|
|
516
|
+
} = useCredentials();
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Authorization
|
|
520
|
+
|
|
521
|
+
```tsx
|
|
522
|
+
const {
|
|
523
|
+
checkPermission, // Check if action is allowed
|
|
524
|
+
isLoading,
|
|
525
|
+
error,
|
|
526
|
+
} = useAuthorize();
|
|
527
|
+
|
|
528
|
+
// Usage
|
|
529
|
+
const canInvite = await checkPermission({
|
|
530
|
+
orgId: 'org-123',
|
|
531
|
+
action: 'member:invite',
|
|
532
|
+
resourceType: 'member',
|
|
533
|
+
});
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
## Configuration
|
|
537
|
+
|
|
538
|
+
### Apple Sign In (Web)
|
|
539
|
+
|
|
540
|
+
This library uses Apple's JS SDK in popup mode and initializes it with:
|
|
541
|
+
|
|
542
|
+
- `redirectURI: window.location.origin`
|
|
543
|
+
|
|
544
|
+
To avoid popup flows hanging or failing to return an `id_token`, configure your Apple Services ID
|
|
545
|
+
with a Return URL that exactly matches your site's origin.
|
|
546
|
+
|
|
547
|
+
Example:
|
|
548
|
+
|
|
549
|
+
- If your login page is served from `https://login.example.com/...`, set a Return URL of
|
|
550
|
+
`https://login.example.com`.
|
|
551
|
+
|
|
552
|
+
Note: Apple Sign In generally requires HTTPS and a verified domain.
|
|
553
|
+
|
|
554
|
+
### WebAuthn / Passkeys (Server-managed)
|
|
555
|
+
|
|
556
|
+
This library supports **server-managed passkeys** (WebAuthn) for authentication via:
|
|
557
|
+
|
|
558
|
+
- `POST /webauthn/auth/options` -> `navigator.credentials.get(...)` -> `POST /webauthn/auth/verify`
|
|
559
|
+
- `POST /webauthn/register/options` -> `navigator.credentials.create(...)` -> `POST /webauthn/register/verify`
|
|
560
|
+
|
|
561
|
+
Server requirements:
|
|
562
|
+
|
|
563
|
+
- `WEBAUTHN_ENABLED=true`
|
|
564
|
+
- `WEBAUTHN_RP_ID=<domain>` (e.g. `login.example.com` or `example.com`)
|
|
565
|
+
- `WEBAUTHN_RP_ORIGIN=<origin>` (e.g. `https://login.example.com`)
|
|
566
|
+
|
|
567
|
+
Browser requirements:
|
|
568
|
+
|
|
569
|
+
- HTTPS (secure context)
|
|
570
|
+
|
|
571
|
+
The `LoginForm` includes a "Continue with Passkey" button by default. Disable it with:
|
|
572
|
+
|
|
573
|
+
```ts
|
|
574
|
+
features: { webauthn: false }
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
```tsx
|
|
578
|
+
<CedrosLoginProvider
|
|
579
|
+
config={{
|
|
580
|
+
// Required
|
|
581
|
+
serverUrl: 'http://localhost:8080',
|
|
582
|
+
|
|
583
|
+
// Feature flags
|
|
584
|
+
features: {
|
|
585
|
+
email: true, // Email/password auth
|
|
586
|
+
google: true, // Google OAuth
|
|
587
|
+
solana: false, // Solana wallet
|
|
588
|
+
},
|
|
589
|
+
|
|
590
|
+
// Google OAuth
|
|
591
|
+
googleClientId: 'your-google-client-id',
|
|
592
|
+
|
|
593
|
+
// Apple Sign In (Services ID)
|
|
594
|
+
appleClientId: 'com.your.app.service',
|
|
595
|
+
|
|
596
|
+
// Solana wallet
|
|
597
|
+
solana: {
|
|
598
|
+
network: 'mainnet-beta', // 'mainnet-beta' | 'devnet' | 'testnet'
|
|
599
|
+
},
|
|
600
|
+
|
|
601
|
+
// Session storage
|
|
602
|
+
session: {
|
|
603
|
+
// Recommended: cookie storage (tokens in httpOnly cookies)
|
|
604
|
+
storage: 'cookie', // 'cookie' | 'localStorage' | 'sessionStorage' | 'memory'
|
|
605
|
+
|
|
606
|
+
// If you must use web storage (XSS-vulnerable), you must explicitly opt in:
|
|
607
|
+
// storage: 'localStorage',
|
|
608
|
+
// allowWebStorage: true,
|
|
609
|
+
persistKey: 'cedros_auth',
|
|
610
|
+
},
|
|
611
|
+
|
|
612
|
+
// Two-factor authentication
|
|
613
|
+
totp: {
|
|
614
|
+
enabled: true, // Show 2FA options
|
|
615
|
+
required: false, // Require all users to enable 2FA
|
|
616
|
+
issuer: 'MyApp', // Name shown in authenticator apps
|
|
617
|
+
},
|
|
618
|
+
|
|
619
|
+
// Embedded wallet (server-side signing)
|
|
620
|
+
wallet: {
|
|
621
|
+
exposeAvailability: true, // Expose via window global for cedros-pay
|
|
622
|
+
// Server config: WALLET_ENABLED, WALLET_RECOVERY_MODE, WALLET_UNLOCK_TTL
|
|
623
|
+
},
|
|
624
|
+
|
|
625
|
+
// Theming
|
|
626
|
+
theme: 'auto', // 'light' | 'dark' | 'auto'
|
|
627
|
+
themeOverrides: {
|
|
628
|
+
'--cedros-primary': '#6366f1',
|
|
629
|
+
'--cedros-destructive': '#ef4444',
|
|
630
|
+
},
|
|
631
|
+
|
|
632
|
+
// Callbacks
|
|
633
|
+
callbacks: {
|
|
634
|
+
onLoginSuccess: (user) => console.log('User logged in:', user),
|
|
635
|
+
onLogout: () => console.log('User logged out'),
|
|
636
|
+
onLoginError: (error) => console.error('Auth error:', error),
|
|
637
|
+
},
|
|
638
|
+
}}
|
|
639
|
+
>
|
|
640
|
+
{children}
|
|
641
|
+
</CedrosLoginProvider>
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
## Bundle Optimization
|
|
645
|
+
|
|
646
|
+
Import only the auth methods you need to reduce bundle size:
|
|
647
|
+
|
|
648
|
+
```tsx
|
|
649
|
+
// Email only (smallest bundle)
|
|
650
|
+
import { EmailLoginForm, useEmailAuth } from '@cedros/login-react/email-only';
|
|
651
|
+
|
|
652
|
+
// Google only
|
|
653
|
+
import { GoogleLoginButton, useGoogleAuth } from '@cedros/login-react/google-only';
|
|
654
|
+
|
|
655
|
+
// Solana only
|
|
656
|
+
import { SolanaLoginButton, useSolanaAuth } from '@cedros/login-react/solana-only';
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
## Styling
|
|
660
|
+
|
|
661
|
+
### Using Default Styles
|
|
662
|
+
|
|
663
|
+
```tsx
|
|
664
|
+
import '@cedros/login-react/style.css';
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
### CSS Variables
|
|
668
|
+
|
|
669
|
+
Customize the theme using CSS variables:
|
|
670
|
+
|
|
671
|
+
```css
|
|
672
|
+
:root {
|
|
673
|
+
/* Colors */
|
|
674
|
+
--cedros-primary: #6366f1;
|
|
675
|
+
--cedros-primary-hover: #4f46e5;
|
|
676
|
+
--cedros-error: #ef4444;
|
|
677
|
+
--cedros-success: #22c55e;
|
|
678
|
+
--cedros-text: #1f2937;
|
|
679
|
+
--cedros-text-muted: #6b7280;
|
|
680
|
+
--cedros-bg: #ffffff;
|
|
681
|
+
--cedros-bg-muted: #f3f4f6;
|
|
682
|
+
--cedros-border: #e5e7eb;
|
|
683
|
+
|
|
684
|
+
/* Typography */
|
|
685
|
+
--cedros-font-family: system-ui, sans-serif;
|
|
686
|
+
--cedros-font-size-sm: 0.875rem;
|
|
687
|
+
--cedros-font-size-base: 1rem;
|
|
688
|
+
--cedros-font-size-lg: 1.125rem;
|
|
689
|
+
|
|
690
|
+
/* Spacing */
|
|
691
|
+
--cedros-radius: 0.5rem;
|
|
692
|
+
--cedros-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/* Dark mode */
|
|
696
|
+
[data-theme='dark'] {
|
|
697
|
+
--cedros-text: #f9fafb;
|
|
698
|
+
--cedros-text-muted: #9ca3af;
|
|
699
|
+
--cedros-bg: #1f2937;
|
|
700
|
+
--cedros-bg-muted: #374151;
|
|
701
|
+
--cedros-border: #4b5563;
|
|
702
|
+
}
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
## Internationalization
|
|
706
|
+
|
|
707
|
+
### Using Built-in Translations
|
|
708
|
+
|
|
709
|
+
```tsx
|
|
710
|
+
import { I18nProvider, CedrosLoginProvider } from '@cedros/login-react';
|
|
711
|
+
|
|
712
|
+
<I18nProvider locale="en">
|
|
713
|
+
<CedrosLoginProvider config={config}>
|
|
714
|
+
{children}
|
|
715
|
+
</CedrosLoginProvider>
|
|
716
|
+
</I18nProvider>
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
### Custom Translations
|
|
720
|
+
|
|
721
|
+
```tsx
|
|
722
|
+
import { I18nProvider, mergeTranslations, defaultTranslations } from '@cedros/login-react';
|
|
723
|
+
|
|
724
|
+
const customTranslations = mergeTranslations(defaultTranslations, {
|
|
725
|
+
en: {
|
|
726
|
+
login: {
|
|
727
|
+
title: 'Welcome Back',
|
|
728
|
+
submit: 'Sign In',
|
|
729
|
+
},
|
|
730
|
+
},
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
<I18nProvider translations={customTranslations} locale="en">
|
|
734
|
+
{children}
|
|
735
|
+
</I18nProvider>
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### Using Translations in Components
|
|
739
|
+
|
|
740
|
+
```tsx
|
|
741
|
+
import { useTranslations, useLocale } from '@cedros/login-react';
|
|
742
|
+
|
|
743
|
+
function MyComponent() {
|
|
744
|
+
const t = useTranslations();
|
|
745
|
+
const { locale, setLocale } = useLocale();
|
|
746
|
+
|
|
747
|
+
return (
|
|
748
|
+
<div>
|
|
749
|
+
<h1>{t.login.title}</h1>
|
|
750
|
+
<button onClick={() => setLocale('es')}>
|
|
751
|
+
Switch to Spanish
|
|
752
|
+
</button>
|
|
753
|
+
</div>
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
## Examples
|
|
759
|
+
|
|
760
|
+
### Basic Login Page
|
|
761
|
+
|
|
762
|
+
```tsx
|
|
763
|
+
import { CedrosLoginProvider, LoginForm } from '@cedros/login-react';
|
|
764
|
+
import '@cedros/login-react/style.css';
|
|
765
|
+
|
|
766
|
+
export function LoginPage() {
|
|
767
|
+
return (
|
|
768
|
+
<CedrosLoginProvider
|
|
769
|
+
config={{
|
|
770
|
+
serverUrl: '/api/auth',
|
|
771
|
+
features: { email: true, google: true },
|
|
772
|
+
}}
|
|
773
|
+
>
|
|
774
|
+
<div className="login-container">
|
|
775
|
+
<h1>Sign In</h1>
|
|
776
|
+
<LoginForm
|
|
777
|
+
onSuccess={(user) => {
|
|
778
|
+
window.location.href = '/dashboard';
|
|
779
|
+
}}
|
|
780
|
+
/>
|
|
781
|
+
</div>
|
|
782
|
+
</CedrosLoginProvider>
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### Organization Switcher
|
|
788
|
+
|
|
789
|
+
```tsx
|
|
790
|
+
import { useOrgs, OrgSwitcher } from '@cedros/login-react';
|
|
791
|
+
|
|
792
|
+
function Header() {
|
|
793
|
+
const { activeOrg } = useOrgs();
|
|
794
|
+
const [showSwitcher, setShowSwitcher] = useState(false);
|
|
795
|
+
|
|
796
|
+
return (
|
|
797
|
+
<header>
|
|
798
|
+
<button onClick={() => setShowSwitcher(true)}>
|
|
799
|
+
{activeOrg?.name || 'Select Organization'}
|
|
800
|
+
</button>
|
|
801
|
+
{showSwitcher && (
|
|
802
|
+
<OrgSwitcher
|
|
803
|
+
onClose={() => setShowSwitcher(false)}
|
|
804
|
+
onSwitch={(org) => {
|
|
805
|
+
console.log('Switched to:', org.name);
|
|
806
|
+
setShowSwitcher(false);
|
|
807
|
+
}}
|
|
808
|
+
/>
|
|
809
|
+
)}
|
|
810
|
+
</header>
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
### Team Management
|
|
816
|
+
|
|
817
|
+
```tsx
|
|
818
|
+
import { useMembers, useInvites, MemberList, InviteForm, InviteList } from '@cedros/login-react';
|
|
819
|
+
import { useOrgs } from '@cedros/login-react';
|
|
820
|
+
|
|
821
|
+
function TeamSettings() {
|
|
822
|
+
const { activeOrg } = useOrgs();
|
|
823
|
+
const orgId = activeOrg?.id;
|
|
824
|
+
|
|
825
|
+
if (!orgId) return <p>Select an organization</p>;
|
|
826
|
+
|
|
827
|
+
return (
|
|
828
|
+
<div>
|
|
829
|
+
<h2>Team Members</h2>
|
|
830
|
+
<MemberList orgId={orgId} />
|
|
831
|
+
|
|
832
|
+
<h2>Invite New Member</h2>
|
|
833
|
+
<InviteForm
|
|
834
|
+
orgId={orgId}
|
|
835
|
+
onSuccess={() => console.log('Invite sent!')}
|
|
836
|
+
/>
|
|
837
|
+
|
|
838
|
+
<h2>Pending Invites</h2>
|
|
839
|
+
<InviteList orgId={orgId} />
|
|
840
|
+
</div>
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
### Session Management
|
|
846
|
+
|
|
847
|
+
```tsx
|
|
848
|
+
import { useSessions, SessionList } from '@cedros/login-react';
|
|
849
|
+
|
|
850
|
+
function SecuritySettings() {
|
|
851
|
+
const { revokeAll, isLoading } = useSessions();
|
|
852
|
+
|
|
853
|
+
return (
|
|
854
|
+
<div>
|
|
855
|
+
<h2>Active Sessions</h2>
|
|
856
|
+
<SessionList />
|
|
857
|
+
|
|
858
|
+
<button
|
|
859
|
+
onClick={revokeAll}
|
|
860
|
+
disabled={isLoading}
|
|
861
|
+
>
|
|
862
|
+
Logout from all devices
|
|
863
|
+
</button>
|
|
864
|
+
</div>
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
### Two-Factor Authentication
|
|
870
|
+
|
|
871
|
+
```tsx
|
|
872
|
+
import { TotpSettings, TotpSetup, TotpVerify } from '@cedros/login-react';
|
|
873
|
+
|
|
874
|
+
// Settings page - enable/disable 2FA
|
|
875
|
+
function SecuritySettings() {
|
|
876
|
+
return (
|
|
877
|
+
<div>
|
|
878
|
+
<h2>Two-Factor Authentication</h2>
|
|
879
|
+
<TotpSettings
|
|
880
|
+
onStatusChange={(enabled) => {
|
|
881
|
+
console.log('2FA is now', enabled ? 'enabled' : 'disabled');
|
|
882
|
+
}}
|
|
883
|
+
/>
|
|
884
|
+
</div>
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// Standalone setup wizard (if you need custom placement)
|
|
889
|
+
function TwoFactorSetupPage() {
|
|
890
|
+
return (
|
|
891
|
+
<TotpSetup
|
|
892
|
+
onSuccess={() => {
|
|
893
|
+
window.location.href = '/settings';
|
|
894
|
+
}}
|
|
895
|
+
onCancel={() => {
|
|
896
|
+
window.location.href = '/settings';
|
|
897
|
+
}}
|
|
898
|
+
/>
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// Custom verification UI during login
|
|
903
|
+
function TwoFactorChallenge({ onSuccess, email }) {
|
|
904
|
+
return (
|
|
905
|
+
<TotpVerify
|
|
906
|
+
email={email}
|
|
907
|
+
onSuccess={onSuccess}
|
|
908
|
+
onCancel={() => window.location.href = '/login'}
|
|
909
|
+
/>
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
### Embedded Wallet
|
|
915
|
+
|
|
916
|
+
```tsx
|
|
917
|
+
import { useWallet, useWalletSigning, WalletStatus } from '@cedros/login-react';
|
|
918
|
+
|
|
919
|
+
function WalletPage() {
|
|
920
|
+
const { status, solanaPubkey, authMethod } = useWallet();
|
|
921
|
+
const { unlock, signTransaction, isUnlocked, isLoading } = useWalletSigning();
|
|
922
|
+
|
|
923
|
+
const handleSign = async () => {
|
|
924
|
+
// If not unlocked, prompt for credential first
|
|
925
|
+
if (!isUnlocked) {
|
|
926
|
+
await unlock({ password: userPassword }); // or { prfOutput }
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// Sign transaction (server-side)
|
|
930
|
+
const { signature } = await signTransaction(transactionBytes);
|
|
931
|
+
console.log('Signed:', signature);
|
|
932
|
+
};
|
|
933
|
+
|
|
934
|
+
return (
|
|
935
|
+
<div>
|
|
936
|
+
<WalletStatus
|
|
937
|
+
status={status}
|
|
938
|
+
publicKey={solanaPubkey}
|
|
939
|
+
onEnroll={() => navigate('/wallet/enroll')}
|
|
940
|
+
onUnlock={() => setShowUnlockModal(true)}
|
|
941
|
+
onLock={() => lock()}
|
|
942
|
+
/>
|
|
943
|
+
|
|
944
|
+
<button onClick={handleSign} disabled={isLoading}>
|
|
945
|
+
Sign Transaction
|
|
946
|
+
</button>
|
|
947
|
+
</div>
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
### Permission-Based UI
|
|
953
|
+
|
|
954
|
+
```tsx
|
|
955
|
+
import { useAuthorize } from '@cedros/login-react';
|
|
956
|
+
|
|
957
|
+
function InviteButton({ orgId }) {
|
|
958
|
+
const { checkPermission } = useAuthorize();
|
|
959
|
+
const [canInvite, setCanInvite] = useState(false);
|
|
960
|
+
|
|
961
|
+
useEffect(() => {
|
|
962
|
+
checkPermission({
|
|
963
|
+
orgId,
|
|
964
|
+
action: 'member:invite',
|
|
965
|
+
resourceType: 'member',
|
|
966
|
+
}).then(setCanInvite);
|
|
967
|
+
}, [orgId]);
|
|
968
|
+
|
|
969
|
+
if (!canInvite) return null;
|
|
970
|
+
|
|
971
|
+
return <button>Invite Member</button>;
|
|
972
|
+
}
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
### Privacy Cash
|
|
976
|
+
|
|
977
|
+
**Deposits work in all wallet recovery modes**, but private (privacy-preserving) deposits require the wallet to be configured in "no-recovery" mode for security reasons.
|
|
978
|
+
|
|
979
|
+
| Recovery Mode | Private Deposits | Public Deposits | Notes |
|
|
980
|
+
|--------------|-----------------|-----------------|-------|
|
|
981
|
+
| `None` | ✅ Available | ✅ Available | Maximum privacy, no key export |
|
|
982
|
+
| `ShareCOnly` | ❌ Blocked | ✅ Available | In-app recovery only |
|
|
983
|
+
| `FullSeed` | ❌ Blocked | ✅ Available | Full key portability |
|
|
984
|
+
|
|
985
|
+
**Why private deposits require no-recovery mode:** In recovery modes where users can export their private key, they could potentially front-run withdrawal transactions by extracting their key and submitting a competing transaction before the Privacy Cash relayer processes the batched withdrawal.
|
|
986
|
+
|
|
987
|
+
When `privateDepositsEnabled` is `false` (recovery mode enabled), the DepositFlow component automatically forces "receive" mode and shows public tier labels.
|
|
988
|
+
|
|
989
|
+
```tsx
|
|
990
|
+
import {
|
|
991
|
+
DepositForm,
|
|
992
|
+
CreditBalance,
|
|
993
|
+
CreditHistory,
|
|
994
|
+
DepositList,
|
|
995
|
+
useDeposit,
|
|
996
|
+
useCredits,
|
|
997
|
+
} from '@cedros/login-react';
|
|
998
|
+
|
|
999
|
+
// User's credit dashboard
|
|
1000
|
+
function CreditDashboard() {
|
|
1001
|
+
return (
|
|
1002
|
+
<div>
|
|
1003
|
+
<h2>Your Balance</h2>
|
|
1004
|
+
<CreditBalance showRefresh />
|
|
1005
|
+
|
|
1006
|
+
<h2>Make a Deposit</h2>
|
|
1007
|
+
<DepositForm
|
|
1008
|
+
minAmountLamports={10_000_000} // 0.01 SOL
|
|
1009
|
+
onSuccess={(response) => {
|
|
1010
|
+
console.log('Deposit initiated:', response.sessionId);
|
|
1011
|
+
}}
|
|
1012
|
+
/>
|
|
1013
|
+
|
|
1014
|
+
<h2>Transaction History</h2>
|
|
1015
|
+
<CreditHistory pageSize={10} />
|
|
1016
|
+
|
|
1017
|
+
<h2>Your Deposits</h2>
|
|
1018
|
+
<DepositList
|
|
1019
|
+
pageSize={10}
|
|
1020
|
+
onDepositClick={(deposit) => {
|
|
1021
|
+
console.log('View deposit:', deposit.sessionId);
|
|
1022
|
+
}}
|
|
1023
|
+
/>
|
|
1024
|
+
</div>
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// Using hooks directly
|
|
1029
|
+
function CustomDepositUI() {
|
|
1030
|
+
const { deposit, getStatus, isLoading, error } = useDeposit();
|
|
1031
|
+
const { getBalance } = useCredits();
|
|
1032
|
+
|
|
1033
|
+
const handleDeposit = async (amountLamports: number) => {
|
|
1034
|
+
const result = await deposit(amountLamports);
|
|
1035
|
+
console.log('Deposit session:', result.sessionId);
|
|
1036
|
+
|
|
1037
|
+
// Poll for status updates
|
|
1038
|
+
const status = await getStatus(result.sessionId);
|
|
1039
|
+
console.log('Status:', status.status);
|
|
1040
|
+
};
|
|
1041
|
+
|
|
1042
|
+
return (
|
|
1043
|
+
<button onClick={() => handleDeposit(100_000_000)} disabled={isLoading}>
|
|
1044
|
+
Deposit 0.1 SOL
|
|
1045
|
+
</button>
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
```
|
|
1049
|
+
|
|
1050
|
+
### Privacy Cash Admin
|
|
1051
|
+
|
|
1052
|
+
```tsx
|
|
1053
|
+
import {
|
|
1054
|
+
PrivacyCashAdminPanel,
|
|
1055
|
+
AdminDepositStats,
|
|
1056
|
+
useAdminDeposits,
|
|
1057
|
+
} from '@cedros/login-react';
|
|
1058
|
+
|
|
1059
|
+
// Full admin dashboard
|
|
1060
|
+
function AdminDashboard() {
|
|
1061
|
+
return (
|
|
1062
|
+
<PrivacyCashAdminPanel
|
|
1063
|
+
pageSize={20}
|
|
1064
|
+
refreshInterval={30000} // Auto-refresh every 30s
|
|
1065
|
+
onDepositClick={(deposit) => {
|
|
1066
|
+
console.log('View deposit:', deposit.id, 'User:', deposit.userId);
|
|
1067
|
+
}}
|
|
1068
|
+
onWithdrawalClick={(item) => {
|
|
1069
|
+
console.log('Process withdrawal:', item.id);
|
|
1070
|
+
}}
|
|
1071
|
+
/>
|
|
1072
|
+
);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// Using admin hooks directly
|
|
1076
|
+
function AdminStatsWidget() {
|
|
1077
|
+
const { getStats, isLoading, error } = useAdminDeposits();
|
|
1078
|
+
const [stats, setStats] = useState(null);
|
|
1079
|
+
|
|
1080
|
+
useEffect(() => {
|
|
1081
|
+
getStats().then(setStats);
|
|
1082
|
+
}, []);
|
|
1083
|
+
|
|
1084
|
+
if (!stats) return null;
|
|
1085
|
+
|
|
1086
|
+
return (
|
|
1087
|
+
<div>
|
|
1088
|
+
<p>Total Deposits: {stats.totalDeposits}</p>
|
|
1089
|
+
<p>Total Volume: {stats.totalDepositedSol} SOL</p>
|
|
1090
|
+
<p>Pending Withdrawals: {stats.pendingWithdrawalCount}</p>
|
|
1091
|
+
</div>
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
```
|
|
1095
|
+
|
|
1096
|
+
## TypeScript
|
|
1097
|
+
|
|
1098
|
+
All components and hooks are fully typed:
|
|
1099
|
+
|
|
1100
|
+
```tsx
|
|
1101
|
+
import type {
|
|
1102
|
+
// Auth types
|
|
1103
|
+
AuthUser,
|
|
1104
|
+
AuthMethod,
|
|
1105
|
+
TokenPair,
|
|
1106
|
+
AuthState,
|
|
1107
|
+
|
|
1108
|
+
// Organization types
|
|
1109
|
+
Organization,
|
|
1110
|
+
Membership,
|
|
1111
|
+
OrgRole,
|
|
1112
|
+
|
|
1113
|
+
// Member types
|
|
1114
|
+
Member,
|
|
1115
|
+
|
|
1116
|
+
// Invite types
|
|
1117
|
+
Invite,
|
|
1118
|
+
CreateInviteRequest,
|
|
1119
|
+
|
|
1120
|
+
// Session types
|
|
1121
|
+
Session,
|
|
1122
|
+
|
|
1123
|
+
// Wallet types
|
|
1124
|
+
WalletStatus,
|
|
1125
|
+
WalletMaterial,
|
|
1126
|
+
WalletCapabilities,
|
|
1127
|
+
UnlockCredential,
|
|
1128
|
+
SignTransactionRequest,
|
|
1129
|
+
SignTransactionResponse,
|
|
1130
|
+
|
|
1131
|
+
// Privacy Cash types
|
|
1132
|
+
DepositRequest,
|
|
1133
|
+
DepositResponse,
|
|
1134
|
+
DepositStatusResponse,
|
|
1135
|
+
DepositConfigResponse,
|
|
1136
|
+
DepositItemResponse,
|
|
1137
|
+
DepositListResponse,
|
|
1138
|
+
CreditBalanceResponse,
|
|
1139
|
+
CreditTransactionResponse,
|
|
1140
|
+
CreditHistoryResponse,
|
|
1141
|
+
AdminDepositItem,
|
|
1142
|
+
AdminDepositListResponse,
|
|
1143
|
+
AdminDepositStatsResponse,
|
|
1144
|
+
|
|
1145
|
+
// System settings types
|
|
1146
|
+
SystemSetting,
|
|
1147
|
+
UpdateSettingRequest,
|
|
1148
|
+
ListSystemSettingsResponse,
|
|
1149
|
+
UpdateSystemSettingsResponse,
|
|
1150
|
+
UseSystemSettingsReturn,
|
|
1151
|
+
|
|
1152
|
+
// Config types
|
|
1153
|
+
CedrosLoginConfig,
|
|
1154
|
+
FeatureFlags,
|
|
1155
|
+
ThemeOverrides,
|
|
1156
|
+
} from '@cedros/login-react';
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
## Development
|
|
1160
|
+
|
|
1161
|
+
```bash
|
|
1162
|
+
# Install dependencies
|
|
1163
|
+
npm install
|
|
1164
|
+
|
|
1165
|
+
# Run dev server
|
|
1166
|
+
npm run dev
|
|
1167
|
+
|
|
1168
|
+
# Run tests
|
|
1169
|
+
npm test
|
|
1170
|
+
|
|
1171
|
+
# Build library
|
|
1172
|
+
npm run build
|
|
1173
|
+
|
|
1174
|
+
# Type check
|
|
1175
|
+
npm run typecheck
|
|
1176
|
+
|
|
1177
|
+
# Lint
|
|
1178
|
+
npm run lint
|
|
1179
|
+
```
|
|
1180
|
+
|
|
1181
|
+
## License
|
|
1182
|
+
|
|
1183
|
+
MIT
|