@rockerone/xprnkit 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,10 +98,12 @@ function YourComponent() {
98
98
  profile,
99
99
  identityProof,
100
100
  identityProofStatus,
101
+ identityProofError,
101
102
  connect,
102
103
  disconnect,
103
104
  pushTransaction,
104
105
  switchToSession,
106
+ requestIdentityProof,
105
107
  } = useXPRN();
106
108
 
107
109
  // Use the context values and functions
@@ -120,6 +122,7 @@ The `useXPRN` hook returns an object with the following properties:
120
122
  - `profile`: `XPRNKitProfile | null` - Profile data for the active session.
121
123
  - `identityProof`: `XPRNKitIdentityProof | null` - Identity proof for the active session (when identity proof is configured).
122
124
  - `identityProofStatus`: `XPRNKitIdentityProofStatus` - Current status of the identity proof process (`"idle"` | `"signing"` | `"verifying"` | `"validating"` | `"success"` | `"expired"` | `"error"`).
125
+ - `identityProofError`: `Error | null` - The error from the last failed identity proof attempt, or `null` when there is no error.
123
126
 
124
127
  #### Methods
125
128
 
@@ -127,6 +130,7 @@ The `useXPRN` hook returns an object with the following properties:
127
130
  - `disconnect()`: Disconnects the current active session.
128
131
  - `pushTransaction(actions: any[])`: Pushes a transaction with the given actions using the active session.
129
132
  - `switchToSession(actor: string, permission: string)`: Switches to a different stored session by restoring it from the Proton Web SDK storage.
133
+ - `requestIdentityProof()`: Triggers the identity proof flow (restore, sign, authenticate) for the current session. Can be used to retry after an error or to request proof on demand when `identityProof.required` is `false`.
130
134
 
131
135
  ### Basic Example
132
136
 
@@ -229,6 +233,8 @@ type XPRNKitIdentityProofConfig = {
229
233
  3. If no valid proof exists, the user is prompted to sign a message in their wallet.
230
234
  4. The signed message is sent to the `createUrl` backend endpoint for verification.
231
235
  5. The backend returns a JWT token which is stored in localStorage and made available via `useXPRN().identityProof`.
236
+ 6. If any step fails, `identityProofStatus` is set to `"error"` and the error is available via `useXPRN().identityProofError`.
237
+ 7. You can call `requestIdentityProof()` to retry after a failure, or to trigger proof on demand when `required` is `false`.
232
238
 
233
239
  ## Backend Endpoints
234
240
 
@@ -280,14 +286,21 @@ Validates an existing JWT token:
280
286
  Use `XPRNIdentityProofGate` to conditionally render content based on identity proof status:
281
287
 
282
288
  ```tsx
283
- import { XPRNIdentityProofGate } from '@rockerone/xprnkit';
289
+ import { XPRNIdentityProofGate, useXPRN } from '@rockerone/xprnkit';
284
290
 
285
291
  function ProtectedContent() {
292
+ const { identityProofError, requestIdentityProof } = useXPRN();
293
+
286
294
  return (
287
295
  <XPRNIdentityProofGate
288
296
  fallback={<p>Please verify your identity to access this content.</p>}
289
297
  loading={<p>Verifying identity...</p>}
290
- error={<p>Verification failed. Please try again.</p>}
298
+ error={
299
+ <div>
300
+ <p>Verification failed: {identityProofError?.message}</p>
301
+ <button onClick={requestIdentityProof}>Retry</button>
302
+ </div>
303
+ }
291
304
  notConnected={<p>Please connect your wallet first.</p>}
292
305
  >
293
306
  <p>This content is only visible after identity verification.</p>
@@ -13,6 +13,9 @@ export type XPRNKitIdentityProof = {
13
13
  permission: string;
14
14
  };
15
15
  token: string;
16
+ metadata: {
17
+ [key: string]: any;
18
+ };
16
19
  };
17
20
  export type XPRNKitIdentityProofConfig = {
18
21
  required: boolean;
@@ -13,10 +13,12 @@ type XPRNProviderContext = {
13
13
  profile: XPRNKitProfile | null;
14
14
  identityProof: XPRNKitIdentityProof | null;
15
15
  identityProofStatus: XPRNKitIdentityProofStatus;
16
+ identityProofError: Error | null;
16
17
  connect: (restore?: boolean) => void;
17
18
  disconnect: () => Promise<void>;
18
19
  pushTransaction: (actions: any[]) => Promise<void>;
19
20
  switchToSession: (actor: string, permission: string) => Promise<void>;
21
+ requestIdentityProof: () => Promise<void>;
20
22
  };
21
23
  export declare const XPRNProvider: React.FunctionComponent<XPRNProviderProps>;
22
24
  export declare function useXPRN(): XPRNProviderContext;
@@ -14,10 +14,12 @@ const XPRNContext = React.createContext({
14
14
  profile: null,
15
15
  identityProof: null,
16
16
  identityProofStatus: "idle",
17
+ identityProofError: null,
17
18
  connect: () => { },
18
19
  disconnect: async () => { },
19
20
  pushTransaction: async () => { },
20
21
  switchToSession: async () => { },
22
+ requestIdentityProof: async () => { },
21
23
  });
22
24
  export const XPRNProvider = ({ children, config, }) => {
23
25
  const [session, setSession] = useState(null);
@@ -25,6 +27,7 @@ export const XPRNProvider = ({ children, config, }) => {
25
27
  const [profile, setProfile] = useState(null);
26
28
  const [identityProof, setIdentityProof] = useState(null);
27
29
  const [identityProofStatus, setIdentityProofStatus] = useState("idle");
30
+ const [identityProofError, setIdentityProofError] = useState(null);
28
31
  const profileStorage = new XPRNKitProfileStorage();
29
32
  const identityProofStorage = new XPRNKitIdentityStorage();
30
33
  async function fetchProfile(session) {
@@ -144,6 +147,35 @@ export const XPRNProvider = ({ children, config, }) => {
144
147
  }
145
148
  });
146
149
  }
150
+ async function processIdentityProof(session) {
151
+ if (!config.identityProof)
152
+ return;
153
+ try {
154
+ setIdentityProofError(null);
155
+ setIdentityProofStatus("verifying");
156
+ const existingIdentityProof = await restoreIdentityProof(session).catch(() => null);
157
+ if (existingIdentityProof) {
158
+ setIdentityProof(existingIdentityProof);
159
+ setIdentityProofStatus("success");
160
+ return;
161
+ }
162
+ setIdentityProofStatus("signing");
163
+ const identityProofPayload = await createIdentityProof(session);
164
+ setIdentityProofStatus("verifying");
165
+ const proof = await fetchIdentityProof(identityProofPayload, session);
166
+ setIdentityProof(proof);
167
+ setIdentityProofStatus("success");
168
+ }
169
+ catch (error) {
170
+ setIdentityProofStatus("error");
171
+ setIdentityProofError(error instanceof Error ? error : new Error(String(error)));
172
+ }
173
+ }
174
+ const requestIdentityProof_ = useCallback(async () => {
175
+ if (!session)
176
+ return;
177
+ await processIdentityProof(session);
178
+ }, [session, config]);
147
179
  const connect = useCallback(async (restore) => {
148
180
  const { session, link } = await ConnectWallet({
149
181
  linkOptions: {
@@ -167,24 +199,7 @@ export const XPRNProvider = ({ children, config, }) => {
167
199
  setLink(link);
168
200
  await fetchProfile(session);
169
201
  if (config.identityProof && config.identityProof.required) {
170
- console.log('verifying identity proof');
171
- setIdentityProofStatus("verifying");
172
- const existingIdentityProof = await restoreIdentityProof(session).catch(() => {
173
- console.log('Identity proof not found, creating new one through catch');
174
- });
175
- console.log('existingIdentityProof', existingIdentityProof);
176
- if (!existingIdentityProof) {
177
- console.log('creating identity proof');
178
- const identityProofPayload = await createIdentityProof(session);
179
- const identityProof = await fetchIdentityProof(identityProofPayload, session);
180
- setIdentityProof(identityProof);
181
- setIdentityProofStatus("success");
182
- }
183
- else {
184
- console.log('restoring identity proof');
185
- setIdentityProof(existingIdentityProof);
186
- setIdentityProofStatus("success");
187
- }
202
+ await processIdentityProof(session);
188
203
  }
189
204
  }, [config]);
190
205
  const disconnect = useCallback(async () => {
@@ -217,7 +232,7 @@ export const XPRNProvider = ({ children, config, }) => {
217
232
  if (!session)
218
233
  connect(true);
219
234
  }, []);
220
- return (_jsx(XPRNContext.Provider, { value: { config, session, link, profile, identityProof, identityProofStatus, connect, disconnect, pushTransaction, switchToSession }, children: children }));
235
+ return (_jsx(XPRNContext.Provider, { value: { config, session, link, profile, identityProof, identityProofStatus, identityProofError, connect, disconnect, pushTransaction, switchToSession, requestIdentityProof: requestIdentityProof_ }, children: children }));
221
236
  };
222
237
  export function useXPRN() {
223
238
  return useContext(XPRNContext);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rockerone/xprnkit",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "source": "src/index.ts",
5
5
  "main": "build/index.js",
6
6
  "type": "module",