shogun-button-react 6.2.3 → 6.3.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/README.md CHANGED
@@ -1,752 +1,752 @@
1
- # Shogun Button React
2
-
3
- A comprehensive React component library for seamless integration of Shogun authentication into your applications. This library provides a simple yet powerful way to add multi-method authentication, account management, and real-time data synchronization to your React applications.
4
-
5
- > **Version 5.0.0** - Compatible with shogun-core ^2.0.0
6
-
7
- ## ✨ Features
8
-
9
- - 🚀 **Easy Integration** - Simple setup with minimal configuration
10
- - 🎨 **Customizable UI** - Modern, responsive design with dark mode support
11
- - 🔒 **Multi-Authentication** - Support for Password, MetaMask, WebAuthn, Nostr, and ZK-Proof
12
- - 🔑 **Account Management** - Export/import Gun pairs for account backup and recovery
13
- - 📱 **Responsive Design** - Works seamlessly across all device sizes
14
- - 🌍 **TypeScript Support** - Full type safety and IntelliSense support
15
- - 🔌 **Plugin System** - Advanced Gun operations with custom hooks
16
- - 📊 **Real-time Data** - Reactive data synchronization with RxJS observables
17
- - ✅ **Robust Foundation** - Built on shogun-core v5.0.0 with 99.86% test coverage
18
- - 🗄️ **Flexible Storage** - Support for GunDB, SQLite, PostgreSQL, MongoDB via TransportLayer
19
-
20
- ## 📦 Requirements
21
-
22
- - **React**: ^18.0.0
23
- - **shogun-core**: ^2.0.0
24
- - **Node.js**: ≥18
25
-
26
- ## 🚀 Quick Start
27
-
28
- ### Installation
29
-
30
- ```bash
31
- npm install shogun-button-react shogun-core
32
- # or
33
- yarn add shogun-button-react shogun-core
34
- ```
35
-
36
- ### Updating from 3.x
37
-
38
- If you're upgrading from version 3.x:
39
-
40
- ```bash
41
- yarn upgrade shogun-button-react shogun-core
42
- # or
43
- npm update shogun-button-react shogun-core
44
- ```
45
-
46
- ### Basic Usage
47
-
48
- ```tsx
49
- import React from "react";
50
- import { ShogunButton, ShogunButtonProvider, shogunConnector } from "shogun-button-react";
51
- import "shogun-button-react/styles.css";
52
-
53
- function App() {
54
- const { core, options } = shogunConnector({
55
- appName: "My Awesome App",
56
- // Enable specific authentication methods
57
- showMetamask: true,
58
- showWebauthn: true,
59
- showNostr: true,
60
- showZkProof: true,
61
- // Optional peers
62
- peers: [
63
- "https://gun-manhattan.herokuapp.com/gun"
64
- ],
65
- });
66
-
67
- return (
68
- <ShogunButtonProvider
69
- core={core}
70
- options={options}
71
- onLoginSuccess={(data) => {
72
- console.log("Login successful!", data);
73
- }}
74
- onSignupSuccess={(data) => {
75
- console.log("Account created successfully!", data);
76
- }}
77
- onError={(error) => {
78
- console.error("Authentication error:", error);
79
- }}
80
- >
81
- <div className="app">
82
- <header>
83
- <h1>Welcome to My Awesome App</h1>
84
- <ShogunButton />
85
- </header>
86
- <main>{/* Your app content */}</main>
87
- </div>
88
- </ShogunButtonProvider>
89
- );
90
- }
91
-
92
- export default App;
93
- ```
94
-
95
- ## 🔧 Advanced Configuration
96
-
97
- ### Custom Authentication Options
98
-
99
- ```tsx
100
- const { core, options } = shogunConnector({
101
- appName: "My App",
102
-
103
- // Toggle authentication methods in the UI
104
- showMetamask: true,
105
- showWebauthn: true,
106
- showNostr: true,
107
- showZkProof: true,
108
-
109
- // Network configuration (backward compatible)
110
- peers: [
111
- "https://gun-manhattan.herokuapp.com/gun"
112
- ],
113
-
114
- // ZK-Proof configuration
115
- zkproof: {
116
- enabled: true,
117
- defaultGroupId: "my-app-users",
118
- },
119
-
120
- // Gun Advanced Plugin configuration
121
- enableGunDebug: true,
122
- enableConnectionMonitoring: true,
123
- defaultPageSize: 20,
124
- connectionTimeout: 10000,
125
- });
126
- ```
127
-
128
- ### Advanced Transport Layer Configuration (New in v5.0.0)
129
-
130
- ```tsx
131
- const { core, options } = shogunConnector({
132
- appName: "My App",
133
-
134
- // Use new transport layer system
135
- transport: {
136
- type: "gun", // or "sqlite", "postgresql", "mongodb", "custom"
137
- options: {
138
- peers: ["https://gun-manhattan.herokuapp.com/gun"],
139
- // Additional transport-specific options
140
- }
141
- },
142
-
143
- // Alternative: Use SQLite for local development
144
- transport: {
145
- type: "sqlite",
146
- options: {
147
- filename: "./my-app.db",
148
- // SQLite-specific options
149
- }
150
- },
151
-
152
- // Alternative: Use PostgreSQL for production
153
- transport: {
154
- type: "postgresql",
155
- options: {
156
- host: "localhost",
157
- port: 5432,
158
- database: "myapp",
159
- username: "user",
160
- password: "password",
161
- // PostgreSQL-specific options
162
- }
163
- },
164
-
165
- // Authentication methods
166
- showMetamask: true,
167
- showWebauthn: true,
168
- showNostr: true,
169
- showZkProof: true,
170
- });
171
- ```
172
-
173
- ## 🎯 API Reference
174
-
175
- ### ShogunButtonProvider
176
-
177
- The provider component that supplies Shogun context to your application.
178
-
179
- #### Props
180
-
181
- | Name | Type | Description | Required |
182
- |------|------|-------------|----------|
183
- | `core` | `ShogunCore` | Shogun SDK instance created by `shogunConnector` | ✅ |
184
- | `options` | `ShogunConnectorOptions` | Configuration options | ✅ |
185
- | `onLoginSuccess` | `(data: AuthData) => void` | Callback fired on successful login | ❌ |
186
- | `onSignupSuccess` | `(data: AuthData) => void` | Callback fired on successful signup | ❌ |
187
- | `onError` | `(error: string) => void` | Callback fired when an error occurs | ❌ |
188
-
189
- #### AuthData Interface
190
-
191
- ```typescript
192
- interface AuthData {
193
- userPub: string; // User's public key
194
- username: string; // Display name
195
- password?: string; // Password (if applicable)
196
- seedPhrase?: string; // Seed phrase/trapdoor (for ZK-Proof)
197
- authMethod?: "password" | "web3" | "webauthn" | "nostr" | "zkproof" | "pair";
198
- }
199
- ```
200
-
201
- ### ShogunButton
202
-
203
- The main button component that provides a complete authentication UI with modal dialogs for login, signup, and account management.
204
-
205
- **Features:**
206
- - Multi-method authentication selection
207
- - Password-based login/signup with recovery
208
- - Gun pair export/import for account backup
209
- - Responsive modal design
210
- - Error handling and user feedback
211
-
212
- ### useShogun Hook
213
-
214
- A comprehensive hook to access Shogun authentication state and functions.
215
-
216
- ```tsx
217
- import React, { useEffect } from "react";
218
- import { useShogun } from "shogun-button-react";
219
-
220
- function UserProfile() {
221
- const {
222
- // Authentication state
223
- isLoggedIn,
224
- userPub,
225
- username,
226
-
227
- // Authentication methods
228
- login,
229
- signUp,
230
- logout,
231
-
232
- // Plugin management
233
- hasPlugin,
234
- getPlugin,
235
-
236
- // Account management
237
- exportGunPair,
238
- importGunPair,
239
-
240
- // Data operations
241
- observe,
242
- put,
243
- get,
244
- remove,
245
-
246
- // Advanced Gun hooks
247
- useGunState,
248
- useGunCollection,
249
- useGunConnection,
250
- useGunDebug,
251
- useGunRealtime,
252
- } = useShogun();
253
-
254
- // Example: Login with different methods
255
- const handlePasswordLogin = async () => {
256
- try {
257
- const result = await login("password", "username", "password");
258
- if (result.success) {
259
- console.log("Password login successful!");
260
- }
261
- } catch (error) {
262
- console.error("Login failed:", error);
263
- }
264
- };
265
-
266
- const handleMetaMaskLogin = async () => {
267
- try {
268
- const result = await login("web3");
269
- if (result.success) {
270
- console.log("MetaMask login successful!");
271
- }
272
- } catch (error) {
273
- console.error("MetaMask login failed:", error);
274
- }
275
- };
276
-
277
- const handleWebAuthnLogin = async () => {
278
- try {
279
- const result = await login("webauthn", "username");
280
- if (result.success) {
281
- console.log("WebAuthn login successful!");
282
- }
283
- } catch (error) {
284
- console.error("WebAuthn login failed:", error);
285
- }
286
- };
287
-
288
- const handleZkProofSignup = async () => {
289
- try {
290
- const result = await signUp("zkproof");
291
- if (result.success && result.seedPhrase) {
292
- console.log("ZK-Proof signup successful!");
293
- console.log("SAVE THIS TRAPDOOR:", result.seedPhrase);
294
- // CRITICAL: User must save the trapdoor for account recovery
295
- }
296
- } catch (error) {
297
- console.error("ZK-Proof signup failed:", error);
298
- }
299
- };
300
-
301
- const handleZkProofLogin = async () => {
302
- try {
303
- const trapdoor = "user-saved-trapdoor-here";
304
- const result = await login("zkproof", trapdoor);
305
- if (result.success) {
306
- console.log("ZK-Proof anonymous login successful!");
307
- }
308
- } catch (error) {
309
- console.error("ZK-Proof login failed:", error);
310
- }
311
- };
312
-
313
- // Example: Account backup and recovery
314
- const handleExportAccount = async () => {
315
- try {
316
- const pairData = await exportGunPair("my-secure-password");
317
- console.log("Account exported successfully!");
318
-
319
- // Save to file or copy to clipboard
320
- if (navigator.clipboard) {
321
- await navigator.clipboard.writeText(pairData);
322
- alert("Account data copied to clipboard!");
323
- }
324
- } catch (error) {
325
- console.error("Export failed:", error);
326
- }
327
- };
328
-
329
- const handleImportAccount = async (pairData: string, password?: string) => {
330
- try {
331
- const success = await importGunPair(pairData, password);
332
- if (success) {
333
- console.log("Account imported successfully!");
334
- }
335
- } catch (error) {
336
- console.error("Import failed:", error);
337
- }
338
- };
339
-
340
- // Example: Real-time data observation
341
- useEffect(() => {
342
- if (isLoggedIn) {
343
- const subscription = observe<any>('user/profile').subscribe(data => {
344
- console.log('Profile updated:', data);
345
- });
346
-
347
- return () => subscription.unsubscribe();
348
- }
349
- }, [isLoggedIn, observe]);
350
-
351
- if (!isLoggedIn) {
352
- return <div>Please log in to view your profile</div>;
353
- }
354
-
355
- return (
356
- <div className="user-profile">
357
- <h2>Welcome, {username}!</h2>
358
- <div className="profile-info">
359
- <p><strong>Public Key:</strong> {userPub}</p>
360
- <p><strong>Authentication Method:</strong> {authMethod}</p>
361
- </div>
362
-
363
- <div className="actions">
364
- <button onClick={handleExportAccount}>Export Account</button>
365
- <button onClick={logout}>Logout</button>
366
- </div>
367
- </div>
368
- );
369
- }
370
- ```
371
-
372
- ## 🔌 Advanced Gun Plugin Usage
373
-
374
- ### Using Gun State Hooks
375
-
376
- ```tsx
377
- function UserSettings() {
378
- const { useGunState, useGunCollection } = useShogun();
379
-
380
- // Single value state
381
- const profile = useGunState('user/profile', {
382
- name: '',
383
- email: '',
384
- preferences: {}
385
- });
386
-
387
- // Collection management
388
- const posts = useGunCollection('user/posts', {
389
- pageSize: 10,
390
- sortBy: 'createdAt',
391
- sortOrder: 'desc',
392
- filter: (post) => post.isPublished
393
- });
394
-
395
- const updateProfile = async () => {
396
- await profile.update({
397
- name: 'New Name',
398
- preferences: { theme: 'dark' }
399
- });
400
- };
401
-
402
- const addPost = async () => {
403
- await posts.addItem({
404
- title: 'New Post',
405
- content: 'Post content...',
406
- createdAt: Date.now(),
407
- isPublished: true
408
- });
409
- };
410
-
411
- return (
412
- <div>
413
- <h3>Profile Settings</h3>
414
- {profile.isLoading ? (
415
- <p>Loading...</p>
416
- ) : profile.error ? (
417
- <p>Error: {profile.error}</p>
418
- ) : (
419
- <div>
420
- <input
421
- value={profile.data?.name || ''}
422
- onChange={(e) => profile.update({ name: e.target.value })}
423
- placeholder="Name"
424
- />
425
- <button onClick={updateProfile}>Save Changes</button>
426
- </div>
427
- )}
428
-
429
- <h3>Your Posts ({posts.items.length})</h3>
430
- {posts.isLoading ? (
431
- <p>Loading posts...</p>
432
- ) : (
433
- <div>
434
- {posts.items.map((post, index) => (
435
- <div key={index}>
436
- <h4>{post.title}</h4>
437
- <p>{post.content}</p>
438
- </div>
439
- ))}
440
-
441
- <div className="pagination">
442
- {posts.hasPrevPage && (
443
- <button onClick={posts.prevPage}>Previous</button>
444
- )}
445
- <span>Page {posts.currentPage + 1} of {posts.totalPages}</span>
446
- {posts.hasNextPage && (
447
- <button onClick={posts.nextPage}>Next</button>
448
- )}
449
- </div>
450
- </div>
451
- )}
452
- </div>
453
- );
454
- }
455
- ```
456
-
457
- ### ZK-Proof Anonymous Authentication
458
-
459
- ZK-Proof (Zero-Knowledge Proof) authentication provides complete anonymity using Semaphore protocol. Users can authenticate without revealing their identity.
460
-
461
- ```tsx
462
- function ZkProofExample() {
463
- const { login, signUp } = useShogun();
464
- const [trapdoor, setTrapdoor] = useState("");
465
-
466
- // Signup: Creates anonymous identity and returns trapdoor
467
- const handleSignup = async () => {
468
- try {
469
- const result = await signUp("zkproof");
470
-
471
- if (result.success && result.seedPhrase) {
472
- // CRITICAL: User MUST save this trapdoor!
473
- // It's the ONLY way to recover the anonymous account
474
- console.log("Your trapdoor (save securely):", result.seedPhrase);
475
-
476
- // Recommend user to:
477
- // 1. Write it down on paper
478
- // 2. Store in password manager
479
- // 3. Keep multiple secure copies
480
- alert(`Save this trapdoor securely:\n\n${result.seedPhrase}\n\nYou'll need it to login on other devices!`);
481
- }
482
- } catch (error) {
483
- console.error("ZK-Proof signup failed:", error);
484
- }
485
- };
486
-
487
- // Login: Use saved trapdoor to restore anonymous identity
488
- const handleLogin = async () => {
489
- try {
490
- const result = await login("zkproof", trapdoor);
491
-
492
- if (result.success) {
493
- console.log("Logged in anonymously!");
494
- console.log("Identity commitment:", result.userPub);
495
- }
496
- } catch (error) {
497
- console.error("ZK-Proof login failed:", error);
498
- }
499
- };
500
-
501
- return (
502
- <div>
503
- <h3>Anonymous Authentication with ZK-Proof</h3>
504
-
505
- <div>
506
- <button onClick={handleSignup}>
507
- Create Anonymous Identity
508
- </button>
509
- </div>
510
-
511
- <div>
512
- <input
513
- type="text"
514
- value={trapdoor}
515
- onChange={(e) => setTrapdoor(e.target.value)}
516
- placeholder="Enter your trapdoor to login"
517
- />
518
- <button onClick={handleLogin}>
519
- Login Anonymously
520
- </button>
521
- </div>
522
- </div>
523
- );
524
- }
525
- ```
526
-
527
- **Important Notes about ZK-Proof:**
528
-
529
- - **Trapdoor is Critical**: The trapdoor is like a master password - without it, the account is permanently lost
530
- - **No Recovery**: Unlike traditional auth, there's no "forgot password" - trapdoor loss means permanent account loss
531
- - **Complete Anonymity**: Your identity remains private even from the application
532
- - **Multi-Device Support**: Use the same trapdoor on different devices
533
- - **Privacy-Preserving**: Uses Semaphore protocol for zero-knowledge proofs
534
-
535
- ### Connection Monitoring
536
-
537
- ```tsx
538
- function ConnectionStatus() {
539
- const { useGunConnection, useGunDebug } = useShogun();
540
-
541
- // Monitor connection status
542
- const connection = useGunConnection('user/data');
543
-
544
- // Enable debug logging
545
- useGunDebug('user/data', true);
546
-
547
- return (
548
- <div className="connection-status">
549
- <div className={`status-indicator ${connection.isConnected ? 'connected' : 'disconnected'}`}>
550
- {connection.isConnected ? '🟢 Connected' : '🔴 Disconnected'}
551
- </div>
552
-
553
- {connection.lastSeen && (
554
- <p>Last seen: {connection.lastSeen.toLocaleTimeString()}</p>
555
- )}
556
-
557
- {connection.error && (
558
- <p className="error">Error: {connection.error}</p>
559
- )}
560
- </div>
561
- );
562
- }
563
- ```
564
-
565
- ## 🎨 Customization
566
-
567
- ### CSS Variables
568
-
569
- Customize the appearance using CSS variables:
570
-
571
- ```css
572
- :root {
573
- /* Primary colors */
574
- --shogun-primary: #3b82f6;
575
- --shogun-primary-hover: #2563eb;
576
-
577
- /* Background colors */
578
- --shogun-bg: #ffffff;
579
- --shogun-bg-secondary: #f3f4f6;
580
-
581
- /* Text colors */
582
- --shogun-text: #1f2937;
583
- --shogun-text-secondary: #6b7280;
584
-
585
- /* Border and shadow */
586
- --shogun-border: #e5e7eb;
587
- --shogun-border-radius: 12px;
588
- --shogun-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
589
-
590
- /* Transitions */
591
- --shogun-transition: all 0.2s ease;
592
- }
593
-
594
- /* Dark mode overrides */
595
- @media (prefers-color-scheme: dark) {
596
- :root {
597
- --shogun-bg: #1f2937;
598
- --shogun-bg-secondary: #374151;
599
- --shogun-text: #f3f4f6;
600
- --shogun-text-secondary: #9ca3af;
601
- --shogun-border: #4b5563;
602
- }
603
- }
604
- ```
605
-
606
- ### Custom Styling
607
-
608
- ```css
609
- /* Custom button styles */
610
- .shogun-connect-button {
611
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
612
- border-radius: 25px;
613
- font-weight: 700;
614
- text-transform: uppercase;
615
- letter-spacing: 1px;
616
- }
617
-
618
- /* Custom modal styles */
619
- .shogun-modal {
620
- border-radius: 20px;
621
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
622
- }
623
-
624
- /* Custom form styles */
625
- .shogun-form-group input {
626
- border-radius: 10px;
627
- border: 2px solid transparent;
628
- transition: border-color 0.3s ease;
629
- }
630
-
631
- .shogun-form-group input:focus {
632
- border-color: var(--shogun-primary);
633
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
634
- }
635
- ```
636
-
637
- ## 🔧 Configuration Options
638
-
639
- ### Complete Configuration Interface
640
-
641
- ```typescript
642
- interface ShogunConnectorOptions {
643
- // App information
644
- appName: string;
645
-
646
- // Feature toggles
647
- showMetamask?: boolean;
648
- showWebauthn?: boolean;
649
- showNostr?: boolean;
650
- darkMode?: boolean;
651
-
652
- // Network configuration (backward compatible)
653
- peers?: string[];
654
- authToken?: string;
655
- gunInstance?: IGunInstance<any>;
656
- gunOptions?: any;
657
-
658
- // Transport layer configuration (new in v5.0.0)
659
- transport?: {
660
- type: "gun" | "sqlite" | "postgresql" | "mongodb" | "custom";
661
- options?: any;
662
- customTransport?: any;
663
- };
664
-
665
- // Timeouts and provider configs
666
- timeouts?: {
667
- login?: number;
668
- signup?: number;
669
- operation?: number;
670
- };
671
-
672
- // Gun Advanced Plugin configuration
673
- enableGunDebug?: boolean;
674
- enableConnectionMonitoring?: boolean;
675
- defaultPageSize?: number;
676
- connectionTimeout?: number;
677
- debounceInterval?: number;
678
- }
679
- ```
680
-
681
- ### Connector Result
682
-
683
- ```typescript
684
- interface ShogunConnectorResult {
685
- core: ShogunCore;
686
- options: ShogunConnectorOptions;
687
- setProvider: (provider: any) => boolean;
688
- getCurrentProviderUrl: () => string | null;
689
- registerPlugin: (plugin: any) => boolean;
690
- hasPlugin: (name: string) => boolean;
691
- gunPlugin: null;
692
- }
693
- ```
694
-
695
- ## 🌐 Browser Support
696
-
697
- - **Chrome** ≥ 60
698
- - **Firefox** ≥ 60
699
- - **Safari** ≥ 12
700
- - **Edge** ≥ 79
701
-
702
- ## 📱 Mobile Support
703
-
704
- The library is fully responsive and works seamlessly on mobile devices. All authentication methods are optimized for touch interfaces.
705
-
706
- ## 🔒 Security Features
707
-
708
- - **Encrypted Storage**: Gun pairs can be encrypted with passwords
709
- - **Secure Authentication**: Multiple secure authentication methods
710
- - **Session Management**: Automatic session handling and cleanup
711
- - **Error Handling**: Comprehensive error handling and user feedback
712
-
713
- ## 🚀 Performance
714
-
715
- - **Lazy Loading**: Components load only when needed
716
- - **Optimized Rendering**: Efficient React rendering with proper memoization
717
- - **Connection Pooling**: Smart connection management for optimal performance
718
- - **Debounced Updates**: Prevents excessive re-renders during rapid data changes
719
-
720
- ## 🤝 Contributing
721
-
722
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
723
-
724
- ### Development Setup
725
-
726
- ```bash
727
- # Clone the repository
728
- git clone https://github.com/shogun/shogun-button-react.git
729
-
730
- # Install dependencies
731
- yarn install
732
-
733
- # Start development server
734
- yarn dev
735
-
736
- # Build the library
737
- yarn build
738
-
739
- # Run tests
740
- yarn test
741
- ```
742
-
743
- ## 📄 License
744
-
745
- MIT © [Shogun](https://github.com/shogun)
746
-
747
- ## 🆘 Support
748
-
749
- - **Documentation**: [Full API Reference](https://docs.shogun.dev)
750
- - **Issues**: [GitHub Issues](https://github.com/shogun/shogun-button-react/issues)
751
- - **Discussions**: [GitHub Discussions](https://github.com/shogun/shogun-button-react/discussions)
752
- - **Discord**: [Join our community](https://discord.gg/shogun)
1
+ # Shogun Button React
2
+
3
+ A comprehensive React component library for seamless integration of Shogun authentication into your applications. This library provides a simple yet powerful way to add multi-method authentication, account management, and real-time data synchronization to your React applications.
4
+
5
+ > **Version 5.0.0** - Compatible with shogun-core ^2.0.0
6
+
7
+ ## ✨ Features
8
+
9
+ - 🚀 **Easy Integration** - Simple setup with minimal configuration
10
+ - 🎨 **Customizable UI** - Modern, responsive design with dark mode support
11
+ - 🔒 **Multi-Authentication** - Support for Password, MetaMask, WebAuthn, Nostr, and ZK-Proof
12
+ - 🔑 **Account Management** - Export/import Gun pairs for account backup and recovery
13
+ - 📱 **Responsive Design** - Works seamlessly across all device sizes
14
+ - 🌍 **TypeScript Support** - Full type safety and IntelliSense support
15
+ - 🔌 **Plugin System** - Advanced Gun operations with custom hooks
16
+ - 📊 **Real-time Data** - Reactive data synchronization with RxJS observables
17
+ - ✅ **Robust Foundation** - Built on shogun-core v5.0.0 with 99.86% test coverage
18
+ - 🗄️ **Flexible Storage** - Support for GunDB, SQLite, PostgreSQL, MongoDB via TransportLayer
19
+
20
+ ## 📦 Requirements
21
+
22
+ - **React**: ^18.0.0
23
+ - **shogun-core**: ^2.0.0
24
+ - **Node.js**: ≥18
25
+
26
+ ## 🚀 Quick Start
27
+
28
+ ### Installation
29
+
30
+ ```bash
31
+ npm install shogun-button-react shogun-core
32
+ # or
33
+ yarn add shogun-button-react shogun-core
34
+ ```
35
+
36
+ ### Updating from 3.x
37
+
38
+ If you're upgrading from version 3.x:
39
+
40
+ ```bash
41
+ yarn upgrade shogun-button-react shogun-core
42
+ # or
43
+ npm update shogun-button-react shogun-core
44
+ ```
45
+
46
+ ### Basic Usage
47
+
48
+ ```tsx
49
+ import React from "react";
50
+ import { ShogunButton, ShogunButtonProvider, shogunConnector } from "shogun-button-react";
51
+ import "shogun-button-react/styles.css";
52
+
53
+ function App() {
54
+ const { core, options } = shogunConnector({
55
+ appName: "My Awesome App",
56
+ // Enable specific authentication methods
57
+ showMetamask: true,
58
+ showWebauthn: true,
59
+ showNostr: true,
60
+ showZkProof: true,
61
+ // Optional peers
62
+ peers: [
63
+ "https://gun-manhattan.herokuapp.com/gun"
64
+ ],
65
+ });
66
+
67
+ return (
68
+ <ShogunButtonProvider
69
+ core={core}
70
+ options={options}
71
+ onLoginSuccess={(data) => {
72
+ console.log("Login successful!", data);
73
+ }}
74
+ onSignupSuccess={(data) => {
75
+ console.log("Account created successfully!", data);
76
+ }}
77
+ onError={(error) => {
78
+ console.error("Authentication error:", error);
79
+ }}
80
+ >
81
+ <div className="app">
82
+ <header>
83
+ <h1>Welcome to My Awesome App</h1>
84
+ <ShogunButton />
85
+ </header>
86
+ <main>{/* Your app content */}</main>
87
+ </div>
88
+ </ShogunButtonProvider>
89
+ );
90
+ }
91
+
92
+ export default App;
93
+ ```
94
+
95
+ ## 🔧 Advanced Configuration
96
+
97
+ ### Custom Authentication Options
98
+
99
+ ```tsx
100
+ const { core, options } = shogunConnector({
101
+ appName: "My App",
102
+
103
+ // Toggle authentication methods in the UI
104
+ showMetamask: true,
105
+ showWebauthn: true,
106
+ showNostr: true,
107
+ showZkProof: true,
108
+
109
+ // Network configuration (backward compatible)
110
+ peers: [
111
+ "https://gun-manhattan.herokuapp.com/gun"
112
+ ],
113
+
114
+ // ZK-Proof configuration
115
+ zkproof: {
116
+ enabled: true,
117
+ defaultGroupId: "my-app-users",
118
+ },
119
+
120
+ // Gun Advanced Plugin configuration
121
+ enableGunDebug: true,
122
+ enableConnectionMonitoring: true,
123
+ defaultPageSize: 20,
124
+ connectionTimeout: 10000,
125
+ });
126
+ ```
127
+
128
+ ### Advanced Transport Layer Configuration (New in v5.0.0)
129
+
130
+ ```tsx
131
+ const { core, options } = shogunConnector({
132
+ appName: "My App",
133
+
134
+ // Use new transport layer system
135
+ transport: {
136
+ type: "gun", // or "sqlite", "postgresql", "mongodb", "custom"
137
+ options: {
138
+ peers: ["https://gun-manhattan.herokuapp.com/gun"],
139
+ // Additional transport-specific options
140
+ }
141
+ },
142
+
143
+ // Alternative: Use SQLite for local development
144
+ transport: {
145
+ type: "sqlite",
146
+ options: {
147
+ filename: "./my-app.db",
148
+ // SQLite-specific options
149
+ }
150
+ },
151
+
152
+ // Alternative: Use PostgreSQL for production
153
+ transport: {
154
+ type: "postgresql",
155
+ options: {
156
+ host: "localhost",
157
+ port: 5432,
158
+ database: "myapp",
159
+ username: "user",
160
+ password: "password",
161
+ // PostgreSQL-specific options
162
+ }
163
+ },
164
+
165
+ // Authentication methods
166
+ showMetamask: true,
167
+ showWebauthn: true,
168
+ showNostr: true,
169
+ showZkProof: true,
170
+ });
171
+ ```
172
+
173
+ ## 🎯 API Reference
174
+
175
+ ### ShogunButtonProvider
176
+
177
+ The provider component that supplies Shogun context to your application.
178
+
179
+ #### Props
180
+
181
+ | Name | Type | Description | Required |
182
+ |------|------|-------------|----------|
183
+ | `core` | `ShogunCore` | Shogun SDK instance created by `shogunConnector` | ✅ |
184
+ | `options` | `ShogunConnectorOptions` | Configuration options | ✅ |
185
+ | `onLoginSuccess` | `(data: AuthData) => void` | Callback fired on successful login | ❌ |
186
+ | `onSignupSuccess` | `(data: AuthData) => void` | Callback fired on successful signup | ❌ |
187
+ | `onError` | `(error: string) => void` | Callback fired when an error occurs | ❌ |
188
+
189
+ #### AuthData Interface
190
+
191
+ ```typescript
192
+ interface AuthData {
193
+ userPub: string; // User's public key
194
+ username: string; // Display name
195
+ password?: string; // Password (if applicable)
196
+ seedPhrase?: string; // Seed phrase/trapdoor (for ZK-Proof)
197
+ authMethod?: "password" | "web3" | "webauthn" | "nostr" | "zkproof" | "pair";
198
+ }
199
+ ```
200
+
201
+ ### ShogunButton
202
+
203
+ The main button component that provides a complete authentication UI with modal dialogs for login, signup, and account management.
204
+
205
+ **Features:**
206
+ - Multi-method authentication selection
207
+ - Password-based login/signup with recovery
208
+ - Gun pair export/import for account backup
209
+ - Responsive modal design
210
+ - Error handling and user feedback
211
+
212
+ ### useShogun Hook
213
+
214
+ A comprehensive hook to access Shogun authentication state and functions.
215
+
216
+ ```tsx
217
+ import React, { useEffect } from "react";
218
+ import { useShogun } from "shogun-button-react";
219
+
220
+ function UserProfile() {
221
+ const {
222
+ // Authentication state
223
+ isLoggedIn,
224
+ userPub,
225
+ username,
226
+
227
+ // Authentication methods
228
+ login,
229
+ signUp,
230
+ logout,
231
+
232
+ // Plugin management
233
+ hasPlugin,
234
+ getPlugin,
235
+
236
+ // Account management
237
+ exportGunPair,
238
+ importGunPair,
239
+
240
+ // Data operations
241
+ observe,
242
+ put,
243
+ get,
244
+ remove,
245
+
246
+ // Advanced Gun hooks
247
+ useGunState,
248
+ useGunCollection,
249
+ useGunConnection,
250
+ useGunDebug,
251
+ useGunRealtime,
252
+ } = useShogun();
253
+
254
+ // Example: Login with different methods
255
+ const handlePasswordLogin = async () => {
256
+ try {
257
+ const result = await login("password", "username", "password");
258
+ if (result.success) {
259
+ console.log("Password login successful!");
260
+ }
261
+ } catch (error) {
262
+ console.error("Login failed:", error);
263
+ }
264
+ };
265
+
266
+ const handleMetaMaskLogin = async () => {
267
+ try {
268
+ const result = await login("web3");
269
+ if (result.success) {
270
+ console.log("MetaMask login successful!");
271
+ }
272
+ } catch (error) {
273
+ console.error("MetaMask login failed:", error);
274
+ }
275
+ };
276
+
277
+ const handleWebAuthnLogin = async () => {
278
+ try {
279
+ const result = await login("webauthn", "username");
280
+ if (result.success) {
281
+ console.log("WebAuthn login successful!");
282
+ }
283
+ } catch (error) {
284
+ console.error("WebAuthn login failed:", error);
285
+ }
286
+ };
287
+
288
+ const handleZkProofSignup = async () => {
289
+ try {
290
+ const result = await signUp("zkproof");
291
+ if (result.success && result.seedPhrase) {
292
+ console.log("ZK-Proof signup successful!");
293
+ console.log("SAVE THIS TRAPDOOR:", result.seedPhrase);
294
+ // CRITICAL: User must save the trapdoor for account recovery
295
+ }
296
+ } catch (error) {
297
+ console.error("ZK-Proof signup failed:", error);
298
+ }
299
+ };
300
+
301
+ const handleZkProofLogin = async () => {
302
+ try {
303
+ const trapdoor = "user-saved-trapdoor-here";
304
+ const result = await login("zkproof", trapdoor);
305
+ if (result.success) {
306
+ console.log("ZK-Proof anonymous login successful!");
307
+ }
308
+ } catch (error) {
309
+ console.error("ZK-Proof login failed:", error);
310
+ }
311
+ };
312
+
313
+ // Example: Account backup and recovery
314
+ const handleExportAccount = async () => {
315
+ try {
316
+ const pairData = await exportGunPair("my-secure-password");
317
+ console.log("Account exported successfully!");
318
+
319
+ // Save to file or copy to clipboard
320
+ if (navigator.clipboard) {
321
+ await navigator.clipboard.writeText(pairData);
322
+ alert("Account data copied to clipboard!");
323
+ }
324
+ } catch (error) {
325
+ console.error("Export failed:", error);
326
+ }
327
+ };
328
+
329
+ const handleImportAccount = async (pairData: string, password?: string) => {
330
+ try {
331
+ const success = await importGunPair(pairData, password);
332
+ if (success) {
333
+ console.log("Account imported successfully!");
334
+ }
335
+ } catch (error) {
336
+ console.error("Import failed:", error);
337
+ }
338
+ };
339
+
340
+ // Example: Real-time data observation
341
+ useEffect(() => {
342
+ if (isLoggedIn) {
343
+ const subscription = observe<any>('user/profile').subscribe(data => {
344
+ console.log('Profile updated:', data);
345
+ });
346
+
347
+ return () => subscription.unsubscribe();
348
+ }
349
+ }, [isLoggedIn, observe]);
350
+
351
+ if (!isLoggedIn) {
352
+ return <div>Please log in to view your profile</div>;
353
+ }
354
+
355
+ return (
356
+ <div className="user-profile">
357
+ <h2>Welcome, {username}!</h2>
358
+ <div className="profile-info">
359
+ <p><strong>Public Key:</strong> {userPub}</p>
360
+ <p><strong>Authentication Method:</strong> {authMethod}</p>
361
+ </div>
362
+
363
+ <div className="actions">
364
+ <button onClick={handleExportAccount}>Export Account</button>
365
+ <button onClick={logout}>Logout</button>
366
+ </div>
367
+ </div>
368
+ );
369
+ }
370
+ ```
371
+
372
+ ## 🔌 Advanced Gun Plugin Usage
373
+
374
+ ### Using Gun State Hooks
375
+
376
+ ```tsx
377
+ function UserSettings() {
378
+ const { useGunState, useGunCollection } = useShogun();
379
+
380
+ // Single value state
381
+ const profile = useGunState('user/profile', {
382
+ name: '',
383
+ email: '',
384
+ preferences: {}
385
+ });
386
+
387
+ // Collection management
388
+ const posts = useGunCollection('user/posts', {
389
+ pageSize: 10,
390
+ sortBy: 'createdAt',
391
+ sortOrder: 'desc',
392
+ filter: (post) => post.isPublished
393
+ });
394
+
395
+ const updateProfile = async () => {
396
+ await profile.update({
397
+ name: 'New Name',
398
+ preferences: { theme: 'dark' }
399
+ });
400
+ };
401
+
402
+ const addPost = async () => {
403
+ await posts.addItem({
404
+ title: 'New Post',
405
+ content: 'Post content...',
406
+ createdAt: Date.now(),
407
+ isPublished: true
408
+ });
409
+ };
410
+
411
+ return (
412
+ <div>
413
+ <h3>Profile Settings</h3>
414
+ {profile.isLoading ? (
415
+ <p>Loading...</p>
416
+ ) : profile.error ? (
417
+ <p>Error: {profile.error}</p>
418
+ ) : (
419
+ <div>
420
+ <input
421
+ value={profile.data?.name || ''}
422
+ onChange={(e) => profile.update({ name: e.target.value })}
423
+ placeholder="Name"
424
+ />
425
+ <button onClick={updateProfile}>Save Changes</button>
426
+ </div>
427
+ )}
428
+
429
+ <h3>Your Posts ({posts.items.length})</h3>
430
+ {posts.isLoading ? (
431
+ <p>Loading posts...</p>
432
+ ) : (
433
+ <div>
434
+ {posts.items.map((post, index) => (
435
+ <div key={index}>
436
+ <h4>{post.title}</h4>
437
+ <p>{post.content}</p>
438
+ </div>
439
+ ))}
440
+
441
+ <div className="pagination">
442
+ {posts.hasPrevPage && (
443
+ <button onClick={posts.prevPage}>Previous</button>
444
+ )}
445
+ <span>Page {posts.currentPage + 1} of {posts.totalPages}</span>
446
+ {posts.hasNextPage && (
447
+ <button onClick={posts.nextPage}>Next</button>
448
+ )}
449
+ </div>
450
+ </div>
451
+ )}
452
+ </div>
453
+ );
454
+ }
455
+ ```
456
+
457
+ ### ZK-Proof Anonymous Authentication
458
+
459
+ ZK-Proof (Zero-Knowledge Proof) authentication provides complete anonymity using Semaphore protocol. Users can authenticate without revealing their identity.
460
+
461
+ ```tsx
462
+ function ZkProofExample() {
463
+ const { login, signUp } = useShogun();
464
+ const [trapdoor, setTrapdoor] = useState("");
465
+
466
+ // Signup: Creates anonymous identity and returns trapdoor
467
+ const handleSignup = async () => {
468
+ try {
469
+ const result = await signUp("zkproof");
470
+
471
+ if (result.success && result.seedPhrase) {
472
+ // CRITICAL: User MUST save this trapdoor!
473
+ // It's the ONLY way to recover the anonymous account
474
+ console.log("Your trapdoor (save securely):", result.seedPhrase);
475
+
476
+ // Recommend user to:
477
+ // 1. Write it down on paper
478
+ // 2. Store in password manager
479
+ // 3. Keep multiple secure copies
480
+ alert(`Save this trapdoor securely:\n\n${result.seedPhrase}\n\nYou'll need it to login on other devices!`);
481
+ }
482
+ } catch (error) {
483
+ console.error("ZK-Proof signup failed:", error);
484
+ }
485
+ };
486
+
487
+ // Login: Use saved trapdoor to restore anonymous identity
488
+ const handleLogin = async () => {
489
+ try {
490
+ const result = await login("zkproof", trapdoor);
491
+
492
+ if (result.success) {
493
+ console.log("Logged in anonymously!");
494
+ console.log("Identity commitment:", result.userPub);
495
+ }
496
+ } catch (error) {
497
+ console.error("ZK-Proof login failed:", error);
498
+ }
499
+ };
500
+
501
+ return (
502
+ <div>
503
+ <h3>Anonymous Authentication with ZK-Proof</h3>
504
+
505
+ <div>
506
+ <button onClick={handleSignup}>
507
+ Create Anonymous Identity
508
+ </button>
509
+ </div>
510
+
511
+ <div>
512
+ <input
513
+ type="text"
514
+ value={trapdoor}
515
+ onChange={(e) => setTrapdoor(e.target.value)}
516
+ placeholder="Enter your trapdoor to login"
517
+ />
518
+ <button onClick={handleLogin}>
519
+ Login Anonymously
520
+ </button>
521
+ </div>
522
+ </div>
523
+ );
524
+ }
525
+ ```
526
+
527
+ **Important Notes about ZK-Proof:**
528
+
529
+ - **Trapdoor is Critical**: The trapdoor is like a master password - without it, the account is permanently lost
530
+ - **No Recovery**: Unlike traditional auth, there's no "forgot password" - trapdoor loss means permanent account loss
531
+ - **Complete Anonymity**: Your identity remains private even from the application
532
+ - **Multi-Device Support**: Use the same trapdoor on different devices
533
+ - **Privacy-Preserving**: Uses Semaphore protocol for zero-knowledge proofs
534
+
535
+ ### Connection Monitoring
536
+
537
+ ```tsx
538
+ function ConnectionStatus() {
539
+ const { useGunConnection, useGunDebug } = useShogun();
540
+
541
+ // Monitor connection status
542
+ const connection = useGunConnection('user/data');
543
+
544
+ // Enable debug logging
545
+ useGunDebug('user/data', true);
546
+
547
+ return (
548
+ <div className="connection-status">
549
+ <div className={`status-indicator ${connection.isConnected ? 'connected' : 'disconnected'}`}>
550
+ {connection.isConnected ? '🟢 Connected' : '🔴 Disconnected'}
551
+ </div>
552
+
553
+ {connection.lastSeen && (
554
+ <p>Last seen: {connection.lastSeen.toLocaleTimeString()}</p>
555
+ )}
556
+
557
+ {connection.error && (
558
+ <p className="error">Error: {connection.error}</p>
559
+ )}
560
+ </div>
561
+ );
562
+ }
563
+ ```
564
+
565
+ ## 🎨 Customization
566
+
567
+ ### CSS Variables
568
+
569
+ Customize the appearance using CSS variables:
570
+
571
+ ```css
572
+ :root {
573
+ /* Primary colors */
574
+ --shogun-primary: #3b82f6;
575
+ --shogun-primary-hover: #2563eb;
576
+
577
+ /* Background colors */
578
+ --shogun-bg: #ffffff;
579
+ --shogun-bg-secondary: #f3f4f6;
580
+
581
+ /* Text colors */
582
+ --shogun-text: #1f2937;
583
+ --shogun-text-secondary: #6b7280;
584
+
585
+ /* Border and shadow */
586
+ --shogun-border: #e5e7eb;
587
+ --shogun-border-radius: 12px;
588
+ --shogun-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
589
+
590
+ /* Transitions */
591
+ --shogun-transition: all 0.2s ease;
592
+ }
593
+
594
+ /* Dark mode overrides */
595
+ @media (prefers-color-scheme: dark) {
596
+ :root {
597
+ --shogun-bg: #1f2937;
598
+ --shogun-bg-secondary: #374151;
599
+ --shogun-text: #f3f4f6;
600
+ --shogun-text-secondary: #9ca3af;
601
+ --shogun-border: #4b5563;
602
+ }
603
+ }
604
+ ```
605
+
606
+ ### Custom Styling
607
+
608
+ ```css
609
+ /* Custom button styles */
610
+ .shogun-connect-button {
611
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
612
+ border-radius: 25px;
613
+ font-weight: 700;
614
+ text-transform: uppercase;
615
+ letter-spacing: 1px;
616
+ }
617
+
618
+ /* Custom modal styles */
619
+ .shogun-modal {
620
+ border-radius: 20px;
621
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
622
+ }
623
+
624
+ /* Custom form styles */
625
+ .shogun-form-group input {
626
+ border-radius: 10px;
627
+ border: 2px solid transparent;
628
+ transition: border-color 0.3s ease;
629
+ }
630
+
631
+ .shogun-form-group input:focus {
632
+ border-color: var(--shogun-primary);
633
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
634
+ }
635
+ ```
636
+
637
+ ## 🔧 Configuration Options
638
+
639
+ ### Complete Configuration Interface
640
+
641
+ ```typescript
642
+ interface ShogunConnectorOptions {
643
+ // App information
644
+ appName: string;
645
+
646
+ // Feature toggles
647
+ showMetamask?: boolean;
648
+ showWebauthn?: boolean;
649
+ showNostr?: boolean;
650
+ darkMode?: boolean;
651
+
652
+ // Network configuration (backward compatible)
653
+ peers?: string[];
654
+ authToken?: string;
655
+ gunInstance?: IGunInstance<any>;
656
+ gunOptions?: any;
657
+
658
+ // Transport layer configuration (new in v5.0.0)
659
+ transport?: {
660
+ type: "gun" | "sqlite" | "postgresql" | "mongodb" | "custom";
661
+ options?: any;
662
+ customTransport?: any;
663
+ };
664
+
665
+ // Timeouts and provider configs
666
+ timeouts?: {
667
+ login?: number;
668
+ signup?: number;
669
+ operation?: number;
670
+ };
671
+
672
+ // Gun Advanced Plugin configuration
673
+ enableGunDebug?: boolean;
674
+ enableConnectionMonitoring?: boolean;
675
+ defaultPageSize?: number;
676
+ connectionTimeout?: number;
677
+ debounceInterval?: number;
678
+ }
679
+ ```
680
+
681
+ ### Connector Result
682
+
683
+ ```typescript
684
+ interface ShogunConnectorResult {
685
+ core: ShogunCore;
686
+ options: ShogunConnectorOptions;
687
+ setProvider: (provider: any) => boolean;
688
+ getCurrentProviderUrl: () => string | null;
689
+ registerPlugin: (plugin: any) => boolean;
690
+ hasPlugin: (name: string) => boolean;
691
+ gunPlugin: null;
692
+ }
693
+ ```
694
+
695
+ ## 🌐 Browser Support
696
+
697
+ - **Chrome** ≥ 60
698
+ - **Firefox** ≥ 60
699
+ - **Safari** ≥ 12
700
+ - **Edge** ≥ 79
701
+
702
+ ## 📱 Mobile Support
703
+
704
+ The library is fully responsive and works seamlessly on mobile devices. All authentication methods are optimized for touch interfaces.
705
+
706
+ ## 🔒 Security Features
707
+
708
+ - **Encrypted Storage**: Gun pairs can be encrypted with passwords
709
+ - **Secure Authentication**: Multiple secure authentication methods
710
+ - **Session Management**: Automatic session handling and cleanup
711
+ - **Error Handling**: Comprehensive error handling and user feedback
712
+
713
+ ## 🚀 Performance
714
+
715
+ - **Lazy Loading**: Components load only when needed
716
+ - **Optimized Rendering**: Efficient React rendering with proper memoization
717
+ - **Connection Pooling**: Smart connection management for optimal performance
718
+ - **Debounced Updates**: Prevents excessive re-renders during rapid data changes
719
+
720
+ ## 🤝 Contributing
721
+
722
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
723
+
724
+ ### Development Setup
725
+
726
+ ```bash
727
+ # Clone the repository
728
+ git clone https://github.com/shogun/shogun-button-react.git
729
+
730
+ # Install dependencies
731
+ yarn install
732
+
733
+ # Start development server
734
+ yarn dev
735
+
736
+ # Build the library
737
+ yarn build
738
+
739
+ # Run tests
740
+ yarn test
741
+ ```
742
+
743
+ ## 📄 License
744
+
745
+ MIT © [Shogun](https://github.com/shogun)
746
+
747
+ ## 🆘 Support
748
+
749
+ - **Documentation**: [Full API Reference](https://docs.shogun.dev)
750
+ - **Issues**: [GitHub Issues](https://github.com/shogun/shogun-button-react/issues)
751
+ - **Discussions**: [GitHub Discussions](https://github.com/shogun/shogun-button-react/discussions)
752
+ - **Discord**: [Join our community](https://discord.gg/shogun)