shogun-core 1.1.4 → 1.2.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 +61 -1327
- package/dist/browser/shogun-core.js +1 -1
- package/dist/browser/shogun-core.js.LICENSE.txt +0 -9
- package/dist/browser/shogun-core.light.js +1 -1
- package/dist/browser/shogun-core.vendors.light.js +1 -1
- package/dist/browser.js +27 -11
- package/dist/core.js +603 -0
- package/dist/{gun → gundb}/crypto.js +38 -8
- package/dist/gundb/gun.js +676 -0
- package/dist/{gun → gundb}/index.js +0 -5
- package/dist/{gun → gundb}/utils.js +6 -0
- package/dist/index.js +1 -807
- package/dist/plugins/index.js +15 -28
- package/dist/plugins/{stealth → nostr}/index.js +3 -4
- package/dist/plugins/nostr/nostrConnector.js +656 -0
- package/dist/plugins/nostr/nostrConnectorPlugin.js +259 -0
- package/dist/plugins/{metamask → web3}/index.js +2 -2
- package/dist/plugins/{metamask/metamask.js → web3/web3Connector.js} +8 -8
- package/dist/plugins/{metamask/metamaskPlugin.js → web3/web3ConnectorPlugin.js} +32 -42
- package/dist/plugins/webauthn/webauthnPlugin.js +4 -0
- package/dist/types/browser.d.ts +9 -4
- package/dist/types/core.d.ts +221 -0
- package/dist/types/{gun → gundb}/crypto.d.ts +20 -5
- package/dist/types/{gun → gundb}/gun.d.ts +56 -28
- package/dist/types/gundb/index.d.ts +1 -0
- package/dist/types/{gun → gundb}/utils.d.ts +1 -0
- package/dist/types/index.d.ts +1 -282
- package/dist/types/plugins/index.d.ts +7 -10
- package/dist/types/plugins/nostr/index.d.ts +3 -0
- package/dist/types/plugins/nostr/nostrConnector.d.ts +111 -0
- package/dist/types/plugins/nostr/nostrConnectorPlugin.d.ts +87 -0
- package/dist/types/plugins/nostr/types.d.ts +122 -0
- package/dist/types/plugins/web3/index.d.ts +3 -0
- package/dist/types/plugins/{metamask → web3}/types.d.ts +4 -4
- package/dist/types/plugins/{metamask/metamask.d.ts → web3/web3Connector.d.ts} +7 -7
- package/dist/types/plugins/{metamask/metamaskPlugin.d.ts → web3/web3ConnectorPlugin.d.ts} +4 -4
- package/dist/types/shogun.js +40 -15
- package/dist/types/types/shogun.d.ts +67 -67
- package/dist/types/utils/errorHandler.d.ts +39 -36
- package/dist/types/utils/utility.d.ts +0 -4
- package/dist/utils/errorHandler.js +43 -40
- package/dist/utils/utility.js +0 -8
- package/package.json +2 -2
- package/dist/config.js +0 -18
- package/dist/gun/gun.js +0 -542
- package/dist/plugins/stealth/stealth.js +0 -176
- package/dist/plugins/stealth/stealthPlugin.js +0 -113
- package/dist/plugins/stealth/types.js +0 -2
- package/dist/plugins/utils/stubs/didStub.js +0 -35
- package/dist/plugins/utils/stubs/stealthStub.js +0 -35
- package/dist/plugins/utils/stubs/webauthnStub.js +0 -29
- package/dist/plugins/wallet/index.js +0 -20
- package/dist/plugins/wallet/types.js +0 -15
- package/dist/plugins/wallet/walletManager.js +0 -1832
- package/dist/plugins/wallet/walletPlugin.js +0 -236
- package/dist/types/config.d.ts +0 -15
- package/dist/types/gun/index.d.ts +0 -6
- package/dist/types/gun/types.d.ts +0 -2
- package/dist/types/plugins/metamask/index.d.ts +0 -3
- package/dist/types/plugins/stealth/index.d.ts +0 -3
- package/dist/types/plugins/stealth/stealth.d.ts +0 -93
- package/dist/types/plugins/stealth/stealthPlugin.d.ts +0 -60
- package/dist/types/plugins/stealth/types.d.ts +0 -93
- package/dist/types/plugins/utils/stubs/didStub.d.ts +0 -15
- package/dist/types/plugins/utils/stubs/stealthStub.d.ts +0 -15
- package/dist/types/plugins/utils/stubs/webauthnStub.d.ts +0 -13
- package/dist/types/plugins/wallet/index.d.ts +0 -3
- package/dist/types/plugins/wallet/types.d.ts +0 -167
- package/dist/types/plugins/wallet/walletManager.d.ts +0 -306
- package/dist/types/plugins/wallet/walletPlugin.d.ts +0 -126
- package/dist/types/utils/stubs/didStub.d.ts +0 -15
- package/dist/types/utils/stubs/stealthStub.d.ts +0 -15
- package/dist/types/utils/stubs/webauthnStub.d.ts +0 -13
- package/dist/utils/stubs/didStub.js +0 -35
- package/dist/utils/stubs/stealthStub.js +0 -35
- package/dist/utils/stubs/webauthnStub.js +0 -29
- /package/dist/{gun → gundb}/errors.js +0 -0
- /package/dist/{gun → gundb}/rxjs-integration.js +0 -0
- /package/dist/{gun → plugins/nostr}/types.js +0 -0
- /package/dist/plugins/{metamask → web3}/types.js +0 -0
- /package/dist/types/{gun → gundb}/errors.d.ts +0 -0
- /package/dist/types/{gun → gundb}/rxjs-integration.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,1376 +1,110 @@
|
|
|
1
1
|
# Shogun Core 📦
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/shogun-core)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://www.typescriptlang.org/)
|
|
6
6
|
|
|
7
|
-
## Table of Contents
|
|
8
|
-
|
|
9
|
-
- [Overview](#overview)
|
|
10
|
-
- [Why Choose Shogun?](#why-choose-shogun)
|
|
11
|
-
- [The Web3 Challenge](#the-web3-challenge)
|
|
12
|
-
- [The Shogun Solution](#the-shogun-solution)
|
|
13
|
-
- [Core Features](#core-features)
|
|
14
|
-
- [Authentication](#authentication)
|
|
15
|
-
- [Storage](#storage)
|
|
16
|
-
- [Reactive Data](#reactive-data)
|
|
17
|
-
- [Wallet Management](#wallet-management)
|
|
18
|
-
- [Security](#security)
|
|
19
|
-
- [Technologies Used](#technologies-used)
|
|
20
|
-
- [Core Technologies](#core-technologies)
|
|
21
|
-
- [Security & Cryptography](#security--cryptography)
|
|
22
|
-
- [Development & Build Tools](#development--build-tools)
|
|
23
|
-
- [Browser Support](#browser-support)
|
|
24
|
-
- [Getting Started](#getting-started)
|
|
25
|
-
- [Installation](#installation)
|
|
26
|
-
- [Basic Usage](#basic-usage)
|
|
27
|
-
- [Authentication Methods](#authentication-methods)
|
|
28
|
-
- [Reactive Programming with RxJS](#reactive-programming-with-rxjs)
|
|
29
|
-
- [Use Cases](#use-cases)
|
|
30
|
-
- [Documentation](#documentation)
|
|
31
|
-
- [Custom Plugins](#custom-plugins)
|
|
32
|
-
- [Creating a Plugin](#creating-a-plugin)
|
|
33
|
-
- [Registering a Plugin](#registering-a-plugin)
|
|
34
|
-
- [Using the Plugin](#using-the-plugin)
|
|
35
|
-
- [Stealth Transactions](#stealth-transactions)
|
|
36
|
-
- [Contracts SDK](#contracts-sdk)
|
|
37
|
-
- [Browser Integration](#browser-integration)
|
|
38
|
-
- [Setup](#setup)
|
|
39
|
-
- [Examples](#examples)
|
|
40
|
-
- [Compatibility](#compatibility)
|
|
41
|
-
- [Contributing](#contribute)
|
|
42
|
-
- [License](#license)
|
|
43
|
-
|
|
44
7
|
## Overview
|
|
45
8
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
## Why Choose Shogun?
|
|
49
|
-
|
|
50
|
-
### The Web3 Challenge
|
|
51
|
-
|
|
52
|
-
In today's Web3 landscape, developers face significant challenges in managing user authentication and crypto operations while maintaining security and usability. Traditional solutions often require compromises between security, usability, and decentralization.
|
|
53
|
-
|
|
54
|
-
### The Shogun Solution
|
|
55
|
-
|
|
56
|
-
Shogun combines GunDB's decentralization, modern authentication standards, and the Ethereum ecosystem into a comprehensive SDK that prioritizes both security and user experience.
|
|
57
|
-
|
|
58
|
-
## Core Features
|
|
59
|
-
|
|
60
|
-
### Authentication
|
|
61
|
-
|
|
62
|
-
- **Multi-layer Support**:
|
|
63
|
-
- WebAuthn for biometric and hardware authentication
|
|
64
|
-
- MetaMask integration
|
|
65
|
-
- Traditional username/password
|
|
66
|
-
- **Flexible Implementation**: Adapt to different user needs and security requirements
|
|
67
|
-
|
|
68
|
-
### Storage
|
|
69
|
-
|
|
70
|
-
- **Decentralized with GunDB**:
|
|
71
|
-
- True data decentralization
|
|
72
|
-
- Offline resilience
|
|
73
|
-
- Real-time synchronization
|
|
74
|
-
- **Local Storage Support**: Efficient client-side data persistence
|
|
75
|
-
|
|
76
|
-
### Reactive Data
|
|
77
|
-
|
|
78
|
-
- **RxJS Integration**:
|
|
79
|
-
- Observe real-time data changes through Observables
|
|
80
|
-
- Reactive collections with filtering and transformations
|
|
81
|
-
- Computed values derived from multiple data sources
|
|
82
|
-
- Simplified data flow with RxJS operators
|
|
83
|
-
- **Two Programming Models**:
|
|
84
|
-
- Promise-based for traditional async workflows
|
|
85
|
-
- Observable-based for reactive programming
|
|
86
|
-
|
|
87
|
-
### Wallet Management
|
|
88
|
-
|
|
89
|
-
- **BIP-44 Standard**: Compatible with major wallet services
|
|
90
|
-
- **Stealth Addresses**: Enhanced transaction privacy
|
|
91
|
-
- **Backup & Recovery**: Robust security measures
|
|
92
|
-
|
|
93
|
-
### Security
|
|
94
|
-
|
|
95
|
-
- **End-to-End Encryption**: Protected sensitive data
|
|
96
|
-
- **Modern Standards**: WebAuthn and best practices
|
|
97
|
-
- **Audit Trail**: Complete operation tracking
|
|
98
|
-
|
|
99
|
-
## Technologies Used
|
|
9
|
+
Shogun SDK is a comprehensive toolkit for Web3 developers that simplifies decentralized authentication, wallet management, and data storage. It combines GunDB's decentralization with modern authentication standards and blockchain integration to provide a secure and user-friendly foundation for decentralized applications.
|
|
100
10
|
|
|
101
|
-
|
|
11
|
+
## Key Features
|
|
102
12
|
|
|
103
|
-
- **
|
|
104
|
-
- **
|
|
105
|
-
- **
|
|
106
|
-
- **
|
|
107
|
-
- **WebAuthn**: W3C standard for passwordless authentication
|
|
13
|
+
- **[Authentication](wiki/core.md#authentication)**: Multi-method auth with WebAuthn, Ethereum wallets, and traditional approaches
|
|
14
|
+
- **[Storage](wiki/gundb.md)**: Decentralized with GunDB, with offline resilience and real-time sync
|
|
15
|
+
- **[Reactive Data](wiki/gundb.md#reactive-programming-with-rxjs)**: RxJS integration for real-time reactive data flows
|
|
16
|
+
- **[Security](wiki/core.md)**: End-to-end encryption and modern security standards
|
|
108
17
|
|
|
109
|
-
|
|
18
|
+
## Core Components
|
|
110
19
|
|
|
111
|
-
- **
|
|
112
|
-
- **
|
|
113
|
-
- **
|
|
20
|
+
- **[Core SDK](wiki/core.md)**: Main SDK entry point and configuration
|
|
21
|
+
- **[GunDB Integration](wiki/gundb.md)**: Enhanced wrapper around GunDB with additional features
|
|
22
|
+
- **[WebAuthn](wiki/webauthn.md)**: Passwordless authentication with biometrics and security keys
|
|
23
|
+
- **[Web3](wiki/web3.md)**: Ethereum wallet integration and authentication
|
|
24
|
+
- **[Nostr](wiki/nostr.md)**: Bitcoin and Nostr protocol integration
|
|
25
|
+
- **[Contracts SDK](wiki/contracts.md)**: Tools for interacting with Shogun Protocol smart contracts
|
|
114
26
|
|
|
115
|
-
|
|
27
|
+
## Additional Plugins
|
|
116
28
|
|
|
117
|
-
|
|
118
|
-
- **TypeDoc**: Automated documentation generation
|
|
119
|
-
- **Prettier**: Code formatting and style consistency
|
|
29
|
+
For extended functionality, install these separate plugins:
|
|
120
30
|
|
|
121
|
-
|
|
31
|
+
- **[@shogun/bip44](https://github.com/scobru/shogun-BIP44)**: BIP-44 HD wallet management
|
|
32
|
+
- **[@shogun/stealth-address](https://github.com/scobru/shogun-stealth-address)**: Privacy-enhancing stealth addresses
|
|
122
33
|
|
|
123
|
-
|
|
124
|
-
- **IndexedDB/LocalStorage**: Client-side data persistence
|
|
125
|
-
- **WebSocket**: Real-time P2P communication
|
|
126
|
-
|
|
127
|
-
## Getting Started
|
|
128
|
-
|
|
129
|
-
### Installation
|
|
34
|
+
## Installation
|
|
130
35
|
|
|
131
36
|
```bash
|
|
132
37
|
npm install shogun-core
|
|
133
38
|
# or
|
|
134
39
|
yarn add shogun-core
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### Basic Usage
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
import {
|
|
141
|
-
ShogunCore,
|
|
142
|
-
CorePlugins,
|
|
143
|
-
PluginCategory,
|
|
144
|
-
initShogunBrowser,
|
|
145
|
-
} from "shogun-core";
|
|
146
|
-
|
|
147
|
-
// Inizializzazione per ambiente Node.js
|
|
148
|
-
const shogun = new ShogunCore({
|
|
149
|
-
gundb: {
|
|
150
|
-
peers: ["https://your-gun-peer.com/gun"],
|
|
151
|
-
localStorage: true,
|
|
152
|
-
},
|
|
153
|
-
providerUrl: "https://ethereum-rpc-url.com",
|
|
154
|
-
// Abilitazione plugin integrati
|
|
155
|
-
webauthn: { enabled: true },
|
|
156
|
-
metamask: { enabled: true },
|
|
157
|
-
stealth: { enabled: true },
|
|
158
|
-
walletManager: { enabled: true },
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// Oppure per browser (consigliato per applicazioni web)
|
|
162
|
-
const shogunBrowser = initShogunBrowser({
|
|
163
|
-
gundb: {
|
|
164
|
-
peers: ["https://your-gun-peer.com/gun"],
|
|
165
|
-
websocket: true,
|
|
166
|
-
},
|
|
167
|
-
providerUrl: "https://ethereum-rpc-url.com",
|
|
168
|
-
webauthn: {
|
|
169
|
-
enabled: true,
|
|
170
|
-
rpName: "Your App",
|
|
171
|
-
rpId: "yourdomain.com",
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// Authentication examples
|
|
176
|
-
// Autenticazione standard
|
|
177
|
-
const passwordLogin = await shogun.login("username", "password");
|
|
178
|
-
|
|
179
|
-
// Accesso ai plugin
|
|
180
|
-
const webauthnPlugin = shogun.getPlugin(CorePlugins.WebAuthn);
|
|
181
|
-
const metamaskPlugin = shogun.getPlugin(CorePlugins.MetaMask);
|
|
182
|
-
const walletPlugin = shogun.getPlugin(CorePlugins.Wallet);
|
|
183
|
-
|
|
184
|
-
if (webauthnPlugin) {
|
|
185
|
-
const credentials = await webauthnPlugin.generateCredentials(
|
|
186
|
-
"username",
|
|
187
|
-
null,
|
|
188
|
-
true
|
|
189
|
-
); // true = login
|
|
190
|
-
if (credentials.success) {
|
|
191
|
-
// Usa le credenziali per autenticare...
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (metamaskPlugin) {
|
|
196
|
-
// Login con MetaMask
|
|
197
|
-
try {
|
|
198
|
-
// Connessione e autenticazione con MetaMask
|
|
199
|
-
const connectResult = await metamaskPlugin.connectMetaMask();
|
|
200
|
-
if (connectResult.success) {
|
|
201
|
-
const address = connectResult.address;
|
|
202
|
-
// Login usando l'indirizzo
|
|
203
|
-
const loginResult = await metamaskPlugin.loginWithMetaMask(address);
|
|
204
|
-
console.log("MetaMask login result:", loginResult);
|
|
205
|
-
}
|
|
206
|
-
} catch (error) {
|
|
207
|
-
console.error("Error during MetaMask login:", error);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Wallet operations
|
|
212
|
-
if (walletPlugin) {
|
|
213
|
-
const wallet = await walletPlugin.createWallet();
|
|
214
|
-
const mainWallet = walletPlugin.getMainWallet();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Utilizzo dello Stealth Plugin
|
|
218
|
-
if (shogun.hasPlugin(CorePlugins.Stealth)) {
|
|
219
|
-
const stealthPlugin = shogun.getPlugin(CorePlugins.Stealth);
|
|
220
|
-
|
|
221
|
-
// Genera un indirizzo stealth per ricevere pagamenti in modo privato
|
|
222
|
-
const stealthAddress = await stealthPlugin.generateStealthAddress();
|
|
223
|
-
console.log("Indirizzo stealth generato:", stealthAddress);
|
|
224
40
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const amount = "0.01"; // Quantità in ETH
|
|
228
|
-
const txResult = await stealthPlugin.createStealthTransaction(
|
|
229
|
-
receiverStealthAddress,
|
|
230
|
-
amount
|
|
231
|
-
);
|
|
232
|
-
console.log("Transazione stealth inviata:", txResult);
|
|
233
|
-
|
|
234
|
-
// Scansiona la blockchain per trovare pagamenti stealth indirizzati a te
|
|
235
|
-
const payments = await stealthPlugin.scanStealthPayments();
|
|
236
|
-
console.log("Pagamenti stealth trovati:", payments);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Ottenere i plugin per categoria
|
|
240
|
-
const walletPlugins = shogun.getPluginsByCategory(PluginCategory.Wallet);
|
|
241
|
-
const authPlugins = shogun.getPluginsByCategory(PluginCategory.Authentication);
|
|
242
|
-
console.log(
|
|
243
|
-
`Found ${walletPlugins.length} wallet plugins and ${authPlugins.length} auth plugins`
|
|
244
|
-
);
|
|
41
|
+
# Optional plugins
|
|
42
|
+
npm install @shogun/bip44 @shogun/stealth-address
|
|
245
43
|
```
|
|
246
44
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
Shogun provides a modern approach to access authentication methods via the `getAuthenticationMethod` API. This simplifies working with different authentication types by providing a consistent interface.
|
|
250
|
-
|
|
251
|
-
```typescript
|
|
252
|
-
// Recommended modern approach to access authentication methods
|
|
253
|
-
// Approach 1: Get the standard password authentication
|
|
254
|
-
const passwordAuth = shogun.getAuthenticationMethod("password");
|
|
255
|
-
const loginResult = await passwordAuth.login("username", "password123");
|
|
256
|
-
const signupResult = await passwordAuth.signUp("newuser", "securepassword");
|
|
257
|
-
|
|
258
|
-
// Approach 2: Get the WebAuthn authentication (if enabled)
|
|
259
|
-
const webauthnAuth = shogun.getAuthenticationMethod("webauthn");
|
|
260
|
-
if (webauthnAuth) {
|
|
261
|
-
// WebAuthn is available
|
|
262
|
-
const isSupported = await webauthnAuth.isSupported();
|
|
263
|
-
if (isSupported) {
|
|
264
|
-
const credentials = await webauthnAuth.generateCredentials(
|
|
265
|
-
"username",
|
|
266
|
-
null,
|
|
267
|
-
true
|
|
268
|
-
);
|
|
269
|
-
// Use the credentials...
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Approach 3: Get the MetaMask authentication (if enabled)
|
|
274
|
-
const metamaskAuth = shogun.getAuthenticationMethod("metamask");
|
|
275
|
-
if (metamaskAuth) {
|
|
276
|
-
// MetaMask is available
|
|
277
|
-
const isAvailable = await metamaskAuth.isAvailable();
|
|
278
|
-
if (isAvailable) {
|
|
279
|
-
const connectResult = await metamaskAuth.connectMetaMask();
|
|
280
|
-
if (connectResult.success) {
|
|
281
|
-
const loginResult = await metamaskAuth.login(connectResult.address);
|
|
282
|
-
console.log("Logged in with MetaMask:", loginResult);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Example: Dynamic authentication based on user choice
|
|
288
|
-
function authenticateUser(
|
|
289
|
-
method: "password" | "webauthn" | "metamask",
|
|
290
|
-
username: string,
|
|
291
|
-
password?: string
|
|
292
|
-
) {
|
|
293
|
-
const auth = shogun.getAuthenticationMethod(method);
|
|
294
|
-
|
|
295
|
-
if (!auth) {
|
|
296
|
-
console.error(`Authentication method ${method} not available`);
|
|
297
|
-
return Promise.resolve({ success: false, error: "Method not available" });
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
switch (method) {
|
|
301
|
-
case "password":
|
|
302
|
-
return auth.login(username, password);
|
|
303
|
-
case "webauthn":
|
|
304
|
-
return auth.generateCredentials(username).then((creds) => {
|
|
305
|
-
if (creds.success) {
|
|
306
|
-
return auth.login(username);
|
|
307
|
-
}
|
|
308
|
-
return { success: false, error: "WebAuthn failed" };
|
|
309
|
-
});
|
|
310
|
-
case "metamask":
|
|
311
|
-
return auth.connectMetaMask().then((result) => {
|
|
312
|
-
if (result.success) {
|
|
313
|
-
return auth.login(result.address);
|
|
314
|
-
}
|
|
315
|
-
return { success: false, error: "MetaMask connection failed" };
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Usage
|
|
321
|
-
authenticateUser("password", "username", "password123").then((result) => {
|
|
322
|
-
console.log("Authentication result:", result);
|
|
323
|
-
});
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Reactive Programming with RxJS
|
|
327
|
-
|
|
328
|
-
Shogun SDK provides first-class RxJS integration, enabling reactive programming patterns with GunDB:
|
|
329
|
-
|
|
330
|
-
```typescript
|
|
331
|
-
import { map, filter } from "rxjs/operators";
|
|
332
|
-
|
|
333
|
-
// Observe a user profile in real-time
|
|
334
|
-
shogun.observe<{ name: string; status: string }>("users/profile/123").subscribe(
|
|
335
|
-
(profile) => console.log("Profile updated:", profile),
|
|
336
|
-
(error) => console.error("Error observing profile:", error)
|
|
337
|
-
);
|
|
338
|
-
|
|
339
|
-
// Work with reactive collections
|
|
340
|
-
const todos$ = shogun.match<{ id: string; task: string; completed: boolean }>(
|
|
341
|
-
"todos"
|
|
342
|
-
);
|
|
343
|
-
todos$.subscribe((todos) => console.log("All todos:", todos));
|
|
344
|
-
|
|
345
|
-
// Filter collections with RxJS operators
|
|
346
|
-
todos$
|
|
347
|
-
.pipe(map((todos) => todos.filter((todo) => !todo.completed)))
|
|
348
|
-
.subscribe((pendingTodos) => console.log("Pending todos:", pendingTodos));
|
|
349
|
-
|
|
350
|
-
// Update data reactively
|
|
351
|
-
shogun
|
|
352
|
-
.rxPut<{ name: string; status: string }>("users/profile/123", {
|
|
353
|
-
name: "John Doe",
|
|
354
|
-
status: "online",
|
|
355
|
-
})
|
|
356
|
-
.subscribe(() => console.log("Profile updated"));
|
|
357
|
-
|
|
358
|
-
// Create computed values from multiple data sources
|
|
359
|
-
shogun
|
|
360
|
-
.compute<
|
|
361
|
-
any,
|
|
362
|
-
{ username: string; pendingCount: number; completedCount: number }
|
|
363
|
-
>(["todos", "users/profile/123"], (todos, profile) => ({
|
|
364
|
-
username: profile.name,
|
|
365
|
-
pendingCount: todos.filter((t) => !t.completed).length,
|
|
366
|
-
completedCount: todos.filter((t) => t.completed).length,
|
|
367
|
-
}))
|
|
368
|
-
.subscribe((stats) => console.log("Dashboard stats:", stats));
|
|
369
|
-
|
|
370
|
-
// Work with user data
|
|
371
|
-
if (shogun.isLoggedIn()) {
|
|
372
|
-
shogun
|
|
373
|
-
.observeUser<{ theme: string; notifications: boolean }>("preferences")
|
|
374
|
-
.subscribe((prefs) => console.log("User preferences:", prefs));
|
|
375
|
-
}
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
### Advanced GunDB Features
|
|
379
|
-
|
|
380
|
-
Shogun Core includes advanced GunDB features that allow you to build complex and robust decentralized applications.
|
|
381
|
-
|
|
382
|
-
#### Repository Pattern
|
|
383
|
-
|
|
384
|
-
The Repository Pattern provides an elegant abstraction for data access, with support for typing, transformation, and encryption.
|
|
385
|
-
|
|
386
|
-
```typescript
|
|
387
|
-
import { ShogunCore, GunRepository } from "shogun-core";
|
|
388
|
-
|
|
389
|
-
// Define an interface for your data type
|
|
390
|
-
interface User {
|
|
391
|
-
id?: string;
|
|
392
|
-
name: string;
|
|
393
|
-
email: string;
|
|
394
|
-
role: string;
|
|
395
|
-
lastLogin?: number;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// Create a typed repository class
|
|
399
|
-
class UserRepository extends GunRepository<User> {
|
|
400
|
-
constructor(shogun: ShogunCore) {
|
|
401
|
-
// Initialize with options: userScope=true, encryption=true
|
|
402
|
-
super(shogun.gun, "users", {
|
|
403
|
-
userScope: true,
|
|
404
|
-
useEncryption: true,
|
|
405
|
-
encryptionKey: shogun.gun.getCurrentUser()?.user._?.sea,
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// Implement transformation from raw data to entity
|
|
410
|
-
protected mapToEntity(data: any): User {
|
|
411
|
-
return {
|
|
412
|
-
id: data.id,
|
|
413
|
-
name: data.name || "",
|
|
414
|
-
email: data.email || "",
|
|
415
|
-
role: data.role || "user",
|
|
416
|
-
lastLogin: data.lastLogin || Date.now(),
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// Implement transformation from entity to data to save
|
|
421
|
-
protected mapToData(entity: User): any {
|
|
422
|
-
// Remove computed or unnecessary fields
|
|
423
|
-
const { id, ...data } = entity;
|
|
424
|
-
return data;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Add entity-specific methods
|
|
428
|
-
async findByRole(role: string): Promise<User[]> {
|
|
429
|
-
const all = await this.findAll();
|
|
430
|
-
return all.filter((user) => user.role === role);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Usage:
|
|
435
|
-
const shogun = new ShogunCore({
|
|
436
|
-
/* config */
|
|
437
|
-
});
|
|
438
|
-
const userRepo = new UserRepository(shogun);
|
|
439
|
-
|
|
440
|
-
// Create a new user
|
|
441
|
-
const userId = await userRepo.save({
|
|
442
|
-
name: "John Smith",
|
|
443
|
-
email: "john@example.com",
|
|
444
|
-
role: "admin",
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
// Find a specific user
|
|
448
|
-
const user = await userRepo.findById(userId);
|
|
449
|
-
|
|
450
|
-
// Update a user
|
|
451
|
-
await userRepo.update(userId, { role: "superadmin" });
|
|
452
|
-
|
|
453
|
-
// Delete a user
|
|
454
|
-
await userRepo.remove(userId);
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
#### Distributed Consensus
|
|
458
|
-
|
|
459
|
-
The Consensus module allows you to implement decentralized decision-making mechanisms based on voting.
|
|
460
|
-
|
|
461
|
-
```typescript
|
|
462
|
-
import { ShogunCore } from "shogun-core";
|
|
463
|
-
|
|
464
|
-
const shogun = new ShogunCore({
|
|
465
|
-
/* config */
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
// Consensus configuration (optional)
|
|
469
|
-
const consensusConfig = {
|
|
470
|
-
threshold: 0.66, // Require 66% of votes in favor
|
|
471
|
-
timeWindow: 3600000, // 1 hour voting window
|
|
472
|
-
minVotes: 5, // Require at least 5 votes
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
// Access the consensus system
|
|
476
|
-
const consensus = shogun.gun.consensus(consensusConfig);
|
|
477
|
-
|
|
478
|
-
// 1. Propose a change
|
|
479
|
-
async function proposeChange() {
|
|
480
|
-
const proposalId = await consensus.proposeChange(
|
|
481
|
-
"config-update",
|
|
482
|
-
{ maxUsers: 1000, featureFlag: true },
|
|
483
|
-
{ importance: "high" }
|
|
484
|
-
);
|
|
485
|
-
console.log(`Proposal created: ${proposalId}`);
|
|
486
|
-
return proposalId;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// 2. Vote on a proposal
|
|
490
|
-
async function vote(proposalId, approve) {
|
|
491
|
-
await consensus.vote(proposalId, approve, "Reason for vote");
|
|
492
|
-
console.log(`Vote recorded: ${approve ? "Approved" : "Rejected"}`);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// 3. Check proposal status
|
|
496
|
-
async function checkProposal(proposalId) {
|
|
497
|
-
const proposal = await consensus.getProposal(proposalId);
|
|
498
|
-
console.log(`Proposal status: ${proposal.status}`);
|
|
499
|
-
|
|
500
|
-
// Count votes
|
|
501
|
-
const voteCount = await consensus.countVotes(proposalId);
|
|
502
|
-
console.log(
|
|
503
|
-
`Votes: ${voteCount.approvalCount} approvals, ${voteCount.rejectionCount} rejections`
|
|
504
|
-
);
|
|
505
|
-
console.log(
|
|
506
|
-
`The proposal is ${voteCount.approved ? "approved" : "rejected or pending"}`
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
#### Immutable Data Space (Frozen Space)
|
|
512
|
-
|
|
513
|
-
The Frozen Space provides a mechanism for immutable data, ideal for logs, audit trails, and content archiving.
|
|
514
|
-
|
|
515
|
-
```typescript
|
|
516
|
-
import { ShogunCore } from "shogun-core";
|
|
517
|
-
|
|
518
|
-
const shogun = new ShogunCore({
|
|
519
|
-
/* config */
|
|
520
|
-
});
|
|
521
|
-
|
|
522
|
-
// Save immutable data
|
|
523
|
-
async function savePermanentData() {
|
|
524
|
-
const data = {
|
|
525
|
-
content: "This content cannot be modified",
|
|
526
|
-
timestamp: Date.now(),
|
|
527
|
-
author: "John Smith",
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
// Add to Frozen Space
|
|
531
|
-
await shogun.gun.addToFrozenSpace("documents", "doc1", data);
|
|
532
|
-
console.log("Document saved immutably");
|
|
533
|
-
|
|
534
|
-
// Alternative: use content hash as key
|
|
535
|
-
const contentHash = await shogun.gun.addHashedToFrozenSpace(
|
|
536
|
-
"documents",
|
|
537
|
-
data
|
|
538
|
-
);
|
|
539
|
-
console.log(`Document saved with hash: ${contentHash}`);
|
|
540
|
-
|
|
541
|
-
return contentHash;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// Retrieve immutable data
|
|
545
|
-
async function getPermanentData(hash) {
|
|
546
|
-
// Retrieve data using hash, with integrity verification
|
|
547
|
-
const data = await shogun.gun.getHashedFrozenData("documents", hash, true);
|
|
548
|
-
console.log("Document retrieved:", data);
|
|
549
|
-
return data;
|
|
550
|
-
}
|
|
551
|
-
```
|
|
552
|
-
|
|
553
|
-
#### Authorization Certificates
|
|
554
|
-
|
|
555
|
-
The certificate system enables decentralized and delegated authorizations.
|
|
45
|
+
## Quick Start
|
|
556
46
|
|
|
557
47
|
```typescript
|
|
558
48
|
import { ShogunCore } from "shogun-core";
|
|
559
49
|
|
|
50
|
+
// Initialize for Node.js environment
|
|
560
51
|
const shogun = new ShogunCore({
|
|
561
|
-
|
|
52
|
+
peers: ["https://your-gun-peer.com/gun"],
|
|
53
|
+
scope: "app-namespace",
|
|
54
|
+
|
|
55
|
+
// Enable core plugins
|
|
56
|
+
webauthn: { enabled: true },
|
|
57
|
+
ethereum: { enabled: true },
|
|
58
|
+
bitcoin: { enabled: true }
|
|
562
59
|
});
|
|
563
60
|
|
|
564
|
-
//
|
|
565
|
-
|
|
566
|
-
// Get the key pair from the current user
|
|
567
|
-
const pair = shogun.gun.getCurrentUser()?.user._?.sea;
|
|
568
|
-
|
|
569
|
-
// Generate a single certificate
|
|
570
|
-
const cert = await shogun.gun.issueCert({
|
|
571
|
-
pair,
|
|
572
|
-
tag: "write", // Authorization type
|
|
573
|
-
dot: "tasks", // Authorized path
|
|
574
|
-
users: "*", // For all users ('*') or specific ('~pubKey')
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
// Generate multiple certificates at once
|
|
578
|
-
const certs = await shogun.gun.generateCerts({
|
|
579
|
-
pair,
|
|
580
|
-
list: [
|
|
581
|
-
{ tag: "read", dot: "profiles", users: "*" },
|
|
582
|
-
{ tag: "write", dot: "profiles", users: "~ABCDEF" }, // Specific user
|
|
583
|
-
{ tag: "admin", dot: "settings", personal: true }, // For personal use only
|
|
584
|
-
],
|
|
585
|
-
});
|
|
61
|
+
// Authentication
|
|
62
|
+
const loginResult = await shogun.login("username", "password");
|
|
586
63
|
|
|
587
|
-
|
|
588
|
-
|
|
64
|
+
// Access core plugins
|
|
65
|
+
const webauthnPlugin = shogun.getPlugin("webauthn");
|
|
66
|
+
const web3Plugin = shogun.getPlugin("web3");
|
|
67
|
+
const nostrPlugin = shogun.getPlugin("nostr");
|
|
589
68
|
|
|
590
|
-
//
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
console.log(`Certificate is ${isValid ? "valid" : "invalid"}`);
|
|
69
|
+
// Optional: Use external plugins
|
|
70
|
+
import { HDWalletPlugin } from "@shogun/bip44";
|
|
71
|
+
import { StealthPlugin } from "@shogun/stealth-address";
|
|
594
72
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
console.log("Certificate policy:", policy);
|
|
73
|
+
shogun.registerPlugin(new HDWalletPlugin());
|
|
74
|
+
shogun.registerPlugin(new StealthPlugin());
|
|
598
75
|
|
|
599
|
-
|
|
600
|
-
|
|
76
|
+
const bip44Plugin = shogun.getPlugin("bip44");
|
|
77
|
+
const stealthPlugin = shogun.getPlugin("stealth");
|
|
601
78
|
```
|
|
602
79
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
The Collections API simplifies managing collections of data with common operations.
|
|
606
|
-
|
|
607
|
-
```typescript
|
|
608
|
-
import { ShogunCore } from "shogun-core";
|
|
609
|
-
|
|
610
|
-
const shogun = new ShogunCore({
|
|
611
|
-
/* config */
|
|
612
|
-
});
|
|
613
|
-
|
|
614
|
-
// Access the Collections module
|
|
615
|
-
const collections = shogun.gun.collections();
|
|
616
|
-
|
|
617
|
-
// Add an item to a collection
|
|
618
|
-
async function addToCollection() {
|
|
619
|
-
const itemId = await collections.add("products", {
|
|
620
|
-
name: "Smartphone XYZ",
|
|
621
|
-
price: 499.99,
|
|
622
|
-
category: "electronics",
|
|
623
|
-
inStock: true,
|
|
624
|
-
});
|
|
625
|
-
console.log(`Product added with ID: ${itemId}`);
|
|
626
|
-
return itemId;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
// Update an item
|
|
630
|
-
async function updateCollectionItem(id) {
|
|
631
|
-
await collections.update("products", id, {
|
|
632
|
-
price: 449.99,
|
|
633
|
-
inStock: false,
|
|
634
|
-
});
|
|
635
|
-
console.log("Product updated");
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
// Retrieve all items
|
|
639
|
-
async function getAllItems() {
|
|
640
|
-
const items = await collections.findAll("products");
|
|
641
|
-
console.log(`Found ${items.length} products`);
|
|
642
|
-
return items;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
// Retrieve a specific item
|
|
646
|
-
async function getItem(id) {
|
|
647
|
-
const item = await collections.findById("products", id);
|
|
648
|
-
console.log("Product found:", item);
|
|
649
|
-
return item;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
// Remove an item
|
|
653
|
-
async function removeItem(id) {
|
|
654
|
-
await collections.remove("products", id);
|
|
655
|
-
console.log("Product removed");
|
|
656
|
-
}
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
#### Advanced Cryptographic Utilities
|
|
660
|
-
|
|
661
|
-
Shogun Core provides advanced cryptographic utilities for encryption, signing, and hash management.
|
|
662
|
-
|
|
663
|
-
```typescript
|
|
664
|
-
import { ShogunCore } from "shogun-core";
|
|
665
|
-
|
|
666
|
-
const shogun = new ShogunCore({
|
|
667
|
-
/* config */
|
|
668
|
-
});
|
|
669
|
-
|
|
670
|
-
// Cryptographic operations examples
|
|
671
|
-
async function cryptoExamples() {
|
|
672
|
-
// Generate key pair
|
|
673
|
-
const keyPair = await shogun.gun.generateKeyPair();
|
|
674
|
-
|
|
675
|
-
// Encryption
|
|
676
|
-
const encrypted = await shogun.gun.encrypt("Secret message", keyPair.epriv);
|
|
677
|
-
const decrypted = await shogun.gun.decrypt(encrypted, keyPair.epriv);
|
|
678
|
-
|
|
679
|
-
// Signing and verification
|
|
680
|
-
const signed = await shogun.gun.sign({ data: "Authenticated data" }, keyPair);
|
|
681
|
-
const verified = await shogun.gun.verify(signed, keyPair.pub);
|
|
682
|
-
|
|
683
|
-
// Hashing
|
|
684
|
-
const textHash = await shogun.gun.hashText("Text to hash");
|
|
685
|
-
const objHash = await shogun.gun.hashObj({
|
|
686
|
-
complex: "object",
|
|
687
|
-
with: ["arrays"],
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
// Short hashes (useful for identifiers)
|
|
691
|
-
const shortHash = await shogun.gun.getShortHash(
|
|
692
|
-
"user@example.com",
|
|
693
|
-
"salt123"
|
|
694
|
-
);
|
|
695
|
-
|
|
696
|
-
// URL-safe hashes
|
|
697
|
-
const safeHash = shogun.gun.safeHash(textHash);
|
|
698
|
-
const originalHash = shogun.gun.unsafeHash(safeHash);
|
|
699
|
-
|
|
700
|
-
return {
|
|
701
|
-
encrypted,
|
|
702
|
-
decrypted,
|
|
703
|
-
verified,
|
|
704
|
-
textHash,
|
|
705
|
-
objHash,
|
|
706
|
-
shortHash,
|
|
707
|
-
safeHash,
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// End-to-end encryption between users
|
|
712
|
-
async function encryptForUser(receiverPub) {
|
|
713
|
-
const senderPair = shogun.gun.getCurrentUser()?.user._?.sea;
|
|
714
|
-
const receiverKey = { epub: receiverPub };
|
|
715
|
-
|
|
716
|
-
// Encrypt data for a specific recipient
|
|
717
|
-
const message = "This message is only readable by the recipient";
|
|
718
|
-
const encrypted = await shogun.gun.encFor(message, senderPair, receiverKey);
|
|
80
|
+
## Documentation
|
|
719
81
|
|
|
720
|
-
|
|
721
|
-
}
|
|
82
|
+
For detailed documentation on each component, please refer to the wiki pages:
|
|
722
83
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
84
|
+
- **[Core SDK Documentation](wiki/core.md)**
|
|
85
|
+
- **[GunDB Integration](wiki/gundb.md)**
|
|
86
|
+
- **[WebAuthn Plugin](wiki/webauthn.md)**
|
|
87
|
+
- **[Web3 Plugin](wiki/web3.md)**
|
|
88
|
+
- **[Nostr Plugin](wiki/nostr.md)**
|
|
89
|
+
- **[Contracts SDK](wiki/contracts.md)**
|
|
727
90
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
senderKey,
|
|
732
|
-
receiverPair
|
|
733
|
-
);
|
|
91
|
+
External plugin documentation:
|
|
92
|
+
- **[BIP44 HD Wallet Plugin](https://github.com/scobru/shogun-BIP44)**
|
|
93
|
+
- **[Stealth Address Plugin](https://github.com/scobru/shogun-stealth-address)**
|
|
734
94
|
|
|
735
|
-
|
|
736
|
-
}
|
|
737
|
-
```
|
|
95
|
+
Full technical documentation is available [here](https://shogun-core-docs.vercel.app/).
|
|
738
96
|
|
|
739
97
|
## Use Cases
|
|
740
98
|
|
|
741
99
|
Shogun is particularly suitable for:
|
|
742
100
|
|
|
743
|
-
- **dApps**: Decentralized applications requiring user authentication and wallet management
|
|
744
|
-
- **Web Wallets**: Implementation of crypto wallets directly in the browser
|
|
745
|
-
- **Social dApps**: Social applications requiring decentralized storage and crypto identities
|
|
746
|
-
- **Privacy-Focused Apps**: Applications needing stealth features and advanced privacy
|
|
747
|
-
- **Real-time Applications**: Chat apps, live dashboards, and collaborative tools using reactive data
|
|
748
|
-
- **Reactive UIs**: User interfaces that need to respond to data changes in real-time.
|
|
749
|
-
|
|
750
|
-
## Documentation
|
|
751
|
-
|
|
752
|
-
Shogun SDK includes a complete technical documentation generated with TSDoc:
|
|
753
|
-
|
|
754
|
-
Read the documentation [here](https://shogun-core-docs.vercel.app/)
|
|
755
|
-
|
|
756
|
-
- **Local documentation**: View the documentation by opening `./docs/index.html`
|
|
757
|
-
- **Main classes**: View `./docs/classes/` for details on the main classes
|
|
758
|
-
- **Interfaces**: View `./docs/interfaces/` for details on the interfaces
|
|
759
|
-
|
|
760
|
-
## Custom Plugins
|
|
761
|
-
|
|
762
|
-
Shogun SDK supports extending its functionality through custom plugins. This allows you to add new features while maintaining system modularity.
|
|
763
|
-
|
|
764
|
-
### Creating a Plugin
|
|
765
|
-
|
|
766
|
-
1. Create a new class that extends `BasePlugin` or directly implements the `ShogunPlugin` interface:
|
|
767
|
-
|
|
768
|
-
```typescript
|
|
769
|
-
import { BasePlugin } from "shogun-core/src/plugins/base";
|
|
770
|
-
import { ShogunCore } from "shogun-core";
|
|
771
|
-
import { PluginCategory } from "shogun-core/src/types/shogun";
|
|
772
|
-
|
|
773
|
-
// Define an interface for the plugin's public functionality
|
|
774
|
-
export interface MyPluginInterface {
|
|
775
|
-
exampleFunction(): void;
|
|
776
|
-
// Other public functions
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
// Implement the plugin by extending BasePlugin
|
|
780
|
-
export class MyPlugin extends BasePlugin implements MyPluginInterface {
|
|
781
|
-
// Required properties
|
|
782
|
-
name = "my-plugin";
|
|
783
|
-
version = "1.0.0";
|
|
784
|
-
description = "My custom plugin for shogun-core";
|
|
785
|
-
|
|
786
|
-
// Initialization
|
|
787
|
-
initialize(core: ShogunCore): void {
|
|
788
|
-
super.initialize(core);
|
|
789
|
-
// Specific initialization logic
|
|
790
|
-
console.log("MyPlugin initialized");
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
// Implement interface functions
|
|
794
|
-
exampleFunction(): void {
|
|
795
|
-
const core = this.assertInitialized();
|
|
796
|
-
// Implementation...
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
// Optional: implement destroy method
|
|
800
|
-
destroy(): void {
|
|
801
|
-
// Cleanup resources
|
|
802
|
-
super.destroy();
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
```
|
|
806
|
-
|
|
807
|
-
### Registering a Plugin
|
|
808
|
-
|
|
809
|
-
There are two ways to register a plugin with Shogun Core:
|
|
810
|
-
|
|
811
|
-
1. **Manual registration** after creating the ShogunCore instance:
|
|
812
|
-
|
|
813
|
-
```typescript
|
|
814
|
-
import { ShogunCore, PluginCategory } from "shogun-core";
|
|
815
|
-
import { MyPlugin } from "./my-plugin";
|
|
816
|
-
|
|
817
|
-
// Create ShogunCore instance
|
|
818
|
-
const shogun = new ShogunCore({
|
|
819
|
-
// Configuration...
|
|
820
|
-
});
|
|
821
|
-
|
|
822
|
-
// Create and register the plugin
|
|
823
|
-
const myPlugin = new MyPlugin();
|
|
824
|
-
myPlugin._category = PluginCategory.Utility; // Optional: assign a category
|
|
825
|
-
shogun.register(myPlugin);
|
|
826
|
-
```
|
|
827
|
-
|
|
828
|
-
2. **Automatic registration** during initialization:
|
|
829
|
-
|
|
830
|
-
```typescript
|
|
831
|
-
import { ShogunCore } from "shogun-core";
|
|
832
|
-
import { MyPlugin } from "./my-plugin";
|
|
833
|
-
|
|
834
|
-
const shogun = new ShogunCore({
|
|
835
|
-
// Configuration...
|
|
836
|
-
plugins: {
|
|
837
|
-
autoRegister: [new MyPlugin()],
|
|
838
|
-
},
|
|
839
|
-
});
|
|
840
|
-
```
|
|
841
|
-
|
|
842
|
-
### Using the Plugin
|
|
843
|
-
|
|
844
|
-
Once registered, you can access the plugin in two ways:
|
|
845
|
-
|
|
846
|
-
1. **Direct access by name**:
|
|
847
|
-
|
|
848
|
-
```typescript
|
|
849
|
-
const plugin = shogun.getPlugin<MyPluginInterface>("my-plugin");
|
|
850
|
-
if (plugin) {
|
|
851
|
-
plugin.exampleFunction();
|
|
852
|
-
}
|
|
853
|
-
```
|
|
854
|
-
|
|
855
|
-
2. **Access by category**:
|
|
856
|
-
|
|
857
|
-
```typescript
|
|
858
|
-
import { PluginCategory } from "shogun-core";
|
|
859
|
-
|
|
860
|
-
const utilityPlugins = shogun.getPluginsByCategory(PluginCategory.Utility);
|
|
861
|
-
console.log(`Found ${utilityPlugins.length} utility plugins`);
|
|
862
|
-
|
|
863
|
-
// Use the found plugins
|
|
864
|
-
utilityPlugins.forEach((plugin) => {
|
|
865
|
-
console.log(`Plugin: ${plugin.name}, version: ${plugin.version}`);
|
|
866
|
-
});
|
|
867
|
-
```
|
|
868
|
-
|
|
869
|
-
Available categories include:
|
|
870
|
-
|
|
871
|
-
- `PluginCategory.Authentication`: plugins for authentication
|
|
872
|
-
- `PluginCategory.Wallet`: plugins for wallet management
|
|
873
|
-
- `PluginCategory.Privacy`: plugins for privacy and anonymization
|
|
874
|
-
- `PluginCategory.Identity`: plugins for decentralized identity
|
|
875
|
-
- `PluginCategory.Utility`: plugins for other functionalities
|
|
876
|
-
|
|
877
|
-
## Stealth Transactions
|
|
878
|
-
|
|
879
|
-
Shogun SDK supports stealth transactions for enhanced privacy in blockchain operations. The Stealth plugin allows creating stealth addresses that hide the true recipient of a transaction.
|
|
880
|
-
|
|
881
|
-
```typescript
|
|
882
|
-
import { ShogunCore, CorePlugins } from "shogun-core";
|
|
883
|
-
|
|
884
|
-
// Initialize Shogun with the Stealth plugin enabled
|
|
885
|
-
const shogun = new ShogunCore({
|
|
886
|
-
// Configuration...
|
|
887
|
-
stealth: { enabled: true },
|
|
888
|
-
});
|
|
889
|
-
|
|
890
|
-
// Access the Stealth plugin
|
|
891
|
-
const stealthPlugin = shogun.getPlugin(CorePlugins.Stealth);
|
|
892
|
-
|
|
893
|
-
// 1. Generate ephemeral keys
|
|
894
|
-
async function generateEphemeralKeys() {
|
|
895
|
-
const ephemeralKeys = await stealthPlugin.generateEphemeralKeyPair();
|
|
896
|
-
console.log("Ephemeral private key:", ephemeralKeys.privateKey);
|
|
897
|
-
console.log("Ephemeral public key:", ephemeralKeys.publicKey);
|
|
898
|
-
return ephemeralKeys;
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
// 2. Retrieve the user's stealth keys
|
|
902
|
-
async function getMyStealthKeys() {
|
|
903
|
-
const stealthKeys = await stealthPlugin.getStealthKeys();
|
|
904
|
-
console.log("Viewing key:", stealthKeys.viewingKey);
|
|
905
|
-
console.log("Spending key:", stealthKeys.spendingKey);
|
|
906
|
-
return stealthKeys;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
// 3. Generate a stealth address for the recipient
|
|
910
|
-
async function createStealthAddressForRecipient(recipientViewingPublicKey, recipientSpendingPublicKey) {
|
|
911
|
-
try {
|
|
912
|
-
// Generate a stealth address for the recipient
|
|
913
|
-
const stealthAddressResult = await stealthPlugin.generateStealthAddress(
|
|
914
|
-
recipientViewingPublicKey,
|
|
915
|
-
recipientSpendingPublicKey
|
|
916
|
-
);
|
|
917
|
-
|
|
918
|
-
console.log("Generated stealth address:", stealthAddressResult.stealthAddress);
|
|
919
|
-
console.log("Ephemeral public key:", stealthAddressResult.ephemeralPublicKey);
|
|
920
|
-
console.log("Encrypted random number:", stealthAddressResult.encryptedRandomNumber);
|
|
921
|
-
|
|
922
|
-
return stealthAddressResult;
|
|
923
|
-
} catch (error) {
|
|
924
|
-
console.error("Error generating stealth address:", error);
|
|
925
|
-
throw error;
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
// 4. Open a received stealth address
|
|
930
|
-
async function openReceivedStealthAddress(stealthAddress, encryptedRandomNumber, ephemeralPublicKey) {
|
|
931
|
-
try {
|
|
932
|
-
// Open a stealth address using the user's keys
|
|
933
|
-
const wallet = await stealthPlugin.openStealthAddress(
|
|
934
|
-
stealthAddress,
|
|
935
|
-
encryptedRandomNumber,
|
|
936
|
-
ephemeralPublicKey
|
|
937
|
-
);
|
|
938
|
-
|
|
939
|
-
console.log("Derived wallet address:", wallet.address);
|
|
940
|
-
console.log("Wallet private key:", wallet.privateKey);
|
|
941
|
-
|
|
942
|
-
// This wallet can be used to access funds sent to the stealth address
|
|
943
|
-
return wallet;
|
|
944
|
-
} catch (error) {
|
|
945
|
-
console.error("Error opening stealth address:", error);
|
|
946
|
-
throw error;
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
// 5. Send funds to a stealth address (using ethers.js separately)
|
|
951
|
-
async function sendFundsToStealthAddress(stealthAddress, amountInEth) {
|
|
952
|
-
try {
|
|
953
|
-
// Get a wallet to send the transaction
|
|
954
|
-
const walletPlugin = shogun.getPlugin(CorePlugins.Wallet);
|
|
955
|
-
const senderWallet = walletPlugin.getMainWallet();
|
|
956
|
-
|
|
957
|
-
// Prepare the transaction using ethers.js
|
|
958
|
-
const tx = {
|
|
959
|
-
to: stealthAddress,
|
|
960
|
-
value: ethers.parseEther(amountInEth)
|
|
961
|
-
};
|
|
962
|
-
|
|
963
|
-
// Send the transaction
|
|
964
|
-
const txResponse = await senderWallet.sendTransaction(tx);
|
|
965
|
-
console.log("Transaction sent:", txResponse.hash);
|
|
966
|
-
|
|
967
|
-
// Wait for confirmation
|
|
968
|
-
const receipt = await txResponse.wait();
|
|
969
|
-
console.log("Transaction confirmed in block:", receipt.blockNumber);
|
|
970
|
-
|
|
971
|
-
return receipt;
|
|
972
|
-
} catch (error) {
|
|
973
|
-
console.error("Error sending funds to stealth address:", error);
|
|
974
|
-
throw error;
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
```
|
|
978
|
-
|
|
979
|
-
### Benefits of Stealth Transactions
|
|
980
|
-
|
|
981
|
-
- **Enhanced Privacy**: Stealth addresses hide the true identity of the recipient
|
|
982
|
-
- **Unlinkable Transactions**: Each transaction uses a different address
|
|
983
|
-
- **Compatibility**: Works with any Ethereum wallet
|
|
984
|
-
- **Security**: Only the recipient can derive the private key needed to access the funds
|
|
985
|
-
|
|
986
|
-
### How It Works
|
|
987
|
-
|
|
988
|
-
1. **Stealth Keys**: Each user has a pair of viewing and spending keys
|
|
989
|
-
2. **Address Generation**: The sender generates a unique stealth address for the recipient using their public keys
|
|
990
|
-
3. **Sending Funds**: The sender transfers funds to the generated stealth address
|
|
991
|
-
4. **Funds Recovery**: The recipient can derive the private key of the stealth address using the encryptedRandomNumber and ephemeralPublicKey provided by the sender
|
|
992
|
-
5. **Secure Access**: Only the legitimate recipient can calculate the private key needed to move the funds
|
|
993
|
-
|
|
994
|
-
### Implementation Notes
|
|
995
|
-
|
|
996
|
-
- Shogun's stealth protocol uses asymmetric cryptography to ensure that only the intended recipient can derive the private key of the stealth address
|
|
997
|
-
- The implementation allows the creation of ephemeral wallets for each transaction
|
|
998
|
-
- The communication of necessary information (ephemeralPublicKey, encryptedRandomNumber) takes place off-chain between sender and recipient
|
|
999
|
-
|
|
1000
|
-
## Contracts SDK
|
|
1001
|
-
|
|
1002
|
-
Shogun integrates a complete system for verification and interaction with blockchain relays, offering functionality to verify subscriptions, identities, and manage decentralized relays.
|
|
1003
|
-
|
|
1004
|
-
The Relay system consists of three main contracts:
|
|
1005
|
-
|
|
1006
|
-
1. **Registry**: Central registry of all available relays
|
|
1007
|
-
2. **SimpleRelay**: Individual relays that manage subscriptions and public keys
|
|
1008
|
-
3. **EntryPoint**: Centralized access point for interacting with multiple relays
|
|
1009
|
-
|
|
1010
|
-
```typescript
|
|
1011
|
-
import {
|
|
1012
|
-
Registry,
|
|
1013
|
-
SimpleRelay,
|
|
1014
|
-
EntryPoint,
|
|
1015
|
-
RegistryConfig,
|
|
1016
|
-
SimpleRelayConfig,
|
|
1017
|
-
EntryPointConfig
|
|
1018
|
-
} from "shogun-core/src/contracts";
|
|
1019
|
-
|
|
1020
|
-
// Registry configuration
|
|
1021
|
-
const registryConfig: RegistryConfig = {
|
|
1022
|
-
registryAddress: "0xRegistryContractAddress",
|
|
1023
|
-
providerUrl: "https://ethereum-rpc-url.com"
|
|
1024
|
-
};
|
|
1025
|
-
|
|
1026
|
-
// Initialize the Registry
|
|
1027
|
-
const registry = new Registry(registryConfig);
|
|
1028
|
-
|
|
1029
|
-
// Find a relay by URL
|
|
1030
|
-
async function findRelayByUrl(url: string) {
|
|
1031
|
-
const relayAddress = await registry.findRelayByUrl(url);
|
|
1032
|
-
console.log(`Relay found at address: ${relayAddress}`);
|
|
1033
|
-
return relayAddress;
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
// Configuration for a specific SimpleRelay
|
|
1037
|
-
const relayConfig: SimpleRelayConfig = {
|
|
1038
|
-
relayAddress: "0xRelayContractAddress",
|
|
1039
|
-
registryAddress: "0xRegistryContractAddress",
|
|
1040
|
-
providerUrl: "https://ethereum-rpc-url.com"
|
|
1041
|
-
};
|
|
1042
|
-
|
|
1043
|
-
// Initialize the SimpleRelay
|
|
1044
|
-
const relay = new SimpleRelay(relayConfig);
|
|
1045
|
-
|
|
1046
|
-
// Check if an address has an active subscription
|
|
1047
|
-
async function checkSubscription(userAddress: string) {
|
|
1048
|
-
const isActive = await relay.isSubscriptionActive(userAddress);
|
|
1049
|
-
console.log(`User subscription ${userAddress} is ${isActive ? 'active' : 'inactive'}`);
|
|
1050
|
-
return isActive;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
// Check if a public key is authorized
|
|
1054
|
-
async function checkPublicKeyAuthorization(pubKey: string) {
|
|
1055
|
-
const isAuthorized = await relay.isAuthorizedByPubKey(pubKey);
|
|
1056
|
-
console.log(`Public key is ${isAuthorized ? 'authorized' : 'unauthorized'}`);
|
|
1057
|
-
return isAuthorized;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
// Configuration for EntryPoint
|
|
1061
|
-
const entryPointConfig: EntryPointConfig = {
|
|
1062
|
-
entryPointAddress: "0xEntryPointContractAddress",
|
|
1063
|
-
registryAddress: "0xRegistryContractAddress",
|
|
1064
|
-
providerUrl: "https://ethereum-rpc-url.com"
|
|
1065
|
-
};
|
|
1066
|
-
|
|
1067
|
-
// Initialize EntryPoint
|
|
1068
|
-
const entryPoint = new EntryPoint(entryPointConfig);
|
|
1069
|
-
|
|
1070
|
-
// Subscribe to a relay via URL
|
|
1071
|
-
async function subscribeToRelayByUrl(
|
|
1072
|
-
relayUrl: string,
|
|
1073
|
-
months: number,
|
|
1074
|
-
pubKey: string,
|
|
1075
|
-
value: bigint
|
|
1076
|
-
) {
|
|
1077
|
-
const txResponse = await entryPoint.subscribeViaUrl(relayUrl, months, pubKey, value);
|
|
1078
|
-
if (txResponse) {
|
|
1079
|
-
console.log(`Subscription created with tx hash: ${txResponse.hash}`);
|
|
1080
|
-
await txResponse.wait();
|
|
1081
|
-
console.log("Subscription confirmed!");
|
|
1082
|
-
}
|
|
1083
|
-
return txResponse;
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
// Check subscriptions across multiple relays for a user
|
|
1087
|
-
async function checkMultipleSubscriptions(userAddress: string, relayAddresses: string[]) {
|
|
1088
|
-
const subscriptionStatuses = await entryPoint.batchCheckSubscriptions(
|
|
1089
|
-
userAddress,
|
|
1090
|
-
relayAddresses
|
|
1091
|
-
);
|
|
1092
|
-
|
|
1093
|
-
console.log("Subscription statuses:");
|
|
1094
|
-
relayAddresses.forEach((addr, i) => {
|
|
1095
|
-
console.log(`- Relay ${addr}: ${subscriptionStatuses[i] ? 'Active' : 'Inactive'}`);
|
|
1096
|
-
});
|
|
1097
|
-
|
|
1098
|
-
return subscriptionStatuses;
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
// Get network statistics
|
|
1102
|
-
async function getSystemStatistics() {
|
|
1103
|
-
const stats = await entryPoint.getStatistics();
|
|
1104
|
-
if (stats) {
|
|
1105
|
-
console.log("System statistics:");
|
|
1106
|
-
console.log(`- Total users: ${stats.userCount}`);
|
|
1107
|
-
console.log(`- Total subscriptions: ${stats.totalSubscriptions}`);
|
|
1108
|
-
console.log(`- Total processed amount: ${ethers.formatEther(stats.totalAmountProcessed)} ETH`);
|
|
1109
|
-
console.log(`- Total fees collected: ${ethers.formatEther(stats.totalFeesCollected)} ETH`);
|
|
1110
|
-
}
|
|
1111
|
-
return stats;
|
|
1112
|
-
}
|
|
1113
|
-
```
|
|
1114
|
-
Read more in the [Contracts SDK](https://github.com/scobru/shogun-contracts/blob/main/README.md) documentation.
|
|
1115
|
-
|
|
1116
|
-
### Main Features
|
|
1117
|
-
|
|
1118
|
-
#### Registry
|
|
1119
|
-
|
|
1120
|
-
- **Relay Management**: Registration, updating, and deactivation of relays
|
|
1121
|
-
- **Relay Search**: Find relays by URL or owner
|
|
1122
|
-
- **Relay Information**: Details about each registered relay
|
|
1123
|
-
|
|
1124
|
-
#### SimpleRelay
|
|
1125
|
-
|
|
1126
|
-
- **Subscription Management**: Verification and management of user subscriptions
|
|
1127
|
-
- **Key Authorization**: Verification of authorized public keys
|
|
1128
|
-
- **Operational Configuration**: Management of prices, duration, and URL
|
|
1129
|
-
|
|
1130
|
-
#### EntryPoint
|
|
1131
|
-
|
|
1132
|
-
- **Centralized Management**: Unified interface for all relays
|
|
1133
|
-
- **Multi-Relay Subscription**: Subscribe to multiple relays in a single transaction
|
|
1134
|
-
- **Batch Verification**: Check subscriptions and public keys across multiple relays
|
|
1135
|
-
|
|
1136
|
-
### Additional Utilities
|
|
1137
|
-
|
|
1138
|
-
The Contracts module also includes utilities for:
|
|
1139
|
-
|
|
1140
|
-
- Getting all registered relay URLs
|
|
1141
|
-
- Retrieving public keys registered across multiple relays
|
|
1142
|
-
- Viewing relay performance statistics
|
|
1143
|
-
- Monitoring relay system events and activities
|
|
1144
|
-
|
|
1145
|
-
```typescript
|
|
1146
|
-
import {
|
|
1147
|
-
getRelayUrls,
|
|
1148
|
-
getRegisteredPubKeys,
|
|
1149
|
-
getNetworkSummary,
|
|
1150
|
-
subscribeToRelayEvents,
|
|
1151
|
-
RelayEventType
|
|
1152
|
-
} from "shogun-core/src/contracts";
|
|
1153
|
-
|
|
1154
|
-
// Example of using the utilities
|
|
1155
|
-
async function relaySystemOverview() {
|
|
1156
|
-
// Get all relay URLs
|
|
1157
|
-
const relayUrls = await getRelayUrls(registry);
|
|
1158
|
-
console.log(`Found ${relayUrls.length} relays in the system`);
|
|
1159
|
-
|
|
1160
|
-
// Get registered public keys
|
|
1161
|
-
const pubKeys = await getRegisteredPubKeys(registry, entryPoint);
|
|
1162
|
-
console.log(`Found ${Object.keys(pubKeys).length} unique public keys`);
|
|
1163
|
-
|
|
1164
|
-
// Get network summary
|
|
1165
|
-
const summary = await getNetworkSummary(registry, entryPoint);
|
|
1166
|
-
console.log(`Active relays: ${summary.activeRelays}/${summary.totalRelays}`);
|
|
1167
|
-
console.log(`Average price: ${summary.averagePrice} ETH`);
|
|
1168
|
-
|
|
1169
|
-
// Subscribe to relay events
|
|
1170
|
-
const unsubscribe = subscribeToRelayEvents(registry, (event) => {
|
|
1171
|
-
console.log(`Event ${event.type} detected at ${new Date(event.timestamp).toLocaleString()}`);
|
|
1172
|
-
if (event.type === RelayEventType.NEW_SUBSCRIPTION) {
|
|
1173
|
-
console.log(`New subscription for ${event.userAddress} on ${event.relayAddress}`);
|
|
1174
|
-
}
|
|
1175
|
-
});
|
|
1176
|
-
|
|
1177
|
-
// To unsubscribe
|
|
1178
|
-
// unsubscribe();
|
|
1179
|
-
}
|
|
1180
|
-
```
|
|
1181
|
-
|
|
1182
|
-
This architecture allows developers to easily integrate relay-based verification and authentication into their projects, with options for both direct interactions with individual relays and centralized operations through the EntryPoint.
|
|
1183
|
-
|
|
1184
|
-
## Browser Integration
|
|
1185
|
-
|
|
1186
|
-
Shogun Core can be used directly in modern web browsers. This makes it possible to create decentralized applications that run entirely from the client's browser.
|
|
1187
|
-
|
|
1188
|
-
### Setup
|
|
1189
|
-
|
|
1190
|
-
You can include Shogun Core in two ways:
|
|
1191
|
-
|
|
1192
|
-
#### 1. Using script tags
|
|
1193
|
-
|
|
1194
|
-
```html
|
|
1195
|
-
<script src="path/to/shogun-core.js"></script>
|
|
1196
|
-
```
|
|
1197
|
-
|
|
1198
|
-
#### 2. Using npm/yarn in a frontend project
|
|
1199
|
-
|
|
1200
|
-
```bash
|
|
1201
|
-
npm install shogun-core
|
|
1202
|
-
# or
|
|
1203
|
-
yarn add shogun-core
|
|
1204
|
-
```
|
|
1205
|
-
|
|
1206
|
-
And then import it in your applications:
|
|
1207
|
-
|
|
1208
|
-
```javascript
|
|
1209
|
-
// ESM
|
|
1210
|
-
import {
|
|
1211
|
-
ShogunCore,
|
|
1212
|
-
initShogunBrowser,
|
|
1213
|
-
CorePlugins,
|
|
1214
|
-
PluginCategory,
|
|
1215
|
-
} from "shogun-core";
|
|
1216
|
-
|
|
1217
|
-
// CommonJS
|
|
1218
|
-
const {
|
|
1219
|
-
ShogunCore,
|
|
1220
|
-
initShogunBrowser,
|
|
1221
|
-
CorePlugins,
|
|
1222
|
-
PluginCategory,
|
|
1223
|
-
} = require("shogun-core");
|
|
1224
|
-
```
|
|
1225
|
-
|
|
1226
|
-
### Examples
|
|
1227
|
-
|
|
1228
|
-
```javascript
|
|
1229
|
-
// Initialize Shogun with browser-optimized configuration
|
|
1230
|
-
const shogun = initShogunBrowser({
|
|
1231
|
-
gundb: {
|
|
1232
|
-
peers: ["https://your-gun-relay.com/gun"],
|
|
1233
|
-
websocket: true, // Use WebSocket for communication
|
|
1234
|
-
},
|
|
1235
|
-
providerUrl: "https://ethereum-rpc-url.com",
|
|
1236
|
-
// WebAuthn configuration for biometric/device authentication
|
|
1237
|
-
webauthn: {
|
|
1238
|
-
enabled: true,
|
|
1239
|
-
rpName: "Your App",
|
|
1240
|
-
rpId: window.location.hostname,
|
|
1241
|
-
},
|
|
1242
|
-
// Optional: attiva stealth e wallet manager
|
|
1243
|
-
stealth: {
|
|
1244
|
-
enabled: true,
|
|
1245
|
-
},
|
|
1246
|
-
walletManager: {
|
|
1247
|
-
enabled: true,
|
|
1248
|
-
},
|
|
1249
|
-
});
|
|
1250
|
-
|
|
1251
|
-
// Registration
|
|
1252
|
-
async function signup() {
|
|
1253
|
-
try {
|
|
1254
|
-
const result = await shogun.signUp("username", "password");
|
|
1255
|
-
console.log("Registration completed:", result);
|
|
1256
|
-
} catch (error) {
|
|
1257
|
-
console.error("Error during registration:", error);
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
// Login
|
|
1262
|
-
async function login() {
|
|
1263
|
-
try {
|
|
1264
|
-
const result = await shogun.login("username", "password");
|
|
1265
|
-
console.log("Login completed:", result);
|
|
1266
|
-
} catch (error) {
|
|
1267
|
-
console.error("Error during login:", error);
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
// WebAuthn Login using the getAuthenticationMethod (modern way)
|
|
1272
|
-
async function webAuthnLogin() {
|
|
1273
|
-
try {
|
|
1274
|
-
const username = document.getElementById("webauthnUsername").value;
|
|
1275
|
-
const authMethod = shogun.getAuthenticationMethod("webauthn");
|
|
1276
|
-
|
|
1277
|
-
if (authMethod && (await authMethod.isSupported())) {
|
|
1278
|
-
const credentials = await authMethod.generateCredentials(
|
|
1279
|
-
username,
|
|
1280
|
-
null,
|
|
1281
|
-
true
|
|
1282
|
-
);
|
|
1283
|
-
if (credentials.success) {
|
|
1284
|
-
// Utilizza le credenziali per autenticare l'utente
|
|
1285
|
-
const loginResult = await authMethod.login(username);
|
|
1286
|
-
console.log("WebAuthn login result:", loginResult);
|
|
1287
|
-
}
|
|
1288
|
-
} else {
|
|
1289
|
-
console.error("WebAuthn not supported by this browser");
|
|
1290
|
-
}
|
|
1291
|
-
} catch (error) {
|
|
1292
|
-
console.error("Error during WebAuthn login:", error);
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
// MetaMask Login using the getAuthenticationMethod (modern way)
|
|
1297
|
-
async function metamaskLogin() {
|
|
1298
|
-
try {
|
|
1299
|
-
const authMethod = shogun.getAuthenticationMethod("metamask");
|
|
1300
|
-
|
|
1301
|
-
if (authMethod && (await authMethod.isAvailable())) {
|
|
1302
|
-
// Get connection
|
|
1303
|
-
const connectResult = await authMethod.connectMetaMask();
|
|
1304
|
-
if (connectResult.success) {
|
|
1305
|
-
// Login with the address
|
|
1306
|
-
const loginResult = await authMethod.login(connectResult.address);
|
|
1307
|
-
console.log("MetaMask login result:", loginResult);
|
|
1308
|
-
}
|
|
1309
|
-
} else {
|
|
1310
|
-
console.error("MetaMask not available");
|
|
1311
|
-
}
|
|
1312
|
-
} catch (error) {
|
|
1313
|
-
console.error("Error during MetaMask login:", error);
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
// Creating a wallet
|
|
1318
|
-
async function createWallet() {
|
|
1319
|
-
if (!shogun.isLoggedIn()) {
|
|
1320
|
-
console.error("You must log in first!");
|
|
1321
|
-
return;
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
try {
|
|
1325
|
-
const walletPlugin = shogun.getPlugin(CorePlugins.Wallet);
|
|
1326
|
-
if (walletPlugin) {
|
|
1327
|
-
const wallet = await walletPlugin.createWallet();
|
|
1328
|
-
console.log("Wallet created:", wallet);
|
|
1329
|
-
} else {
|
|
1330
|
-
console.error("Wallet plugin not available");
|
|
1331
|
-
}
|
|
1332
|
-
} catch (error) {
|
|
1333
|
-
console.error("Error while creating wallet:", error);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
|
|
1337
|
-
// Using reactive data
|
|
1338
|
-
function setupReactiveUI() {
|
|
1339
|
-
// Subscribe to user profile changes
|
|
1340
|
-
shogun.observe("users/current").subscribe((user) => {
|
|
1341
|
-
document.getElementById("username").textContent = user.name;
|
|
1342
|
-
document.getElementById("status").className = user.online
|
|
1343
|
-
? "online"
|
|
1344
|
-
: "offline";
|
|
1345
|
-
});
|
|
1346
|
-
|
|
1347
|
-
// Handle real-time messages
|
|
1348
|
-
shogun.match("messages").subscribe((messages) => {
|
|
1349
|
-
const chatBox = document.getElementById("chat");
|
|
1350
|
-
chatBox.innerHTML = "";
|
|
1351
|
-
|
|
1352
|
-
messages.forEach((msg) => {
|
|
1353
|
-
const msgEl = document.createElement("div");
|
|
1354
|
-
msgEl.className = "message";
|
|
1355
|
-
msgEl.textContent = `${msg.sender}: ${msg.text}`;
|
|
1356
|
-
chatBox.appendChild(msgEl);
|
|
1357
|
-
});
|
|
1358
|
-
});
|
|
1359
|
-
}
|
|
1360
|
-
```
|
|
1361
|
-
|
|
1362
|
-
For a complete example, check the [examples/browser-example.html](examples/browser-example.html) file.
|
|
1363
|
-
|
|
1364
|
-
### Compatibility
|
|
1365
|
-
|
|
1366
|
-
The browser version of Shogun Core:
|
|
1367
|
-
|
|
1368
|
-
- Supports all modern browsers (Chrome, Firefox, Safari, Edge)
|
|
1369
|
-
- Includes necessary polyfills for node.js functionalities used by GunDB
|
|
1370
|
-
- Automatically optimizes settings for the browser environment
|
|
1371
|
-
- Provides WebAuthn support when available in the browser
|
|
101
|
+
- **dApps**: Decentralized applications requiring user authentication and wallet management
|
|
102
|
+
- **Web Wallets**: Implementation of crypto wallets directly in the browser
|
|
103
|
+
- **Social dApps**: Social applications requiring decentralized storage and crypto identities
|
|
104
|
+
- **Privacy-Focused Apps**: Applications needing stealth features and advanced privacy (with optional plugins)
|
|
105
|
+
- **Real-time Applications**: Chat apps, live dashboards, and collaborative tools using reactive data
|
|
1372
106
|
|
|
1373
|
-
##
|
|
107
|
+
## Contributing
|
|
1374
108
|
|
|
1375
109
|
Contributions are welcome! If you would like to contribute to the project, please:
|
|
1376
110
|
|