@rockerone/xprnkit 0.3.12 → 0.4.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 (62) hide show
  1. package/build/components/identity/xprn-account-list.d.ts +5 -5
  2. package/build/components/identity/xprn-account-list.js +15 -20
  3. package/build/components/identity/xprn-avatar.js +1 -1
  4. package/build/components/identity/xprn-identity-proof-gate.d.ts +5 -4
  5. package/build/components/identity/xprn-identity-proof-gate.js +10 -12
  6. package/build/components/identity/xprn-identity.d.ts +10 -0
  7. package/build/components/identity/xprn-identity.js +3 -3
  8. package/build/components/identity/xprn-session-actor.js +1 -1
  9. package/build/components/identity/xprn-session-name.d.ts +0 -6
  10. package/build/components/identity/xprn-session-name.js +6 -9
  11. package/build/components/swap/xprn-swap-provider.js +1 -1
  12. package/build/components/xprn-container.js +1 -1
  13. package/build/components/xprn-session.d.ts +10 -0
  14. package/build/components/xprn-session.js +15 -4
  15. package/build/components/xprn-transaction.js +5 -5
  16. package/build/hooks/index.d.ts +0 -0
  17. package/build/hooks/index.js +1 -0
  18. package/build/hooks/useIdentityProof.d.ts +2 -0
  19. package/build/hooks/useIdentityProof.js +14 -0
  20. package/build/hooks/useProfileList.d.ts +2 -0
  21. package/build/hooks/useProfileList.js +13 -0
  22. package/build/index.d.ts +1 -1
  23. package/build/index.js +1 -1
  24. package/build/interfaces/config.d.ts +12 -0
  25. package/build/interfaces/identity-proof.d.ts +28 -0
  26. package/build/interfaces/identity-proof.js +1 -0
  27. package/build/interfaces/index.d.ts +4 -0
  28. package/build/interfaces/index.js +4 -0
  29. package/build/interfaces/profile.d.ts +5 -0
  30. package/build/interfaces/profile.js +1 -0
  31. package/build/providers/xprnkit-provider.d.ts +23 -0
  32. package/build/providers/xprnkit-provider.js +224 -0
  33. package/build/services/identity-proof/authenticate-identity-proof.d.ts +2 -0
  34. package/build/services/identity-proof/authenticate-identity-proof.js +42 -0
  35. package/build/services/identity-proof/index.d.ts +3 -10
  36. package/build/services/identity-proof/index.js +3 -8
  37. package/build/services/identity-proof/request-identity-proof.d.ts +7 -0
  38. package/build/services/identity-proof/{create-identity-proof.js → request-identity-proof.js} +2 -17
  39. package/build/services/identity-proof/verify-identity-proof.d.ts +5 -22
  40. package/build/services/identity-proof/verify-identity-proof.js +58 -68
  41. package/build/utils/identity-proof-storage.d.ts +14 -0
  42. package/build/utils/identity-proof-storage.js +33 -0
  43. package/build/utils/index.d.ts +1 -1
  44. package/build/utils/index.js +1 -1
  45. package/build/utils/profile-storage.d.ts +17 -0
  46. package/build/utils/profile-storage.js +48 -0
  47. package/build/utils/storage-key.d.ts +1 -0
  48. package/build/utils/storage-key.js +3 -0
  49. package/build/utils/xprnkit-storage.d.ts +9 -0
  50. package/build/utils/xprnkit-storage.js +23 -0
  51. package/package.json +3 -2
  52. package/build/providers/XPRNProvider.d.ts +0 -96
  53. package/build/providers/XPRNProvider.js +0 -473
  54. package/build/services/identity-proof/create-identity-proof.d.ts +0 -23
  55. package/build/services/identity-proof/types.d.ts +0 -82
  56. package/build/services/identity-proof/use-identity-proof.d.ts +0 -38
  57. package/build/services/identity-proof/use-identity-proof.js +0 -145
  58. package/build/services/identity-proof/validate-identity-proof.d.ts +0 -51
  59. package/build/services/identity-proof/validate-identity-proof.js +0 -93
  60. package/build/utils/auth-storage.d.ts +0 -126
  61. package/build/utils/auth-storage.js +0 -216
  62. /package/build/{services/identity-proof/types.js → interfaces/config.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { type SessionStorageEntry } from "../../utils/auth-storage";
2
+ import { XPRNKitProfileStorageEntry } from "../../utils/profile-storage";
3
3
  type XPRNAccountListProps = React.HTMLAttributes<HTMLDivElement> & {
4
4
  /** Show remove button for each account */
5
5
  showRemove?: boolean;
@@ -12,9 +12,9 @@ type XPRNAccountListProps = React.HTMLAttributes<HTMLDivElement> & {
12
12
  /** Custom render for each account item */
13
13
  renderItem?: (props: AccountItemRenderProps) => React.ReactNode;
14
14
  /** Called when an account is selected */
15
- onSelect?: (entry: SessionStorageEntry) => void;
15
+ onSelect?: (entry: XPRNKitProfileStorageEntry) => void;
16
16
  /** Called when an account is removed */
17
- onRemove?: (entry: SessionStorageEntry) => void;
17
+ onRemove?: (entry: XPRNKitProfileStorageEntry) => void;
18
18
  /** Called when add account is clicked */
19
19
  onAddAccount?: () => void;
20
20
  /** Class name for account items */
@@ -23,7 +23,7 @@ type XPRNAccountListProps = React.HTMLAttributes<HTMLDivElement> & {
23
23
  activeClassName?: string;
24
24
  };
25
25
  type AccountItemRenderProps = {
26
- entry: SessionStorageEntry;
26
+ entry: XPRNKitProfileStorageEntry;
27
27
  isActive: boolean;
28
28
  onSelect: () => void;
29
29
  onRemove?: () => void;
@@ -33,7 +33,7 @@ type AccountItemRenderProps = {
33
33
  */
34
34
  export declare const XPRNAccountList: React.FunctionComponent<XPRNAccountListProps>;
35
35
  type XPRNAccountItemProps = {
36
- entry: SessionStorageEntry;
36
+ entry: XPRNKitProfileStorageEntry;
37
37
  isActive: boolean;
38
38
  isSwitching?: boolean;
39
39
  onSelect: () => void;
@@ -1,26 +1,24 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
3
  import classNames from "classnames";
5
- import { useXPRN } from "../../providers/XPRNProvider";
6
- import { sessionStorage } from "../../utils/auth-storage";
7
- import { XPRNAvatarWrapper, XPRNAvatarImage, XPRNAvatarFallback } from "./xprn-avatar";
4
+ import * as React from "react";
8
5
  import { cn } from "../../lib/utils";
6
+ import { useXPRN } from "../../providers/xprnkit-provider";
7
+ import { getProfileStorageKey, XPRNKitProfileStorage } from "../../utils/profile-storage";
8
+ import { XPRNAvatarFallback, XPRNAvatarImage, XPRNAvatarWrapper } from "./xprn-avatar";
9
+ import { useProfileList } from "../../hooks/useProfileList";
10
+ import { useIdentityProof } from "../../hooks/useIdentityProof";
9
11
  /**
10
12
  * Component that lists all stored accounts and allows switching between them
11
13
  */
12
14
  export const XPRNAccountList = ({ className, showRemove = false, showAddAccount = false, addAccountLabel = "Add Account", addAccountClassName, renderItem, onSelect, onRemove, onAddAccount, itemClassName, activeClassName, ...props }) => {
13
15
  const { config, session, switchToSession, disconnect, connect } = useXPRN();
14
- const [entries, setEntries] = React.useState([]);
15
16
  const [switching, setSwitching] = React.useState(null);
16
17
  const dAppName = config?.requesterAccount ?? '';
18
+ const profileStorage = new XPRNKitProfileStorage();
19
+ const entries = useProfileList();
20
+ console.log('entries', entries);
17
21
  // Load entries on mount and when session changes
18
- React.useEffect(() => {
19
- if (typeof window === 'undefined' || !dAppName)
20
- return;
21
- const storedEntries = sessionStorage.list(dAppName);
22
- setEntries(storedEntries);
23
- }, [session, dAppName]);
24
22
  const currentAuth = session ? {
25
23
  actor: session.auth.actor.toString(),
26
24
  permission: session.auth.permission.toString(),
@@ -36,10 +34,8 @@ export const XPRNAccountList = ({ className, showRemove = false, showAddAccount
36
34
  const handleSelect = async (entry) => {
37
35
  if (isActive(entry))
38
36
  return;
39
- const authString = `${entry.auth.actor}@${entry.auth.permission}`;
40
- setSwitching(authString);
41
37
  try {
42
- await switchToSession(authString, entry.chainId);
38
+ await switchToSession(entry.auth.actor, entry.auth.permission);
43
39
  onSelect?.(entry);
44
40
  }
45
41
  catch (error) {
@@ -57,11 +53,8 @@ export const XPRNAccountList = ({ className, showRemove = false, showAddAccount
57
53
  await disconnect();
58
54
  }
59
55
  // Remove from storage
60
- sessionStorage.remove(dAppName, entry.auth, entry.chainId);
61
- // Update local state
62
- setEntries(prev => prev.filter(e => !(e.auth.actor === entry.auth.actor &&
63
- e.auth.permission === entry.auth.permission &&
64
- e.chainId === entry.chainId)));
56
+ const profileStorageKey = getProfileStorageKey(entry.auth.actor, entry.auth.permission, entry.chainId);
57
+ profileStorage.remove(profileStorageKey);
65
58
  onRemove?.(entry);
66
59
  };
67
60
  const handleAddAccount = () => {
@@ -97,7 +90,9 @@ export const XPRNAccountList = ({ className, showRemove = false, showAddAccount
97
90
  */
98
91
  export const XPRNAccountItem = ({ entry, isActive, isSwitching, onSelect, onRemove, className, activeClassName, }) => {
99
92
  const itemClasses = cn("flex items-center gap-3 p-2 rounded-lg cursor-pointer transition-colors text-white", "hover:bg-gray-800", isActive && "bg-gray-900", isActive && activeClassName, className);
100
- return (_jsxs("div", { className: itemClasses, onClick: onSelect, children: [_jsxs(XPRNAvatarWrapper, { className: "w-10 h-10 shrink-0", children: [_jsx(XPRNAvatarFallback, { children: entry.auth.actor[0]?.toUpperCase() }), entry.profile?.avatar && (_jsx(XPRNAvatarImage, { src: `data:image/png;base64,${entry.profile.avatar}` }))] }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "font-medium truncate flex items-center gap-1", children: [entry.profile?.displayName || entry.auth.actor, entry.profile?.isKyc && (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-gray-300 shrink-0", children: [_jsx("path", { d: "M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" }), _jsx("path", { d: "m9 12 2 2 4-4" })] })), entry.identityProofToken && (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-white shrink-0", children: [_jsx("path", { d: "M16 10h2" }), _jsx("path", { d: "M16 14h2" }), _jsx("path", { d: "M6.17 15a3 3 0 0 1 5.66 0" }), _jsx("circle", { cx: "9", cy: "11", r: "2" }), _jsx("rect", { x: "2", y: "5", width: "20", height: "14", rx: "2" })] }))] }), _jsxs("div", { className: "text-sm text-gray-300 truncate", children: [entry.auth.actor, "@", entry.auth.permission] })] }), isSwitching && (_jsxs("svg", { className: "animate-spin h-5 w-5 text-gray-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] })), isActive && !isSwitching && (_jsx("svg", { className: "h-5 w-5 text-green-500", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M20 6 9 17l-5-5" }) })), onRemove && !isActive && (_jsx("button", { onClick: (e) => {
93
+ const identityProof = useIdentityProof(entry.auth.actor, entry.auth.permission, entry.chainId);
94
+ console.log('identityProof', identityProof);
95
+ return (_jsxs("div", { className: itemClasses, onClick: onSelect, children: [_jsxs(XPRNAvatarWrapper, { className: "w-10 h-10 shrink-0", children: [_jsx(XPRNAvatarFallback, { children: entry.auth.actor[0]?.toUpperCase() }), entry?.profile?.avatar && (_jsx(XPRNAvatarImage, { src: `data:image/png;base64,${entry.profile.avatar}` }))] }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "font-medium truncate flex items-center gap-1", children: [entry?.profile?.displayName || entry.auth.actor, entry?.profile?.isKyc && (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-gray-300 shrink-0", children: [_jsx("path", { d: "M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" }), _jsx("path", { d: "m9 12 2 2 4-4" })] })), identityProof && (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-white shrink-0", children: [_jsx("path", { d: "M16 10h2" }), _jsx("path", { d: "M16 14h2" }), _jsx("path", { d: "M6.17 15a3 3 0 0 1 5.66 0" }), _jsx("circle", { cx: "9", cy: "11", r: "2" }), _jsx("rect", { x: "2", y: "5", width: "20", height: "14", rx: "2" })] }))] }), _jsxs("div", { className: "text-sm text-gray-300 truncate", children: [entry.auth.actor, "@", entry.auth.permission] })] }), isSwitching && (_jsxs("svg", { className: "animate-spin h-5 w-5 text-gray-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] })), isActive && !isSwitching && (_jsx("svg", { className: "h-5 w-5 text-green-500", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M20 6 9 17l-5-5" }) })), onRemove && !isActive && (_jsx("button", { onClick: (e) => {
101
96
  e.stopPropagation();
102
97
  onRemove();
103
98
  }, className: "p-1 hover:bg-gray-700 rounded", title: "Remove account", children: _jsxs("svg", { className: "h-4 w-4 text-gray-400", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M18 6 6 18" }), _jsx("path", { d: "m6 6 12 12" })] }) }))] }));
@@ -10,7 +10,7 @@ XPRNAvatarImage.displayName = AvatarPrimitive.Image.displayName;
10
10
  const XPRNAvatarFallback = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Fallback, { ref: ref, className: cn("flex h-full w-full items-center justify-center rounded-full ", className), ...props })));
11
11
  XPRNAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
12
12
  import classNames from "classnames";
13
- import { useXPRN } from "../../providers/XPRNProvider";
13
+ import { useXPRN } from "../../providers/xprnkit-provider";
14
14
  const XPRNAvatar = ({ className, ...props }) => {
15
15
  const { profile, session } = useXPRN();
16
16
  const rootClasses = classNames({
@@ -43,8 +43,10 @@ type XPRNIdentityProofGateProps = {
43
43
  */
44
44
  export declare const XPRNIdentityProofGate: React.FunctionComponent<XPRNIdentityProofGateProps>;
45
45
  /**
46
- * Hook to check identity proof gate status
47
- * Returns the same information used by XPRNIdentityProofGate
46
+ * Hook to check identity proof gate status.
47
+ * Returns the same information used by XPRNIdentityProofGate.
48
+ *
49
+ * For requesting identity proof, use the `useIdentityProof` hook from services.
48
50
  */
49
51
  export declare function useIdentityProofGate(): {
50
52
  isGateActive: boolean;
@@ -54,7 +56,6 @@ export declare function useIdentityProofGate(): {
54
56
  isVerified: boolean;
55
57
  shouldRenderChildren: boolean;
56
58
  needsIdentityProof: boolean;
57
- requestIdentityProof: (success: (res: import("../../providers/XPRNProvider").XPRNIdentityProof) => void, fail: (e: any) => void) => void;
58
- identityProofStatus: import("../..").IdentityProofStatus;
59
+ identityProofStatus: import("../../interfaces").XPRNKitIdentityProofStatus;
59
60
  };
60
61
  export {};
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
- import { useXPRN } from "../../providers/XPRNProvider";
3
+ import { useXPRN } from "../../providers/xprnkit-provider";
4
4
  /**
5
5
  * Conditionally renders children based on identity proof status.
6
6
  *
@@ -18,11 +18,8 @@ import { useXPRN } from "../../providers/XPRNProvider";
18
18
  * ```
19
19
  */
20
20
  export const XPRNIdentityProofGate = ({ children, fallback = null, loading, error, notConnected, }) => {
21
- const { session, identityProof, identityProofStatus, isIdentityProofEnabled, } = useXPRN();
21
+ const { session, identityProof, identityProofStatus, } = useXPRN();
22
22
  // If identity proof is not enabled, render children directly
23
- if (!isIdentityProofEnabled) {
24
- return _jsx(_Fragment, { children: children });
25
- }
26
23
  // No session connected
27
24
  if (!session) {
28
25
  return _jsx(_Fragment, { children: notConnected ?? fallback });
@@ -44,29 +41,30 @@ export const XPRNIdentityProofGate = ({ children, fallback = null, loading, erro
44
41
  };
45
42
  XPRNIdentityProofGate.displayName = "XPRNIdentityProofGate";
46
43
  /**
47
- * Hook to check identity proof gate status
48
- * Returns the same information used by XPRNIdentityProofGate
44
+ * Hook to check identity proof gate status.
45
+ * Returns the same information used by XPRNIdentityProofGate.
46
+ *
47
+ * For requesting identity proof, use the `useIdentityProof` hook from services.
49
48
  */
50
49
  export function useIdentityProofGate() {
51
- const { session, identityProof, identityProofStatus, isIdentityProofEnabled, requestIdentityProof, } = useXPRN();
50
+ const { session, identityProof, identityProofStatus, } = useXPRN();
52
51
  // Determine current state
53
52
  const isConnected = session !== null;
54
53
  const isInProgress = identityProofStatus === "signing" || identityProofStatus === "verifying" || identityProofStatus === "validating";
55
54
  const hasError = identityProofStatus === "error" || identityProofStatus === "expired";
56
55
  const isVerified = identityProof !== null;
57
56
  // Should render protected content?
58
- const shouldRenderChildren = !isIdentityProofEnabled || isVerified;
57
+ const shouldRenderChildren = false;
59
58
  // Needs identity proof: enabled, connected, and not yet verified
60
- const needsIdentityProof = isIdentityProofEnabled && isConnected && !isVerified;
59
+ const needsIdentityProof = false;
61
60
  return {
62
- isGateActive: isIdentityProofEnabled,
61
+ isGateActive: false,
63
62
  isConnected,
64
63
  isInProgress,
65
64
  hasError,
66
65
  isVerified,
67
66
  shouldRenderChildren,
68
67
  needsIdentityProof,
69
- requestIdentityProof,
70
68
  identityProofStatus,
71
69
  };
72
70
  }
@@ -1,4 +1,8 @@
1
1
  import * as React from "react";
2
+ import type { Link, LinkSession } from "@proton/link";
3
+ import type { ProtonWebLink } from "@proton/web-sdk";
4
+ import { XPRNKitProfile } from "interfaces/profile";
5
+ import { XPRNKitIdentityProof } from "interfaces/identity-proof";
2
6
  type XPRNIdentityProps = React.HTMLAttributes<HTMLDivElement> & {
3
7
  showLogout?: boolean;
4
8
  activeSessionClassName?: string;
@@ -8,6 +12,12 @@ type XPRNIdentityProps = React.HTMLAttributes<HTMLDivElement> & {
8
12
  matchDropdownWidth?: boolean;
9
13
  /** Close dropdown when children are clicked */
10
14
  closeOnSelect?: boolean;
15
+ /** Called when session is established */
16
+ onSession?: (session: LinkSession, link: ProtonWebLink | Link) => void;
17
+ /** Called when profile is fetched */
18
+ onProfile?: (profile: XPRNKitProfile) => void;
19
+ /** Called when identity proof is obtained */
20
+ onIdentityProof?: (proof: XPRNKitIdentityProof) => void;
11
21
  };
12
22
  export declare const XPRNIdentity: React.FunctionComponent<XPRNIdentityProps>;
13
23
  export {};
@@ -5,10 +5,10 @@ import * as React from "react";
5
5
  import { XPRNAvatar } from "./xprn-avatar";
6
6
  import { XPRNSessionActor } from "./xprn-session-actor";
7
7
  import { XPRNSessionName } from "./xprn-session-name";
8
- import { useXPRN } from "../../providers/XPRNProvider";
8
+ import { useXPRN } from "../../providers/xprnkit-provider";
9
9
  import { XPRNConnectButton } from "./../xprn-session";
10
10
  import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from "./../ui/dropdown";
11
- export const XPRNIdentity = ({ children, className, showLogout, activeSessionClassName, dropdownClassName, avatarClassName, matchDropdownWidth = true, closeOnSelect = true, }) => {
11
+ export const XPRNIdentity = ({ children, className, showLogout, activeSessionClassName, dropdownClassName, avatarClassName, matchDropdownWidth = true, closeOnSelect = true, onSession, onProfile, onIdentityProof, }) => {
12
12
  const [open, setOpen] = React.useState(false);
13
13
  const rootClasses = classNames({
14
14
  "grid grid-cols-[min-content,1fr] gap-4 items-center inline": true,
@@ -27,5 +27,5 @@ export const XPRNIdentity = ({ children, className, showLogout, activeSessionCla
27
27
  e.preventDefault();
28
28
  disconnect();
29
29
  }, [disconnect]);
30
- return (_jsx(_Fragment, { children: session ? (_jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, children: [_jsx(DropdownMenuTrigger, { className: "inline w-auto flex-grow-0", children: _jsxs("div", { className: activeSessionClasses, children: [_jsx("div", { className: "w-10 h-10", children: _jsx(XPRNAvatar, { className: avatarClassName }) }), _jsxs("div", { className: "flex flex-col", children: [_jsx(XPRNSessionName, { className: "text-md font-bold" }), _jsxs("div", { className: "flex gap-2", children: [_jsx(XPRNSessionActor, { className: "text-md" }), showLogout && (_jsx("a", { href: "#", className: "underline", onClick: e => handleDisconnect(e), children: "Log out" }))] })] })] }) }), children && (_jsx(DropdownMenuContent, { className: dropdownClasses, matchTriggerWidth: matchDropdownWidth, onClick: () => closeOnSelect && setOpen(false), children: children }))] })) : (_jsx(XPRNConnectButton, { className: rootClasses, children: "Connect" })) }));
30
+ return (_jsx(_Fragment, { children: session ? (_jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, children: [_jsx(DropdownMenuTrigger, { className: "inline w-auto flex-grow-0", children: _jsxs("div", { className: activeSessionClasses, children: [_jsx("div", { className: "w-10 h-10", children: _jsx(XPRNAvatar, { className: avatarClassName }) }), _jsxs("div", { className: "flex flex-col", children: [_jsx(XPRNSessionName, { className: "text-md font-bold", showIdentityProof: true }), _jsxs("div", { className: "flex gap-2", children: [_jsx(XPRNSessionActor, { className: "text-md" }), showLogout && (_jsx("a", { href: "#", className: "underline", onClick: e => handleDisconnect(e), children: "Log out" }))] })] })] }) }), children && (_jsx(DropdownMenuContent, { className: dropdownClasses, matchTriggerWidth: matchDropdownWidth, onClick: () => closeOnSelect && setOpen(false), children: children }))] })) : (_jsx(XPRNConnectButton, { className: rootClasses, onSession: onSession, onProfile: onProfile, onIdentityProof: onIdentityProof, children: "Connect" })) }));
31
31
  };
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import classNames from 'classnames';
4
- import { useXPRN } from '../../providers/XPRNProvider';
4
+ import { useXPRN } from '../../providers/xprnkit-provider';
5
5
  export const XPRNSessionActor = ({ children, className }) => {
6
6
  const { session } = useXPRN();
7
7
  const rootClasses = classNames({
@@ -9,12 +9,6 @@ type XPRNSessionNameProps = React.HTMLAttributes<HTMLHeadElement> & {
9
9
  * Get badge styling based on identity proof status
10
10
  */
11
11
  declare function useIdentityProofBadgeStyle(): {
12
- visible: boolean;
13
- className: string;
14
- isPending?: undefined;
15
- isSuccess?: undefined;
16
- isError?: undefined;
17
- } | {
18
12
  visible: boolean;
19
13
  className: string;
20
14
  isPending: boolean;
@@ -2,16 +2,13 @@
2
2
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useMemo } from "react";
4
4
  import classNames from "classnames";
5
- import { useXPRN } from "../../providers/XPRNProvider";
5
+ import { useXPRN } from "../../providers/xprnkit-provider";
6
6
  /**
7
7
  * Get badge styling based on identity proof status
8
8
  */
9
9
  function useIdentityProofBadgeStyle() {
10
- const { identityProofStatus, isIdentityProofEnabled, identityProof, session } = useXPRN();
10
+ const { identityProofStatus, identityProof, session } = useXPRN();
11
11
  return useMemo(() => {
12
- if (!isIdentityProofEnabled) {
13
- return { visible: false, className: "" };
14
- }
15
12
  const isPending = identityProofStatus === "signing" ||
16
13
  identityProofStatus === "verifying" ||
17
14
  identityProofStatus === "validating";
@@ -43,14 +40,14 @@ function useIdentityProofBadgeStyle() {
43
40
  isSuccess,
44
41
  isError,
45
42
  };
46
- }, [identityProofStatus, isIdentityProofEnabled, identityProof, session]);
43
+ }, [identityProofStatus, identityProof, session]);
47
44
  }
48
45
  export const XPRNSessionName = ({ children, className, showIdentityProof = false, }) => {
49
- const { profile, session } = useXPRN();
46
+ const { profile, session, identityProof } = useXPRN();
50
47
  const badgeStyle = useIdentityProofBadgeStyle();
51
- const showBadge = showIdentityProof && badgeStyle.visible;
48
+ const showBadge = showIdentityProof && badgeStyle.visible && identityProof !== null;
52
49
  const rootClasses = classNames({
53
- "flex gap-2 items-center justify-center": true,
50
+ "flex gap-2 items-center": true,
54
51
  [`${className}`]: className,
55
52
  });
56
53
  if (!profile || !session)
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import React, { useCallback, useContext, useEffect, useMemo, useState, } from "react";
4
4
  import { getSwapMarkets } from "./xprn-swap-markets";
5
- import { useXPRN } from "../../providers/XPRNProvider";
5
+ import { useXPRN } from "../../providers/xprnkit-provider";
6
6
  const XPRNSwapContext = React.createContext({
7
7
  marketProviders: [],
8
8
  currentMarketProvider: null,
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
- import { useXPRN } from "../providers/XPRNProvider";
3
+ import { useXPRN } from "../providers/xprnkit-provider";
4
4
  export const XRPNContainer = ({ children, className, noSessionState, }) => {
5
5
  const { session } = useXPRN();
6
6
  return _jsx(_Fragment, { children: session ? _jsx(_Fragment, { children: children }) : _jsx(_Fragment, { children: noSessionState }) });
@@ -1,11 +1,21 @@
1
+ import type { Link, LinkSession } from "@proton/link";
2
+ import type { ProtonWebLink } from "@proton/web-sdk";
1
3
  import * as React from "react";
2
4
  import { type VariantProps } from "class-variance-authority";
5
+ import { XPRNKitProfile } from "interfaces/profile";
6
+ import { XPRNKitIdentityProof } from "interfaces/identity-proof";
3
7
  declare const XPRNConnectButtonVariants: (props?: ({
4
8
  variant?: null | undefined;
5
9
  size?: null | undefined;
6
10
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
7
11
  export interface XPRNConnectButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof XPRNConnectButtonVariants> {
8
12
  asChild?: boolean;
13
+ /** Called when session is established */
14
+ onSession?: (session: LinkSession, link: ProtonWebLink | Link) => void;
15
+ /** Called when profile is fetched */
16
+ onProfile?: (profile: XPRNKitProfile) => void;
17
+ /** Called when identity proof is obtained */
18
+ onIdentityProof?: (proof: XPRNKitIdentityProof) => void;
9
19
  }
10
20
  declare const XPRNConnectButton: React.ForwardRefExoticComponent<XPRNConnectButtonProps & React.RefAttributes<HTMLButtonElement>>;
11
21
  export { XPRNConnectButton, XPRNConnectButtonVariants };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useXPRN } from "../providers/XPRNProvider";
3
+ import { useXPRN } from "../providers/xprnkit-provider";
4
4
  import * as React from "react";
5
5
  import { Slot } from "@radix-ui/react-slot";
6
6
  import { cva } from "class-variance-authority";
@@ -12,10 +12,21 @@ const XPRNConnectButtonVariants = cva("inline-flex items-center justify-center w
12
12
  },
13
13
  defaultVariants: {},
14
14
  });
15
- const XPRNConnectButton = React.forwardRef(({ className, variant, size, asChild = false, onClick, children, ...props }, ref) => {
15
+ const XPRNConnectButton = React.forwardRef(({ className, variant, size, asChild = false, onClick, children, onSession, onProfile, onIdentityProof, ...props }, ref) => {
16
16
  const Comp = asChild ? Slot : "button";
17
- const { session, connect, disconnect } = useXPRN();
18
- return (_jsxs(_Fragment, { children: [!session && (_jsx(Comp, { onClick: () => connect(), className: cn(XPRNConnectButtonVariants({ variant, size, className })), ref: ref, children: children, ...props })), session && (_jsx(Comp, { onClick: () => disconnect(), className: cn(XPRNConnectButtonVariants({ variant, size, className })), ref: ref, children: `Log out (${session.auth.actor.toString()})`, ...props }))] }));
17
+ const { session, connect, disconnect, identityProof } = useXPRN();
18
+ const prevIdentityProofRef = React.useRef(identityProof);
19
+ // Call onIdentityProof when identity proof changes from null to a value
20
+ React.useEffect(() => {
21
+ if (identityProof && !prevIdentityProofRef.current && onIdentityProof) {
22
+ onIdentityProof(identityProof);
23
+ }
24
+ prevIdentityProofRef.current = identityProof;
25
+ }, [identityProof, onIdentityProof]);
26
+ const handleConnect = React.useCallback(() => {
27
+ connect();
28
+ }, [connect, onSession, onProfile]);
29
+ return (_jsxs(_Fragment, { children: [!session && (_jsx(Comp, { onClick: handleConnect, className: cn(XPRNConnectButtonVariants({ variant, size, className })), ref: ref, children: children, ...props })), session && (_jsx(Comp, { onClick: () => disconnect(), className: cn(XPRNConnectButtonVariants({ variant, size, className })), ref: ref, children: `Log out (${session.auth.actor.toString()})`, ...props }))] }));
19
30
  });
20
31
  XPRNConnectButton.displayName = "XPRNConnectButton";
21
32
  export { XPRNConnectButton, XPRNConnectButtonVariants };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useXPRN } from "../providers/XPRNProvider";
3
+ import { useXPRN } from "../providers/xprnkit-provider";
4
4
  import * as React from "react";
5
5
  import { Slot } from "@radix-ui/react-slot";
6
6
  import { cva } from "class-variance-authority";
@@ -14,7 +14,7 @@ const XPRNTransactionVariants = cva("inline-flex items-center justify-center whi
14
14
  });
15
15
  const XPRNTransaction = React.forwardRef(({ className, variant, size, asChild = false, onClick, children, actions, onTransactionStart, onTransactionSuccess, onTransactionFail, ...props }, ref) => {
16
16
  const Comp = asChild ? Slot : "button";
17
- const { session, connect, addTransactionError } = useXPRN();
17
+ const { session, connect } = useXPRN();
18
18
  const [txStatus, setTxStatus] = React.useState('idle');
19
19
  const TxStatusNode = React.useMemo(() => {
20
20
  if (txStatus == 'idle')
@@ -39,13 +39,13 @@ const XPRNTransaction = React.forwardRef(({ className, variant, size, asChild =
39
39
  }).catch((e) => {
40
40
  console.error(e);
41
41
  setTxStatus('fail');
42
- addTransactionError(e);
42
+ if (onTransactionFail)
43
+ onTransactionFail(e);
43
44
  });
44
45
  }
45
46
  catch (e) {
46
47
  setTxStatus('fail');
47
48
  console.error(e);
48
- addTransactionError(e.toString());
49
49
  if (onTransactionFail)
50
50
  onTransactionFail(e);
51
51
  setTimeout(() => {
@@ -54,7 +54,7 @@ const XPRNTransaction = React.forwardRef(({ className, variant, size, asChild =
54
54
  }
55
55
  }
56
56
  }, [session, actions, setTxStatus]);
57
- return (_jsxs(_Fragment, { children: [!session && (_jsx(Comp, { onClick: () => connect(false, () => pushTransaction()), className: cn(XPRNTransactionVariants({ variant, size, className })), ref: ref, children: "Connecte Me!", ...props })), session && (_jsx(Comp, { onClick: () => pushTransaction(), className: cn(XPRNTransactionVariants({ variant, size, className })), ref: ref, children: TxStatusNode, ...props }))] }));
57
+ return (_jsxs(_Fragment, { children: [!session && (_jsx(Comp, { onClick: () => connect(false), className: cn(XPRNTransactionVariants({ variant, size, className })), ref: ref, children: "Connecte Me!", ...props })), session && (_jsx(Comp, { onClick: () => pushTransaction(), className: cn(XPRNTransactionVariants({ variant, size, className })), ref: ref, children: TxStatusNode, ...props }))] }));
58
58
  });
59
59
  XPRNTransaction.displayName = "XPRNTransaction";
60
60
  export { XPRNTransaction, XPRNTransactionVariants };
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,2 @@
1
+ import { XPRNKitIdentityProof } from "../interfaces";
2
+ export declare function useIdentityProof(actor: string, permission: string, chainId: string): XPRNKitIdentityProof | null;
@@ -0,0 +1,14 @@
1
+ import { useEffect, useState } from "react";
2
+ import { getIdentityProofStorageKey, XPRNKitIdentityStorage } from "../utils/identity-proof-storage";
3
+ export function useIdentityProof(actor, permission, chainId) {
4
+ const [identityProof, setIdentityProof] = useState(null);
5
+ useEffect(() => {
6
+ const identityProofStorage = new XPRNKitIdentityStorage();
7
+ const identityProofStorageKey = getIdentityProofStorageKey(actor, permission, chainId);
8
+ identityProofStorage.read(identityProofStorageKey).then((storedIdentityProof) => {
9
+ const identity = storedIdentityProof ? JSON.parse(storedIdentityProof) : null;
10
+ setIdentityProof(identity);
11
+ });
12
+ }, []);
13
+ return identityProof;
14
+ }
@@ -0,0 +1,2 @@
1
+ import { XPRNKitProfileStorageEntry } from "../utils/profile-storage";
2
+ export declare function useProfileList(): XPRNKitProfileStorageEntry[];
@@ -0,0 +1,13 @@
1
+ import { useEffect, useState } from "react";
2
+ import { XPRNKitProfileStorage } from "../utils/profile-storage";
3
+ export function useProfileList() {
4
+ const [profileList, setProfileList] = useState([]);
5
+ useEffect(() => {
6
+ const profileStorage = new XPRNKitProfileStorage();
7
+ profileStorage.list().then((list) => {
8
+ const rawListData = JSON.parse(list);
9
+ setProfileList(rawListData);
10
+ });
11
+ }, []);
12
+ return profileList;
13
+ }
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export * from './providers/XPRNProvider';
1
+ export * from './providers/xprnkit-provider';
2
2
  export * from './components';
3
3
  export * from './utils';
4
4
  export * from './services';
package/build/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export * from './providers/XPRNProvider';
1
+ export * from './providers/xprnkit-provider';
2
2
  export * from './components';
3
3
  export * from './utils';
4
4
  export * from './services';
@@ -0,0 +1,12 @@
1
+ import { XPRNKitIdentityProofConfig } from "./identity-proof";
2
+ export type XPRProviderConfig = {
3
+ chainId: string;
4
+ endpoints: string[];
5
+ dAppName: string;
6
+ requesterAccount: string;
7
+ requesterLogo?: string;
8
+ apiMode: "testnet" | "mainnet";
9
+ restoreSession?: boolean;
10
+ /** Identity proof configuration (optional - if not provided, identity proof is disabled) */
11
+ identityProof?: XPRNKitIdentityProofConfig;
12
+ };
@@ -0,0 +1,28 @@
1
+ export type XPRNKitIdentityProofPayload = {
2
+ signer: {
3
+ actor: string;
4
+ permission: string;
5
+ };
6
+ transaction: any;
7
+ signatures: string[];
8
+ chainId: string;
9
+ };
10
+ export type XPRNKitIdentityProof = {
11
+ auth: {
12
+ actor: string;
13
+ permission: string;
14
+ };
15
+ token: string;
16
+ };
17
+ export type XPRNKitIdentityProofConfig = {
18
+ required: boolean;
19
+ createUrl: string;
20
+ validationUrl?: string;
21
+ validationBuffer?: number;
22
+ headers?: Record<string, string>;
23
+ timeout?: number;
24
+ };
25
+ /**
26
+ * Status of identity proof process
27
+ */
28
+ export type XPRNKitIdentityProofStatus = "idle" | "signing" | "verifying" | "validating" | "success" | "expired" | "error";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from "./config";
2
+ export * from "./identity-proof";
3
+ export * from "./profile";
4
+ export * from "./service-status";
@@ -0,0 +1,4 @@
1
+ export * from "./config";
2
+ export * from "./identity-proof";
3
+ export * from "./profile";
4
+ export * from "./service-status";
@@ -0,0 +1,5 @@
1
+ export type XPRNKitProfile = {
2
+ displayName: string;
3
+ avatar?: string;
4
+ isKyc: boolean;
5
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import type { Link, LinkSession } from "@proton/link";
2
+ import { ProtonWebLink } from "@proton/web-sdk";
3
+ import React from "react";
4
+ import { XPRNKitIdentityProof, XPRNKitIdentityProofStatus, XPRNKitProfile, XPRProviderConfig } from "../interfaces";
5
+ type XPRNProviderProps = {
6
+ children: React.ReactNode | React.ReactNode[];
7
+ config: XPRProviderConfig;
8
+ };
9
+ type XPRNProviderContext = {
10
+ config: XPRProviderConfig | null;
11
+ session: LinkSession | null;
12
+ link: ProtonWebLink | Link | null;
13
+ profile: XPRNKitProfile | null;
14
+ identityProof: XPRNKitIdentityProof | null;
15
+ identityProofStatus: XPRNKitIdentityProofStatus;
16
+ connect: (restore?: boolean) => void;
17
+ disconnect: () => Promise<void>;
18
+ pushTransaction: (actions: any[]) => Promise<void>;
19
+ switchToSession: (actor: string, permission: string) => Promise<void>;
20
+ };
21
+ export declare const XPRNProvider: React.FunctionComponent<XPRNProviderProps>;
22
+ export declare function useXPRN(): XPRNProviderContext;
23
+ export {};