@oobit/react-native-sdk 1.0.7 → 2.0.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/src/WidgetSDK.tsx CHANGED
@@ -26,7 +26,10 @@ import { isWalletAvailable, openNativeWallet } from "./walletUtils";
26
26
  import * as Clipboard from "expo-clipboard";
27
27
 
28
28
  export interface WidgetSDKRef {
29
+ /** Navigate back within the widget */
29
30
  navigateBack: () => void;
31
+ /** Reload the widget */
32
+ reload: () => void;
30
33
  }
31
34
 
32
35
  export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
@@ -36,13 +39,25 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
36
39
  userWalletAddress,
37
40
  environment,
38
41
  onReady,
39
- onCardCreated,
40
42
  onError,
41
43
  onClose,
42
44
  onTransactionRequested,
45
+ onLoadingChange,
46
+ debug = false,
47
+ loadingIndicatorColor = "#007AFF",
43
48
  },
44
49
  ref
45
50
  ) => {
51
+ // Debug logger - only logs when debug is enabled
52
+ const log = debug
53
+ ? (...args: unknown[]) => console.log("[WidgetSDK]", ...args)
54
+ : () => {};
55
+ const logError = debug
56
+ ? (...args: unknown[]) => console.error("[WidgetSDK]", ...args)
57
+ : () => {};
58
+ const logWarn = debug
59
+ ? (...args: unknown[]) => console.warn("[WidgetSDK]", ...args)
60
+ : () => {};
46
61
  const webViewRef = useRef<WebView>(null);
47
62
  const [walletAvailable, setWalletAvailable] = useState(false);
48
63
  const [isLoading, setIsLoading] = useState(true);
@@ -71,7 +86,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
71
86
  return () => backHandler.remove();
72
87
  }, []);
73
88
 
74
- // Expose navigateBack method via ref
89
+ // Expose methods via ref
75
90
  useImperativeHandle(ref, () => ({
76
91
  navigateBack: () => {
77
92
  sendMessageToWidget({
@@ -79,8 +94,19 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
79
94
  timestamp: Date.now(),
80
95
  });
81
96
  },
97
+ reload: () => {
98
+ log("Reloading widget");
99
+ setIsLoading(true);
100
+ hasLoadedOnce.current = false;
101
+ webViewRef.current?.reload();
102
+ },
82
103
  }));
83
104
 
105
+ // Notify parent of loading state changes
106
+ useEffect(() => {
107
+ onLoadingChange?.(isLoading);
108
+ }, [isLoading, onLoadingChange]);
109
+
84
110
  const checkWalletAvailability = async () => {
85
111
  const available = await isWalletAvailable();
86
112
  setWalletAvailable(available);
@@ -93,7 +119,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
93
119
  try {
94
120
  const message: WidgetMessage = JSON.parse(event.nativeEvent.data);
95
121
 
96
- console.log("[WidgetSDK] Received message:", message.type);
122
+ log("Received message:", message.type);
97
123
 
98
124
  switch (message.type) {
99
125
  case "widget:ready":
@@ -104,10 +130,6 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
104
130
  handleOpenWallet();
105
131
  break;
106
132
 
107
- case "widget:card-created":
108
- handleCardCreated(message);
109
- break;
110
-
111
133
  case "widget:error":
112
134
  handleError(message);
113
135
  break;
@@ -121,7 +143,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
121
143
  break;
122
144
 
123
145
  case "widget:token-expired":
124
- console.error("[WidgetSDK] Access token expired");
146
+ logError("Access token expired");
125
147
  onError?.("TOKEN_EXPIRED", "Access token has expired");
126
148
  break;
127
149
 
@@ -130,16 +152,16 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
130
152
  break;
131
153
 
132
154
  default:
133
- console.warn("[WidgetSDK] Unknown message type:", message);
155
+ logWarn("Unknown message type:", message);
134
156
  }
135
157
  } catch (error) {
136
- console.error("[WidgetSDK] Failed to parse message:", error);
158
+ logError("Failed to parse message:", error);
137
159
  onError?.("PARSE_ERROR", "Failed to parse widget message");
138
160
  }
139
161
  };
140
162
 
141
163
  const handleReady = () => {
142
- console.log("[WidgetSDK] Widget ready");
164
+ log("Widget ready");
143
165
  onReady?.();
144
166
 
145
167
  // Send platform info to widget
@@ -153,7 +175,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
153
175
  };
154
176
 
155
177
  const handleOpenWallet = async () => {
156
- console.log("[WidgetSDK] Opening native wallet...");
178
+ log("Opening native wallet...");
157
179
 
158
180
  const success = await openNativeWallet();
159
181
 
@@ -164,26 +186,17 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
164
186
  });
165
187
  };
166
188
 
167
- const handleCardCreated = (message: WidgetMessage) => {
168
- if (message.type !== "widget:card-created") return;
169
-
170
- const { cardId, cardType, last4 } = message.payload;
171
- console.log("[WidgetSDK] Card created:", cardId);
172
-
173
- onCardCreated?.(cardId, cardType, last4);
174
- };
175
-
176
189
  const handleError = (message: WidgetMessage) => {
177
190
  if (message.type !== "widget:error") return;
178
191
 
179
192
  const { code, message: errorMessage } = message.payload;
180
- console.error("[WidgetSDK] Widget error:", code, errorMessage);
193
+ logError("Widget error:", code, errorMessage);
181
194
 
182
195
  onError?.(code, errorMessage);
183
196
  };
184
197
 
185
198
  const handleClose = () => {
186
- console.log("[WidgetSDK] Widget closed");
199
+ log("Widget closed");
187
200
  onClose?.();
188
201
  };
189
202
 
@@ -192,11 +205,10 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
192
205
 
193
206
  const { token, cryptoAmount, depositAddress, depositAddressTag } =
194
207
  message.payload;
195
- console.log("[WidgetSDK] Transaction requested:", {
196
- token,
208
+ log("Transaction requested:", {
209
+ token: token.symbol,
197
210
  cryptoAmount,
198
211
  depositAddress,
199
- depositAddressTag,
200
212
  });
201
213
 
202
214
  onTransactionRequested?.(
@@ -214,7 +226,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
214
226
  const handleCopyToClipboard = async (message: CopyToClipboardMessage) => {
215
227
  const { text, label } = message.payload;
216
228
  // Log only the label, never the actual text content (security)
217
- console.log("[WidgetSDK] Copy to clipboard requested:", label || "unlabeled");
229
+ log("Copy to clipboard requested:", label || "unlabeled");
218
230
 
219
231
  try {
220
232
  await Clipboard.setStringAsync(text);
@@ -223,7 +235,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
223
235
  payload: { success: true, label },
224
236
  });
225
237
  } catch (error) {
226
- console.error("[WidgetSDK] Clipboard copy failed:", error);
238
+ logError("Clipboard copy failed:", error);
227
239
  sendMessageToWidget({
228
240
  type: "native:clipboard-result",
229
241
  payload: {
@@ -259,7 +271,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
259
271
  });
260
272
 
261
273
  const url = `${baseUrl}?${params.toString()}`;
262
- console.log("[WidgetSDK] Widget URL:", url.substring(0, 100) + "...");
274
+ log("Widget URL:", url.substring(0, 100) + "...");
263
275
  return url;
264
276
  }, [accessToken, userWalletAddress, environment]);
265
277
 
@@ -278,7 +290,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
278
290
  }}
279
291
  onError={(syntheticEvent) => {
280
292
  const { nativeEvent } = syntheticEvent;
281
- console.error("[WidgetSDK] WebView error:", nativeEvent);
293
+ logError("WebView error:", nativeEvent);
282
294
  setIsLoading(false);
283
295
  onError?.("WEBVIEW_ERROR", "Failed to load widget");
284
296
  }}
@@ -293,9 +305,9 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
293
305
  url.includes("wallet.google.com") ||
294
306
  url.includes("wallet.apple.com")
295
307
  ) {
296
- console.log("[WidgetSDK] Opening external URL:", url);
308
+ log("Opening external URL:", url);
297
309
  Linking.openURL(url).catch((err) => {
298
- console.error("[WidgetSDK] Failed to open URL:", err);
310
+ logError("Failed to open URL:", err);
299
311
  });
300
312
  return false; // Don't load in WebView
301
313
  }
@@ -315,7 +327,7 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
315
327
  />
316
328
  {isLoading && (
317
329
  <View style={styles.loadingOverlay}>
318
- <ActivityIndicator size="large" color="#007AFF" />
330
+ <ActivityIndicator size="large" color={loadingIndicatorColor} />
319
331
  </View>
320
332
  )}
321
333
  </View>
package/src/index.ts CHANGED
@@ -3,59 +3,43 @@
3
3
  * Export all public components, types, and utilities
4
4
  */
5
5
 
6
- export { WidgetSDK } from './WidgetSDK';
7
- export type { WidgetSDKRef } from './WidgetSDK';
6
+ export { WidgetSDK } from "./WidgetSDK";
7
+ export type { WidgetSDKRef } from "./WidgetSDK";
8
8
 
9
9
  // Export all message types for clients to use
10
10
  export type {
11
- // Configuration
12
- WidgetSDKConfig,
13
- WidgetEnvironment,
14
- DepositToken,
15
-
16
- // Widget → Native message types
17
- WidgetMessageType,
18
11
  BaseWidgetMessage,
19
- WidgetMessage,
20
- WidgetReadyMessage,
21
- OpenWalletMessage,
22
- CardCreatedMessage,
23
- WidgetErrorMessage,
24
- WidgetCloseMessage,
25
- TransactionRequestedMessage,
26
- RequestCardDetailsSessionMessage,
27
-
12
+ CopyToClipboardMessage,
13
+ DepositToken,
14
+ NativeBackPressedMessage,
15
+ NativeBiometricFailedMessage,
16
+ NativeCardDetailsSessionMessage,
17
+ NativeMessage,
28
18
  // Native → Widget message types
29
19
  NativeMessageType,
30
- NativeMessage,
31
- NativeBackPressedMessage,
32
20
  NativeNavigateBackMessage,
33
21
  NativePlatformInfoMessage,
34
22
  NativeWalletOpenedMessage,
35
- NativeCardDetailsSessionMessage,
36
- NativeBiometricFailedMessage,
37
- } from './types';
23
+ OpenWalletMessage,
24
+ RequestCardDetailsSessionMessage,
25
+ // Error codes
26
+ SDKErrorCode,
27
+ TokenExpiredMessage,
28
+ TransactionRequestedMessage,
29
+ WidgetCloseMessage,
30
+ WidgetEnvironment,
31
+ WidgetErrorMessage,
32
+ WidgetMessage,
33
+ // Widget → Native message types
34
+ WidgetMessageType,
35
+ WidgetReadyMessage,
36
+ // Configuration
37
+ WidgetSDKConfig,
38
+ } from "./types";
38
39
 
39
40
  // Export constants
40
- export { WALLET_URLS, MessageTypes } from './types';
41
- export { WIDGET_URLS, getWidgetUrl } from './config';
41
+ export { getWidgetUrl, WIDGET_URLS } from "./config";
42
+ export { MessageTypes, WALLET_URLS } from "./types";
42
43
 
43
44
  // Export wallet utilities
44
- export { openNativeWallet, isWalletAvailable } from './walletUtils';
45
-
46
- // Export biometric utilities
47
- export {
48
- authenticateWithBiometrics,
49
- isBiometricAvailable,
50
- getBiometryTypeLabel,
51
- AuthenticationType,
52
- } from './biometricUtils';
53
- export type { BiometricResult, BiometricAvailability } from './biometricUtils';
54
-
55
- // Export crypto utilities (for advanced usage)
56
- export {
57
- generateSessionCredentials,
58
- generateRandomHexKey,
59
- hexToBase64,
60
- } from './cryptoUtils';
61
- export type { SessionCredentials } from './cryptoUtils';
45
+ export { isWalletAvailable, openNativeWallet } from "./walletUtils";
package/src/types.ts CHANGED
@@ -10,14 +10,13 @@
10
10
  export interface DepositToken {
11
11
  symbol: string;
12
12
  name: string;
13
- iconUrl: string | null;
14
13
  networkName: string;
14
+ chainId: number;
15
15
  }
16
16
 
17
17
  export type WidgetMessageType =
18
18
  | "widget:ready"
19
19
  | "widget:open-wallet"
20
- | "widget:card-created"
21
20
  | "widget:error"
22
21
  | "widget:close"
23
22
  | "widget:transaction-requested"
@@ -51,7 +50,7 @@ export interface NativeNavigateBackMessage {
51
50
  export interface NativePlatformInfoMessage {
52
51
  type: "native:platform-info";
53
52
  payload: {
54
- platform: string;
53
+ platform: "ios" | "android";
55
54
  walletAvailable: boolean;
56
55
  };
57
56
  }
@@ -113,15 +112,6 @@ export interface OpenWalletMessage extends BaseWidgetMessage {
113
112
  };
114
113
  }
115
114
 
116
- export interface CardCreatedMessage extends BaseWidgetMessage {
117
- type: "widget:card-created";
118
- payload: {
119
- cardId: string;
120
- cardType: "virtual" | "physical";
121
- last4: string;
122
- };
123
- }
124
-
125
115
  export interface WidgetErrorMessage extends BaseWidgetMessage {
126
116
  type: "widget:error";
127
117
  payload: {
@@ -169,7 +159,6 @@ export interface CopyToClipboardMessage extends BaseWidgetMessage {
169
159
  export type WidgetMessage =
170
160
  | WidgetReadyMessage
171
161
  | OpenWalletMessage
172
- | CardCreatedMessage
173
162
  | WidgetErrorMessage
174
163
  | WidgetCloseMessage
175
164
  | TransactionRequestedMessage
@@ -184,6 +173,14 @@ export type WidgetMessage =
184
173
  */
185
174
  export type WidgetEnvironment = "development" | "production";
186
175
 
176
+ /**
177
+ * Known SDK error codes
178
+ * - TOKEN_EXPIRED: The access token has expired
179
+ * - PARSE_ERROR: Failed to parse a message from the widget
180
+ * - WEBVIEW_ERROR: The WebView failed to load
181
+ */
182
+ export type SDKErrorCode = "TOKEN_EXPIRED" | "PARSE_ERROR" | "WEBVIEW_ERROR";
183
+
187
184
  /**
188
185
  * SDK Configuration
189
186
  */
@@ -197,16 +194,44 @@ export interface WidgetSDKConfig {
197
194
  * @default 'production'
198
195
  */
199
196
  environment?: WidgetEnvironment;
197
+ /**
198
+ * Called when the widget is ready and loaded
199
+ */
200
200
  onReady?: () => void;
201
- onCardCreated?: (cardId: string, cardType: string, last4: string) => void;
202
- onError?: (code: string, message: string) => void;
201
+ /**
202
+ * Called when an error occurs
203
+ * @param code - Error code (SDKErrorCode or custom widget error code)
204
+ * @param message - Human-readable error message
205
+ */
206
+ onError?: (code: SDKErrorCode | string, message: string) => void;
207
+ /**
208
+ * Called when the widget requests to close
209
+ */
203
210
  onClose?: () => void;
211
+ /**
212
+ * Called when a crypto transaction is requested
213
+ */
204
214
  onTransactionRequested?: (
205
215
  token: DepositToken,
206
216
  cryptoAmount: string,
207
217
  depositAddress: string,
208
218
  depositAddressTag: string | null
209
219
  ) => void;
220
+ /**
221
+ * Called when the loading state changes
222
+ * @param isLoading - Whether the widget is currently loading
223
+ */
224
+ onLoadingChange?: (isLoading: boolean) => void;
225
+ /**
226
+ * Enable debug logging to console
227
+ * @default false
228
+ */
229
+ debug?: boolean;
230
+ /**
231
+ * Custom color for the loading indicator
232
+ * @default "#007AFF"
233
+ */
234
+ loadingIndicatorColor?: string;
210
235
  }
211
236
 
212
237
  /**
@@ -234,7 +259,6 @@ export const MessageTypes = {
234
259
  // Widget → Native
235
260
  READY: "widget:ready",
236
261
  OPEN_WALLET: "widget:open-wallet",
237
- CARD_CREATED: "widget:card-created",
238
262
  ERROR: "widget:error",
239
263
  CLOSE: "widget:close",
240
264
  TRANSACTION_REQUESTED: "widget:transaction-requested",
@@ -1,66 +0,0 @@
1
- /**
2
- * Biometric Authentication Utilities
3
- *
4
- * Provides cross-platform biometric authentication for card details access.
5
- * Uses expo-local-authentication which works in Expo Go without native modules.
6
- *
7
- * @requires expo-local-authentication - included in Expo SDK
8
- */
9
- import * as LocalAuthentication from 'expo-local-authentication';
10
- /**
11
- * Result of a biometric authentication attempt
12
- */
13
- export interface BiometricResult {
14
- /** Whether authentication was successful */
15
- success: boolean;
16
- /** Error details if authentication failed */
17
- error?: {
18
- reason: 'cancelled' | 'failed' | 'not_available' | 'not_enrolled';
19
- message?: string;
20
- };
21
- }
22
- /**
23
- * Information about biometric capabilities on the device
24
- */
25
- export interface BiometricAvailability {
26
- /** Whether any biometric authentication is available */
27
- available: boolean;
28
- /** The types of biometry available */
29
- biometryTypes: LocalAuthentication.AuthenticationType[];
30
- }
31
- /**
32
- * Checks if biometric authentication is available on the device
33
- *
34
- * @returns Object containing availability status and biometry types
35
- */
36
- export declare function isBiometricAvailable(): Promise<BiometricAvailability>;
37
- /**
38
- * Prompts the user for biometric authentication
39
- *
40
- * This function should be called before generating session credentials
41
- * for viewing card details. It ensures proper user verification before
42
- * accessing sensitive payment card information.
43
- *
44
- * @param promptMessage - Message to display in the biometric prompt
45
- * @returns Result indicating success or failure with reason
46
- *
47
- * @example
48
- * ```typescript
49
- * const result = await authenticateWithBiometrics('Authenticate to view card details');
50
- * if (result.success) {
51
- * // Proceed with generating session credentials
52
- * } else {
53
- * // Handle failure based on result.error.reason
54
- * }
55
- * ```
56
- */
57
- export declare function authenticateWithBiometrics(promptMessage?: string): Promise<BiometricResult>;
58
- /**
59
- * Gets a user-friendly description of the biometric type
60
- *
61
- * @param biometryType - The biometry type from the device
62
- * @returns Human-readable string for the biometry type
63
- */
64
- export declare function getBiometryTypeLabel(biometryType: LocalAuthentication.AuthenticationType): string;
65
- export { AuthenticationType } from 'expo-local-authentication';
66
- //# sourceMappingURL=biometricUtils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"biometricUtils.d.ts","sourceRoot":"","sources":["../src/biometricUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,mBAAmB,MAAM,2BAA2B,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,KAAK,CAAC,EAAE;QACN,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,eAAe,GAAG,cAAc,CAAC;QAClE,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,wDAAwD;IACxD,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,aAAa,EAAE,mBAAmB,CAAC,kBAAkB,EAAE,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAiB3E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,0BAA0B,CAC9C,aAAa,GAAE,MAA4C,GAC1D,OAAO,CAAC,eAAe,CAAC,CA8E1B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,mBAAmB,CAAC,kBAAkB,GACnD,MAAM,CAWR;AAGD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -1,183 +0,0 @@
1
- "use strict";
2
- /**
3
- * Biometric Authentication Utilities
4
- *
5
- * Provides cross-platform biometric authentication for card details access.
6
- * Uses expo-local-authentication which works in Expo Go without native modules.
7
- *
8
- * @requires expo-local-authentication - included in Expo SDK
9
- */
10
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- var desc = Object.getOwnPropertyDescriptor(m, k);
13
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
- desc = { enumerable: true, get: function() { return m[k]; } };
15
- }
16
- Object.defineProperty(o, k2, desc);
17
- }) : (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- o[k2] = m[k];
20
- }));
21
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
- Object.defineProperty(o, "default", { enumerable: true, value: v });
23
- }) : function(o, v) {
24
- o["default"] = v;
25
- });
26
- var __importStar = (this && this.__importStar) || (function () {
27
- var ownKeys = function(o) {
28
- ownKeys = Object.getOwnPropertyNames || function (o) {
29
- var ar = [];
30
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
- return ar;
32
- };
33
- return ownKeys(o);
34
- };
35
- return function (mod) {
36
- if (mod && mod.__esModule) return mod;
37
- var result = {};
38
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
- __setModuleDefault(result, mod);
40
- return result;
41
- };
42
- })();
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.AuthenticationType = void 0;
45
- exports.isBiometricAvailable = isBiometricAvailable;
46
- exports.authenticateWithBiometrics = authenticateWithBiometrics;
47
- exports.getBiometryTypeLabel = getBiometryTypeLabel;
48
- const LocalAuthentication = __importStar(require("expo-local-authentication"));
49
- /**
50
- * Checks if biometric authentication is available on the device
51
- *
52
- * @returns Object containing availability status and biometry types
53
- */
54
- async function isBiometricAvailable() {
55
- try {
56
- const hasHardware = await LocalAuthentication.hasHardwareAsync();
57
- const isEnrolled = await LocalAuthentication.isEnrolledAsync();
58
- const supportedTypes = await LocalAuthentication.supportedAuthenticationTypesAsync();
59
- return {
60
- available: hasHardware && isEnrolled,
61
- biometryTypes: supportedTypes,
62
- };
63
- }
64
- catch (error) {
65
- console.error('[BiometricUtils] Error checking biometric availability:', error);
66
- return {
67
- available: false,
68
- biometryTypes: [],
69
- };
70
- }
71
- }
72
- /**
73
- * Prompts the user for biometric authentication
74
- *
75
- * This function should be called before generating session credentials
76
- * for viewing card details. It ensures proper user verification before
77
- * accessing sensitive payment card information.
78
- *
79
- * @param promptMessage - Message to display in the biometric prompt
80
- * @returns Result indicating success or failure with reason
81
- *
82
- * @example
83
- * ```typescript
84
- * const result = await authenticateWithBiometrics('Authenticate to view card details');
85
- * if (result.success) {
86
- * // Proceed with generating session credentials
87
- * } else {
88
- * // Handle failure based on result.error.reason
89
- * }
90
- * ```
91
- */
92
- async function authenticateWithBiometrics(promptMessage = 'Authenticate to view card details') {
93
- try {
94
- // First check if biometrics are available
95
- const hasHardware = await LocalAuthentication.hasHardwareAsync();
96
- if (!hasHardware) {
97
- console.log('[BiometricUtils] Biometrics not available on device');
98
- return {
99
- success: false,
100
- error: {
101
- reason: 'not_available',
102
- message: 'Biometric authentication is not available on this device',
103
- },
104
- };
105
- }
106
- // Check if biometrics are enrolled
107
- const isEnrolled = await LocalAuthentication.isEnrolledAsync();
108
- if (!isEnrolled) {
109
- console.log('[BiometricUtils] No biometrics enrolled');
110
- return {
111
- success: false,
112
- error: {
113
- reason: 'not_enrolled',
114
- message: 'No biometric authentication is set up on this device',
115
- },
116
- };
117
- }
118
- console.log('[BiometricUtils] Attempting biometric authentication...');
119
- // Perform the biometric authentication
120
- const result = await LocalAuthentication.authenticateAsync({
121
- promptMessage,
122
- cancelLabel: 'Cancel',
123
- disableDeviceFallback: false, // Allow PIN/password fallback
124
- fallbackLabel: 'Use Passcode',
125
- });
126
- if (result.success) {
127
- console.log('[BiometricUtils] Biometric authentication successful');
128
- return { success: true };
129
- }
130
- // Handle various failure reasons
131
- console.log('[BiometricUtils] Biometric authentication failed:', result.error);
132
- let reason = 'failed';
133
- if (result.error === 'user_cancel' || result.error === 'system_cancel') {
134
- reason = 'cancelled';
135
- }
136
- else if (result.error === 'not_enrolled') {
137
- reason = 'not_enrolled';
138
- }
139
- else if (result.error === 'not_available') {
140
- reason = 'not_available';
141
- }
142
- return {
143
- success: false,
144
- error: {
145
- reason,
146
- message: result.warning || 'Authentication failed',
147
- },
148
- };
149
- }
150
- catch (error) {
151
- console.error('[BiometricUtils] Biometric authentication error:', error);
152
- const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
153
- return {
154
- success: false,
155
- error: {
156
- reason: 'failed',
157
- message: errorMessage,
158
- },
159
- };
160
- }
161
- }
162
- /**
163
- * Gets a user-friendly description of the biometric type
164
- *
165
- * @param biometryType - The biometry type from the device
166
- * @returns Human-readable string for the biometry type
167
- */
168
- function getBiometryTypeLabel(biometryType) {
169
- switch (biometryType) {
170
- case LocalAuthentication.AuthenticationType.FACIAL_RECOGNITION:
171
- return 'Face ID';
172
- case LocalAuthentication.AuthenticationType.FINGERPRINT:
173
- return 'Touch ID';
174
- case LocalAuthentication.AuthenticationType.IRIS:
175
- return 'Iris';
176
- default:
177
- return 'Biometric Authentication';
178
- }
179
- }
180
- // Re-export AuthenticationType for convenience
181
- var expo_local_authentication_1 = require("expo-local-authentication");
182
- Object.defineProperty(exports, "AuthenticationType", { enumerable: true, get: function () { return expo_local_authentication_1.AuthenticationType; } });
183
- //# sourceMappingURL=biometricUtils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"biometricUtils.js","sourceRoot":"","sources":["../src/biometricUtils.ts"],"names":[],"mappings":"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"}