@volr/react-ui 0.1.0 → 0.1.2
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/README.md +114 -189
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
# @volr/react-ui
|
|
1
|
+
# @volr/react-ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pre-built UI components for Volr SDK with minimal, modern design.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @volr/react-ui @volr/react
|
|
9
|
-
#
|
|
9
|
+
# or
|
|
10
10
|
yarn add @volr/react-ui @volr/react
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Quick Start
|
|
14
14
|
|
|
15
|
-
### 1.
|
|
16
|
-
|
|
17
|
-
앱의 최상위 레벨에서 `VolrUIProvider`로 앱을 래핑합니다.
|
|
15
|
+
### 1. Wrap your app with VolrUIProvider
|
|
18
16
|
|
|
19
17
|
```tsx
|
|
20
18
|
import { VolrUIProvider } from '@volr/react-ui';
|
|
21
|
-
import { VolrConfig } from '@volr/react';
|
|
19
|
+
import type { VolrConfig } from '@volr/react';
|
|
22
20
|
|
|
23
21
|
const volrConfig: VolrConfig = {
|
|
24
|
-
|
|
25
|
-
defaultChainId: 1,
|
|
22
|
+
defaultChainId: 8453,
|
|
26
23
|
projectApiKey: 'your-project-api-key',
|
|
27
24
|
};
|
|
28
25
|
|
|
@@ -30,9 +27,9 @@ function App() {
|
|
|
30
27
|
return (
|
|
31
28
|
<VolrUIProvider
|
|
32
29
|
config={volrConfig}
|
|
33
|
-
accentColor="#3b82f6"
|
|
34
|
-
enabledLoginMethods={['email', 'social', 'siwe']}
|
|
35
|
-
socialProviders={['google', 'twitter', 'apple']}
|
|
30
|
+
accentColor="#3b82f6"
|
|
31
|
+
enabledLoginMethods={['email', 'social', 'siwe']}
|
|
32
|
+
socialProviders={['google', 'twitter', 'apple']}
|
|
36
33
|
>
|
|
37
34
|
<YourApp />
|
|
38
35
|
</VolrUIProvider>
|
|
@@ -40,9 +37,7 @@ function App() {
|
|
|
40
37
|
}
|
|
41
38
|
```
|
|
42
39
|
|
|
43
|
-
### 2. LoginModal
|
|
44
|
-
|
|
45
|
-
로그인 모달을 표시하려면 `LoginModal` 컴포넌트를 사용합니다.
|
|
40
|
+
### 2. Use LoginModal
|
|
46
41
|
|
|
47
42
|
```tsx
|
|
48
43
|
import { useState } from 'react';
|
|
@@ -53,14 +48,13 @@ function LoginButton() {
|
|
|
53
48
|
|
|
54
49
|
return (
|
|
55
50
|
<>
|
|
56
|
-
<button onClick={() => setIsOpen(true)}
|
|
51
|
+
<button onClick={() => setIsOpen(true)}>Login</button>
|
|
57
52
|
|
|
58
53
|
<LoginModal
|
|
59
54
|
isOpen={isOpen}
|
|
60
55
|
onClose={() => setIsOpen(false)}
|
|
61
56
|
onError={(error) => {
|
|
62
|
-
console.error('
|
|
63
|
-
// 에러 처리 로직
|
|
57
|
+
console.error('Login error:', error);
|
|
64
58
|
}}
|
|
65
59
|
/>
|
|
66
60
|
</>
|
|
@@ -68,52 +62,78 @@ function LoginButton() {
|
|
|
68
62
|
}
|
|
69
63
|
```
|
|
70
64
|
|
|
71
|
-
##
|
|
65
|
+
## Configuration
|
|
72
66
|
|
|
73
67
|
### VolrUIProvider Props
|
|
74
68
|
|
|
75
69
|
| Prop | Type | Default | Description |
|
|
76
70
|
|------|------|---------|-------------|
|
|
77
|
-
| `config` | `VolrConfig` |
|
|
78
|
-
| `accentColor` | `string` | `'#303030'` |
|
|
79
|
-
| `appName` | `string` | `undefined` |
|
|
80
|
-
| `enabledLoginMethods` | `('email' \| 'social' \| 'siwe')[]` | `['email', 'social', 'siwe']` |
|
|
81
|
-
| `socialProviders` | `('google' \| 'twitter' \| 'apple')[]` | `['google', 'twitter', 'apple']` |
|
|
82
|
-
| `volrLogoUrl` | `string` | `undefined` | Volr
|
|
83
|
-
| `providerPolicy` | `object` | `{ enforceOnFirstLogin: true }` | Provider
|
|
71
|
+
| `config` | `VolrConfig` | **Required** | Volr configuration (defaultChainId, projectApiKey) |
|
|
72
|
+
| `accentColor` | `string` | `'#303030'` | Accent color for buttons and links |
|
|
73
|
+
| `appName` | `string` | `undefined` | Application name |
|
|
74
|
+
| `enabledLoginMethods` | `('email' \| 'social' \| 'siwe')[]` | `['email', 'social', 'siwe']` | Enabled login methods |
|
|
75
|
+
| `socialProviders` | `('google' \| 'twitter' \| 'apple')[]` | `['google', 'twitter', 'apple']` | Enabled social providers |
|
|
76
|
+
| `volrLogoUrl` | `string` | `undefined` | Custom Volr logo URL |
|
|
77
|
+
| `providerPolicy` | `object` | `{ enforceOnFirstLogin: true }` | Provider policy settings |
|
|
84
78
|
|
|
85
79
|
### LoginModal Props
|
|
86
80
|
|
|
87
81
|
| Prop | Type | Default | Description |
|
|
88
82
|
|------|------|---------|-------------|
|
|
89
|
-
| `isOpen` | `boolean` |
|
|
90
|
-
| `onClose` | `() => void` |
|
|
91
|
-
| `onError` | `(error: Error) => void` | `undefined` |
|
|
92
|
-
|
|
93
|
-
##
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
83
|
+
| `isOpen` | `boolean` | **Required** | Modal open/close state |
|
|
84
|
+
| `onClose` | `() => void` | **Required** | Close callback |
|
|
85
|
+
| `onError` | `(error: Error) => void` | `undefined` | Error callback |
|
|
86
|
+
|
|
87
|
+
## Features
|
|
88
|
+
|
|
89
|
+
- **Email Login**: Email verification with 6-digit code
|
|
90
|
+
- **Social Login**: Google, Twitter, Apple OAuth
|
|
91
|
+
- **SIWE**: Sign-In with Ethereum (wallet login)
|
|
92
|
+
- **Passkey Wallet**: Automatic passkey-based wallet creation for new users
|
|
93
|
+
- **Minimal Design**: Clean, modern UI without emojis
|
|
94
|
+
- **Customizable**: Accent color and enabled methods
|
|
95
|
+
- **Type-Safe**: Full TypeScript support
|
|
96
|
+
|
|
97
|
+
## Login Flow
|
|
98
|
+
|
|
99
|
+
### Email Login
|
|
100
|
+
1. User clicks "Email Login"
|
|
101
|
+
2. Enter email address
|
|
102
|
+
3. Receive 6-digit verification code
|
|
103
|
+
4. Enter code
|
|
104
|
+
5. **New users**: Passkey setup
|
|
105
|
+
6. **Existing users**: Success
|
|
106
|
+
|
|
107
|
+
### Social Login (Google, Twitter, Apple)
|
|
108
|
+
1. User clicks social login button
|
|
109
|
+
2. Redirect to OAuth provider
|
|
110
|
+
3. Authorize and return
|
|
111
|
+
4. **New users**: Passkey setup
|
|
112
|
+
5. **Existing users**: Success
|
|
113
|
+
|
|
114
|
+
### Wallet Login (SIWE)
|
|
115
|
+
1. User clicks "Wallet Login"
|
|
116
|
+
2. Connect MetaMask or other wallet
|
|
117
|
+
3. Sign SIWE message
|
|
118
|
+
4. **New users**: Passkey setup
|
|
119
|
+
5. **Existing users**: Success
|
|
120
|
+
|
|
121
|
+
## Passkey Setup
|
|
122
|
+
|
|
123
|
+
For new users, a passkey-based wallet is automatically created:
|
|
124
|
+
|
|
125
|
+
1. **Create Passkey**: WebAuthn API with platform authenticator
|
|
126
|
+
2. **Derive Wrap Key**: From Passkey PRF
|
|
127
|
+
3. **Generate Master Seed**: 32-byte random seed
|
|
128
|
+
4. **Encrypt**: AES-256-GCM with Wrap Key
|
|
129
|
+
5. **Upload**: Encrypted seed to S3
|
|
130
|
+
6. **Register Provider**: Backend registration
|
|
131
|
+
7. **Derive EVM Key**: BIP-32 derivation
|
|
132
|
+
8. **Complete**: Wallet address confirmed
|
|
133
|
+
|
|
134
|
+
## Examples
|
|
135
|
+
|
|
136
|
+
### Email Only
|
|
117
137
|
|
|
118
138
|
```tsx
|
|
119
139
|
<VolrUIProvider
|
|
@@ -125,7 +145,7 @@ function App() {
|
|
|
125
145
|
</VolrUIProvider>
|
|
126
146
|
```
|
|
127
147
|
|
|
128
|
-
### Google
|
|
148
|
+
### Google and Apple Only
|
|
129
149
|
|
|
130
150
|
```tsx
|
|
131
151
|
<VolrUIProvider
|
|
@@ -138,7 +158,7 @@ function App() {
|
|
|
138
158
|
</VolrUIProvider>
|
|
139
159
|
```
|
|
140
160
|
|
|
141
|
-
###
|
|
161
|
+
### Custom Error Handling
|
|
142
162
|
|
|
143
163
|
```tsx
|
|
144
164
|
function App() {
|
|
@@ -159,7 +179,7 @@ function App() {
|
|
|
159
179
|
</div>
|
|
160
180
|
)}
|
|
161
181
|
|
|
162
|
-
<button onClick={() => setShowLogin(true)}
|
|
182
|
+
<button onClick={() => setShowLogin(true)}>Login</button>
|
|
163
183
|
|
|
164
184
|
<LoginModal
|
|
165
185
|
isOpen={showLogin}
|
|
@@ -169,7 +189,6 @@ function App() {
|
|
|
169
189
|
}}
|
|
170
190
|
onError={(err) => {
|
|
171
191
|
setError(err.message);
|
|
172
|
-
// 3초 후 에러 메시지 자동 숨김
|
|
173
192
|
setTimeout(() => setError(null), 3000);
|
|
174
193
|
}}
|
|
175
194
|
/>
|
|
@@ -178,57 +197,9 @@ function App() {
|
|
|
178
197
|
}
|
|
179
198
|
```
|
|
180
199
|
|
|
181
|
-
##
|
|
182
|
-
|
|
183
|
-
###
|
|
184
|
-
1. 사용자가 "Email Login" 버튼 클릭
|
|
185
|
-
2. 이메일 주소 입력 화면 표시
|
|
186
|
-
3. 인증 코드 전송
|
|
187
|
-
4. 6자리 코드 입력 화면 표시
|
|
188
|
-
5. 코드 검증
|
|
189
|
-
6. **신규 사용자**: Passkey 설정 화면으로 이동
|
|
190
|
-
7. **기존 사용자**: 성공 화면으로 이동
|
|
191
|
-
|
|
192
|
-
### 소셜 로그인 (Google, Twitter, Apple)
|
|
193
|
-
1. 사용자가 소셜 로그인 버튼 클릭
|
|
194
|
-
2. OAuth 페이지로 리다이렉트
|
|
195
|
-
3. 소셜 계정으로 로그인 및 권한 승인
|
|
196
|
-
4. 백엔드 콜백 처리 후 프론트엔드로 리다이렉트
|
|
197
|
-
5. **신규 사용자**: Passkey 설정 화면으로 이동
|
|
198
|
-
6. **기존 사용자**: 성공 화면으로 이동
|
|
199
|
-
|
|
200
|
-
### 지갑 로그인 (SIWE)
|
|
201
|
-
1. 사용자가 "Wallet Login" 버튼 클릭
|
|
202
|
-
2. MetaMask 또는 다른 지갑 연결
|
|
203
|
-
3. SIWE 메시지에 서명
|
|
204
|
-
4. 백엔드에서 서명 검증
|
|
205
|
-
5. **신규 사용자**: Passkey 설정 화면으로 이동
|
|
206
|
-
6. **기존 사용자**: 성공 화면으로 이동
|
|
207
|
-
|
|
208
|
-
## Passkey 설정
|
|
209
|
-
|
|
210
|
-
신규 사용자의 경우 자동으로 Passkey 지갑이 생성됩니다:
|
|
211
|
-
|
|
212
|
-
1. **Passkey 생성**: WebAuthn API를 사용하여 플랫폼 인증자(생체 인증) 생성
|
|
213
|
-
2. **Wrap Key 파생**: Passkey PRF에서 Wrap Key 생성
|
|
214
|
-
3. **Master Seed 생성 및 암호화**:
|
|
215
|
-
- 32바이트 무작위 Master Seed 생성
|
|
216
|
-
- Wrap Key로 AES-256-GCM 암호화
|
|
217
|
-
4. **S3 업로드**: 암호화된 Master Seed를 S3에 업로드
|
|
218
|
-
5. **Provider 등록**: 백엔드에 Provider 정보 등록
|
|
219
|
-
6. **EVM 키 파생**: Master Seed에서 BIP-32로 EVM 키 쌍 파생
|
|
220
|
-
7. **완료**: 지갑 주소 확인 및 로그인 완료
|
|
221
|
-
|
|
222
|
-
## 디자인 원칙
|
|
223
|
-
|
|
224
|
-
- **미니멀리즘**: 깔끔하고 모던한 디자인, 불필요한 장식 없음
|
|
225
|
-
- **accentColor 사용**: 버튼, 링크 등 강조 요소에 config의 accentColor 활용
|
|
226
|
-
- **이모지 금지**: 모든 UI 요소에서 이모지 사용 안 함, SVG 아이콘만 사용
|
|
227
|
-
- **일관된 여백과 타이포그래피**: 명확한 시각적 계층
|
|
228
|
-
|
|
229
|
-
## 백엔드 설정
|
|
230
|
-
|
|
231
|
-
로그인 기능을 사용하려면 백엔드에 다음 환경 변수를 설정해야 합니다:
|
|
200
|
+
## Backend Requirements
|
|
201
|
+
|
|
202
|
+
### Environment Variables
|
|
232
203
|
|
|
233
204
|
```bash
|
|
234
205
|
# Google OAuth
|
|
@@ -245,97 +216,51 @@ TWITTER_REDIRECT_URI=http://localhost:3000/auth/twitter/callback
|
|
|
245
216
|
APPLE_CLIENT_ID=your_apple_client_id
|
|
246
217
|
APPLE_REDIRECT_URI=http://localhost:3000/auth/apple/callback
|
|
247
218
|
|
|
248
|
-
# Frontend URL (OAuth
|
|
219
|
+
# Frontend URL (OAuth callback redirect)
|
|
249
220
|
FRONTEND_URL=http://localhost:5173
|
|
250
221
|
|
|
251
222
|
# API Base URL
|
|
252
223
|
API_BASE_URL=http://localhost:3000
|
|
253
224
|
```
|
|
254
225
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
백엔드에서 제공해야 하는 엔드포인트:
|
|
258
|
-
|
|
259
|
-
### 이메일 로그인
|
|
260
|
-
- `POST /auth/email/send` - 인증 코드 전송
|
|
261
|
-
- `POST /auth/email/verify` - 인증 코드 검증 및 로그인
|
|
262
|
-
|
|
263
|
-
### 소셜 로그인
|
|
264
|
-
- `GET /auth/google` - Google OAuth 시작
|
|
265
|
-
- `GET /auth/google/callback` - Google OAuth 콜백
|
|
266
|
-
- `GET /auth/twitter` - Twitter OAuth 시작
|
|
267
|
-
- `GET /auth/twitter/callback` - Twitter OAuth 콜백
|
|
268
|
-
- `GET /auth/apple` - Apple OAuth 시작
|
|
269
|
-
- `POST /auth/apple/callback` - Apple OAuth 콜백
|
|
226
|
+
### Required Endpoints
|
|
270
227
|
|
|
271
|
-
|
|
272
|
-
- `POST /auth/
|
|
273
|
-
- `POST /auth/
|
|
228
|
+
**Email Login**
|
|
229
|
+
- `POST /auth/email/send` - Send verification code
|
|
230
|
+
- `POST /auth/email/verify` - Verify code and login
|
|
274
231
|
|
|
275
|
-
|
|
276
|
-
- `
|
|
277
|
-
- `
|
|
232
|
+
**Social Login**
|
|
233
|
+
- `GET /auth/google` - Start Google OAuth
|
|
234
|
+
- `GET /auth/google/callback` - Google OAuth callback
|
|
235
|
+
- `GET /auth/twitter` - Start Twitter OAuth
|
|
236
|
+
- `GET /auth/twitter/callback` - Twitter OAuth callback
|
|
237
|
+
- `GET /auth/apple` - Start Apple OAuth
|
|
238
|
+
- `POST /auth/apple/callback` - Apple OAuth callback
|
|
278
239
|
|
|
279
|
-
|
|
240
|
+
**SIWE**
|
|
241
|
+
- `POST /auth/siwe/nonce` - Generate nonce
|
|
242
|
+
- `POST /auth/siwe/verify` - Verify SIWE signature
|
|
280
243
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
import { VolrConfig } from '@volr/react';
|
|
285
|
-
|
|
286
|
-
const volrConfig: VolrConfig = {
|
|
287
|
-
apiBaseUrl: process.env.VITE_API_BASE_URL || 'http://localhost:3000',
|
|
288
|
-
defaultChainId: 1,
|
|
289
|
-
projectApiKey: process.env.VITE_PROJECT_API_KEY || '',
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
function LoginPage() {
|
|
293
|
-
const [isLoginOpen, setIsLoginOpen] = useState(false);
|
|
294
|
-
|
|
295
|
-
return (
|
|
296
|
-
<>
|
|
297
|
-
<button onClick={() => setIsLoginOpen(true)}>로그인</button>
|
|
298
|
-
|
|
299
|
-
<LoginModal
|
|
300
|
-
isOpen={isLoginOpen}
|
|
301
|
-
onClose={() => setIsLoginOpen(false)}
|
|
302
|
-
onError={(error) => {
|
|
303
|
-
console.error('로그인 오류:', error);
|
|
304
|
-
alert(error.message);
|
|
305
|
-
}}
|
|
306
|
-
/>
|
|
307
|
-
</>
|
|
308
|
-
);
|
|
309
|
-
}
|
|
244
|
+
**Passkey**
|
|
245
|
+
- `POST /blob/presign` - Generate S3 upload URL
|
|
246
|
+
- `POST /wallet/provider/register` - Register provider
|
|
310
247
|
|
|
311
|
-
|
|
312
|
-
return (
|
|
313
|
-
<VolrUIProvider
|
|
314
|
-
config={volrConfig}
|
|
315
|
-
accentColor="#6366f1"
|
|
316
|
-
enabledLoginMethods={['email', 'social', 'siwe']}
|
|
317
|
-
socialProviders={['google', 'twitter', 'apple']}
|
|
318
|
-
>
|
|
319
|
-
<LoginPage />
|
|
320
|
-
</VolrUIProvider>
|
|
321
|
-
);
|
|
322
|
-
}
|
|
248
|
+
## Troubleshooting
|
|
323
249
|
|
|
324
|
-
|
|
325
|
-
|
|
250
|
+
### OAuth Redirect Failure
|
|
251
|
+
- Verify OAuth Client ID and Secret
|
|
252
|
+
- Check Redirect URI matches OAuth app settings
|
|
253
|
+
- Verify CORS configuration
|
|
326
254
|
|
|
327
|
-
|
|
255
|
+
### SIWE Signature Failure
|
|
256
|
+
- Ensure MetaMask or wallet is installed
|
|
257
|
+
- Check wallet is connected to correct network
|
|
328
258
|
|
|
329
|
-
###
|
|
330
|
-
-
|
|
331
|
-
-
|
|
332
|
-
-
|
|
259
|
+
### Passkey Creation Failure
|
|
260
|
+
- HTTPS or localhost required (HTTP not supported)
|
|
261
|
+
- Verify browser supports WebAuthn
|
|
262
|
+
- Check biometric authentication is enabled on device
|
|
333
263
|
|
|
334
|
-
|
|
335
|
-
- MetaMask 또는 다른 지갑이 설치되어 있는지 확인
|
|
336
|
-
- 지갑이 올바른 네트워크에 연결되어 있는지 확인
|
|
264
|
+
## License
|
|
337
265
|
|
|
338
|
-
|
|
339
|
-
- HTTPS 또는 localhost에서만 작동 (HTTP는 불가)
|
|
340
|
-
- 브라우저가 WebAuthn을 지원하는지 확인
|
|
341
|
-
- 디바이스에 생체 인증이 활성화되어 있는지 확인
|
|
266
|
+
MIT
|