@oobit/react-native-sdk 1.0.4 → 1.0.5
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/dist/WidgetSDK.d.ts.map +1 -1
- package/dist/WidgetSDK.js +60 -3
- package/dist/WidgetSDK.js.map +1 -1
- package/dist/biometricUtils.d.ts +66 -0
- package/dist/biometricUtils.d.ts.map +1 -0
- package/dist/biometricUtils.js +179 -0
- package/dist/biometricUtils.js.map +1 -0
- package/dist/cryptoUtils.d.ts +67 -0
- package/dist/cryptoUtils.d.ts.map +1 -0
- package/dist/cryptoUtils.js +143 -0
- package/dist/cryptoUtils.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +41 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +18 -15
- package/dist/types.js.map +1 -1
- package/package.json +7 -7
- package/src/WidgetSDK.tsx +108 -7
- package/src/biometricUtils.ts +189 -0
- package/src/cryptoUtils.ts +160 -0
- package/src/index.ts +20 -0
- package/src/types.ts +80 -44
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Export all public components, types, and utilities
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.isWalletAvailable = exports.openNativeWallet = exports.getWidgetUrl = exports.WIDGET_URLS = exports.MessageTypes = exports.WALLET_URLS = exports.WidgetSDK = void 0;
|
|
7
|
+
exports.hexToBase64 = exports.generateRandomHexKey = exports.generateSessionCredentials = exports.BiometryTypes = exports.getBiometryTypeLabel = exports.isBiometricAvailable = exports.authenticateWithBiometrics = exports.isWalletAvailable = exports.openNativeWallet = exports.getWidgetUrl = exports.WIDGET_URLS = exports.MessageTypes = exports.WALLET_URLS = exports.WidgetSDK = void 0;
|
|
8
8
|
var WidgetSDK_1 = require("./WidgetSDK");
|
|
9
9
|
Object.defineProperty(exports, "WidgetSDK", { enumerable: true, get: function () { return WidgetSDK_1.WidgetSDK; } });
|
|
10
10
|
// Export constants
|
|
@@ -18,4 +18,15 @@ Object.defineProperty(exports, "getWidgetUrl", { enumerable: true, get: function
|
|
|
18
18
|
var walletUtils_1 = require("./walletUtils");
|
|
19
19
|
Object.defineProperty(exports, "openNativeWallet", { enumerable: true, get: function () { return walletUtils_1.openNativeWallet; } });
|
|
20
20
|
Object.defineProperty(exports, "isWalletAvailable", { enumerable: true, get: function () { return walletUtils_1.isWalletAvailable; } });
|
|
21
|
+
// Export biometric utilities
|
|
22
|
+
var biometricUtils_1 = require("./biometricUtils");
|
|
23
|
+
Object.defineProperty(exports, "authenticateWithBiometrics", { enumerable: true, get: function () { return biometricUtils_1.authenticateWithBiometrics; } });
|
|
24
|
+
Object.defineProperty(exports, "isBiometricAvailable", { enumerable: true, get: function () { return biometricUtils_1.isBiometricAvailable; } });
|
|
25
|
+
Object.defineProperty(exports, "getBiometryTypeLabel", { enumerable: true, get: function () { return biometricUtils_1.getBiometryTypeLabel; } });
|
|
26
|
+
Object.defineProperty(exports, "BiometryTypes", { enumerable: true, get: function () { return biometricUtils_1.BiometryTypes; } });
|
|
27
|
+
// Export crypto utilities (for advanced usage)
|
|
28
|
+
var cryptoUtils_1 = require("./cryptoUtils");
|
|
29
|
+
Object.defineProperty(exports, "generateSessionCredentials", { enumerable: true, get: function () { return cryptoUtils_1.generateSessionCredentials; } });
|
|
30
|
+
Object.defineProperty(exports, "generateRandomHexKey", { enumerable: true, get: function () { return cryptoUtils_1.generateRandomHexKey; } });
|
|
31
|
+
Object.defineProperty(exports, "hexToBase64", { enumerable: true, get: function () { return cryptoUtils_1.hexToBase64; } });
|
|
21
32
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,yCAAwC;AAA/B,sGAAA,SAAS,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,yCAAwC;AAA/B,sGAAA,SAAS,OAAA;AAiClB,mBAAmB;AACnB,iCAAoD;AAA3C,oGAAA,WAAW,OAAA;AAAE,qGAAA,YAAY,OAAA;AAClC,mCAAqD;AAA5C,qGAAA,WAAW,OAAA;AAAE,sGAAA,YAAY,OAAA;AAElC,0BAA0B;AAC1B,6CAAoE;AAA3D,+GAAA,gBAAgB,OAAA;AAAE,gHAAA,iBAAiB,OAAA;AAE5C,6BAA6B;AAC7B,mDAK0B;AAJxB,4HAAA,0BAA0B,OAAA;AAC1B,sHAAA,oBAAoB,OAAA;AACpB,sHAAA,oBAAoB,OAAA;AACpB,+GAAA,aAAa,OAAA;AAIf,+CAA+C;AAC/C,6CAIuB;AAHrB,yHAAA,0BAA0B,OAAA;AAC1B,mHAAA,oBAAoB,OAAA;AACpB,0GAAA,WAAW,OAAA"}
|
package/dist/types.d.ts
CHANGED
|
@@ -12,67 +12,81 @@ export interface DepositToken {
|
|
|
12
12
|
iconUrl: string | null;
|
|
13
13
|
networkName: string;
|
|
14
14
|
}
|
|
15
|
-
export type WidgetMessageType =
|
|
15
|
+
export type WidgetMessageType = "widget:ready" | "widget:open-wallet" | "widget:card-created" | "widget:error" | "widget:close" | "widget:transaction-requested" | "widget:token-expired" | "widget:request-card-details-session";
|
|
16
16
|
/**
|
|
17
17
|
* Native Message Types
|
|
18
18
|
* Messages sent from the native app to the web widget
|
|
19
19
|
*/
|
|
20
|
-
export type NativeMessageType =
|
|
20
|
+
export type NativeMessageType = "native:platform-info" | "native:wallet-opened" | "native:back-pressed" | "native:navigate-back" | "native:card-details-session" | "native:biometric-failed";
|
|
21
21
|
export interface NativeBackPressedMessage {
|
|
22
|
-
type:
|
|
22
|
+
type: "native:back-pressed";
|
|
23
23
|
timestamp: number;
|
|
24
24
|
}
|
|
25
25
|
export interface NativeNavigateBackMessage {
|
|
26
|
-
type:
|
|
26
|
+
type: "native:navigate-back";
|
|
27
27
|
timestamp: number;
|
|
28
28
|
}
|
|
29
29
|
export interface NativePlatformInfoMessage {
|
|
30
|
-
type:
|
|
30
|
+
type: "native:platform-info";
|
|
31
31
|
payload: {
|
|
32
32
|
platform: string;
|
|
33
33
|
walletAvailable: boolean;
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
export interface NativeWalletOpenedMessage {
|
|
37
|
-
type:
|
|
37
|
+
type: "native:wallet-opened";
|
|
38
38
|
payload: {
|
|
39
39
|
success: boolean;
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
-
export
|
|
42
|
+
export interface NativeCardDetailsSessionMessage {
|
|
43
|
+
type: "native:card-details-session";
|
|
44
|
+
payload: {
|
|
45
|
+
sessionId: string;
|
|
46
|
+
secretKey: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export interface NativeBiometricFailedMessage {
|
|
50
|
+
type: "native:biometric-failed";
|
|
51
|
+
payload: {
|
|
52
|
+
reason: "cancelled" | "failed" | "not_available" | "not_enrolled";
|
|
53
|
+
message?: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export type NativeMessage = NativeBackPressedMessage | NativeNavigateBackMessage | NativePlatformInfoMessage | NativeWalletOpenedMessage | NativeCardDetailsSessionMessage | NativeBiometricFailedMessage;
|
|
43
57
|
export interface BaseWidgetMessage {
|
|
44
58
|
type: WidgetMessageType;
|
|
45
59
|
timestamp: number;
|
|
46
60
|
}
|
|
47
61
|
export interface WidgetReadyMessage extends BaseWidgetMessage {
|
|
48
|
-
type:
|
|
62
|
+
type: "widget:ready";
|
|
49
63
|
}
|
|
50
64
|
export interface OpenWalletMessage extends BaseWidgetMessage {
|
|
51
|
-
type:
|
|
65
|
+
type: "widget:open-wallet";
|
|
52
66
|
payload: {
|
|
53
|
-
platform:
|
|
67
|
+
platform: "ios" | "android";
|
|
54
68
|
};
|
|
55
69
|
}
|
|
56
70
|
export interface CardCreatedMessage extends BaseWidgetMessage {
|
|
57
|
-
type:
|
|
71
|
+
type: "widget:card-created";
|
|
58
72
|
payload: {
|
|
59
73
|
cardId: string;
|
|
60
|
-
cardType:
|
|
74
|
+
cardType: "virtual" | "physical";
|
|
61
75
|
last4: string;
|
|
62
76
|
};
|
|
63
77
|
}
|
|
64
78
|
export interface WidgetErrorMessage extends BaseWidgetMessage {
|
|
65
|
-
type:
|
|
79
|
+
type: "widget:error";
|
|
66
80
|
payload: {
|
|
67
81
|
code: string;
|
|
68
82
|
message: string;
|
|
69
83
|
};
|
|
70
84
|
}
|
|
71
85
|
export interface WidgetCloseMessage extends BaseWidgetMessage {
|
|
72
|
-
type:
|
|
86
|
+
type: "widget:close";
|
|
73
87
|
}
|
|
74
88
|
export interface TransactionRequestedMessage extends BaseWidgetMessage {
|
|
75
|
-
type:
|
|
89
|
+
type: "widget:transaction-requested";
|
|
76
90
|
payload: {
|
|
77
91
|
token: DepositToken;
|
|
78
92
|
cryptoAmount: string;
|
|
@@ -81,18 +95,24 @@ export interface TransactionRequestedMessage extends BaseWidgetMessage {
|
|
|
81
95
|
};
|
|
82
96
|
}
|
|
83
97
|
export interface TokenExpiredMessage extends BaseWidgetMessage {
|
|
84
|
-
type:
|
|
98
|
+
type: "widget:token-expired";
|
|
85
99
|
payload?: {
|
|
86
100
|
reason?: string;
|
|
87
101
|
};
|
|
88
102
|
}
|
|
89
|
-
export
|
|
103
|
+
export interface RequestCardDetailsSessionMessage extends BaseWidgetMessage {
|
|
104
|
+
type: "widget:request-card-details-session";
|
|
105
|
+
payload: {
|
|
106
|
+
publicKey: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export type WidgetMessage = WidgetReadyMessage | OpenWalletMessage | CardCreatedMessage | WidgetErrorMessage | WidgetCloseMessage | TransactionRequestedMessage | TokenExpiredMessage | RequestCardDetailsSessionMessage;
|
|
90
110
|
/**
|
|
91
111
|
* Widget environment configuration
|
|
92
112
|
* - 'development': Uses development/staging widget URL
|
|
93
113
|
* - 'production': Uses production widget URL
|
|
94
114
|
*/
|
|
95
|
-
export type WidgetEnvironment =
|
|
115
|
+
export type WidgetEnvironment = "development" | "production";
|
|
96
116
|
/**
|
|
97
117
|
* SDK Configuration
|
|
98
118
|
*/
|
|
@@ -140,9 +160,12 @@ export declare const MessageTypes: {
|
|
|
140
160
|
readonly CLOSE: "widget:close";
|
|
141
161
|
readonly TRANSACTION_REQUESTED: "widget:transaction-requested";
|
|
142
162
|
readonly TOKEN_EXPIRED: "widget:token-expired";
|
|
163
|
+
readonly REQUEST_CARD_DETAILS_SESSION: "widget:request-card-details-session";
|
|
143
164
|
readonly PLATFORM_INFO: "native:platform-info";
|
|
144
165
|
readonly WALLET_OPENED: "native:wallet-opened";
|
|
145
166
|
readonly BACK_PRESSED: "native:back-pressed";
|
|
146
167
|
readonly NAVIGATE_BACK: "native:navigate-back";
|
|
168
|
+
readonly CARD_DETAILS_SESSION: "native:card-details-session";
|
|
169
|
+
readonly BIOMETRIC_FAILED: "native:biometric-failed";
|
|
147
170
|
};
|
|
148
171
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GACzB,cAAc,GACd,oBAAoB,GACpB,qBAAqB,GACrB,cAAc,GACd,cAAc,GACd,8BAA8B,GAC9B,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -10,12 +10,12 @@ exports.MessageTypes = exports.WALLET_URLS = void 0;
|
|
|
10
10
|
*/
|
|
11
11
|
exports.WALLET_URLS = {
|
|
12
12
|
ios: {
|
|
13
|
-
passkit:
|
|
14
|
-
fallback:
|
|
13
|
+
passkit: "shoebox://", // Apple Wallet deep link
|
|
14
|
+
fallback: "https://wallet.apple.com",
|
|
15
15
|
},
|
|
16
16
|
android: {
|
|
17
|
-
googlePay:
|
|
18
|
-
fallback:
|
|
17
|
+
googlePay: "https://pay.google.com/gp/w/home/wallet",
|
|
18
|
+
fallback: "https://wallet.google.com",
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
@@ -27,17 +27,20 @@ exports.WALLET_URLS = {
|
|
|
27
27
|
*/
|
|
28
28
|
exports.MessageTypes = {
|
|
29
29
|
// Widget → Native
|
|
30
|
-
READY:
|
|
31
|
-
OPEN_WALLET:
|
|
32
|
-
CARD_CREATED:
|
|
33
|
-
ERROR:
|
|
34
|
-
CLOSE:
|
|
35
|
-
TRANSACTION_REQUESTED:
|
|
36
|
-
TOKEN_EXPIRED:
|
|
30
|
+
READY: "widget:ready",
|
|
31
|
+
OPEN_WALLET: "widget:open-wallet",
|
|
32
|
+
CARD_CREATED: "widget:card-created",
|
|
33
|
+
ERROR: "widget:error",
|
|
34
|
+
CLOSE: "widget:close",
|
|
35
|
+
TRANSACTION_REQUESTED: "widget:transaction-requested",
|
|
36
|
+
TOKEN_EXPIRED: "widget:token-expired",
|
|
37
|
+
REQUEST_CARD_DETAILS_SESSION: "widget:request-card-details-session",
|
|
37
38
|
// Native → Widget
|
|
38
|
-
PLATFORM_INFO:
|
|
39
|
-
WALLET_OPENED:
|
|
40
|
-
BACK_PRESSED:
|
|
41
|
-
NAVIGATE_BACK:
|
|
39
|
+
PLATFORM_INFO: "native:platform-info",
|
|
40
|
+
WALLET_OPENED: "native:wallet-opened",
|
|
41
|
+
BACK_PRESSED: "native:back-pressed",
|
|
42
|
+
NAVIGATE_BACK: "native:navigate-back",
|
|
43
|
+
CARD_DETAILS_SESSION: "native:card-details-session",
|
|
44
|
+
BIOMETRIC_FAILED: "native:biometric-failed",
|
|
42
45
|
};
|
|
43
46
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA2LH;;GAEG;AACU,QAAA,WAAW,GAAG;IACzB,GAAG,EAAE;QACH,OAAO,EAAE,YAAY,EAAE,yBAAyB;QAChD,QAAQ,EAAE,0BAA0B;KACrC;IACD,OAAO,EAAE;QACP,SAAS,EAAE,yCAAyC;QACpD,QAAQ,EAAE,2BAA2B;KACtC;CACO,CAAC;AAEX;;;;;;GAMG;AACU,QAAA,YAAY,GAAG;IAC1B,kBAAkB;IAClB,KAAK,EAAE,cAAc;IACrB,WAAW,EAAE,oBAAoB;IACjC,YAAY,EAAE,qBAAqB;IACnC,KAAK,EAAE,cAAc;IACrB,KAAK,EAAE,cAAc;IACrB,qBAAqB,EAAE,8BAA8B;IACrD,aAAa,EAAE,sBAAsB;IACrC,4BAA4B,EAAE,qCAAqC;IACnE,kBAAkB;IAClB,aAAa,EAAE,sBAAsB;IACrC,aAAa,EAAE,sBAAsB;IACrC,YAAY,EAAE,qBAAqB;IACnC,aAAa,EAAE,sBAAsB;IACrC,oBAAoB,EAAE,6BAA6B;IACnD,gBAAgB,EAAE,yBAAyB;CACnC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oobit/react-native-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "React Native SDK for integrating Oobit crypto payments into wallet apps",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -39,15 +39,13 @@
|
|
|
39
39
|
"url": "git+https://github.com/oobit-tech/react-native-SDK.git"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
+
"expo-intent-launcher": ">=6.0.0",
|
|
42
43
|
"expo-linking": ">=6.0.0",
|
|
43
44
|
"react": ">=18.0.0",
|
|
44
45
|
"react-native": ">=0.70.0",
|
|
45
|
-
"react-native-webview": ">=13.0.0"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"expo-intent-launcher": {
|
|
49
|
-
"optional": true
|
|
50
|
-
}
|
|
46
|
+
"react-native-webview": ">=13.0.0",
|
|
47
|
+
"react-native-biometrics": ">=3.0.0",
|
|
48
|
+
"react-native-quick-crypto": ">=0.7.0"
|
|
51
49
|
},
|
|
52
50
|
"devDependencies": {
|
|
53
51
|
"@types/react": "~19.1.0",
|
|
@@ -58,6 +56,8 @@
|
|
|
58
56
|
"expo-linking": "~8.0.8",
|
|
59
57
|
"react": "19.1.0",
|
|
60
58
|
"react-native": "0.81.5",
|
|
59
|
+
"react-native-biometrics": "^3.0.1",
|
|
60
|
+
"react-native-quick-crypto": "^0.7.9",
|
|
61
61
|
"react-native-webview": "13.15.0",
|
|
62
62
|
"typescript": "~5.9.2"
|
|
63
63
|
},
|
package/src/WidgetSDK.tsx
CHANGED
|
@@ -11,10 +11,24 @@ import React, {
|
|
|
11
11
|
useRef,
|
|
12
12
|
useState,
|
|
13
13
|
} from "react";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
ActivityIndicator,
|
|
16
|
+
BackHandler,
|
|
17
|
+
Linking,
|
|
18
|
+
Platform,
|
|
19
|
+
StyleSheet,
|
|
20
|
+
View,
|
|
21
|
+
} from "react-native";
|
|
15
22
|
import { WebView, WebViewMessageEvent } from "react-native-webview";
|
|
23
|
+
import { authenticateWithBiometrics } from "./biometricUtils";
|
|
16
24
|
import { getWidgetUrl } from "./config";
|
|
17
|
-
import {
|
|
25
|
+
import { generateSessionCredentials } from "./cryptoUtils";
|
|
26
|
+
import {
|
|
27
|
+
NativeBiometricFailedMessage,
|
|
28
|
+
NativeCardDetailsSessionMessage,
|
|
29
|
+
WidgetMessage,
|
|
30
|
+
WidgetSDKConfig,
|
|
31
|
+
} from "./types";
|
|
18
32
|
import { isWalletAvailable, openNativeWallet } from "./walletUtils";
|
|
19
33
|
|
|
20
34
|
export interface WidgetSDKRef {
|
|
@@ -117,6 +131,10 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
|
|
|
117
131
|
onError?.("TOKEN_EXPIRED", "Access token has expired");
|
|
118
132
|
break;
|
|
119
133
|
|
|
134
|
+
case "widget:request-card-details-session":
|
|
135
|
+
handleCardDetailsRequest(message);
|
|
136
|
+
break;
|
|
137
|
+
|
|
120
138
|
default:
|
|
121
139
|
console.warn("[WidgetSDK] Unknown message type:", message);
|
|
122
140
|
}
|
|
@@ -178,7 +196,8 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
|
|
|
178
196
|
const handleTransactionRequested = (message: WidgetMessage) => {
|
|
179
197
|
if (message.type !== "widget:transaction-requested") return;
|
|
180
198
|
|
|
181
|
-
const { token, cryptoAmount, depositAddress, depositAddressTag } =
|
|
199
|
+
const { token, cryptoAmount, depositAddress, depositAddressTag } =
|
|
200
|
+
message.payload;
|
|
182
201
|
console.log("[WidgetSDK] Transaction requested:", {
|
|
183
202
|
token,
|
|
184
203
|
cryptoAmount,
|
|
@@ -186,7 +205,89 @@ export const WidgetSDK = forwardRef<WidgetSDKRef, WidgetSDKConfig>(
|
|
|
186
205
|
depositAddressTag,
|
|
187
206
|
});
|
|
188
207
|
|
|
189
|
-
onTransactionRequested?.(
|
|
208
|
+
onTransactionRequested?.(
|
|
209
|
+
token,
|
|
210
|
+
cryptoAmount,
|
|
211
|
+
depositAddress,
|
|
212
|
+
depositAddressTag
|
|
213
|
+
);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Handle card details session request from widget
|
|
218
|
+
* 1. Show biometric prompt for user authentication
|
|
219
|
+
* 2. Generate cryptographically linked sessionId + secretKey pair
|
|
220
|
+
* 3. Send credentials back to widget for API call and decryption
|
|
221
|
+
*/
|
|
222
|
+
const handleCardDetailsRequest = async (message: WidgetMessage) => {
|
|
223
|
+
if (message.type !== "widget:request-card-details-session") return;
|
|
224
|
+
|
|
225
|
+
const { publicKey } = message.payload;
|
|
226
|
+
console.log(
|
|
227
|
+
"[WidgetSDK] Card details requested, initiating biometric auth..."
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
// Step 1: Authenticate with biometrics
|
|
231
|
+
const biometricResult = await authenticateWithBiometrics(
|
|
232
|
+
"Authenticate to view card details"
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
if (!biometricResult.success) {
|
|
236
|
+
console.log(
|
|
237
|
+
"[WidgetSDK] Biometric auth failed:",
|
|
238
|
+
biometricResult.error
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const failedMessage: NativeBiometricFailedMessage = {
|
|
242
|
+
type: "native:biometric-failed",
|
|
243
|
+
payload: {
|
|
244
|
+
reason: biometricResult.error?.reason || "failed",
|
|
245
|
+
message: biometricResult.error?.message,
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
sendMessageToWidget(failedMessage);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Step 2: Generate session credentials
|
|
254
|
+
try {
|
|
255
|
+
console.log(
|
|
256
|
+
"[WidgetSDK] Biometric auth successful, generating session credentials..."
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
const { secretKeyHex, sessionId } = await generateSessionCredentials(
|
|
260
|
+
publicKey
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
console.log("[WidgetSDK] Session credentials generated successfully");
|
|
264
|
+
|
|
265
|
+
// Step 3: Send credentials to widget
|
|
266
|
+
const sessionMessage: NativeCardDetailsSessionMessage = {
|
|
267
|
+
type: "native:card-details-session",
|
|
268
|
+
payload: {
|
|
269
|
+
sessionId,
|
|
270
|
+
secretKey: secretKeyHex,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
sendMessageToWidget(sessionMessage);
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error(
|
|
277
|
+
"[WidgetSDK] Failed to generate session credentials:",
|
|
278
|
+
error
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
const failedMessage: NativeBiometricFailedMessage = {
|
|
282
|
+
type: "native:biometric-failed",
|
|
283
|
+
payload: {
|
|
284
|
+
reason: "failed",
|
|
285
|
+
message: "Failed to generate secure session",
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
sendMessageToWidget(failedMessage);
|
|
290
|
+
}
|
|
190
291
|
};
|
|
191
292
|
|
|
192
293
|
/**
|
|
@@ -286,8 +387,8 @@ const styles = StyleSheet.create({
|
|
|
286
387
|
},
|
|
287
388
|
loadingOverlay: {
|
|
288
389
|
...StyleSheet.absoluteFillObject,
|
|
289
|
-
backgroundColor:
|
|
290
|
-
justifyContent:
|
|
291
|
-
alignItems:
|
|
390
|
+
backgroundColor: "rgba(255, 255, 255, 0.9)",
|
|
391
|
+
justifyContent: "center",
|
|
392
|
+
alignItems: "center",
|
|
292
393
|
},
|
|
293
394
|
});
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Biometric Authentication Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides cross-platform biometric authentication for card details access.
|
|
5
|
+
* Supports Face ID, Touch ID, and Android biometrics.
|
|
6
|
+
*
|
|
7
|
+
* @requires react-native-biometrics - npm install react-native-biometrics
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import ReactNativeBiometrics, { BiometryTypes, type BiometryType } from 'react-native-biometrics';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Result of a biometric authentication attempt
|
|
14
|
+
*/
|
|
15
|
+
export interface BiometricResult {
|
|
16
|
+
/** Whether authentication was successful */
|
|
17
|
+
success: boolean;
|
|
18
|
+
/** Error details if authentication failed */
|
|
19
|
+
error?: {
|
|
20
|
+
reason: 'cancelled' | 'failed' | 'not_available' | 'not_enrolled';
|
|
21
|
+
message?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Information about biometric capabilities on the device
|
|
27
|
+
*/
|
|
28
|
+
export interface BiometricAvailability {
|
|
29
|
+
/** Whether any biometric authentication is available */
|
|
30
|
+
available: boolean;
|
|
31
|
+
/** The type of biometry available (FaceID, TouchID, Biometrics, or null) */
|
|
32
|
+
biometryType: BiometryType | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Singleton instance of ReactNativeBiometrics
|
|
36
|
+
const rnBiometrics = new ReactNativeBiometrics({
|
|
37
|
+
allowDeviceCredentials: false, // Only allow biometric, not PIN/password fallback
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Checks if biometric authentication is available on the device
|
|
42
|
+
*
|
|
43
|
+
* @returns Object containing availability status and biometry type
|
|
44
|
+
*/
|
|
45
|
+
export async function isBiometricAvailable(): Promise<BiometricAvailability> {
|
|
46
|
+
try {
|
|
47
|
+
const { available, biometryType } = await rnBiometrics.isSensorAvailable();
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
available,
|
|
51
|
+
biometryType: biometryType || null,
|
|
52
|
+
};
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error('[BiometricUtils] Error checking biometric availability:', error);
|
|
55
|
+
return {
|
|
56
|
+
available: false,
|
|
57
|
+
biometryType: null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Prompts the user for biometric authentication
|
|
64
|
+
*
|
|
65
|
+
* This function should be called before generating session credentials
|
|
66
|
+
* for viewing card details. It ensures proper user verification before
|
|
67
|
+
* accessing sensitive payment card information.
|
|
68
|
+
*
|
|
69
|
+
* @param promptMessage - Message to display in the biometric prompt
|
|
70
|
+
* @returns Result indicating success or failure with reason
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const result = await authenticateWithBiometrics('Authenticate to view card details');
|
|
75
|
+
* if (result.success) {
|
|
76
|
+
* // Proceed with generating session credentials
|
|
77
|
+
* } else {
|
|
78
|
+
* // Handle failure based on result.error.reason
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export async function authenticateWithBiometrics(
|
|
83
|
+
promptMessage: string = 'Authenticate to view card details'
|
|
84
|
+
): Promise<BiometricResult> {
|
|
85
|
+
try {
|
|
86
|
+
// First check if biometrics are available
|
|
87
|
+
const { available, biometryType } = await rnBiometrics.isSensorAvailable();
|
|
88
|
+
|
|
89
|
+
if (!available) {
|
|
90
|
+
console.log('[BiometricUtils] Biometrics not available on device');
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
error: {
|
|
94
|
+
reason: 'not_available',
|
|
95
|
+
message: 'Biometric authentication is not available on this device',
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check if biometrics are enrolled
|
|
101
|
+
const { keysExist } = await rnBiometrics.biometricKeysExist();
|
|
102
|
+
|
|
103
|
+
// Note: Even without keys, simplePrompt should work for basic authentication
|
|
104
|
+
// The keysExist check is more for cryptographic operations
|
|
105
|
+
|
|
106
|
+
console.log(
|
|
107
|
+
`[BiometricUtils] Attempting biometric auth. Type: ${biometryType}, Keys exist: ${keysExist}`
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// Perform the biometric authentication
|
|
111
|
+
const { success, error } = await rnBiometrics.simplePrompt({
|
|
112
|
+
promptMessage,
|
|
113
|
+
cancelButtonText: 'Cancel',
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (success) {
|
|
117
|
+
console.log('[BiometricUtils] Biometric authentication successful');
|
|
118
|
+
return { success: true };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Handle various failure reasons
|
|
122
|
+
console.log('[BiometricUtils] Biometric authentication failed:', error);
|
|
123
|
+
|
|
124
|
+
// Parse the error message to determine the reason
|
|
125
|
+
const errorMessage = error || 'Authentication failed';
|
|
126
|
+
let reason: NonNullable<BiometricResult['error']>['reason'] = 'failed';
|
|
127
|
+
|
|
128
|
+
if (
|
|
129
|
+
errorMessage.toLowerCase().includes('cancel') ||
|
|
130
|
+
errorMessage.toLowerCase().includes('user cancel')
|
|
131
|
+
) {
|
|
132
|
+
reason = 'cancelled';
|
|
133
|
+
} else if (
|
|
134
|
+
errorMessage.toLowerCase().includes('not enrolled') ||
|
|
135
|
+
errorMessage.toLowerCase().includes('no fingerprint') ||
|
|
136
|
+
errorMessage.toLowerCase().includes('no face')
|
|
137
|
+
) {
|
|
138
|
+
reason = 'not_enrolled';
|
|
139
|
+
} else if (
|
|
140
|
+
errorMessage.toLowerCase().includes('not available') ||
|
|
141
|
+
errorMessage.toLowerCase().includes('not supported')
|
|
142
|
+
) {
|
|
143
|
+
reason = 'not_available';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
success: false,
|
|
148
|
+
error: {
|
|
149
|
+
reason,
|
|
150
|
+
message: errorMessage,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error('[BiometricUtils] Biometric authentication error:', error);
|
|
155
|
+
|
|
156
|
+
const errorMessage =
|
|
157
|
+
error instanceof Error ? error.message : 'Unknown error occurred';
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
success: false,
|
|
161
|
+
error: {
|
|
162
|
+
reason: 'failed',
|
|
163
|
+
message: errorMessage,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Gets a user-friendly description of the biometric type
|
|
171
|
+
*
|
|
172
|
+
* @param biometryType - The biometry type from the device
|
|
173
|
+
* @returns Human-readable string for the biometry type
|
|
174
|
+
*/
|
|
175
|
+
export function getBiometryTypeLabel(biometryType: BiometryType | null): string {
|
|
176
|
+
switch (biometryType) {
|
|
177
|
+
case BiometryTypes.FaceID:
|
|
178
|
+
return 'Face ID';
|
|
179
|
+
case BiometryTypes.TouchID:
|
|
180
|
+
return 'Touch ID';
|
|
181
|
+
case BiometryTypes.Biometrics:
|
|
182
|
+
return 'Biometrics';
|
|
183
|
+
default:
|
|
184
|
+
return 'Biometric Authentication';
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Re-export BiometryTypes for convenience
|
|
189
|
+
export { BiometryTypes };
|