@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.
- package/build/components/identity/xprn-account-list.d.ts +5 -5
- package/build/components/identity/xprn-account-list.js +15 -20
- package/build/components/identity/xprn-avatar.js +1 -1
- package/build/components/identity/xprn-identity-proof-gate.d.ts +5 -4
- package/build/components/identity/xprn-identity-proof-gate.js +10 -12
- package/build/components/identity/xprn-identity.d.ts +10 -0
- package/build/components/identity/xprn-identity.js +3 -3
- package/build/components/identity/xprn-session-actor.js +1 -1
- package/build/components/identity/xprn-session-name.d.ts +0 -6
- package/build/components/identity/xprn-session-name.js +6 -9
- package/build/components/swap/xprn-swap-provider.js +1 -1
- package/build/components/xprn-container.js +1 -1
- package/build/components/xprn-session.d.ts +10 -0
- package/build/components/xprn-session.js +15 -4
- package/build/components/xprn-transaction.js +5 -5
- package/build/hooks/index.d.ts +0 -0
- package/build/hooks/index.js +1 -0
- package/build/hooks/useIdentityProof.d.ts +2 -0
- package/build/hooks/useIdentityProof.js +14 -0
- package/build/hooks/useProfileList.d.ts +2 -0
- package/build/hooks/useProfileList.js +13 -0
- package/build/index.d.ts +1 -1
- package/build/index.js +1 -1
- package/build/interfaces/config.d.ts +12 -0
- package/build/interfaces/identity-proof.d.ts +28 -0
- package/build/interfaces/identity-proof.js +1 -0
- package/build/interfaces/index.d.ts +4 -0
- package/build/interfaces/index.js +4 -0
- package/build/interfaces/profile.d.ts +5 -0
- package/build/interfaces/profile.js +1 -0
- package/build/providers/xprnkit-provider.d.ts +23 -0
- package/build/providers/xprnkit-provider.js +224 -0
- package/build/services/identity-proof/authenticate-identity-proof.d.ts +2 -0
- package/build/services/identity-proof/authenticate-identity-proof.js +42 -0
- package/build/services/identity-proof/index.d.ts +3 -10
- package/build/services/identity-proof/index.js +3 -8
- package/build/services/identity-proof/request-identity-proof.d.ts +7 -0
- package/build/services/identity-proof/{create-identity-proof.js → request-identity-proof.js} +2 -17
- package/build/services/identity-proof/verify-identity-proof.d.ts +5 -22
- package/build/services/identity-proof/verify-identity-proof.js +58 -68
- package/build/utils/identity-proof-storage.d.ts +14 -0
- package/build/utils/identity-proof-storage.js +33 -0
- package/build/utils/index.d.ts +1 -1
- package/build/utils/index.js +1 -1
- package/build/utils/profile-storage.d.ts +17 -0
- package/build/utils/profile-storage.js +48 -0
- package/build/utils/storage-key.d.ts +1 -0
- package/build/utils/storage-key.js +3 -0
- package/build/utils/xprnkit-storage.d.ts +9 -0
- package/build/utils/xprnkit-storage.js +23 -0
- package/package.json +3 -2
- package/build/providers/XPRNProvider.d.ts +0 -96
- package/build/providers/XPRNProvider.js +0 -473
- package/build/services/identity-proof/create-identity-proof.d.ts +0 -23
- package/build/services/identity-proof/types.d.ts +0 -82
- package/build/services/identity-proof/use-identity-proof.d.ts +0 -38
- package/build/services/identity-proof/use-identity-proof.js +0 -145
- package/build/services/identity-proof/validate-identity-proof.d.ts +0 -51
- package/build/services/identity-proof/validate-identity-proof.js +0 -93
- package/build/utils/auth-storage.d.ts +0 -126
- package/build/utils/auth-storage.js +0 -216
- /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 {
|
|
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:
|
|
15
|
+
onSelect?: (entry: XPRNKitProfileStorageEntry) => void;
|
|
16
16
|
/** Called when an account is removed */
|
|
17
|
-
onRemove?: (entry:
|
|
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:
|
|
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:
|
|
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
|
|
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(
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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/
|
|
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
|
-
|
|
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/
|
|
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,
|
|
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,
|
|
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 =
|
|
57
|
+
const shouldRenderChildren = false;
|
|
59
58
|
// Needs identity proof: enabled, connected, and not yet verified
|
|
60
|
-
const needsIdentityProof =
|
|
59
|
+
const needsIdentityProof = false;
|
|
61
60
|
return {
|
|
62
|
-
isGateActive:
|
|
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/
|
|
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/
|
|
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/
|
|
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,
|
|
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,
|
|
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
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
-
|
|
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/
|
|
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
|
|
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
|
-
|
|
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
|
|
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,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,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
package/build/index.js
CHANGED
|
@@ -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 @@
|
|
|
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 {};
|