toss-expo-sdk 0.1.1 → 1.0.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/README.md +490 -81
- package/lib/module/ble.js +59 -4
- package/lib/module/ble.js.map +1 -1
- package/lib/module/client/BLETransactionHandler.js +277 -0
- package/lib/module/client/BLETransactionHandler.js.map +1 -0
- package/lib/module/client/NonceAccountManager.js +364 -0
- package/lib/module/client/NonceAccountManager.js.map +1 -0
- package/lib/module/client/TossClient.js +27 -44
- package/lib/module/client/TossClient.js.map +1 -1
- package/lib/module/contexts/WalletContext.js +4 -4
- package/lib/module/contexts/WalletContext.js.map +1 -1
- package/lib/module/discovery.js +35 -8
- package/lib/module/discovery.js.map +1 -1
- package/lib/module/examples/offlinePaymentFlow.js +27 -2
- package/lib/module/examples/offlinePaymentFlow.js.map +1 -1
- package/lib/module/hooks/useOfflineBLETransactions.js +314 -0
- package/lib/module/hooks/useOfflineBLETransactions.js.map +1 -0
- package/lib/module/index.js +13 -8
- package/lib/module/index.js.map +1 -1
- package/lib/module/intent.js +198 -0
- package/lib/module/intent.js.map +1 -1
- package/lib/module/nfc.js +1 -1
- package/lib/module/noise.js +176 -1
- package/lib/module/noise.js.map +1 -1
- package/lib/module/reconciliation.js +155 -0
- package/lib/module/reconciliation.js.map +1 -1
- package/lib/module/services/authService.js +164 -1
- package/lib/module/services/authService.js.map +1 -1
- package/lib/module/storage/secureStorage.js +102 -0
- package/lib/module/storage/secureStorage.js.map +1 -1
- package/lib/module/storage.js +4 -4
- package/lib/module/sync.js +25 -1
- package/lib/module/sync.js.map +1 -1
- package/lib/module/types/nonceAccount.js +2 -0
- package/lib/module/types/nonceAccount.js.map +1 -0
- package/lib/module/types/tossUser.js +16 -1
- package/lib/module/types/tossUser.js.map +1 -1
- package/lib/typescript/src/__tests__/solana-program-simple.test.d.ts +8 -0
- package/lib/typescript/src/__tests__/solana-program-simple.test.d.ts.map +1 -0
- package/lib/typescript/src/ble.d.ts +31 -2
- package/lib/typescript/src/ble.d.ts.map +1 -1
- package/lib/typescript/src/client/BLETransactionHandler.d.ts +98 -0
- package/lib/typescript/src/client/BLETransactionHandler.d.ts.map +1 -0
- package/lib/typescript/src/client/NonceAccountManager.d.ts +82 -0
- package/lib/typescript/src/client/NonceAccountManager.d.ts.map +1 -0
- package/lib/typescript/src/client/TossClient.d.ts +10 -12
- package/lib/typescript/src/client/TossClient.d.ts.map +1 -1
- package/lib/typescript/src/discovery.d.ts +8 -2
- package/lib/typescript/src/discovery.d.ts.map +1 -1
- package/lib/typescript/src/examples/offlinePaymentFlow.d.ts +9 -1
- package/lib/typescript/src/examples/offlinePaymentFlow.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useOfflineBLETransactions.d.ts +91 -0
- package/lib/typescript/src/hooks/useOfflineBLETransactions.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +11 -4
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/intent.d.ts +26 -0
- package/lib/typescript/src/intent.d.ts.map +1 -1
- package/lib/typescript/src/noise.d.ts +62 -0
- package/lib/typescript/src/noise.d.ts.map +1 -1
- package/lib/typescript/src/reconciliation.d.ts +6 -0
- package/lib/typescript/src/reconciliation.d.ts.map +1 -1
- package/lib/typescript/src/services/authService.d.ts +26 -1
- package/lib/typescript/src/services/authService.d.ts.map +1 -1
- package/lib/typescript/src/storage/secureStorage.d.ts +16 -0
- package/lib/typescript/src/storage/secureStorage.d.ts.map +1 -1
- package/lib/typescript/src/sync.d.ts +6 -1
- package/lib/typescript/src/sync.d.ts.map +1 -1
- package/lib/typescript/src/types/nonceAccount.d.ts +59 -0
- package/lib/typescript/src/types/nonceAccount.d.ts.map +1 -0
- package/lib/typescript/src/types/tossUser.d.ts +16 -0
- package/lib/typescript/src/types/tossUser.d.ts.map +1 -1
- package/package.json +12 -1
- package/src/__tests__/reconciliation.test.tsx +7 -1
- package/src/__tests__/solana-program-simple.test.ts +256 -0
- package/src/ble.ts +105 -4
- package/src/client/BLETransactionHandler.ts +364 -0
- package/src/client/NonceAccountManager.ts +444 -0
- package/src/client/TossClient.ts +36 -49
- package/src/contexts/WalletContext.tsx +4 -4
- package/src/discovery.ts +46 -8
- package/src/examples/offlinePaymentFlow.ts +48 -2
- package/src/hooks/useOfflineBLETransactions.ts +438 -0
- package/src/index.tsx +49 -7
- package/src/intent.ts +254 -0
- package/src/nfc.ts +4 -4
- package/src/noise.ts +239 -1
- package/src/reconciliation.ts +184 -0
- package/src/services/authService.ts +188 -1
- package/src/storage/secureStorage.ts +142 -4
- package/src/storage.ts +4 -4
- package/src/sync.ts +40 -0
- package/src/types/nonceAccount.ts +75 -0
- package/src/types/tossUser.ts +35 -2
package/lib/module/ble.js
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
// src/ble.ts
|
|
4
4
|
import { BleManager } from 'react-native-ble-plx';
|
|
5
5
|
import { PermissionsAndroid, Platform } from 'react-native';
|
|
6
|
+
import { BLETransactionHandler } from "./client/BLETransactionHandler.js";
|
|
6
7
|
const SERVICE_UUID = '0000ff00-0000-1000-8000-00805f9b34fb';
|
|
7
8
|
const USER_CHARACTERISTIC = '0000ff01-0000-1000-8000-00805f9b34fb';
|
|
8
9
|
const INTENT_CHARACTERISTIC = '0000ff02-0000-1000-8000-00805f9b34fb';
|
|
10
|
+
const OFFLINE_TX_CHARACTERISTIC = '0000ff03-0000-1000-8000-00805f9b34fb'; // New for offline transactions
|
|
11
|
+
|
|
9
12
|
const manager = new BleManager();
|
|
13
|
+
const bleTransactionHandler = new BLETransactionHandler(Platform.OS === 'ios' ? 'ios' : 'android');
|
|
10
14
|
export async function requestBLEPermissions() {
|
|
11
15
|
if (Platform.OS === 'android') {
|
|
12
16
|
await PermissionsAndroid.requestMultiple([PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN, PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT, PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION]);
|
|
@@ -21,7 +25,7 @@ async function connect(device) {
|
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
// Scan for BLE devices advertising TOSS service
|
|
24
|
-
export function startTossScan(onUserFound, onIntentFound) {
|
|
28
|
+
export function startTossScan(onUserFound, onIntentFound, onOfflineTransactionFound) {
|
|
25
29
|
manager.startDeviceScan([SERVICE_UUID], null, async (error, device) => {
|
|
26
30
|
if (error) {
|
|
27
31
|
console.warn('BLE scan error', error.message);
|
|
@@ -45,6 +49,20 @@ export function startTossScan(onUserFound, onIntentFound) {
|
|
|
45
49
|
const intent = JSON.parse(intentData.value);
|
|
46
50
|
onIntentFound(intent, device);
|
|
47
51
|
}
|
|
52
|
+
|
|
53
|
+
// Check for offline transaction data (fragmented)
|
|
54
|
+
if (onOfflineTransactionFound) {
|
|
55
|
+
try {
|
|
56
|
+
const txData = await services.readCharacteristicForService(device.id, SERVICE_UUID, OFFLINE_TX_CHARACTERISTIC);
|
|
57
|
+
if (txData?.value) {
|
|
58
|
+
const tx = JSON.parse(txData.value);
|
|
59
|
+
onOfflineTransactionFound(tx, device);
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
// Offline TX characteristic may not be available
|
|
63
|
+
console.debug('Offline transaction characteristic not found');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
48
66
|
} catch (err) {
|
|
49
67
|
console.warn('Error reading device data:', err);
|
|
50
68
|
}
|
|
@@ -96,8 +114,45 @@ export async function sendIntentToDevice(deviceId, intent) {
|
|
|
96
114
|
await device.cancelConnection();
|
|
97
115
|
}
|
|
98
116
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Send fragmented offline transaction over BLE with Noise Protocol encryption
|
|
119
|
+
* Automatically handles MTU limitations and retries
|
|
120
|
+
*/
|
|
121
|
+
export async function sendOfflineTransactionFragmented(device, transaction, noiseEncryptFn, isIntent = false) {
|
|
122
|
+
try {
|
|
123
|
+
const result = await bleTransactionHandler.sendFragmentedTransactionBLE(device, transaction, async (deviceId, charUUID, data) => {
|
|
124
|
+
const dev = await manager.connectToDevice(deviceId);
|
|
125
|
+
await dev.discoverAllServicesAndCharacteristics();
|
|
126
|
+
const characteristic = charUUID === OFFLINE_TX_CHARACTERISTIC ? OFFLINE_TX_CHARACTERISTIC : INTENT_CHARACTERISTIC;
|
|
127
|
+
await dev.writeCharacteristicWithResponseForService(deviceId, SERVICE_UUID, characteristic, data.toString('base64'));
|
|
128
|
+
await dev.cancelConnection();
|
|
129
|
+
}, noiseEncryptFn, isIntent);
|
|
130
|
+
return result;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
133
|
+
console.error('Failed to send offline transaction:', errorMessage);
|
|
134
|
+
throw new Error(`BLE transmission failed: ${errorMessage}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Receive and reassemble fragmented message from BLE
|
|
140
|
+
*/
|
|
141
|
+
export async function receiveOfflineTransactionFragment(fragment, noiseDecryptFn) {
|
|
142
|
+
return bleTransactionHandler.receiveFragmentedMessage(fragment, noiseDecryptFn);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get current BLE MTU configuration
|
|
147
|
+
*/
|
|
148
|
+
export function getBLEMTUConfig() {
|
|
149
|
+
return bleTransactionHandler.getMTUConfig();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Set custom BLE MTU configuration
|
|
154
|
+
*/
|
|
155
|
+
export function setBLEMTUConfig(config) {
|
|
156
|
+
bleTransactionHandler.setMTUConfig(config);
|
|
102
157
|
}
|
|
103
158
|
//# sourceMappingURL=ble.js.map
|
package/lib/module/ble.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["BleManager","PermissionsAndroid","Platform","SERVICE_UUID","USER_CHARACTERISTIC","INTENT_CHARACTERISTIC","manager","
|
|
1
|
+
{"version":3,"names":["BleManager","PermissionsAndroid","Platform","BLETransactionHandler","SERVICE_UUID","USER_CHARACTERISTIC","INTENT_CHARACTERISTIC","OFFLINE_TX_CHARACTERISTIC","manager","bleTransactionHandler","OS","requestBLEPermissions","requestMultiple","PERMISSIONS","BLUETOOTH_SCAN","BLUETOOTH_CONNECT","ACCESS_FINE_LOCATION","connect","device","connectedDevice","connectToDevice","id","discoverAllServicesAndCharacteristics","startTossScan","onUserFound","onIntentFound","onOfflineTransactionFound","startDeviceScan","error","console","warn","message","services","userData","readCharacteristicForService","value","user","JSON","parse","intentData","intent","txData","tx","debug","err","State","advertiseUser","subscription","onStateChange","state","PoweredOn","log","userId","remove","errorMessage","Error","String","stopAdvertising","stopDeviceScan","sendIntentToDevice","deviceId","jsonIntent","stringify","writeCharacteristicWithResponseForService","Buffer","from","toString","cancelConnection","sendOfflineTransactionFragmented","transaction","noiseEncryptFn","isIntent","result","sendFragmentedTransactionBLE","charUUID","data","dev","characteristic","receiveOfflineTransactionFragment","fragment","noiseDecryptFn","receiveFragmentedMessage","getBLEMTUConfig","getMTUConfig","setBLEMTUConfig","config","setMTUConfig"],"sourceRoot":"../../src","sources":["ble.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* BLE MTU Configuration for different device types
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Default MTU configurations
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_MTU_CONFIGS = {
|
|
11
|
+
android: {
|
|
12
|
+
maxPayloadSize: 512,
|
|
13
|
+
// Typical Android BLE MTU
|
|
14
|
+
chunkSize: 480,
|
|
15
|
+
// Conservative chunk size
|
|
16
|
+
maxRetries: 3,
|
|
17
|
+
timeout: 5000
|
|
18
|
+
},
|
|
19
|
+
ios: {
|
|
20
|
+
maxPayloadSize: 512,
|
|
21
|
+
// iOS BLE MTU
|
|
22
|
+
chunkSize: 480,
|
|
23
|
+
maxRetries: 3,
|
|
24
|
+
timeout: 5000
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Represents a fragmented message with header information
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Represents a Noise-encrypted BLE message
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* BLETransactionHandler
|
|
38
|
+
* Manages secure, fragmented BLE transmission of offline transactions
|
|
39
|
+
* with Noise Protocol encryption
|
|
40
|
+
*/
|
|
41
|
+
export class BLETransactionHandler {
|
|
42
|
+
fragmentCache = new Map();
|
|
43
|
+
messageIdMap = new Map();
|
|
44
|
+
constructor(platform = 'android') {
|
|
45
|
+
this.mtuConfig = DEFAULT_MTU_CONFIGS[platform] || DEFAULT_MTU_CONFIGS.android;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Fragment a large transaction/intent into BLE-safe chunks
|
|
50
|
+
* Respects MTU limitations and adds framing information
|
|
51
|
+
*/
|
|
52
|
+
fragmentTransaction(transaction, isIntent = false) {
|
|
53
|
+
const payload = Buffer.from(JSON.stringify(transaction), 'utf-8');
|
|
54
|
+
const messageId = `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
55
|
+
const totalFragments = Math.ceil(payload.length / this.mtuConfig.chunkSize);
|
|
56
|
+
const fragments = [];
|
|
57
|
+
for (let i = 0; i < totalFragments; i++) {
|
|
58
|
+
const start = i * this.mtuConfig.chunkSize;
|
|
59
|
+
const end = Math.min(start + this.mtuConfig.chunkSize, payload.length);
|
|
60
|
+
const chunk = payload.slice(start, end);
|
|
61
|
+
const fragment = {
|
|
62
|
+
messageId,
|
|
63
|
+
sequenceNumber: i,
|
|
64
|
+
totalFragments,
|
|
65
|
+
checksumValue: this.calculateCRC32(chunk),
|
|
66
|
+
payload: chunk
|
|
67
|
+
};
|
|
68
|
+
fragments.push(fragment);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Store fragments for reassembly on receiver end
|
|
72
|
+
this.fragmentCache.set(messageId, fragments);
|
|
73
|
+
this.messageIdMap.set(messageId, isIntent ? transaction : transaction);
|
|
74
|
+
return fragments;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Prepare encrypted BLE message for transmission
|
|
79
|
+
* Uses Noise Protocol for end-to-end encryption
|
|
80
|
+
*/
|
|
81
|
+
async prepareEncryptedMessage(fragment, noiseEncryptFn) {
|
|
82
|
+
// Serialize fragment
|
|
83
|
+
const fragmentData = this.serializeFragment(fragment);
|
|
84
|
+
|
|
85
|
+
// Encrypt using Noise Protocol
|
|
86
|
+
const encrypted = await noiseEncryptFn(fragmentData);
|
|
87
|
+
return encrypted;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Send fragmented transaction over BLE with encryption
|
|
92
|
+
* Handles retries and verification
|
|
93
|
+
*/
|
|
94
|
+
async sendFragmentedTransactionBLE(device, transaction, sendFn, noiseEncryptFn, isIntent = false) {
|
|
95
|
+
const fragments = this.fragmentTransaction(transaction, isIntent);
|
|
96
|
+
const messageId = fragments[0]?.messageId;
|
|
97
|
+
const failedFragments = [];
|
|
98
|
+
if (!messageId) {
|
|
99
|
+
throw new Error('Failed to generate message ID for transaction');
|
|
100
|
+
}
|
|
101
|
+
const CHARACTERISTIC_UUID = '0000ff02-0000-1000-8000-00805f9b34fb'; // Intent characteristic
|
|
102
|
+
|
|
103
|
+
for (const fragment of fragments) {
|
|
104
|
+
let retries = 0;
|
|
105
|
+
let sent = false;
|
|
106
|
+
while (retries < this.mtuConfig.maxRetries && !sent) {
|
|
107
|
+
try {
|
|
108
|
+
let messageData;
|
|
109
|
+
if (noiseEncryptFn) {
|
|
110
|
+
// Encrypt fragment using Noise Protocol
|
|
111
|
+
const encrypted = await this.prepareEncryptedMessage(fragment, noiseEncryptFn);
|
|
112
|
+
messageData = Buffer.from(JSON.stringify(encrypted), 'utf-8');
|
|
113
|
+
} else {
|
|
114
|
+
// Send unencrypted (not recommended)
|
|
115
|
+
messageData = Buffer.from(JSON.stringify(fragment), 'utf-8');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Send via BLE
|
|
119
|
+
await sendFn(device.id, CHARACTERISTIC_UUID, messageData);
|
|
120
|
+
sent = true;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
retries++;
|
|
123
|
+
console.warn(`Failed to send fragment ${fragment.sequenceNumber}, retry ${retries}:`, error);
|
|
124
|
+
if (retries >= this.mtuConfig.maxRetries) {
|
|
125
|
+
failedFragments.push(fragment.sequenceNumber);
|
|
126
|
+
} else {
|
|
127
|
+
// Exponential backoff
|
|
128
|
+
await this.delay(Math.pow(2, retries) * 100);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
success: failedFragments.length === 0,
|
|
135
|
+
sentFragments: fragments.length - failedFragments.length,
|
|
136
|
+
failedFragments,
|
|
137
|
+
messageId
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Receive and reassemble fragmented messages
|
|
143
|
+
*/
|
|
144
|
+
async receiveFragmentedMessage(fragment, _noiseDecryptFn) {
|
|
145
|
+
const messageId = fragment.messageId;
|
|
146
|
+
|
|
147
|
+
// Initialize or retrieve fragment cache
|
|
148
|
+
if (!this.fragmentCache.has(messageId)) {
|
|
149
|
+
this.fragmentCache.set(messageId, []);
|
|
150
|
+
}
|
|
151
|
+
const cachedFragments = this.fragmentCache.get(messageId);
|
|
152
|
+
cachedFragments[fragment.sequenceNumber] = fragment;
|
|
153
|
+
const progress = {
|
|
154
|
+
received: cachedFragments.filter(f => f !== undefined).length,
|
|
155
|
+
total: fragment.totalFragments
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Check if all fragments received
|
|
159
|
+
if (progress.received < fragment.totalFragments) {
|
|
160
|
+
return {
|
|
161
|
+
complete: false,
|
|
162
|
+
progress
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Reassemble message
|
|
167
|
+
const reassembled = this.reassembleMessage(cachedFragments);
|
|
168
|
+
if (!reassembled) {
|
|
169
|
+
return {
|
|
170
|
+
complete: false,
|
|
171
|
+
progress
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
// Parse transaction
|
|
176
|
+
const transactionData = JSON.parse(reassembled);
|
|
177
|
+
const transaction = transactionData;
|
|
178
|
+
|
|
179
|
+
// Cleanup cache
|
|
180
|
+
this.fragmentCache.delete(messageId);
|
|
181
|
+
this.messageIdMap.delete(messageId);
|
|
182
|
+
return {
|
|
183
|
+
complete: true,
|
|
184
|
+
transaction,
|
|
185
|
+
progress
|
|
186
|
+
};
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.error('Failed to parse reassembled message:', error);
|
|
189
|
+
return {
|
|
190
|
+
complete: false,
|
|
191
|
+
progress
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Reassemble fragments into original message
|
|
198
|
+
*/
|
|
199
|
+
reassembleMessage(fragments) {
|
|
200
|
+
try {
|
|
201
|
+
// Sort by sequence number
|
|
202
|
+
const sorted = fragments.sort((a, b) => a.sequenceNumber - b.sequenceNumber);
|
|
203
|
+
|
|
204
|
+
// Verify all fragments present and checksums
|
|
205
|
+
for (const fragment of sorted) {
|
|
206
|
+
const calculatedChecksum = this.calculateCRC32(fragment.payload);
|
|
207
|
+
if (calculatedChecksum !== fragment.checksumValue) {
|
|
208
|
+
console.warn(`Checksum mismatch for fragment ${fragment.sequenceNumber}`);
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Concatenate payloads
|
|
214
|
+
const combined = Buffer.concat(sorted.map(f => Buffer.from(f.payload)));
|
|
215
|
+
return combined.toString('utf-8');
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.error('Failed to reassemble message:', error);
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Serialize BLE fragment for transmission
|
|
224
|
+
*/
|
|
225
|
+
serializeFragment(fragment) {
|
|
226
|
+
const data = {
|
|
227
|
+
messageId: fragment.messageId,
|
|
228
|
+
sequenceNumber: fragment.sequenceNumber,
|
|
229
|
+
totalFragments: fragment.totalFragments,
|
|
230
|
+
checksumValue: fragment.checksumValue,
|
|
231
|
+
payload: Array.from(fragment.payload)
|
|
232
|
+
};
|
|
233
|
+
return new Uint8Array(Buffer.from(JSON.stringify(data), 'utf-8'));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Calculate CRC32 checksum for fragment verification
|
|
238
|
+
*/
|
|
239
|
+
calculateCRC32(data) {
|
|
240
|
+
let crc = 0xffffffff;
|
|
241
|
+
for (let i = 0; i < data.length; i++) {
|
|
242
|
+
const byte = data[i];
|
|
243
|
+
if (byte !== undefined) {
|
|
244
|
+
crc = crc ^ byte;
|
|
245
|
+
for (let j = 0; j < 8; j++) {
|
|
246
|
+
crc = crc >>> 1 ^ (crc & 1 ? 0xedb88320 : 0);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Delay utility for retries
|
|
255
|
+
*/
|
|
256
|
+
delay(ms) {
|
|
257
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Get MTU configuration
|
|
262
|
+
*/
|
|
263
|
+
getMTUConfig() {
|
|
264
|
+
return this.mtuConfig;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Set custom MTU configuration
|
|
269
|
+
*/
|
|
270
|
+
setMTUConfig(config) {
|
|
271
|
+
this.mtuConfig = {
|
|
272
|
+
...this.mtuConfig,
|
|
273
|
+
...config
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=BLETransactionHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DEFAULT_MTU_CONFIGS","android","maxPayloadSize","chunkSize","maxRetries","timeout","ios","BLETransactionHandler","fragmentCache","Map","messageIdMap","constructor","platform","mtuConfig","fragmentTransaction","transaction","isIntent","payload","Buffer","from","JSON","stringify","messageId","Date","now","Math","random","toString","substr","totalFragments","ceil","length","fragments","i","start","end","min","chunk","slice","fragment","sequenceNumber","checksumValue","calculateCRC32","push","set","prepareEncryptedMessage","noiseEncryptFn","fragmentData","serializeFragment","encrypted","sendFragmentedTransactionBLE","device","sendFn","failedFragments","Error","CHARACTERISTIC_UUID","retries","sent","messageData","id","error","console","warn","delay","pow","success","sentFragments","receiveFragmentedMessage","_noiseDecryptFn","has","cachedFragments","get","progress","received","filter","f","undefined","total","complete","reassembled","reassembleMessage","transactionData","parse","delete","sorted","sort","a","b","calculatedChecksum","combined","concat","map","data","Array","Uint8Array","crc","byte","j","ms","Promise","resolve","setTimeout","getMTUConfig","setMTUConfig","config"],"sourceRoot":"../../../src","sources":["client/BLETransactionHandler.ts"],"mappings":"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","ignoreList":[]}
|