toss-expo-sdk 0.1.2 → 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.
Files changed (73) hide show
  1. package/README.md +368 -15
  2. package/lib/module/ble.js +59 -4
  3. package/lib/module/ble.js.map +1 -1
  4. package/lib/module/client/BLETransactionHandler.js +277 -0
  5. package/lib/module/client/BLETransactionHandler.js.map +1 -0
  6. package/lib/module/client/NonceAccountManager.js +364 -0
  7. package/lib/module/client/NonceAccountManager.js.map +1 -0
  8. package/lib/module/client/TossClient.js +1 -1
  9. package/lib/module/client/TossClient.js.map +1 -1
  10. package/lib/module/hooks/useOfflineBLETransactions.js +314 -0
  11. package/lib/module/hooks/useOfflineBLETransactions.js.map +1 -0
  12. package/lib/module/index.js +12 -8
  13. package/lib/module/index.js.map +1 -1
  14. package/lib/module/intent.js +129 -0
  15. package/lib/module/intent.js.map +1 -1
  16. package/lib/module/noise.js +175 -0
  17. package/lib/module/noise.js.map +1 -1
  18. package/lib/module/reconciliation.js +155 -0
  19. package/lib/module/reconciliation.js.map +1 -1
  20. package/lib/module/services/authService.js +164 -1
  21. package/lib/module/services/authService.js.map +1 -1
  22. package/lib/module/storage/secureStorage.js +102 -0
  23. package/lib/module/storage/secureStorage.js.map +1 -1
  24. package/lib/module/sync.js +25 -1
  25. package/lib/module/sync.js.map +1 -1
  26. package/lib/module/types/nonceAccount.js +2 -0
  27. package/lib/module/types/nonceAccount.js.map +1 -0
  28. package/lib/module/types/tossUser.js +16 -1
  29. package/lib/module/types/tossUser.js.map +1 -1
  30. package/lib/typescript/src/__tests__/solana-program-simple.test.d.ts +8 -0
  31. package/lib/typescript/src/__tests__/solana-program-simple.test.d.ts.map +1 -0
  32. package/lib/typescript/src/ble.d.ts +31 -2
  33. package/lib/typescript/src/ble.d.ts.map +1 -1
  34. package/lib/typescript/src/client/BLETransactionHandler.d.ts +98 -0
  35. package/lib/typescript/src/client/BLETransactionHandler.d.ts.map +1 -0
  36. package/lib/typescript/src/client/NonceAccountManager.d.ts +82 -0
  37. package/lib/typescript/src/client/NonceAccountManager.d.ts.map +1 -0
  38. package/lib/typescript/src/hooks/useOfflineBLETransactions.d.ts +91 -0
  39. package/lib/typescript/src/hooks/useOfflineBLETransactions.d.ts.map +1 -0
  40. package/lib/typescript/src/index.d.ts +9 -4
  41. package/lib/typescript/src/index.d.ts.map +1 -1
  42. package/lib/typescript/src/intent.d.ts +15 -0
  43. package/lib/typescript/src/intent.d.ts.map +1 -1
  44. package/lib/typescript/src/noise.d.ts +62 -0
  45. package/lib/typescript/src/noise.d.ts.map +1 -1
  46. package/lib/typescript/src/reconciliation.d.ts +6 -0
  47. package/lib/typescript/src/reconciliation.d.ts.map +1 -1
  48. package/lib/typescript/src/services/authService.d.ts +26 -1
  49. package/lib/typescript/src/services/authService.d.ts.map +1 -1
  50. package/lib/typescript/src/storage/secureStorage.d.ts +16 -0
  51. package/lib/typescript/src/storage/secureStorage.d.ts.map +1 -1
  52. package/lib/typescript/src/sync.d.ts +6 -1
  53. package/lib/typescript/src/sync.d.ts.map +1 -1
  54. package/lib/typescript/src/types/nonceAccount.d.ts +59 -0
  55. package/lib/typescript/src/types/nonceAccount.d.ts.map +1 -0
  56. package/lib/typescript/src/types/tossUser.d.ts +16 -0
  57. package/lib/typescript/src/types/tossUser.d.ts.map +1 -1
  58. package/package.json +1 -1
  59. package/src/__tests__/solana-program-simple.test.ts +256 -0
  60. package/src/ble.ts +105 -4
  61. package/src/client/BLETransactionHandler.ts +364 -0
  62. package/src/client/NonceAccountManager.ts +444 -0
  63. package/src/client/TossClient.ts +1 -1
  64. package/src/hooks/useOfflineBLETransactions.ts +438 -0
  65. package/src/index.tsx +40 -6
  66. package/src/intent.ts +166 -0
  67. package/src/noise.ts +238 -0
  68. package/src/reconciliation.ts +184 -0
  69. package/src/services/authService.ts +188 -1
  70. package/src/storage/secureStorage.ts +138 -0
  71. package/src/sync.ts +40 -0
  72. package/src/types/nonceAccount.ts +75 -0
  73. package/src/types/tossUser.ts +35 -2
package/README.md CHANGED
@@ -1,31 +1,39 @@
1
1
  # TOSS Expo SDK
2
2
 
3
- **TOSS (The Offline Solana Stack)** is a robust, production-ready SDK for building offline-capable Solana applications with secure local transport and delayed on-chain settlement.
3
+ **TOSS (The Offline Solana Stack)** implements the complete [TOSS Technical Paper](./TOSS_PAPER_IMPLEMENTATION_VERIFICATION.md) — a protocol-correct approach to building offline-first Solana applications without compromising security or finality guarantees.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/toss-expo-sdk)](https://www.npmjs.com/package/toss-expo-sdk)
6
6
  [![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
7
7
 
8
+ **Solana, extended.** TOSS introduces deterministic separation between transaction intent creation and onchain settlement, enabling applications to function seamlessly in disconnected environments while preserving Solana's security model.
9
+
8
10
  ## 🚀 Features
9
11
 
10
12
  ### Core Capabilities
11
13
 
12
14
  - **Offline-First Architecture**: Create and process transactions without immediate network access
13
- - **Secure Wallet Integration**: Built-in wallet management with support for multiple keypairs
14
- - **Durable Transactions**: Nonce-based transaction handling for reliability
15
+ - **Durable Nonce Accounts**: Replay-protected offline transactions with automatic expiry handling
16
+ - **Secure Wallet Integration**: Built-in wallet management with biometric protection
17
+ - **BLE Transaction Transmission**: MTU-aware message fragmentation with automatic retry
18
+ - **End-to-End Encryption**: Noise Protocol integration for secure device-to-device communication
15
19
  - **TypeScript Support**: Full TypeScript definitions for better developer experience
16
20
 
17
21
  ### Security
18
22
 
19
- - End-to-end encryption for all transactions
20
- - Secure key management with hardware wallet support
21
- - Non-custodial by design - users maintain control of their keys
23
+ - ✅ Biometric-protected nonce accounts (mandatory)
24
+ - Hardware-backed secure key storage (Secure Enclave / Keymaster)
25
+ - Automatic replay protection with durable nonces
26
+ - ✅ Noise Protocol encryption for BLE transmission
27
+ - ✅ CRC32 checksums for fragment verification
28
+ - ✅ Non-custodial by design - users maintain control of their keys
22
29
 
23
30
  ### Developer Experience
24
31
 
25
- - Simple, intuitive API for common operations
26
- - Comprehensive error handling with detailed error codes
32
+ - Simple, intuitive API for offline transactions
33
+ - Custom React hooks for easy integration (`useOfflineTransaction`, `useBLETransactionTransmission`)
34
+ - Comprehensive error handling with detailed messages
27
35
  - Built-in retry mechanisms with exponential backoff
28
- - React hooks for easy integration with React Native components
36
+ - Automatic MTU negotiation and fragmentation
29
37
 
30
38
  ## 📦 Installation
31
39
 
@@ -39,6 +47,27 @@ yarn add toss-expo-sdk
39
47
 
40
48
  All dependencies (Solana Web3.js, Arcium, Noise Protocol, etc.) are automatically included.
41
49
 
50
+ ## 📋 System Model & Design Principles
51
+
52
+ **TOSS operates under these assumptions:**
53
+
54
+ - Devices may be **offline for arbitrary durations**
55
+ - Transport channels are **unreliable and potentially adversarial**
56
+ - Devices are **not mutually trusted**
57
+ - **Onchain state is the sole authority** for settlement
58
+ - Offline execution is limited to **cryptographically verifiable intent generation only**
59
+
60
+ **TOSS maintains these invariants:**
61
+
62
+ - ✅ Onchain state is canonical
63
+ - ✅ Offline execution never mutates global state
64
+ - ✅ All offline artifacts are cryptographically verifiable onchain
65
+ - ✅ No trusted relayers or delegated signing
66
+ - ✅ Failure is deterministic and safe
67
+ - ✅ Privacy is preserved prior to settlement
68
+
69
+ **Violation of any invariant invalidates the offline model.**
70
+
42
71
  ## 🏁 Quick Start
43
72
 
44
73
  ### Initialize the Client
@@ -164,21 +193,295 @@ function PaymentScreen() {
164
193
 
165
194
  ## Core Idea: Intent, Not Transaction
166
195
 
167
- TOSS uses an **intent-based model**.
196
+ TOSS uses an **intent-based model** that fundamentally separates cryptographic commitment from onchain execution.
168
197
 
169
198
  An **intent** is:
170
199
 
171
- - a signed declaration of what a user wants to do
172
- - transferable offline
173
- - verifiable locally
174
- - settled later on-chain
200
+ - A **signed declaration** of what a user wants to do
201
+ - **Transferable offline** via BLE, NFC, QR, or local mesh
202
+ - **Verifiable locally** without network access (signature, expiry, nonce only)
203
+ - **Settled later on-chain** where Solana enforces final state transitions
204
+
205
+ This separation allows applications to function **without connectivity** while preserving Solana's security guarantees.
206
+
207
+ ### The 4-Phase Intent Lifecycle
208
+
209
+ TOSS follows a deterministic 4-phase model (Section 4.3 of Technical Paper):
210
+
211
+ ```
212
+ ┌─────────────────────────────────────────────────────────────────┐
213
+ │ Phase 1: CREATION (Offline) │
214
+ │ • Sender constructs intent locally │
215
+ │ • Signs with native Solana keypair (Ed25519) │
216
+ │ • No network required │
217
+ └──────────────────────────┬──────────────────────────────────────┘
218
+
219
+ ┌─────────────────────────────────────────────────────────────────┐
220
+ │ Phase 2: EXCHANGE (Offline) │
221
+ │ • Signed intent transmitted via proximity (BLE/NFC/QR) │
222
+ │ • Transport integrity not trusted │
223
+ │ • Peer receives intent in untrusted environment │
224
+ └──────────────────────────┬──────────────────────────────────────┘
225
+
226
+ ┌─────────────────────────────────────────────────────────────────┐
227
+ │ Phase 3: OFFLINE VERIFICATION (Offline) │
228
+ │ • Verify signature correctness (Ed25519) │
229
+ │ • Check expiry bounds │
230
+ │ • Validate nonce (replay protection) │
231
+ │ • DEFERRED: Balance, program constraints (onchain only) │
232
+ └──────────────────────────┬──────────────────────────────────────┘
233
+
234
+ ┌─────────────────────────────────────────────────────────────────┐
235
+ │ Phase 4: SETTLEMENT (Online) │
236
+ │ • Connectivity restored │
237
+ │ • Intent submitted to Solana │
238
+ │ • Program verifies signature + state │
239
+ │ • Settlement succeeds or fails deterministically │
240
+ └─────────────────────────────────────────────────────────────────┘
241
+ ```
242
+
243
+ **Key Invariant:** At no stage does offline execution bypass Solana's runtime or programs. Final state transitions occur **exclusively on Solana**.
244
+
245
+ ---
246
+
247
+ ## 💾 Local State Management & Reconciliation
248
+
249
+ TOSS maintains an **encrypted, append-only local intent store** that enables offline operation while waiting for network connectivity.
250
+
251
+ ### What Gets Stored Locally
252
+
253
+ Each device maintains:
254
+
255
+ - **Outbound pending intents** - Intents created but not yet settled
256
+ - **Inbound received intents** - Intents from peers, awaiting verification
257
+ - **Synchronization status** - Track which intents have been submitted
258
+ - **Expiry metadata** - Automatic cleanup of expired intents
259
+
260
+ ```typescript
261
+ import {
262
+ secureStoreIntent,
263
+ getPendingIntents,
264
+ getAllSecureIntents,
265
+ } from 'toss-expo-sdk';
266
+
267
+ // Store an intent locally (encrypted in hardware secure enclave)
268
+ await secureStoreIntent(intent);
269
+
270
+ // Get all pending intents
271
+ const pending = await getPendingIntents();
272
+ console.log(`${pending.length} intents waiting for settlement`);
273
+
274
+ // Later, when online...
275
+ const allIntents = await getAllSecureIntents();
276
+ console.log(`Stored intents: ${allIntents.length}`);
277
+ ```
278
+
279
+ ### Automatic Reconciliation
280
+
281
+ When connectivity is restored, TOSS initiates **deterministic reconciliation**:
282
+
283
+ ```typescript
284
+ import { syncToChain, reconcilePendingIntents } from 'toss-expo-sdk';
285
+
286
+ // Sync all pending intents to Solana
287
+ const syncResult = await syncToChain(connection);
288
+
289
+ console.log(`Settled: ${syncResult.successfulSettlements.length}`);
290
+ console.log(`Failed: ${syncResult.failedSettlements.length}`);
291
+ console.log(`Conflicts detected: ${syncResult.detectedConflicts.length}`);
292
+ ```
293
+
294
+ **Reconciliation Steps:**
295
+
296
+ 1. ✅ Retrieve all pending intents from local storage
297
+ 2. ✅ Submit to Solana
298
+ 3. ✅ Verify signatures and state constraints onchain
299
+ 4. ✅ Deterministically reject invalid or conflicting intents
300
+ 5. ✅ Update local state with finality
301
+
302
+ **No offline state is treated as final.** Solana's verdict is authoritative.
303
+
304
+ ---
305
+
306
+ ## 🔐 Confidential Execution via Arcium (Optional)
307
+
308
+ TOSS integrates **Arcium** for confidential computation in pre-settlement stages, protecting sensitive transaction parameters before onchain execution.
309
+
310
+ ### When to Use Private Transactions
311
+
312
+ By default, intents are created as regular transactions. Use `privateTransaction: true` when:
313
+
314
+ - You want to hide **transaction amounts** from peers during exchange
315
+ - You need to hide **recipient information** before settlement
316
+ - You're working with **sensitive business logic** (payments, transfers)
317
+ - You need **pre-settlement confidentiality** without revealing intent details
318
+
319
+ ### Enabling Confidential Execution
320
+
321
+ ```typescript
322
+ import { createUserIntent, createIntent } from 'toss-expo-sdk';
323
+ import { Provider } from '@project-serum/anchor';
324
+
325
+ // Confidential intent creation
326
+ const confidentialIntent = await createUserIntent(
327
+ senderUser,
328
+ senderKeypair,
329
+ recipientUser,
330
+ amountInLamports,
331
+ connection,
332
+ {
333
+ privateTransaction: true,
334
+ mxeProgramId: new PublicKey('YOUR_MXE_PROGRAM_ID'),
335
+ provider: anchorProvider, // Anchor provider for MXE operations
336
+ expiresIn: 60 * 60, // 1 hour expiry
337
+ }
338
+ );
339
+
340
+ console.log('Intent created with Arcium encryption');
341
+ console.log(`Encrypted data: ${confidentialIntent.encrypted?.ciphertext}`);
342
+ ```
343
+
344
+ ### How It Works
175
345
 
176
- This separation allows applications to function **without connectivity** while preserving Solana’s security guarantees.
346
+ 1. **Pre-Creation:** Construct intent with plaintext values
347
+ 2. **Encryption:** Amount and metadata encrypted with Arcium
348
+ 3. **Storage:** Encrypted intent stored locally
349
+ 4. **Exchange:** Encrypted parameters transmitted (peer cannot decrypt)
350
+ 5. **Settlement:** Solana program decrypts and executes (onchain verification)
351
+
352
+ ### Security Model
353
+
354
+ - **Encryption scope:** Optional (amount, metadata)
355
+ - **Key management:** Arcium handles encryption/decryption
356
+ - **Signature:** Intent signature covers plaintext (authenticity verified before decryption)
357
+ - **Onchain verification:** Only Solana MXE program can decrypt and validate
358
+
359
+ **Important:** Arcium encryption is **optional** and operates strictly before onchain execution. It does **not** alter Solana's trust model — the blockchain remains the final authority.
360
+
361
+ ---
362
+
363
+ TOSS now includes **production-ready offline transaction support** using Solana's durable nonce accounts with biometric protection.
364
+
365
+ ### Quick Start: Offline Transactions
366
+
367
+ ```typescript
368
+ import {
369
+ useOfflineTransaction,
370
+ useBLETransactionTransmission,
371
+ useNonceAccountManagement,
372
+ createOfflineIntent,
373
+ AuthService,
374
+ } from 'toss-expo-sdk';
375
+ import { SystemProgram } from '@solana/web3.js';
376
+
377
+ // Step 1: Create nonce account (requires biometric)
378
+ const updatedUser = await AuthService.createSecureNonceAccount(
379
+ user,
380
+ connection,
381
+ userKeypair
382
+ );
383
+
384
+ // Step 2: Create offline transaction using custom hook
385
+ const { createOfflineTransaction } = useOfflineTransaction(user, connection);
386
+
387
+ const offlineTx = await createOfflineTransaction([
388
+ SystemProgram.transfer({
389
+ fromPubkey: user.wallet.publicKey,
390
+ toPubkey: recipientAddress,
391
+ lamports: amount,
392
+ }),
393
+ ]);
394
+
395
+ // Step 3: Send via BLE with automatic fragmentation
396
+ const { sendTransactionBLE } = useBLETransactionTransmission('ios');
397
+
398
+ const result = await sendTransactionBLE(
399
+ bleDevice,
400
+ offlineTx,
401
+ noiseEncryptFn, // Optional Noise Protocol encryption
402
+ false // This is a transaction, not an intent
403
+ );
404
+
405
+ console.log(`Sent ${result.sentFragments}/${result.totalFragments} fragments`);
406
+ ```
407
+
408
+ ### Key Features
409
+
410
+ **Biometric Protection**
411
+
412
+ - ✅ All nonce operations require biometric authentication
413
+ - ✅ Private keys stored in device's secure enclave (iOS Secure Enclave / Android Keymaster)
414
+ - ✅ User cannot export or backup private keys
415
+
416
+ **Replay Protection**
417
+
418
+ - ✅ Each transaction uses a unique, incrementing nonce from the blockchain
419
+ - ✅ Nonce values automatically validated before transaction execution
420
+ - ✅ Expired nonces automatically detected and rejected
421
+
422
+ **BLE Transmission**
423
+
424
+ - ✅ Automatic MTU-aware message fragmentation
425
+ - ✅ CRC32 checksum verification for each fragment
426
+ - ✅ Automatic retry with exponential backoff
427
+ - ✅ Noise Protocol encryption support
428
+
429
+ **Storage & Renewal**
430
+
431
+ - ✅ Nonce accounts cached efficiently in memory
432
+ - ✅ Automatic renewal from blockchain
433
+ - ✅ Graceful expiry handling with status tracking
434
+
435
+ ### Detailed Guide
436
+
437
+ For comprehensive documentation, guides, and advanced usage examples, see [OFFLINE_TRANSACTIONS_GUIDE.md](./OFFLINE_TRANSACTIONS_GUIDE.md).
438
+
439
+ Topics covered:
440
+
441
+ - Architecture overview
442
+ - Setup guide with step-by-step examples
443
+ - Custom React hooks API reference
444
+ - Noise Protocol integration
445
+ - Security considerations
446
+ - Error handling patterns
447
+ - Testing strategies
448
+ - Migration guide from previous versions
177
449
 
178
450
  ---
179
451
 
180
452
  ## 🔒 Security
181
453
 
454
+ ### TOSS Security Guarantees
455
+
456
+ TOSS guarantees (per Technical Paper, Section 13):
457
+
458
+ 1. **No Unauthorized Signing**
459
+ - Only users with access to their private keys can create intents
460
+ - Ed25519 signatures cannot be forged
461
+ - Biometric protection for nonce accounts (mandatory)
462
+
463
+ 2. **No Offline State Mutation**
464
+ - Offline operations only create local intents (append-only store)
465
+ - No global state changes until onchain settlement
466
+ - Solana remains the sole authority for state transitions
467
+
468
+ 3. **No Forced Execution**
469
+ - Signers can choose whether to submit intents
470
+ - Intents can be rejected before settlement
471
+ - Both parties must verify before committing to offline transfer
472
+
473
+ 4. **Deterministic Settlement**
474
+ - Settlement outcomes are deterministic based on onchain state
475
+ - Conflict resolution is deterministic (nonce + timestamp)
476
+ - Failures are safe and recoverable
477
+
478
+ 5. **Confidential Pre-Settlement Handling**
479
+ - Optional Arcium encryption before submission
480
+ - Private transaction metadata protected from peers
481
+ - Onchain verification ensures integrity
482
+
483
+ **Important:** Offline capability does **not** expand Solana's attack surface. All security guarantees come from cryptography and onchain verification, not the offline layer.
484
+
182
485
  ### Best Practices
183
486
 
184
487
  1. Always verify transaction details before signing
@@ -330,6 +633,56 @@ const activePeers = discovery.getActivePeers();
330
633
  console.log(`${activePeers.length} active peers nearby`);
331
634
  ```
332
635
 
636
+ ## ⚠️ Understanding TOSS Limitations
637
+
638
+ TOSS is designed to fail safely. The following limitations are **by design** and fundamental to any offline system:
639
+
640
+ ### What TOSS Does NOT Do
641
+
642
+ ❌ **Does not resolve offline double-spend**
643
+
644
+ - Multiple devices can create conflicting intents offline
645
+ - Conflicts are resolved deterministically onchain (first valid intent wins)
646
+ - You must verify transaction details before committing to offline transfer
647
+
648
+ ❌ **Does not guarantee settlement success**
649
+
650
+ - Intents may fail onchain due to insufficient balance, nonce violations, or expired intents
651
+ - Settlement is deterministic but failures can occur
652
+ - Always check sync results for failed intents
653
+
654
+ ❌ **Does not replace Solana consensus**
655
+
656
+ - TOSS extends operational boundaries but does not modify Solana's execution semantics
657
+ - All final state transitions occur exclusively on Solana
658
+ - Transaction validity is determined by Solana's runtime, not TOSS
659
+
660
+ ❌ **Does not eliminate finality dependency on network**
661
+
662
+ - Finality still requires network connectivity to Solana
663
+ - Offline operation defers settlement, not finality
664
+ - You cannot validate final state without connectivity
665
+
666
+ ### Settlement Guarantees
667
+
668
+ TOSS **guarantees**:
669
+
670
+ - ✅ Signatures cannot be forged (Ed25519 cryptography)
671
+ - ✅ Offline state never mutates global state (local-only storage)
672
+ - ✅ All artifacts are verifiable onchain (deterministic settlement)
673
+ - ✅ Conflicts resolve deterministically (based on nonce and timestamp)
674
+ - ✅ Pre-settlement confidentiality via Arcium (optional)
675
+
676
+ But TOSS **does not guarantee**:
677
+
678
+ - ❌ That your intent will successfully settle (dependent on onchain state)
679
+ - ❌ Prevention of offline double-spend (conflicts detected onchain)
680
+ - ❌ Immediate finality (requires network connectivity)
681
+
682
+ **The distinction:** TOSS guarantees **protocol correctness**, not **settlement success**. These are different requirements.
683
+
684
+ ---
685
+
333
686
  ## 🌐 Network Support
334
687
 
335
688
  | Network | Status | RPC Endpoint |
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
- // Stop scan
100
- export function stopScan() {
101
- manager.stopDeviceScan();
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
@@ -1 +1 @@
1
- {"version":3,"names":["BleManager","PermissionsAndroid","Platform","SERVICE_UUID","USER_CHARACTERISTIC","INTENT_CHARACTERISTIC","manager","requestBLEPermissions","OS","requestMultiple","PERMISSIONS","BLUETOOTH_SCAN","BLUETOOTH_CONNECT","ACCESS_FINE_LOCATION","connect","device","connectedDevice","connectToDevice","id","discoverAllServicesAndCharacteristics","startTossScan","onUserFound","onIntentFound","startDeviceScan","error","console","warn","message","services","userData","readCharacteristicForService","value","user","JSON","parse","intentData","intent","err","State","advertiseUser","subscription","onStateChange","state","PoweredOn","log","userId","remove","errorMessage","Error","String","stopAdvertising","stopDeviceScan","sendIntentToDevice","deviceId","jsonIntent","stringify","writeCharacteristicWithResponseForService","Buffer","from","toString","cancelConnection","stopScan"],"sourceRoot":"../../src","sources":["ble.ts"],"mappings":"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","ignoreList":[]}
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":[]}