@rockerone/xprnkit 0.3.0

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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1100 -0
  3. package/build/components/identity/index.d.ts +4 -0
  4. package/build/components/identity/index.js +4 -0
  5. package/build/components/identity/xprn-avatar.d.ts +8 -0
  6. package/build/components/identity/xprn-avatar.js +23 -0
  7. package/build/components/identity/xprn-identity.d.ts +9 -0
  8. package/build/components/identity/xprn-identity.js +30 -0
  9. package/build/components/identity/xprn-session-actor.d.ts +4 -0
  10. package/build/components/identity/xprn-session-actor.js +13 -0
  11. package/build/components/identity/xprn-session-name.d.ts +4 -0
  12. package/build/components/identity/xprn-session-name.js +14 -0
  13. package/build/components/index.d.ts +5 -0
  14. package/build/components/index.js +5 -0
  15. package/build/components/swap/index.d.ts +46 -0
  16. package/build/components/swap/index.js +9 -0
  17. package/build/components/swap/xprn-swap-button.d.ts +5 -0
  18. package/build/components/swap/xprn-swap-button.js +21 -0
  19. package/build/components/swap/xprn-swap-field.d.ts +6 -0
  20. package/build/components/swap/xprn-swap-field.js +69 -0
  21. package/build/components/swap/xprn-swap-fields-group.d.ts +6 -0
  22. package/build/components/swap/xprn-swap-fields-group.js +16 -0
  23. package/build/components/swap/xprn-swap-fields.d.ts +4 -0
  24. package/build/components/swap/xprn-swap-fields.js +10 -0
  25. package/build/components/swap/xprn-swap-layout.d.ts +7 -0
  26. package/build/components/swap/xprn-swap-layout.js +21 -0
  27. package/build/components/swap/xprn-swap-markets-selector.d.ts +4 -0
  28. package/build/components/swap/xprn-swap-markets-selector.js +31 -0
  29. package/build/components/swap/xprn-swap-markets.d.ts +8 -0
  30. package/build/components/swap/xprn-swap-markets.js +93 -0
  31. package/build/components/swap/xprn-swap-pair-selector.d.ts +7 -0
  32. package/build/components/swap/xprn-swap-pair-selector.js +37 -0
  33. package/build/components/swap/xprn-swap-provider.d.ts +35 -0
  34. package/build/components/swap/xprn-swap-provider.js +187 -0
  35. package/build/components/swap/xprn-swap-side-button.d.ts +6 -0
  36. package/build/components/swap/xprn-swap-side-button.js +22 -0
  37. package/build/components/swap/xprn-swap.d.ts +9 -0
  38. package/build/components/swap/xprn-swap.js +12 -0
  39. package/build/components/ui/dropdown.d.ts +27 -0
  40. package/build/components/ui/dropdown.js +36 -0
  41. package/build/components/ui/input.d.ts +5 -0
  42. package/build/components/ui/input.js +8 -0
  43. package/build/components/ui/select.d.ts +13 -0
  44. package/build/components/ui/select.js +27 -0
  45. package/build/components/xprn-container.d.ts +9 -0
  46. package/build/components/xprn-container.js +15 -0
  47. package/build/components/xprn-session.d.ts +11 -0
  48. package/build/components/xprn-session.js +21 -0
  49. package/build/components/xprn-transaction.d.ts +23 -0
  50. package/build/components/xprn-transaction.js +58 -0
  51. package/build/global.css +1138 -0
  52. package/build/index.d.ts +5 -0
  53. package/build/index.js +3 -0
  54. package/build/interfaces/proton_wrap.d.ts +141 -0
  55. package/build/interfaces/proton_wrap.js +81 -0
  56. package/build/interfaces/service-status.d.ts +1 -0
  57. package/build/interfaces/service-status.js +1 -0
  58. package/build/interfaces/transaction-error-message.d.ts +5 -0
  59. package/build/interfaces/transaction-error-message.js +1 -0
  60. package/build/lib/utils.d.ts +2 -0
  61. package/build/lib/utils.js +5 -0
  62. package/build/providers/XPRNProvider.d.ts +59 -0
  63. package/build/providers/XPRNProvider.js +336 -0
  64. package/build/utils/index.d.ts +2 -0
  65. package/build/utils/index.js +2 -0
  66. package/build/utils/token-precision.d.ts +1 -0
  67. package/build/utils/token-precision.js +22 -0
  68. package/build/utils/transaction-errors.d.ts +2 -0
  69. package/build/utils/transaction-errors.js +15 -0
  70. package/package.json +49 -0
package/README.md ADDED
@@ -0,0 +1,1100 @@
1
+ # xprnkit
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ # XPRNKit:
10
+
11
+ ## Accelerating dApp Development for XPRNetwork
12
+
13
+ XPRNKit is a React-based library designed to streamline decentralized application (dApp) development and prototyping on the XPRNetwork blockchain. It offers a comprehensive set of tools, components, and utilities that enable developers to rapidly build, deploy, and test dApps with minimal setup. By abstracting away much of the underlying complexity of blockchain interactions, XPRNKit empowers developers to focus on core functionality and user experience.
14
+
15
+ Whether you're creating smart contracts, integrating wallets, or handling token transactions, XPRNKit simplifies common tasks and accelerates the development process. It’s perfect for both experienced blockchain developers looking to prototype quickly and newcomers who want to get up and running with XPRNetwork faster.
16
+
17
+ ## Key Features
18
+
19
+ - **Pre-built Components**: Ready-to-use UI components for common dApp functionality like wallet connections, token balances, and transaction history.
20
+ - **Blockchain Integration**: Simplified access to XPRNetwork's blockchain features, reducing the need for extensive configuration.
21
+ - **Developer-Friendly Hook**: A simple unique hook to access objects and method to maximizing flexibility.
22
+ - **Multi-Session Support**: Connect and manage multiple wallet sessions simultaneously, with easy switching between accounts.
23
+
24
+ XPRNKit is the ideal toolkit for developers who want to build and deploy secure, scalable, and user-friendly dApps on XPRNetwork with greater efficiency.
25
+
26
+ # XPRNProvider and useXPRN Documentation
27
+
28
+ ## XPRNProvider
29
+
30
+ The `XPRNProvider` is a React component that provides a context for XPR Network blockchain interactions within your application.
31
+
32
+ ### Props
33
+
34
+ ```typescript
35
+ type XPRNProviderProps = {
36
+ children: React.ReactNode | React.ReactNode[];
37
+ config: XPRProviderConfig;
38
+ };
39
+ ```
40
+
41
+ - `children`: React components that will have access to the XPRN context.
42
+ - `config`: Configuration object for the XPRN provider.
43
+
44
+ ### Configuration
45
+
46
+ ```typescript
47
+ type XPRProviderConfig = {
48
+ chainId: string;
49
+ endpoints: string[];
50
+ dAppName: string;
51
+ requesterAccount: string;
52
+ requesterLogo?: string;
53
+ authenticationUrl?: string;
54
+ enforceAuthentication?: boolean;
55
+ apiMode: "testnet" | "mainnet";
56
+ restoreSession?: boolean;
57
+ };
58
+ ```
59
+
60
+ - `chainId`: The blockchain chain ID.
61
+ - `endpoints`: Array of RPC endpoints for blockchain communication.
62
+ - `dAppName`: Your dApp's display name.
63
+ - `requesterAccount`: Your dApp's account name.
64
+ - `requesterLogo`: Optional logo URL for your dApp.
65
+ - `authenticationUrl`: Optional URL for user authentication endpoint.
66
+ - `enforceAuthentication`: If true, automatically authenticates users on connection.
67
+ - `apiMode`: Either "testnet" or "mainnet" for different network environments.
68
+ - `restoreSession`: If true, restores the last active session on page refresh.
69
+
70
+ ### Usage
71
+
72
+ ```jsx
73
+ import {XPRNProvider} from "./path/to/XPRNProvider";
74
+
75
+ const config = {
76
+ chainId: "your-chain-id",
77
+ endpoints: ["https://your-endpoint.com"],
78
+ dAppName: "Your dApp Name",
79
+ requesterAccount: "your-account",
80
+ apiMode: "mainnet",
81
+ };
82
+
83
+ function App() {
84
+ return (
85
+ <XPRNProvider config={config}>{/* Your app components */}</XPRNProvider>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ## useXPRN Hook
91
+
92
+ The `useXPRN` hook provides access to the XPRN context within your React components.
93
+
94
+ ### Usage
95
+
96
+ ```jsx
97
+ import {useXPRN} from "./path/to/XPRNProvider";
98
+
99
+ function YourComponent() {
100
+ const {
101
+ session,
102
+ profile,
103
+ connect,
104
+ disconnect,
105
+ authenticate,
106
+ // Multi-session methods
107
+ listSessions,
108
+ setActiveSession,
109
+ getActiveSession,
110
+ } = useXPRN();
111
+
112
+ // Use the context values and functions
113
+ }
114
+ ```
115
+
116
+ ### Returned Values
117
+
118
+ The `useXPRN` hook returns an object with the following properties:
119
+
120
+ #### Backward Compatible Properties (Active Session)
121
+
122
+ - `session`: Current active LinkSession object or null.
123
+ - `link`: ProtonWebLink object for active session or null.
124
+ - `profile`: XPRNProfile object for active session or null.
125
+ - `rpc`: JsonRpc object or null.
126
+ - `authentication`: XPRNAuthentication object for active session or null.
127
+ - `connect`: Function to initiate a connection (newly connected wallet becomes active).
128
+ - `disconnect`: Function to disconnect a session (active or specific by actor).
129
+ - `authenticate`: Function to authenticate the user using the authentication URL (active session or specific by actor).
130
+ - `addTransactionError`: Function to add a transaction error to the stack.
131
+
132
+ #### Multi-Session Management Methods
133
+
134
+ - `getActiveSession`: Returns the current active session object or null.
135
+ - `listSessions`: Returns an array of all connected sessions.
136
+ - `setActiveSession`: Switch the active session by actor name.
137
+ - `switchSession`: Alias for setActiveSession.
138
+ - `removeSession`: Remove a specific session by actor name.
139
+ - `getAllProfiles`: Returns an array of all profiles from all connected sessions.
140
+ - `getSessionById`: Get a specific session by actor name.
141
+ - `getSessionByActor`: Get a specific session by actor name (same as getSessionById).
142
+
143
+ ### Key Functions
144
+
145
+ #### connect
146
+
147
+ ```typescript
148
+ connect(
149
+ restore?: boolean,
150
+ silent?: boolean,
151
+ onSession?: (session: LinkSession) => void,
152
+ onProfile?: (profile: XPRNProfile) => void
153
+ ) => void
154
+ ```
155
+
156
+ Initiates a connection to the WebAuth wallet. The newly connected wallet automatically becomes the active session.
157
+
158
+ #### disconnect
159
+
160
+ ```typescript
161
+ disconnect(actor?: string) => void
162
+ ```
163
+
164
+ Disconnects a session. If `actor` is provided, disconnects that specific session. Otherwise, disconnects the active session.
165
+
166
+ #### authenticate
167
+
168
+ ```typescript
169
+ authenticate(
170
+ success: (res: any) => void,
171
+ fail: (e: any) => void,
172
+ actor?: string
173
+ ) => void
174
+ ```
175
+
176
+ Authenticates a user using the provided authentication URL. If `actor` is provided, authenticates that specific session. Otherwise, authenticates the active session.
177
+
178
+ ### Multi-Session Management Methods
179
+
180
+ #### getActiveSession
181
+
182
+ ```typescript
183
+ getActiveSession(): XPRNSession | null
184
+ ```
185
+
186
+ Returns the complete active session object containing session, link, profile, and authentication data.
187
+
188
+ #### listSessions
189
+
190
+ ```typescript
191
+ listSessions(): XPRNSession[]
192
+ ```
193
+
194
+ Returns an array of all connected sessions.
195
+
196
+ #### setActiveSession / switchSession
197
+
198
+ ```typescript
199
+ setActiveSession(actor: string): void
200
+ switchSession(actor: string): void
201
+ ```
202
+
203
+ Switches the active session to the specified actor. Both methods are identical.
204
+
205
+ #### removeSession
206
+
207
+ ```typescript
208
+ removeSession(actor: string): Promise<void>
209
+ ```
210
+
211
+ Removes a specific session by actor name. If the removed session was active, the active session is set to null.
212
+
213
+ #### getAllProfiles
214
+
215
+ ```typescript
216
+ getAllProfiles(): XPRNProfile[]
217
+ ```
218
+
219
+ Returns an array of profiles from all connected sessions.
220
+
221
+ #### getSessionById / getSessionByActor
222
+
223
+ ```typescript
224
+ getSessionById(actor: string): XPRNSession | null
225
+ getSessionByActor(actor: string): XPRNSession | null
226
+ ```
227
+
228
+ Retrieves a specific session by actor name. Both methods are identical.
229
+
230
+ ## Types
231
+
232
+ ### XPRNAuthentication
233
+
234
+ ```typescript
235
+ type XPRNAuthentication = {
236
+ actor: string;
237
+ publicKey: string;
238
+ data?: any;
239
+ };
240
+ ```
241
+
242
+ ### XPRNProfile
243
+
244
+ ```typescript
245
+ type XPRNProfile = {
246
+ displayName: string;
247
+ avatar?: string;
248
+ authentication?: XPRNAuthentication;
249
+ isKyc: boolean;
250
+ };
251
+ ```
252
+
253
+ ### XPRNSession
254
+
255
+ ```typescript
256
+ type XPRNSession = {
257
+ actor: string;
258
+ session: LinkSession;
259
+ link: ProtonWebLink | Link;
260
+ profile: XPRNProfile | null;
261
+ authentication: XPRNAuthentication | null;
262
+ };
263
+ ```
264
+
265
+ A complete session object that encapsulates all data for a connected wallet.
266
+
267
+ ## Multi-Session Support
268
+
269
+ XPRNKit now supports managing multiple wallet sessions simultaneously. You can connect multiple wallets, switch between them, and manage each session independently.
270
+
271
+ ### Key Concepts
272
+
273
+ - **Active Session**: The currently selected session. All backward-compatible properties (`session`, `link`, `profile`, `authentication`) return data from the active session.
274
+ - **Session Identification**: Sessions are uniquely identified by their actor name (e.g., `user1@proton`).
275
+ - **Auto-Switch**: When a new wallet is connected, it automatically becomes the active session.
276
+ - **Persistence**: Only the active session is persisted and restored on page refresh (when `restoreSession: true` in config).
277
+
278
+ ### Multi-Session Usage Examples
279
+
280
+ #### Connecting Multiple Wallets
281
+
282
+ ```jsx
283
+ import {useXPRN} from "xprnkit";
284
+
285
+ function MultiWalletComponent() {
286
+ const {connect, listSessions, session} = useXPRN();
287
+
288
+ const handleConnectWallet = async () => {
289
+ await connect();
290
+ // Newly connected wallet is now the active session
291
+ };
292
+
293
+ return (
294
+ <div>
295
+ <button onClick={handleConnectWallet}>Connect Another Wallet</button>
296
+ <p>Active: {session?.auth.actor.toString()}</p>
297
+ <p>Total Sessions: {listSessions().length}</p>
298
+ </div>
299
+ );
300
+ }
301
+ ```
302
+
303
+ #### Listing and Switching Sessions
304
+
305
+ ```jsx
306
+ import {useXPRN} from "xprnkit";
307
+
308
+ function SessionSwitcher() {
309
+ const {listSessions, getActiveSession, setActiveSession} = useXPRN();
310
+
311
+ const sessions = listSessions();
312
+ const activeSession = getActiveSession();
313
+
314
+ return (
315
+ <div>
316
+ <h3>Connected Wallets</h3>
317
+ {sessions.map(session => (
318
+ <div key={session.actor}>
319
+ <button
320
+ onClick={() => setActiveSession(session.actor)}
321
+ disabled={activeSession?.actor === session.actor}
322
+ >
323
+ {session.profile?.displayName || session.actor}
324
+ {activeSession?.actor === session.actor && " (Active)"}
325
+ </button>
326
+ </div>
327
+ ))}
328
+ </div>
329
+ );
330
+ }
331
+ ```
332
+
333
+ #### Managing Multiple Sessions
334
+
335
+ ```jsx
336
+ import {useXPRN} from "xprnkit";
337
+
338
+ function SessionManager() {
339
+ const {listSessions, getActiveSession, removeSession, getAllProfiles} =
340
+ useXPRN();
341
+
342
+ const handleRemoveSession = async (actor: string) => {
343
+ await removeSession(actor);
344
+ };
345
+
346
+ return (
347
+ <div>
348
+ <h3>Session Manager</h3>
349
+ {listSessions().map(session => (
350
+ <div key={session.actor}>
351
+ <img
352
+ src={session.profile?.avatar}
353
+ alt={session.profile?.displayName}
354
+ />
355
+ <span>{session.profile?.displayName}</span>
356
+ <span>{session.actor}</span>
357
+ <button onClick={() => handleRemoveSession(session.actor)}>
358
+ Remove
359
+ </button>
360
+ </div>
361
+ ))}
362
+ </div>
363
+ );
364
+ }
365
+ ```
366
+
367
+ #### Authenticating Specific Sessions
368
+
369
+ ```jsx
370
+ import {useXPRN} from "xprnkit";
371
+
372
+ function AuthenticateSession() {
373
+ const {authenticate, listSessions} = useXPRN();
374
+
375
+ const handleAuthenticateSession = (actor: string) => {
376
+ authenticate(
377
+ response => {
378
+ console.log(`${actor} authenticated successfully`, response);
379
+ },
380
+ error => {
381
+ console.error(`${actor} authentication failed`, error);
382
+ },
383
+ actor // Authenticate specific session
384
+ );
385
+ };
386
+
387
+ return (
388
+ <div>
389
+ {listSessions().map(session => (
390
+ <div key={session.actor}>
391
+ <span>{session.actor}</span>
392
+ <span>
393
+ {session.authentication ? "✓ Authenticated" : "✗ Not Authenticated"}
394
+ </span>
395
+ {!session.authentication && (
396
+ <button onClick={() => handleAuthenticateSession(session.actor)}>
397
+ Authenticate
398
+ </button>
399
+ )}
400
+ </div>
401
+ ))}
402
+ </div>
403
+ );
404
+ }
405
+ ```
406
+
407
+ #### Disconnecting Specific Sessions
408
+
409
+ ```jsx
410
+ import {useXPRN} from "xprnkit";
411
+
412
+ function DisconnectSession() {
413
+ const {disconnect, listSessions, getActiveSession} = useXPRN();
414
+
415
+ const handleDisconnect = async (actor?: string) => {
416
+ // If actor is provided, disconnect that session
417
+ // Otherwise, disconnect active session
418
+ await disconnect(actor);
419
+ };
420
+
421
+ return (
422
+ <div>
423
+ <button onClick={() => handleDisconnect()}>
424
+ Disconnect Active Session
425
+ </button>
426
+
427
+ {listSessions().map(session => (
428
+ <div key={session.actor}>
429
+ <span>{session.actor}</span>
430
+ <button onClick={() => handleDisconnect(session.actor)}>
431
+ Disconnect
432
+ </button>
433
+ </div>
434
+ ))}
435
+ </div>
436
+ );
437
+ }
438
+ ```
439
+
440
+ ### Backward Compatibility
441
+
442
+ All existing code continues to work without changes. The `session`, `link`, `profile`, and `authentication` properties always return data from the active session:
443
+
444
+ ```jsx
445
+ // This still works exactly as before
446
+ function ExistingComponent() {
447
+ const {session, profile, connect, disconnect} = useXPRN();
448
+
449
+ // session, profile etc. return active session data
450
+ return (
451
+ <div>
452
+ {session ? (
453
+ <div>
454
+ <p>Logged in as: {profile?.displayName}</p>
455
+ <button onClick={() => disconnect()}>Logout</button>
456
+ </div>
457
+ ) : (
458
+ <button onClick={() => connect()}>Connect</button>
459
+ )}
460
+ </div>
461
+ );
462
+ }
463
+ ```
464
+
465
+ # Components Documentation
466
+
467
+ # XRPNContainer
468
+
469
+ `XRPNContainer` is a React component that conditionally renders its children based on the presence of a session.
470
+
471
+ ## Import
472
+
473
+ ```typescript
474
+ import {XRPNContainer} from "path/to/xprn-container";
475
+ ```
476
+
477
+ ## Props
478
+
479
+ The `XRPNContainer` component accepts the following props:
480
+
481
+ | Prop | Type | Description |
482
+ | ---------------- | -------------------------- | ----------------------------------------------------------- |
483
+ | `children` | `ReactNode \| ReactNode[]` | The content to be rendered when a session is present. |
484
+ | `className` | `string` | Optional CSS class name(s) to be applied to the container. |
485
+ | `noSessionState` | `ReactNode \| ReactNode[]` | Optional content to be rendered when no session is present. |
486
+
487
+ Additionally, `XRPNContainer` accepts all standard HTML div element attributes.
488
+
489
+ ## Usage
490
+
491
+ ```jsx
492
+ import {XRPNContainer} from "path/to/xprn-container";
493
+
494
+ function MyComponent() {
495
+ return (
496
+ <XRPNContainer
497
+ className="my-custom-class"
498
+ noSessionState={<p>Please log in to view content.</p>}
499
+ >
500
+ <h1>Welcome, user!</h1>
501
+ <p>This content is only visible when a session is present.</p>
502
+ </XRPNContainer>
503
+ );
504
+ }
505
+ ```
506
+
507
+ ## Behavior
508
+
509
+ - If a session is present (determined by the `useXPRN` hook), the component renders its `children`.
510
+ - If no session is present, the component renders the `noSessionState` content if provided, otherwise it renders nothing.
511
+
512
+ ## Dependencies
513
+
514
+ - React
515
+ - `useXPRN` hook from "../providers/XPRNProvider"
516
+
517
+ ## Notes
518
+
519
+ - This component uses the "use client" directive, indicating it's designed for client-side rendering in Next.js applications.
520
+ - The component leverages the `useXPRN` hook to determine the session state.
521
+
522
+ # XPRNConnectButton
523
+
524
+ The `XPRNConnectButton` is a React component that provides a customizable button for connecting to and disconnecting from an XPRN session.
525
+
526
+ ## Import
527
+
528
+ ```typescript
529
+ import {XPRNConnectButton} from "packages/xprnkit/src/components/xprn-session";
530
+ ```
531
+
532
+ ## Props
533
+
534
+ The `XPRNConnectButton` accepts the following props:
535
+
536
+ | Prop | Type | Description |
537
+ | ----------- | ----------------------------------------------- | ------------------------------------------------------------------------------- |
538
+ | `className` | `string` | Additional CSS classes to apply to the button |
539
+ | `variant` | `string` | Button variant (style) |
540
+ | `size` | `string` | Button size |
541
+ | `asChild` | `boolean` | If true, renders the component as a child component |
542
+ | `onClick` | `function` | Custom click handler (Note: internal connect/disconnect logic will still apply) |
543
+ | `children` | `React.ReactNode` | Custom content for the button when not connected |
544
+ | `...props` | `React.ButtonHTMLAttributes<HTMLButtonElement>` | Any other props accepted by HTML button element |
545
+
546
+ ## Usage
547
+
548
+ ```jsx
549
+ import {XPRNConnectButton} from "packages/xprnkit/src/components/xprn-session";
550
+
551
+ function MyComponent() {
552
+ return (
553
+ <XPRNConnectButton variant="primary" size="medium" className="custom-class">
554
+ Connect to XPRN
555
+ </XPRNConnectButton>
556
+ );
557
+ }
558
+ ```
559
+
560
+ ## Behavior
561
+
562
+ - When there's no active session, the button displays the provided `children` content and triggers the `connect()` function when clicked.
563
+ - When there's an active session, the button displays "Log out (actor)" and triggers the `disconnect()` function when clicked.
564
+
565
+ ## Notes
566
+
567
+ - The component uses the `useXPRN` hook to access the current session state and connect/disconnect functions.
568
+
569
+ # XPRNIdentity Component
570
+
571
+ ## Overview
572
+
573
+ The `XPRNIdentity` component is a React functional component that displays user identity information and provides session management functionality
574
+
575
+ ## Props
576
+
577
+ The component accepts the following props:
578
+
579
+ - `children`: React nodes to be rendered inside the dropdown menu (optional)
580
+ - `className`: Additional CSS classes for the root element (optional)
581
+ - `showLogout`: Boolean to determine if the logout link should be displayed (optional)
582
+ - `activeSessionClassName`: Additional CSS classes for the active session container (optional)
583
+ - `dropdownClassName`: Additional CSS classes for the dropdown menu (optional)
584
+ - `avatarClassName`: Additional CSS classes for the avatar component (optional)
585
+
586
+ ## Functionality
587
+
588
+ 1. If a user session exists:
589
+
590
+ - Displays a dropdown menu with the user's avatar and session information
591
+ - Shows the user's name and actor information
592
+ - Optionally displays a logout link
593
+ - Renders any child components in the dropdown content
594
+
595
+ 2. If no user session exists:
596
+ - Displays a "Connect" button using the `XPRNConnectButton` component
597
+
598
+ ## Usage
599
+
600
+ ```jsx
601
+ import {XPRNIdentity} from "path/to/xprn-identity";
602
+
603
+ function MyComponent() {
604
+ return (
605
+ <XPRNIdentity showLogout={true} avatarClassName="custom-avatar">
606
+ <div>Additional dropdown content</div>
607
+ </XPRNIdentity>
608
+ );
609
+ }
610
+ ```
611
+
612
+ ## Notes
613
+
614
+ - The component is wrapped in a "use client" directive, indicating it's designed for client-side rendering.
615
+ - It uses the `useXPRN` hook to access session information and the `disconnect` function.
616
+ - The logout functionality is implemented using the `disconnect` function from the XPRN context.
617
+
618
+ ## Identity sub components
619
+
620
+ The following components are used inside XPRNIdentity:
621
+
622
+ 1. **XPRNAvatar**
623
+
624
+ - Exported from: `'./xprn-avatar'`
625
+ - Description: A component for rendering user avatars or profile pictures.
626
+
627
+ 2. **XPRNSessionActor**
628
+
629
+ - Exported from: `'./xprn-session-actor'`
630
+ - Description: Related to the current session's active user or actor.
631
+
632
+ 3. **XPRNSessionName**
633
+ - Exported from: `'./xprn-session-name'`
634
+ - Description: For displaying the current session user's name.
635
+
636
+ ## Usage
637
+
638
+ To use these components in your project, you can import them from this file:
639
+
640
+ ```typescript
641
+ import {
642
+ XPRNAvatar,
643
+ XPRNSessionActor,
644
+ XPRNSessionName,
645
+ } from "xprnkit/src/components/identity";
646
+ ```
647
+
648
+ # XPRNSwap Component
649
+
650
+ The `XPRNSwap` component is a React functional component that provides a user interface for XPR Network tokens swapping functionality out of the box.
651
+
652
+ ## Import
653
+
654
+ ```typescript
655
+ import {XPRNSwap} from "packages/xprnkit/src/components/swap/xprn-swap";
656
+ ```
657
+
658
+ ## Props
659
+
660
+ The `XPRNSwap` component accepts the following props:
661
+
662
+ | Prop | Type | Description |
663
+ | ----------- | ------------------------------- | ----------------------------------------------------------- |
664
+ | `filters` | `XPRNMarketProviderQuoteFilter` | Optional. Filters for market provider quotes. |
665
+ | `sides` | `XPRNSwapSide[]` | Optional. Array of swap sides. |
666
+ | `markets` | `string[]` | Optional. Array of market identifiers. |
667
+ | `className` | `string` | Optional. Additional CSS classes to apply to the component. |
668
+ | `children` | `React.ReactNode` | Optional. Child elements to render within the component. |
669
+
670
+ Additionally, the component accepts all standard HTML attributes for a `div` element.
671
+
672
+ ## Usage
673
+
674
+ ### Basic
675
+
676
+ ```jsx
677
+ <XPRNSwap />
678
+ ```
679
+
680
+ ### With config
681
+
682
+ ```jsx
683
+ <XPRNSwap
684
+ filters={...}
685
+ sides={['buy', 'sell']}
686
+ markets={['market1', 'market2']}
687
+ className="custom-class"
688
+ />
689
+ ```
690
+
691
+ ### Customs using `XPRNSwapProvider`
692
+
693
+ ```jsx
694
+ <XPRNSwapProvider
695
+ config={{filters: {quoteSymbol: "SNIPS", baseSymbol: "XUSDC"}}}
696
+ >
697
+ <div className="p4 bg-green-400 grid grid-cols-[1fr,min-content] gap-6 p-4 w-full">
698
+ <XPRNPairsSelector />
699
+ <XPRNSwapFieldsGroup horizontal className="w-full">
700
+ <XPRNSwapField />
701
+ <XPRNSwapSideButton horizontal>Yo!</XPRNSwapSideButton>
702
+ <XPRNSwapField />
703
+ </XPRNSwapFieldsGroup>
704
+ <XPRNTransaction>Swap</XPRNTransaction>
705
+ </div>
706
+ </XPRNSwapProvider>
707
+ ```
708
+
709
+ ## Behavior
710
+
711
+ 1. The component wraps its content in an `XPRNSwapProvider` to provide context for swap-related data and functionality.
712
+ 2. It renders an `XPRNSwapLayout` component within the provider.
713
+ 3. The component applies a default grid layout with padding and border styling.
714
+ 4. Custom CSS classes can be added via the `className` prop.
715
+
716
+ ## Dependencies
717
+
718
+ - XPRNSwapProvider
719
+ - XPRNSwapLayout
720
+
721
+ ## Notes
722
+
723
+ - Alternatively, XPRNSwap component allow you to rebuild the entire swap component layout the way you want by using it's sub components wrapped in a `XPRNSwapProvider`
724
+
725
+ # XPRNSwapProvider
726
+
727
+ The `XPRNSwapProvider` is a React component that provides context for managing cryptocurrency swap operations.
728
+
729
+ ## Usage
730
+
731
+ ```jsx
732
+ import { XPRNSwapProvider } from 'path/to/xprn-swap-provider';
733
+
734
+ function App() {
735
+ return (
736
+ <XPRNSwapProvider config={/* optional config */}>
737
+ {/* Your app components and XPRNKit swap sub components */}
738
+ </XPRNSwapProvider>
739
+ );
740
+ }
741
+ ```
742
+
743
+ ## Props
744
+
745
+ | Prop | Type | Description |
746
+ | ---------- | -------------------------------------- | ---------------------------------------------- |
747
+ | `children` | `React.ReactNode \| React.ReactNode[]` | Child components to be wrapped by the provider |
748
+ | `config` | `XPRNSwapProviderConfig` (optional) | Configuration options for the swap provider |
749
+
750
+ ### XPRNSwapProviderConfig
751
+
752
+ | Property | Type | Description |
753
+ | --------------- | ------------------------------------------ | ------------------------------------------ |
754
+ | `filters` | `XPRNMarketProviderQuoteFilter` (optional) | Filters for market provider quotes |
755
+ | `marketFilters` | `string[]` (optional) | Filters for specific markets |
756
+ | `sides` | `XPRNSwapSide[]` (optional) | Available swap sides (e.g., "buy", "sell") |
757
+
758
+ ## Context
759
+
760
+ The `XPRNSwapProvider` creates a context with the following properties and methods:
761
+
762
+ | Property/Method | Type | Description |
763
+ | -------------------------- | ----------------------------------------------------------------------- | ------------------------------------------- |
764
+ | `marketProviders` | `XPRNMarketProvider[]` | List of available market providers |
765
+ | `currentMarketProvider` | `XPRNMarketProvider \| null` | Currently selected market provider |
766
+ | `setCurrentMarketProvider` | `(marketProvider: XPRNMarketProvider) => void` | Function to set the current market provider |
767
+ | `refreshMarketPairs` | `() => void` | Function to refresh market pairs |
768
+ | `currentMarketPairs` | `XPRNMarketProviderResult[]` | Current list of market pairs |
769
+ | `refreshStatus` | `ServiceStatus` | Status of the refresh operation |
770
+ | `setCurrentSwapPair` | `(pair: XPRNMarketProviderResult) => void` | Function to set the current swap pair |
771
+ | `currentSwapPair` | `XPRNMarketProviderResult \| null` | Currently selected swap pair |
772
+ | `swapTransaction` | `any[]` | Current swap transaction details |
773
+ | `swapSide` | `XPRNSwapSide` | Current swap side (e.g., "buy" or "sell") |
774
+ | `setSwapSide` | `(value: XPRNSwapSide) => void` | Function to set the swap side |
775
+ | `swapVolume` | `number` | Current swap volume |
776
+ | `setSwapVolume` | `(value: number) => void` | Function to set the swap volume |
777
+ | `config` | `XPRNSwapProviderConfig` (optional) | Current configuration |
778
+ | `swapValues` | `XPRNSwapValues` | Current swap values |
779
+ | `updateSwapValues` | `(base: number, quote: number, lastMutated: "base" \| "quote") => void` | Function to update swap values |
780
+
781
+ ## Hook
782
+
783
+ The `useXPRNSwap` hook can be used to access the `XPRNSwapProvider` context in child components.
784
+
785
+ ### Usage
786
+
787
+ ```jsx
788
+ import { useXPRNSwap } from 'path/to/xprn-swap-provider';
789
+
790
+ function SwapComponent() {
791
+ const { currentSwapPair, swapSide, setSwapSide } = useXPRNSwap();
792
+
793
+ // Use the context values and methods
794
+ // ...
795
+
796
+ return (
797
+ // Your component JSX
798
+ );
799
+ }
800
+ ```
801
+
802
+ ## Notes
803
+
804
+ - The provider fetches market pairs from the selected market provider's endpoint (currently Alcor is the only supported exchange). You can edit or add new provider using the `XPRNMarketProvider` interface.
805
+ - It manages the state of the current swap, including the selected pair, swap side, and volume.
806
+ - The provider automatically updates swap transactions when relevant values change.
807
+ - Error handling is implemented for network requests and configuration issues.
808
+
809
+ # XPRNSwapFieldsGroup
810
+
811
+ The `XPRNSwapFieldsGroup` is a React component that provides a flexible container for grouping swap fields in the XPRN swap interface. It's a utility component that flip swap fields position according to side (buy or sell)
812
+
813
+ ## Import
814
+
815
+ ```typescript
816
+ import {XPRNSwapFieldsGroup} from "packages/xprnkit/src/components/swap/xprn-swap-fields-group";
817
+ ```
818
+
819
+ ## Props
820
+
821
+ The component accepts the following props:
822
+
823
+ | Prop | Type | Default | Description |
824
+ | ------------ | ----------------- | ----------- | --------------------------------------------------------- |
825
+ | `children` | `React.ReactNode` | - | The child components to be rendered within the group. |
826
+ | `className` | `string` | `undefined` | Additional CSS classes to be applied to the root element. |
827
+ | `horizontal` | `boolean` | `false` | Determines if the fields should be arranged horizontally. |
828
+
829
+ Additionally, the component accepts all standard HTML div element attributes.
830
+
831
+ ## Usage
832
+
833
+ ```jsx
834
+ import {XPRNSwapFieldsGroup} from "packages/xprnkit/src/components/swap/xprn-swap-fields-group";
835
+
836
+ function SwapInterface() {
837
+ return (
838
+ <XPRNSwapFieldsGroup horizontal={true} className="custom-class">
839
+ {/* Swap field components go here */}
840
+ </XPRNSwapFieldsGroup>
841
+ );
842
+ }
843
+ ```
844
+
845
+ ## Behavior
846
+
847
+ - The component uses the `useXPRNSwap` hook to access the current swap configuration.
848
+ - It dynamically applies CSS classes based on the `horizontal` prop and the current `swapSide`.
849
+ - The layout of child components is reversed when `swapSide` is "sell".
850
+ - The component supports both vertical (default) and horizontal layouts.
851
+
852
+ # XPRNSwapSideButton
853
+
854
+ The `XPRNSwapSideButton` is a React component that provides a button for switching between "buy" and "sell" sides in a swap interface.
855
+
856
+ ## Import
857
+
858
+ ```typescript
859
+ import {XPRNSwapSideButton} from "path/to/xprn-swap-side-button";
860
+ ```
861
+
862
+ ## Props
863
+
864
+ The component accepts the following props:
865
+
866
+ | Prop | Type | Default | Description |
867
+ | ------------ | ----------------- | ----------- | --------------------------------------------------------------------------------------------- |
868
+ | `horizontal` | `boolean` | `false` | Determines the orientation of the swap icon. If `true`, a horizontal arrow icon is displayed. |
869
+ | `children` | `React.ReactNode` | `undefined` | Custom content to be rendered inside the button. If not provided, a default icon is used. |
870
+ | `className` | `string` | `undefined` | Additional CSS classes to be applied to the button. |
871
+
872
+ The component also accepts all standard HTML attributes for a `div` element.
873
+
874
+ ## Usage
875
+
876
+ ```jsx
877
+ import {XPRNSwapSideButton} from "path/to/xprn-swap-side-button";
878
+
879
+ function SwapInterface() {
880
+ return (
881
+ <div>
882
+ {/* Other swap interface components */}
883
+ <XPRNSwapSideButton horizontal={true} className="custom-class" />
884
+ </div>
885
+ );
886
+ }
887
+ ```
888
+
889
+ ## Behavior
890
+
891
+ - The button toggles between "buy" and "sell" sides when clicked.
892
+ - It uses the `useXPRNSwap` hook to access and modify the swap state.
893
+ - The button is not rendered if the swap configuration only has one side.
894
+ - The button has a hover effect that rotates it 180 degrees.
895
+
896
+ ## Customization
897
+
898
+ - You can provide custom content by passing children to the component.
899
+ - The default icon can be overridden by passing custom JSX as children.
900
+ - Additional styling can be applied using the `className` prop.
901
+
902
+ ## Notes
903
+
904
+ - The component is wrapped with `"use client"` directive, indicating it's a Client Component in Next.js.
905
+ - It uses React hooks (`useCallback`, `useMemo`) for performance optimization.
906
+
907
+ # XPRNSwapField Component
908
+
909
+ ## Overview
910
+
911
+ The `XPRNSwapField` is a React component used in a the `XPRNSwap` interface. It provides an input field for users to enter the amount of tokens they want to swap, either for the base or quote currency of a trading pair. This component should be wrapped in a `XPRNSwapProvider`
912
+
913
+ ## Props
914
+
915
+ The component accepts the following props:
916
+
917
+ - `type`: A string, either "quote" or "base", indicating whether this field is for the quote or base currency.
918
+ - `className`: An optional string for additional CSS classes.
919
+ - `children`: Optional child elements (not used in the current implementation).
920
+
921
+ It also accepts any other props that can be applied to a `div` element.
922
+
923
+ ## Usage
924
+
925
+ ```tsx
926
+ import {XPRNSwapField} from "./path/to/xprn-swap-field";
927
+
928
+ <XPRNSwapField type="base" className="custom-class" />;
929
+ ```
930
+
931
+ ## Styling
932
+
933
+ The component uses CSS classes for styling, including conditional classes based on the `className` prop and predefined classes for the input field.
934
+
935
+ # XPRNSwapMarketsSelector
936
+
937
+ ## Overview
938
+
939
+ `XPRNSwapMarketsSelector` is a React functional component that renders a dropdown selector for swap market providers. It uses the `Select` component from a UI library and populates it with market providers from the `useXPRNSwap` hook. The component must be wrapped in a `XPRNSwapProvider` in order to be fed by markets config provided through `XPRNSwapProvider` config.
940
+
941
+ ## Props
942
+
943
+ The component accepts the following props:
944
+
945
+ - `children`: React node (optional)
946
+ - `className`: string (optional)
947
+
948
+ These props are extended from `React.HTMLAttributes<HTMLDivElement>`.
949
+
950
+ ## Usage
951
+
952
+ ```tsx
953
+ import {XPRNSwapMarketsSelector} from "path/to/xprn-swap-markets-selector";
954
+
955
+ function MyComponent() {
956
+ return <XPRNSwapMarketsSelector className="custom-class" />;
957
+ }
958
+ ```
959
+
960
+ ## Functionality
961
+
962
+ 1. The component uses the `useXPRNSwap` hook to get `marketProviders`.
963
+ 2. It initializes `services` state with `useState`.
964
+ 3. `defaultServices` are memoized using `useMemo` and set to `DEFAULT_SWAP_SERVICES`.
965
+ 4. `defaultService` is memoized to find the first service marked as default or the first service in the list.
966
+ 5. The component renders a `Select` component
967
+
968
+ ## Conditional Rendering
969
+
970
+ The component only renders if there is more than one market provider (`marketProviders.length > 1`).
971
+
972
+ ## Styling
973
+
974
+ The component uses `classNames` for conditional class application. The root `div` element receives the `className` prop if provided.
975
+
976
+ # XPRNPairsSelector Component
977
+
978
+ The `XPRNPairsSelector` is a React component that provides a dropdown selector for available (filtered or not) trading pairs form the selected market provider. It's designed to work within the context of an `XPRNSwapProvider`.
979
+
980
+ ## Import Statement
981
+
982
+ ```typescript
983
+ import * as React from "react";
984
+ import classNames from "classnames";
985
+ import {useXPRNSwap} from "./xprn-swap-provider";
986
+ import {
987
+ Select,
988
+ SelectItem,
989
+ SelectContent,
990
+ SelectTrigger,
991
+ SelectValue,
992
+ } from "../ui/select";
993
+ ```
994
+
995
+ ## Props
996
+
997
+ The component accepts the following props:
998
+
999
+ - `className?: string`: Additional CSS classes for the root element.
1000
+ - `contentClassName?: string`: Additional CSS classes for the dropdown content.
1001
+ - `itemsClassName?: string`: Additional CSS classes for the dropdown items.
1002
+
1003
+ These props extend the standard `HTMLDivElement` attributes.
1004
+
1005
+ ## Functionality
1006
+
1007
+ 1. The component uses the `useXPRNSwap` hook to access swap-related data and functions.
1008
+ 2. It displays a dropdown of available trading pairs when the loaded by the `XPRNSwapProvider` from the default or selected market provider.
1009
+ 3. Users can select a trading pair, which updates the current swap pair inside the `XPRNSwapProvider`.
1010
+ 4. The component shows loading and error states based on the `XPRNSwapProvider` loading status of the pair list.
1011
+
1012
+ ## Usage
1013
+
1014
+ ```tsx
1015
+ <XPRNPairsSelector
1016
+ className="custom-class"
1017
+ contentClassName="content-class"
1018
+ itemsClassName="item-class"
1019
+ />
1020
+ ```
1021
+
1022
+ ## Render Logic
1023
+
1024
+ - If loading of the is "idle":
1025
+ - Renders a `Select` component with the current pairs as options.
1026
+ - If loading of the is "pending":
1027
+ - Displays "Loading Pairs".
1028
+ - If loading of the is "fail":
1029
+ - Displays "Pairs shit" (consider changing this to a more appropriate error message).
1030
+
1031
+ ## Styling
1032
+
1033
+ The component uses `classNames` for conditional styling:
1034
+
1035
+ - Root element: Applies the `className` prop if provided.
1036
+ - Dropdown content: Applies "bg-white" and the `contentClassName` prop if provided.
1037
+ - Dropdown items: Applies "text-black" and the `itemsClassName` prop if provided.
1038
+
1039
+ ## Notes
1040
+
1041
+ - The component doesn't render anything if there's only one or zero market pairs available.
1042
+ - The default selected value is set based on the `currentSwapPair`.
1043
+ - Consider improving the error message for the "fail" state to be more user-friendly and informative.
1044
+
1045
+ # toPrecision
1046
+
1047
+ ## Description
1048
+
1049
+ The `toPrecision` function adjusts a numeric value to a specified precision, with options for rounding behavior and decimal representation. It's used to format the an arbitrary price according to the token precision.
1050
+
1051
+ ## Function Signature
1052
+
1053
+ ```typescript
1054
+ function toPrecision(
1055
+ value: number,
1056
+ precision: number,
1057
+ mode: "ceil" | "floor" | "round" | "none" = "ceil",
1058
+ forceDecimal: boolean = true
1059
+ ): string;
1060
+ ```
1061
+
1062
+ ## Parameters
1063
+
1064
+ - `value` (number): The input number to be adjusted.
1065
+ - `precision` (number): The number of decimal places to round to.
1066
+ - `mode` ('ceil' | 'floor' | 'round' | 'none', optional): The rounding mode to use. Defaults to 'ceil'.
1067
+ - 'ceil': Rounds up to the nearest integer.
1068
+ - 'floor': Rounds down to the nearest integer.
1069
+ - 'round': Rounds to the nearest integer.
1070
+ - 'none': Uses 'ceil' behavior (same as 'ceil').
1071
+ - `forceDecimal` (boolean, optional): Whether to force the output to include decimal places. Defaults to true.
1072
+
1073
+ ## Returns
1074
+
1075
+ - (string): The adjusted value as a string, with or without forced decimal places based on the `forceDecimal` parameter.
1076
+
1077
+ ## Behavior
1078
+
1079
+ 1. Multiplies the input `value` by 10^`precision` to shift the decimal point.
1080
+ 2. Applies the specified rounding `mode` to the shifted value.
1081
+ 3. Divides the result by 10^`precision` to shift the decimal point back.
1082
+ 4. If `forceDecimal` is true, returns the result with the specified number of decimal places.
1083
+ 5. If `forceDecimal` is false, returns the result as a string without forcing decimal places.
1084
+
1085
+ ## Example Usage
1086
+
1087
+ ```typescript
1088
+ console.log(toPrecision(3.14159, 2)); // "3.15"
1089
+ console.log(toPrecision(3.14159, 2, "floor")); // "3.14"
1090
+ console.log(toPrecision(3.14159, 2, "round")); // "3.14"
1091
+ console.log(toPrecision(3.14159, 2, "ceil", false)); // "3.15"
1092
+ console.log(toPrecision(3, 2, "none", true)); // "3.00"
1093
+ console.log(toPrecision(3, 2, "ceil", false)); // "3"
1094
+ ```
1095
+
1096
+ ## Notes
1097
+
1098
+ - The 'none' mode behaves the same as 'ceil' mode.
1099
+ - When `forceDecimal` is true, the output will always have the specified number of decimal places, even if the input is an integer.
1100
+ - When `forceDecimal` is false, the output may have fewer decimal places than specified if they are not needed (e.g., for whole numbers).