react-native-fpay 0.1.1
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/Fpay.podspec +20 -0
- package/LICENSE +20 -0
- package/README.md +37 -0
- package/android/build.gradle +67 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/fpay/FpayModule.kt +15 -0
- package/android/src/main/java/com/fpay/FpayPackage.kt +31 -0
- package/ios/Fpay.h +5 -0
- package/ios/Fpay.mm +21 -0
- package/lib/module/FountainPayProvider.js +18 -0
- package/lib/module/FountainPayProvider.js.map +1 -0
- package/lib/module/core/api/client.js +47 -0
- package/lib/module/core/api/client.js.map +1 -0
- package/lib/module/core/api/index.js +35 -0
- package/lib/module/core/api/index.js.map +1 -0
- package/lib/module/core/types/index.js +4 -0
- package/lib/module/core/types/index.js.map +1 -0
- package/lib/module/engine/BLEReceiverService.js +190 -0
- package/lib/module/engine/BLEReceiverService.js.map +1 -0
- package/lib/module/engine/BLESenderService.js +259 -0
- package/lib/module/engine/BLESenderService.js.map +1 -0
- package/lib/module/engine/FPEngine.js +340 -0
- package/lib/module/engine/FPEngine.js.map +1 -0
- package/lib/module/engine/NearbyUsersService.js +87 -0
- package/lib/module/engine/NearbyUsersService.js.map +1 -0
- package/lib/module/index.js +16 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/ui/components/FPButton.js +71 -0
- package/lib/module/ui/components/FPButton.js.map +1 -0
- package/lib/module/ui/components/LoadingAnimation/InLoading.js +74 -0
- package/lib/module/ui/components/LoadingAnimation/InLoading.js.map +1 -0
- package/lib/module/ui/components/LoadingAnimation/index.js +82 -0
- package/lib/module/ui/components/LoadingAnimation/index.js.map +1 -0
- package/lib/module/ui/components/OtpInput/OTPInputView.js +290 -0
- package/lib/module/ui/components/OtpInput/OTPInputView.js.map +1 -0
- package/lib/module/ui/components/OtpInput/Styles.js +20 -0
- package/lib/module/ui/components/OtpInput/Styles.js.map +1 -0
- package/lib/module/ui/components/OtpInput/helpers/codeToArray.js +7 -0
- package/lib/module/ui/components/OtpInput/helpers/codeToArray.js.map +1 -0
- package/lib/module/ui/components/OtpInput/helpers/device.js +9 -0
- package/lib/module/ui/components/OtpInput/helpers/device.js.map +1 -0
- package/lib/module/ui/components/OtpInput/helpers/styles.js +17 -0
- package/lib/module/ui/components/OtpInput/helpers/styles.js.map +1 -0
- package/lib/module/ui/components/OtpInput/helpers/types.js +4 -0
- package/lib/module/ui/components/OtpInput/helpers/types.js.map +1 -0
- package/lib/module/ui/components/OtpInput/index.js +45 -0
- package/lib/module/ui/components/OtpInput/index.js.map +1 -0
- package/lib/module/ui/components/PulseAnimation.js +61 -0
- package/lib/module/ui/components/PulseAnimation.js.map +1 -0
- package/lib/module/ui/modals/FPPaymentRequestModal.js +253 -0
- package/lib/module/ui/modals/FPPaymentRequestModal.js.map +1 -0
- package/lib/module/ui/modals/FPShell.js +180 -0
- package/lib/module/ui/modals/FPShell.js.map +1 -0
- package/lib/module/ui/screens/ReceiveScreen.js +291 -0
- package/lib/module/ui/screens/ReceiveScreen.js.map +1 -0
- package/lib/module/ui/screens/SendScreen.js +216 -0
- package/lib/module/ui/screens/SendScreen.js.map +1 -0
- package/lib/module/ui/screens/sub/BluetoothSubScreen.js +403 -0
- package/lib/module/ui/screens/sub/BluetoothSubScreen.js.map +1 -0
- package/lib/module/ui/screens/sub/NFCSubScreen.js +169 -0
- package/lib/module/ui/screens/sub/NFCSubScreen.js.map +1 -0
- package/lib/module/ui/screens/sub/NQRSubScreen.js +136 -0
- package/lib/module/ui/screens/sub/NQRSubScreen.js.map +1 -0
- package/lib/module/ui/screens/sub/ProximitySubScreen.js +501 -0
- package/lib/module/ui/screens/sub/ProximitySubScreen.js.map +1 -0
- package/lib/module/ui/screens/sub/TransferSubScreen.js +361 -0
- package/lib/module/ui/screens/sub/TransferSubScreen.js.map +1 -0
- package/lib/module/ui/theme/index.js +64 -0
- package/lib/module/ui/theme/index.js.map +1 -0
- package/lib/module/useFountainPay.js +82 -0
- package/lib/module/useFountainPay.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/FountainPayProvider.d.ts +7 -0
- package/lib/typescript/src/FountainPayProvider.d.ts.map +1 -0
- package/lib/typescript/src/core/api/client.d.ts +7 -0
- package/lib/typescript/src/core/api/client.d.ts.map +1 -0
- package/lib/typescript/src/core/api/index.d.ts +67 -0
- package/lib/typescript/src/core/api/index.d.ts.map +1 -0
- package/lib/typescript/src/core/types/index.d.ts +130 -0
- package/lib/typescript/src/core/types/index.d.ts.map +1 -0
- package/lib/typescript/src/engine/BLEReceiverService.d.ts +43 -0
- package/lib/typescript/src/engine/BLEReceiverService.d.ts.map +1 -0
- package/lib/typescript/src/engine/BLESenderService.d.ts +39 -0
- package/lib/typescript/src/engine/BLESenderService.d.ts.map +1 -0
- package/lib/typescript/src/engine/FPEngine.d.ts +24 -0
- package/lib/typescript/src/engine/FPEngine.d.ts.map +1 -0
- package/lib/typescript/src/engine/NearbyUsersService.d.ts +19 -0
- package/lib/typescript/src/engine/NearbyUsersService.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/FPButton.d.ts +12 -0
- package/lib/typescript/src/ui/components/FPButton.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/LoadingAnimation/InLoading.d.ts +7 -0
- package/lib/typescript/src/ui/components/LoadingAnimation/InLoading.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/LoadingAnimation/index.d.ts +6 -0
- package/lib/typescript/src/ui/components/LoadingAnimation/index.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/OtpInput/OTPInputView.d.ts +29 -0
- package/lib/typescript/src/ui/components/OtpInput/OTPInputView.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/OtpInput/Styles.d.ts +330 -0
- package/lib/typescript/src/ui/components/OtpInput/Styles.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/OtpInput/helpers/codeToArray.d.ts +6 -0
- package/lib/typescript/src/ui/components/OtpInput/helpers/codeToArray.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/OtpInput/helpers/device.d.ts +6 -0
- package/lib/typescript/src/ui/components/OtpInput/helpers/device.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/OtpInput/helpers/styles.d.ts +6 -0
- package/lib/typescript/src/ui/components/OtpInput/helpers/styles.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/OtpInput/helpers/types.d.ts +84 -0
- package/lib/typescript/src/ui/components/OtpInput/helpers/types.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/OtpInput/index.d.ts +9 -0
- package/lib/typescript/src/ui/components/OtpInput/index.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/PulseAnimation.d.ts +2 -0
- package/lib/typescript/src/ui/components/PulseAnimation.d.ts.map +1 -0
- package/lib/typescript/src/ui/modals/FPPaymentRequestModal.d.ts +2 -0
- package/lib/typescript/src/ui/modals/FPPaymentRequestModal.d.ts.map +1 -0
- package/lib/typescript/src/ui/modals/FPShell.d.ts +2 -0
- package/lib/typescript/src/ui/modals/FPShell.d.ts.map +1 -0
- package/lib/typescript/src/ui/screens/ReceiveScreen.d.ts +10 -0
- package/lib/typescript/src/ui/screens/ReceiveScreen.d.ts.map +1 -0
- package/lib/typescript/src/ui/screens/SendScreen.d.ts +9 -0
- package/lib/typescript/src/ui/screens/SendScreen.d.ts.map +1 -0
- package/lib/typescript/src/ui/screens/sub/BluetoothSubScreen.d.ts +552 -0
- package/lib/typescript/src/ui/screens/sub/BluetoothSubScreen.d.ts.map +1 -0
- package/lib/typescript/src/ui/screens/sub/NFCSubScreen.d.ts +19 -0
- package/lib/typescript/src/ui/screens/sub/NFCSubScreen.d.ts.map +1 -0
- package/lib/typescript/src/ui/screens/sub/NQRSubScreen.d.ts +13 -0
- package/lib/typescript/src/ui/screens/sub/NQRSubScreen.d.ts.map +1 -0
- package/lib/typescript/src/ui/screens/sub/ProximitySubScreen.d.ts +552 -0
- package/lib/typescript/src/ui/screens/sub/ProximitySubScreen.d.ts.map +1 -0
- package/lib/typescript/src/ui/screens/sub/TransferSubScreen.d.ts +12 -0
- package/lib/typescript/src/ui/screens/sub/TransferSubScreen.d.ts.map +1 -0
- package/lib/typescript/src/ui/theme/index.d.ts +62 -0
- package/lib/typescript/src/ui/theme/index.d.ts.map +1 -0
- package/lib/typescript/src/useFountainPay.d.ts +3 -0
- package/lib/typescript/src/useFountainPay.d.ts.map +1 -0
- package/package.json +217 -0
- package/src/FountainPayProvider.tsx +21 -0
- package/src/core/api/client.ts +47 -0
- package/src/core/api/index.ts +61 -0
- package/src/core/types/index.ts +144 -0
- package/src/engine/BLEReceiverService.ts +244 -0
- package/src/engine/BLESenderService.ts +314 -0
- package/src/engine/FPEngine.ts +370 -0
- package/src/engine/NearbyUsersService.ts +106 -0
- package/src/index.ts +30 -0
- package/src/ui/components/FPButton.tsx +42 -0
- package/src/ui/components/LoadingAnimation/InLoading.tsx +88 -0
- package/src/ui/components/LoadingAnimation/index.tsx +93 -0
- package/src/ui/components/OtpInput/OTPInputView.tsx +243 -0
- package/src/ui/components/OtpInput/Styles.ts +19 -0
- package/src/ui/components/OtpInput/helpers/codeToArray.ts +3 -0
- package/src/ui/components/OtpInput/helpers/device.ts +6 -0
- package/src/ui/components/OtpInput/helpers/styles.ts +17 -0
- package/src/ui/components/OtpInput/helpers/types.ts +88 -0
- package/src/ui/components/OtpInput/index.tsx +51 -0
- package/src/ui/components/PulseAnimation.tsx +78 -0
- package/src/ui/modals/FPPaymentRequestModal.tsx +158 -0
- package/src/ui/modals/FPShell.tsx +107 -0
- package/src/ui/screens/ReceiveScreen.tsx +119 -0
- package/src/ui/screens/SendScreen.tsx +86 -0
- package/src/ui/screens/sub/BluetoothSubScreen.tsx +433 -0
- package/src/ui/screens/sub/NFCSubScreen.tsx +83 -0
- package/src/ui/screens/sub/NQRSubScreen.tsx +61 -0
- package/src/ui/screens/sub/ProximitySubScreen.tsx +390 -0
- package/src/ui/screens/sub/TransferSubScreen.tsx +146 -0
- package/src/ui/theme/index.ts +24 -0
- package/src/useFountainPay.ts +95 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// FPay SDK — BLESenderService (Central)
|
|
4
|
+
// Ported directly from your BLESenderService.ts.
|
|
5
|
+
// Same UUIDs (imported from BLEReceiverService), same polling strategy,
|
|
6
|
+
// same write fallback (writeWithoutResponse → writeWithResponse).
|
|
7
|
+
// Only changes: renamed types to match SDK conventions, removed Alert imports.
|
|
8
|
+
|
|
9
|
+
import { BleManager, State as BluetoothState, ScanMode } from 'react-native-ble-plx';
|
|
10
|
+
import { PermissionsAndroid, Platform } from 'react-native';
|
|
11
|
+
import { Buffer } from 'buffer';
|
|
12
|
+
import { FP_SERVICE_UUID, FP_REQUEST_CHAR_UUID, FP_RESPONSE_CHAR_UUID, FP_USERINFO_CHAR_UUID } from "./BLEReceiverService.js";
|
|
13
|
+
|
|
14
|
+
// ── Types ─────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
// A discovered FountainPay-capable BLE device (shown in BluetoothSubScreen list)
|
|
17
|
+
|
|
18
|
+
// The payment request written to the receiver's characteristic
|
|
19
|
+
|
|
20
|
+
// The response polled from the receiver's characteristic
|
|
21
|
+
|
|
22
|
+
// ── Class ─────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
class BLESenderService {
|
|
25
|
+
connectedDevices = new Map();
|
|
26
|
+
monitorSubscription = null;
|
|
27
|
+
constructor() {
|
|
28
|
+
this.bleManager = new BleManager();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ── Init ───────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
async initialize() {
|
|
34
|
+
await this._requestPermissions();
|
|
35
|
+
await this._initializeBLE();
|
|
36
|
+
}
|
|
37
|
+
async _requestPermissions() {
|
|
38
|
+
if (Platform.OS !== 'android') return true;
|
|
39
|
+
if (Platform.Version >= 31) {
|
|
40
|
+
const results = await PermissionsAndroid.requestMultiple([PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN, PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT, PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION]);
|
|
41
|
+
return Object.values(results).every(r => r === PermissionsAndroid.RESULTS.GRANTED);
|
|
42
|
+
}
|
|
43
|
+
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
|
|
44
|
+
return granted === PermissionsAndroid.RESULTS.GRANTED;
|
|
45
|
+
}
|
|
46
|
+
_initializeBLE() {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
const sub = this.bleManager.onStateChange(state => {
|
|
49
|
+
switch (state) {
|
|
50
|
+
case BluetoothState.Unsupported:
|
|
51
|
+
reject(new Error('[FPay BLE Sender] Bluetooth not supported on this device'));
|
|
52
|
+
sub.remove();
|
|
53
|
+
break;
|
|
54
|
+
case BluetoothState.PoweredOff:
|
|
55
|
+
// Attempt to enable — works on Android; iOS will prompt the user
|
|
56
|
+
this.bleManager.enable().catch(reject);
|
|
57
|
+
break;
|
|
58
|
+
case BluetoothState.Unauthorized:
|
|
59
|
+
reject(new Error('[FPay BLE Sender] Bluetooth permission denied'));
|
|
60
|
+
sub.remove();
|
|
61
|
+
break;
|
|
62
|
+
case BluetoothState.PoweredOn:
|
|
63
|
+
console.log('[FPay BLE Sender] Bluetooth ready');
|
|
64
|
+
resolve();
|
|
65
|
+
sub.remove();
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}, true);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ── Scanning ───────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
// Scans for nearby FountainPay BLE peripherals.
|
|
75
|
+
// Connects briefly to each to read the USER_INFO characteristic,
|
|
76
|
+
// then disconnects. Same approach as your BLESenderService.readDeviceInfo().
|
|
77
|
+
async scanForDevices(onDeviceFound, durationMs = 5000) {
|
|
78
|
+
const seen = new Set();
|
|
79
|
+
return new Promise((resolve, reject) => {
|
|
80
|
+
console.log('[FPay BLE Sender] Starting scan...');
|
|
81
|
+
this.bleManager.startDeviceScan([FP_SERVICE_UUID], {
|
|
82
|
+
allowDuplicates: false,
|
|
83
|
+
scanMode: ScanMode.LowPower
|
|
84
|
+
}, async (error, device) => {
|
|
85
|
+
if (error) {
|
|
86
|
+
console.error('[FPay BLE Sender] Scan error:', error);
|
|
87
|
+
this.bleManager.stopDeviceScan();
|
|
88
|
+
reject(error);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (device && !seen.has(device.id)) {
|
|
92
|
+
seen.add(device.id);
|
|
93
|
+
console.log('[FPay BLE Sender] Found device:', device.name ?? device.id);
|
|
94
|
+
try {
|
|
95
|
+
const fp = await this._readDeviceInfo(device);
|
|
96
|
+
if (fp) onDeviceFound(fp);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.warn('[FPay BLE Sender] Could not read device info:', err);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
setTimeout(() => {
|
|
103
|
+
this.bleManager.stopDeviceScan();
|
|
104
|
+
console.log('[FPay BLE Sender] Scan complete. Found:', seen.size, 'FPay device(s)');
|
|
105
|
+
resolve();
|
|
106
|
+
}, durationMs);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async _readDeviceInfo(device) {
|
|
110
|
+
try {
|
|
111
|
+
const connected = await this.bleManager.connectToDevice(device.id);
|
|
112
|
+
await connected.discoverAllServicesAndCharacteristics();
|
|
113
|
+
const char = await connected.readCharacteristicForService(FP_SERVICE_UUID, FP_USERINFO_CHAR_UUID);
|
|
114
|
+
await this.bleManager.cancelDeviceConnection(device.id);
|
|
115
|
+
if (!char.value) return null;
|
|
116
|
+
const info = JSON.parse(Buffer.from(char.value, 'base64').toString('utf8'));
|
|
117
|
+
return {
|
|
118
|
+
id: device.id,
|
|
119
|
+
name: device.name ?? 'Unknown Device',
|
|
120
|
+
appName: info.appName ?? 'FountainPay',
|
|
121
|
+
userName: info.userName ?? '',
|
|
122
|
+
rssi: device.rssi ?? -100,
|
|
123
|
+
rawDevice: device
|
|
124
|
+
};
|
|
125
|
+
} catch (err) {
|
|
126
|
+
try {
|
|
127
|
+
await this.bleManager.cancelDeviceConnection(device.id);
|
|
128
|
+
} catch {}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ── Connection ─────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
async connectToDevice(deviceId) {
|
|
136
|
+
console.log('[FPay BLE Sender] Connecting to', deviceId);
|
|
137
|
+
const device = await this.bleManager.connectToDevice(deviceId, {
|
|
138
|
+
timeout: 15000
|
|
139
|
+
});
|
|
140
|
+
await device.discoverAllServicesAndCharacteristics();
|
|
141
|
+
this.connectedDevices.set(deviceId, device);
|
|
142
|
+
console.log('[FPay BLE Sender] Connected and services discovered');
|
|
143
|
+
return device;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ── Send Payment Request ───────────────────────────────────
|
|
147
|
+
//
|
|
148
|
+
// Flow:
|
|
149
|
+
// 1. Connect to receiver device
|
|
150
|
+
// 2. Start polling the RESPONSE characteristic in the background
|
|
151
|
+
// 3. Write the payment request JSON to the REQUEST characteristic
|
|
152
|
+
// (tries writeWithoutResponse first, falls back to writeWithResponse)
|
|
153
|
+
// 4. Wait up to 60s for the receiver to accept/decline
|
|
154
|
+
// The response is matched by requestTimestamp === request.timestamp
|
|
155
|
+
// 5. Return the response (contains accountDetails if accepted)
|
|
156
|
+
//
|
|
157
|
+
// This is your exact polling mechanism, unchanged.
|
|
158
|
+
async sendPaymentRequest(deviceId, request) {
|
|
159
|
+
let responseReceived = false;
|
|
160
|
+
try {
|
|
161
|
+
let device = this.connectedDevices.get(deviceId);
|
|
162
|
+
if (!device) device = await this.connectToDevice(deviceId);
|
|
163
|
+
|
|
164
|
+
// Start polling BEFORE writing the request, so we don't miss a fast response
|
|
165
|
+
const responsePromise = new Promise(async (resolve, reject) => {
|
|
166
|
+
const startTime = Date.now();
|
|
167
|
+
const poll = async () => {
|
|
168
|
+
while (!responseReceived) {
|
|
169
|
+
if (Date.now() - startTime > 60000) {
|
|
170
|
+
reject(new Error('[FPay BLE Sender] Response timeout — receiver did not respond in 60s'));
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
175
|
+
if (responseReceived) break;
|
|
176
|
+
console.log('[FPay BLE Sender] Polling response characteristic...');
|
|
177
|
+
const char = await device.readCharacteristicForService(FP_SERVICE_UUID, FP_RESPONSE_CHAR_UUID);
|
|
178
|
+
if (char.value && char.value.length > 0) {
|
|
179
|
+
const decoded = Buffer.from(char.value, 'base64').toString('utf8');
|
|
180
|
+
const resp = JSON.parse(decoded);
|
|
181
|
+
|
|
182
|
+
// Verify this response matches OUR request via the echoed timestamp
|
|
183
|
+
if (resp.timestamp && resp.requestTimestamp && resp.requestTimestamp === request.timestamp) {
|
|
184
|
+
console.log('[FPay BLE Sender] Response received — accepted:', resp.accepted);
|
|
185
|
+
responseReceived = true;
|
|
186
|
+
resolve(resp);
|
|
187
|
+
break;
|
|
188
|
+
} else {
|
|
189
|
+
console.log('[FPay BLE Sender] Old/unrelated response, still polling...');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
} catch (pollErr) {
|
|
193
|
+
// errorCode 205 = device disconnected — abort immediately
|
|
194
|
+
if (pollErr.errorCode === 205) {
|
|
195
|
+
reject(new Error('[FPay BLE Sender] Device disconnected'));
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
// All other errors: log and keep polling
|
|
199
|
+
console.warn('[FPay BLE Sender] Poll error (non-fatal):', pollErr.message);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
poll().catch(reject);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Write the payment request
|
|
207
|
+
const base64 = Buffer.from(JSON.stringify(request)).toString('base64');
|
|
208
|
+
console.log('[FPay BLE Sender] Writing payment request...');
|
|
209
|
+
try {
|
|
210
|
+
await device.writeCharacteristicWithoutResponseForService(FP_SERVICE_UUID, FP_REQUEST_CHAR_UUID, base64);
|
|
211
|
+
console.log('[FPay BLE Sender] Written without response (preferred)');
|
|
212
|
+
} catch {
|
|
213
|
+
console.log('[FPay BLE Sender] Retrying with response...');
|
|
214
|
+
await device.writeCharacteristicWithResponseForService(FP_SERVICE_UUID, FP_REQUEST_CHAR_UUID, base64);
|
|
215
|
+
console.log('[FPay BLE Sender] Written with response');
|
|
216
|
+
}
|
|
217
|
+
console.log('[FPay BLE Sender] Request sent. Waiting for accept/decline...');
|
|
218
|
+
const response = await responsePromise;
|
|
219
|
+
await this.disconnectDevice(deviceId);
|
|
220
|
+
return response;
|
|
221
|
+
} catch (err) {
|
|
222
|
+
await this.disconnectDevice(deviceId);
|
|
223
|
+
throw err;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ── Disconnect ─────────────────────────────────────────────
|
|
228
|
+
|
|
229
|
+
async disconnectDevice(deviceId) {
|
|
230
|
+
if (this.monitorSubscription) {
|
|
231
|
+
try {
|
|
232
|
+
this.monitorSubscription.remove();
|
|
233
|
+
} catch {}
|
|
234
|
+
this.monitorSubscription = null;
|
|
235
|
+
}
|
|
236
|
+
if (this.connectedDevices.has(deviceId)) {
|
|
237
|
+
try {
|
|
238
|
+
await this.bleManager.cancelDeviceConnection(deviceId);
|
|
239
|
+
} catch {}
|
|
240
|
+
this.connectedDevices.delete(deviceId);
|
|
241
|
+
console.log('[FPay BLE Sender] Disconnected from', deviceId);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ── Cleanup ────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
destroy() {
|
|
248
|
+
this.bleManager.stopDeviceScan();
|
|
249
|
+
this.connectedDevices.clear();
|
|
250
|
+
if (this.monitorSubscription) {
|
|
251
|
+
try {
|
|
252
|
+
this.monitorSubscription.remove();
|
|
253
|
+
} catch {}
|
|
254
|
+
}
|
|
255
|
+
this.bleManager.destroy();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
export default new BLESenderService();
|
|
259
|
+
//# sourceMappingURL=BLESenderService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["BleManager","State","BluetoothState","ScanMode","PermissionsAndroid","Platform","Buffer","FP_SERVICE_UUID","FP_REQUEST_CHAR_UUID","FP_RESPONSE_CHAR_UUID","FP_USERINFO_CHAR_UUID","BLESenderService","connectedDevices","Map","monitorSubscription","constructor","bleManager","initialize","_requestPermissions","_initializeBLE","OS","Version","results","requestMultiple","PERMISSIONS","BLUETOOTH_SCAN","BLUETOOTH_CONNECT","ACCESS_FINE_LOCATION","Object","values","every","r","RESULTS","GRANTED","granted","request","Promise","resolve","reject","sub","onStateChange","state","Unsupported","Error","remove","PoweredOff","enable","catch","Unauthorized","PoweredOn","console","log","scanForDevices","onDeviceFound","durationMs","seen","Set","startDeviceScan","allowDuplicates","scanMode","LowPower","error","device","stopDeviceScan","has","id","add","name","fp","_readDeviceInfo","err","warn","setTimeout","size","connected","connectToDevice","discoverAllServicesAndCharacteristics","char","readCharacteristicForService","cancelDeviceConnection","value","info","JSON","parse","from","toString","appName","userName","rssi","rawDevice","deviceId","timeout","set","sendPaymentRequest","responseReceived","get","responsePromise","startTime","Date","now","poll","length","decoded","resp","timestamp","requestTimestamp","accepted","pollErr","errorCode","message","base64","stringify","writeCharacteristicWithoutResponseForService","writeCharacteristicWithResponseForService","response","disconnectDevice","delete","destroy","clear"],"sourceRoot":"../../../src","sources":["engine/BLESenderService.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// FPay SDK — FPEngine
|
|
4
|
+
// Orchestrates BLEReceiverService, BLESenderService, proximity, and the event bus.
|
|
5
|
+
// This replaces AlwaysOnPaymentListener entirely — all its logic lives here.
|
|
6
|
+
|
|
7
|
+
import { AppState, Vibration } from 'react-native';
|
|
8
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
9
|
+
import Geolocation from '@react-native-community/geolocation';
|
|
10
|
+
import { initClient } from "../core/api/client.js";
|
|
11
|
+
import { proximityAPI, walletAPI } from "../core/api/index.js";
|
|
12
|
+
import BLEReceiverService from "./BLEReceiverService.js";
|
|
13
|
+
import BLESenderService from "./BLESenderService.js";
|
|
14
|
+
|
|
15
|
+
// ── Module-level singleton state ──────────────────────────────
|
|
16
|
+
let _apiKey = null;
|
|
17
|
+
let _user = null;
|
|
18
|
+
let _callbacks = {};
|
|
19
|
+
let _options = {};
|
|
20
|
+
let _isReady = false;
|
|
21
|
+
let _isListening = false;
|
|
22
|
+
let _proximitySessionId = null;
|
|
23
|
+
let _proximityInterval = null;
|
|
24
|
+
let _appStateSub = null;
|
|
25
|
+
|
|
26
|
+
// ── Internal event bus ────────────────────────────────────────
|
|
27
|
+
// Used to communicate between FPEngine and the UI layer
|
|
28
|
+
// without any React coupling.
|
|
29
|
+
|
|
30
|
+
const _listeners = new Map();
|
|
31
|
+
export function _emitEvent(event, data) {
|
|
32
|
+
_listeners.get(event)?.forEach(fn => fn(data));
|
|
33
|
+
}
|
|
34
|
+
export function _onEvent(event, fn) {
|
|
35
|
+
if (!_listeners.has(event)) _listeners.set(event, new Set());
|
|
36
|
+
_listeners.get(event).add(fn);
|
|
37
|
+
return () => _listeners.get(event)?.delete(fn);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ── Proximity helpers ─────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
function _clearProximityInterval() {
|
|
43
|
+
if (_proximityInterval) {
|
|
44
|
+
clearInterval(_proximityInterval);
|
|
45
|
+
_proximityInterval = null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function _getLocation() {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
Geolocation.getCurrentPosition(p => resolve({
|
|
51
|
+
lat: p.coords.latitude,
|
|
52
|
+
lng: p.coords.longitude
|
|
53
|
+
}), e => reject({
|
|
54
|
+
code: 'LOCATION_DENIED',
|
|
55
|
+
message: e.message
|
|
56
|
+
}), {
|
|
57
|
+
enableHighAccuracy: true,
|
|
58
|
+
timeout: 8000,
|
|
59
|
+
maximumAge: 10000
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async function _startProximityBroadcast() {
|
|
64
|
+
if (!_user) return;
|
|
65
|
+
try {
|
|
66
|
+
const loc = await _getLocation();
|
|
67
|
+
const session = await proximityAPI.broadcast({
|
|
68
|
+
latitude: loc.lat,
|
|
69
|
+
longitude: loc.lng,
|
|
70
|
+
accountName: _user.accountName,
|
|
71
|
+
accountNumber: _user.accountNumber,
|
|
72
|
+
bankCode: _user.bankCode,
|
|
73
|
+
bankName: _user.bankName
|
|
74
|
+
});
|
|
75
|
+
_proximitySessionId = session.sessionId;
|
|
76
|
+
_clearProximityInterval();
|
|
77
|
+
_proximityInterval = setInterval(async () => {
|
|
78
|
+
if (!_proximitySessionId) return;
|
|
79
|
+
try {
|
|
80
|
+
const l = await _getLocation();
|
|
81
|
+
await proximityAPI.heartbeat(_proximitySessionId, l.lat, l.lng);
|
|
82
|
+
} catch {/* silent — heartbeat failure is non-fatal */}
|
|
83
|
+
}, 15000);
|
|
84
|
+
console.log('[FPay Engine] Proximity broadcast active');
|
|
85
|
+
} catch (err) {
|
|
86
|
+
// Non-fatal — app still works without proximity
|
|
87
|
+
console.warn('[FPay Engine] Proximity unavailable:', err.message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function _stopProximityBroadcast() {
|
|
91
|
+
_clearProximityInterval();
|
|
92
|
+
if (_proximitySessionId) {
|
|
93
|
+
await proximityAPI.unregister(_proximitySessionId).catch(() => {});
|
|
94
|
+
_proximitySessionId = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ── Security validation ───────────────────────────────────────
|
|
99
|
+
// Ported from AlwaysOnPaymentListener.validatePaymentRequest()
|
|
100
|
+
|
|
101
|
+
async function _validateRequest(req) {
|
|
102
|
+
// 1. Age check — reject requests older than 5 minutes
|
|
103
|
+
const AGE_LIMIT = 5 * 60 * 1000;
|
|
104
|
+
if (Date.now() - req.timestamp > AGE_LIMIT) {
|
|
105
|
+
console.log('[FPay Engine] Rejected: request expired');
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 2. Blocked sender check
|
|
110
|
+
try {
|
|
111
|
+
const raw = await AsyncStorage.getItem('@fp_blocked_users');
|
|
112
|
+
const blocked = raw ? JSON.parse(raw) : [];
|
|
113
|
+
if (blocked.includes(req.senderId)) {
|
|
114
|
+
console.log('[FPay Engine] Rejected: sender is blocked');
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
} catch {}
|
|
118
|
+
|
|
119
|
+
// 3. Amount sanity (must be positive; max 10,000,000 kobo = NGN 100,000)
|
|
120
|
+
if (req.amount <= 0 || req.amount > 10000000) {
|
|
121
|
+
console.log('[FPay Engine] Rejected: invalid amount', req.amount);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 4. Duplicate detection — prevents replay attacks
|
|
126
|
+
try {
|
|
127
|
+
const raw = await AsyncStorage.getItem('@fp_recent_requests');
|
|
128
|
+
const recent = raw ? JSON.parse(raw) : [];
|
|
129
|
+
const isDuplicate = recent.some(r => r.senderId === req.senderId && r.amount === req.amount && Math.abs(r.timestamp - req.timestamp) < 60000 // within 1 minute
|
|
130
|
+
);
|
|
131
|
+
// Store and trim to last 50
|
|
132
|
+
await AsyncStorage.setItem('@fp_recent_requests', JSON.stringify([...recent, req].slice(-50)));
|
|
133
|
+
if (isDuplicate) {
|
|
134
|
+
console.log('[FPay Engine] Rejected: duplicate request');
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
} catch {}
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ── Incoming BLE payment request handler ─────────────────────
|
|
142
|
+
// This is the core of AlwaysOnPaymentListener.handleIncomingPaymentRequest()
|
|
143
|
+
// It fires automatically when BLEReceiverService receives a write event.
|
|
144
|
+
|
|
145
|
+
async function _handleIncomingRequest(req, deviceId) {
|
|
146
|
+
console.log('[FPay Engine] Incoming payment request from:', req.senderName, req.currency + req.amount);
|
|
147
|
+
const isValid = await _validateRequest(req);
|
|
148
|
+
if (!isValid) {
|
|
149
|
+
// Auto-decline invalid requests silently
|
|
150
|
+
await BLEReceiverService.sendPaymentResponse({
|
|
151
|
+
accepted: false,
|
|
152
|
+
timestamp: Date.now()
|
|
153
|
+
}).catch(() => {});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Vibrate to alert user — same pattern as your original code
|
|
158
|
+
Vibration.vibrate([0, 200, 100, 200]);
|
|
159
|
+
|
|
160
|
+
// Map BLEPaymentRequest → FPBluetoothPaymentRequest (the SDK's public type)
|
|
161
|
+
const fpRequest = {
|
|
162
|
+
requestId: req.senderId + '_' + req.timestamp,
|
|
163
|
+
sender: {
|
|
164
|
+
accountName: req.senderName,
|
|
165
|
+
deviceId,
|
|
166
|
+
deviceName: req.senderName
|
|
167
|
+
},
|
|
168
|
+
amount: req.amount,
|
|
169
|
+
currency: req.currency,
|
|
170
|
+
timestamp: new Date(req.timestamp).toISOString()
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// 1. Fire host app callback (optional — host may want to log, update state, etc.)
|
|
174
|
+
_callbacks.onPaymentRequest?.(fpRequest);
|
|
175
|
+
|
|
176
|
+
// 2. Fire internal event → FPPaymentRequestModal will render the Accept/Decline UI
|
|
177
|
+
_emitEvent('incoming_payment_request', fpRequest);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ── FPEngine public API ───────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
export const FPEngine = {
|
|
183
|
+
// Called by pay.initializeSDK()
|
|
184
|
+
// Mirrors AlwaysOnPaymentListener.initializeAlwaysOnService()
|
|
185
|
+
async initialize(apiKey, user, options = {}, callbacks = {}) {
|
|
186
|
+
_apiKey = apiKey;
|
|
187
|
+
_user = user;
|
|
188
|
+
_options = options;
|
|
189
|
+
_callbacks = callbacks;
|
|
190
|
+
|
|
191
|
+
// Boot the HTTP client
|
|
192
|
+
initClient(apiKey, {
|
|
193
|
+
baseUrl: options.baseUrl,
|
|
194
|
+
environment: options.environment
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Initialize BLE receiver with this user's info
|
|
198
|
+
const displayName = options.bluetoothDisplayName ?? user.accountName;
|
|
199
|
+
await BLEReceiverService.initializeWithUserInfo(user.userId ?? user.accountNumber, displayName, 'FountainPay');
|
|
200
|
+
|
|
201
|
+
// Start BLE advertising + proximity broadcast in parallel.
|
|
202
|
+
// Both are non-fatal — SDK still works if either fails.
|
|
203
|
+
await Promise.allSettled([BLEReceiverService.startAdvertising(), _startProximityBroadcast()]);
|
|
204
|
+
|
|
205
|
+
// Initialize BLE sender (central) — used when user sends payments via BT
|
|
206
|
+
await BLESenderService.initialize().catch(err => console.warn('[FPay Engine] BLE sender init failed (non-fatal):', err));
|
|
207
|
+
|
|
208
|
+
// Resume broadcasting when app returns to foreground
|
|
209
|
+
_appStateSub = AppState.addEventListener('change', next => {
|
|
210
|
+
if (next === 'active' && _isReady) {
|
|
211
|
+
_startProximityBroadcast();
|
|
212
|
+
BLEReceiverService.startAdvertising().catch(() => {});
|
|
213
|
+
} else if (next === 'background') {
|
|
214
|
+
_clearProximityInterval();
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
_isReady = true;
|
|
218
|
+
console.log('[FPay Engine] Initialized. Advertising as:', displayName);
|
|
219
|
+
},
|
|
220
|
+
async deviceConnection(deviceId) {
|
|
221
|
+
await BLESenderService.connectToDevice(deviceId);
|
|
222
|
+
},
|
|
223
|
+
// Called by pay.listen()
|
|
224
|
+
// Registers the BLE write callback — same as your:
|
|
225
|
+
// BLEReceiverService.listenForPaymentRequests(handleIncomingPaymentRequest)
|
|
226
|
+
startListening() {
|
|
227
|
+
if (_isListening) return;
|
|
228
|
+
_isListening = true;
|
|
229
|
+
BLEReceiverService.listenForPaymentRequests(_handleIncomingRequest);
|
|
230
|
+
console.log('[FPay Engine] Listening for BLE payment requests');
|
|
231
|
+
},
|
|
232
|
+
stopListening() {
|
|
233
|
+
_isListening = false;
|
|
234
|
+
// Replace with a no-op so the peripheral write handler doesn't crash
|
|
235
|
+
BLEReceiverService.listenForPaymentRequests(() => {});
|
|
236
|
+
},
|
|
237
|
+
// Called by FPPaymentRequestModal when user taps "Accept"
|
|
238
|
+
// Mirrors AlwaysOnPaymentListener.handleAcceptPayment()
|
|
239
|
+
async acceptPaymentRequest(request) {
|
|
240
|
+
try {
|
|
241
|
+
const transactionId = 'txn_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
|
242
|
+
|
|
243
|
+
// Build response — same shape as your original:
|
|
244
|
+
// { accepted, transactionId, timestamp, accountDetails, requestTimestamp }
|
|
245
|
+
const response = {
|
|
246
|
+
accepted: true,
|
|
247
|
+
transactionId,
|
|
248
|
+
timestamp: Date.now(),
|
|
249
|
+
accountDetails: _user ? {
|
|
250
|
+
accountName: _user.accountName,
|
|
251
|
+
accountNumber: _user.accountNumber,
|
|
252
|
+
bankName: _user.bankName,
|
|
253
|
+
bankCode: _user.bankCode
|
|
254
|
+
} : undefined,
|
|
255
|
+
// requestTimestamp is echoed back so the sender's polling can match it
|
|
256
|
+
requestTimestamp: new Date(request.timestamp).getTime()
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// Write response to the BLE characteristic — sender is polling this
|
|
260
|
+
await BLEReceiverService.sendPaymentResponse(response);
|
|
261
|
+
console.log('[FPay Engine] Acceptance response sent to sender');
|
|
262
|
+
|
|
263
|
+
// Notify host app
|
|
264
|
+
const tx = {
|
|
265
|
+
id: transactionId,
|
|
266
|
+
reference: transactionId,
|
|
267
|
+
type: 'credit',
|
|
268
|
+
channel: 'bluetooth',
|
|
269
|
+
amount: request.amount,
|
|
270
|
+
currency: request.currency,
|
|
271
|
+
status: 'successful',
|
|
272
|
+
sender: request.sender,
|
|
273
|
+
createdAt: new Date().toISOString()
|
|
274
|
+
};
|
|
275
|
+
_callbacks.onPaymentReceived?.(tx);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
_callbacks.onError?.(err);
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
// Called by FPPaymentRequestModal when user taps "Decline"
|
|
281
|
+
// Mirrors AlwaysOnPaymentListener.handleDeclinePayment()
|
|
282
|
+
async declinePaymentRequest(request) {
|
|
283
|
+
try {
|
|
284
|
+
await BLEReceiverService.sendPaymentResponse({
|
|
285
|
+
accepted: false,
|
|
286
|
+
timestamp: Date.now()
|
|
287
|
+
});
|
|
288
|
+
console.log('[FPay Engine] Decline response sent to sender');
|
|
289
|
+
} catch {
|
|
290
|
+
// Non-fatal — decline even if response send fails
|
|
291
|
+
}
|
|
292
|
+
_callbacks.onPaymentDeclined?.(request);
|
|
293
|
+
},
|
|
294
|
+
// ── Used by BluetoothSubScreen (Send side) ─────────────────
|
|
295
|
+
|
|
296
|
+
// Scan for nearby FPay BLE devices
|
|
297
|
+
async scanForBluetoothDevices(onDeviceFound, durationMs = 7000) {
|
|
298
|
+
return BLESenderService.scanForDevices(onDeviceFound, durationMs);
|
|
299
|
+
},
|
|
300
|
+
// Send a BLE payment request to a discovered device.
|
|
301
|
+
// Returns the response which contains the receiver's accountDetails
|
|
302
|
+
// if accepted — the calling screen then calls transferAPI to move the money.
|
|
303
|
+
async sendBluetoothPaymentRequest(deviceId, request) {
|
|
304
|
+
return BLESenderService.sendPaymentRequest(deviceId, request);
|
|
305
|
+
},
|
|
306
|
+
// ── Other SDK actions ──────────────────────────────────────
|
|
307
|
+
|
|
308
|
+
async generateAccount(req) {
|
|
309
|
+
return walletAPI.generate(req);
|
|
310
|
+
},
|
|
311
|
+
showSend(amount, currency) {
|
|
312
|
+
_emitEvent('show_send', {
|
|
313
|
+
amount,
|
|
314
|
+
currency
|
|
315
|
+
});
|
|
316
|
+
},
|
|
317
|
+
showReceive(amount, currency) {
|
|
318
|
+
_emitEvent('show_receive', {
|
|
319
|
+
amount,
|
|
320
|
+
currency
|
|
321
|
+
});
|
|
322
|
+
},
|
|
323
|
+
getUser: () => _user,
|
|
324
|
+
isReady: () => _isReady,
|
|
325
|
+
getCallbacks: () => _callbacks,
|
|
326
|
+
async destroy() {
|
|
327
|
+
_clearProximityInterval();
|
|
328
|
+
await _stopProximityBroadcast();
|
|
329
|
+
await BLEReceiverService.stopAdvertising();
|
|
330
|
+
BLESenderService.destroy();
|
|
331
|
+
_isListening = false;
|
|
332
|
+
_appStateSub?.remove();
|
|
333
|
+
_isReady = false;
|
|
334
|
+
_user = null;
|
|
335
|
+
_proximitySessionId = null;
|
|
336
|
+
_listeners.clear();
|
|
337
|
+
console.log('[FPay Engine] Destroyed');
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
//# sourceMappingURL=FPEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["AppState","Vibration","AsyncStorage","Geolocation","initClient","proximityAPI","walletAPI","BLEReceiverService","BLESenderService","_apiKey","_user","_callbacks","_options","_isReady","_isListening","_proximitySessionId","_proximityInterval","_appStateSub","_listeners","Map","_emitEvent","event","data","get","forEach","fn","_onEvent","has","set","Set","add","delete","_clearProximityInterval","clearInterval","_getLocation","Promise","resolve","reject","getCurrentPosition","p","lat","coords","latitude","lng","longitude","e","code","message","enableHighAccuracy","timeout","maximumAge","_startProximityBroadcast","loc","session","broadcast","accountName","accountNumber","bankCode","bankName","sessionId","setInterval","l","heartbeat","console","log","err","warn","_stopProximityBroadcast","unregister","catch","_validateRequest","req","AGE_LIMIT","Date","now","timestamp","raw","getItem","blocked","JSON","parse","includes","senderId","amount","recent","isDuplicate","some","r","Math","abs","setItem","stringify","slice","_handleIncomingRequest","deviceId","senderName","currency","isValid","sendPaymentResponse","accepted","vibrate","fpRequest","requestId","sender","deviceName","toISOString","onPaymentRequest","FPEngine","initialize","apiKey","user","options","callbacks","baseUrl","environment","displayName","bluetoothDisplayName","initializeWithUserInfo","userId","allSettled","startAdvertising","addEventListener","next","deviceConnection","connectToDevice","startListening","listenForPaymentRequests","stopListening","acceptPaymentRequest","request","transactionId","random","toString","substr","response","accountDetails","undefined","requestTimestamp","getTime","tx","id","reference","type","channel","status","createdAt","onPaymentReceived","onError","declinePaymentRequest","onPaymentDeclined","scanForBluetoothDevices","onDeviceFound","durationMs","scanForDevices","sendBluetoothPaymentRequest","sendPaymentRequest","generateAccount","generate","showSend","showReceive","getUser","isReady","getCallbacks","destroy","stopAdvertising","remove","clear"],"sourceRoot":"../../../src","sources":["engine/FPEngine.ts"],"mappings":"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","ignoreList":[]}
|