@functionland/react-native-fula 1.9.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1384 +1,1477 @@
1
- package land.fx.fula;
2
-
3
- import android.util.Log;
4
-
5
- import androidx.annotation.NonNull;
6
-
7
- import com.facebook.react.bridge.Promise;
8
- import com.facebook.react.bridge.ReactApplicationContext;
9
- import com.facebook.react.bridge.ReactContextBaseJavaModule;
10
- import com.facebook.react.bridge.ReactMethod;
11
- import com.facebook.react.bridge.WritableMap;
12
- import com.facebook.react.bridge.WritableNativeMap;
13
- import com.facebook.react.module.annotations.ReactModule;
14
-
15
- import org.apache.commons.io.FileUtils;
16
- import org.jetbrains.annotations.Contract;
17
-
18
- import java.io.File;
19
- import java.io.IOException;
20
- import java.nio.charset.StandardCharsets;
21
- import java.security.GeneralSecurityException;
22
- import java.security.InvalidAlgorithmParameterException;
23
- import java.security.InvalidKeyException;
24
- import java.security.NoSuchAlgorithmException;
25
- import java.util.Arrays;
26
-
27
- import javax.crypto.BadPaddingException;
28
- import javax.crypto.IllegalBlockSizeException;
29
- import javax.crypto.NoSuchPaddingException;
30
- import javax.crypto.SecretKey;
31
-
32
- import java.util.concurrent.Executors;
33
- import java.util.concurrent.ScheduledExecutorService;
34
- import java.util.concurrent.TimeUnit;
35
- import java.util.concurrent.atomic.AtomicBoolean;
36
- import java.util.concurrent.Future;
37
- import java.util.concurrent.TimeoutException;
38
-
39
- import org.json.JSONObject;
40
- import org.json.JSONArray;
41
-
42
- import fulamobile.Config;
43
- import fulamobile.Fulamobile;
44
-
45
- import land.fx.wnfslib.Fs;
46
-
47
- @ReactModule(name = FulaModule.NAME)
48
- public class FulaModule extends ReactContextBaseJavaModule {
49
-
50
-
51
- @Override
52
- public void initialize() {
53
- System.loadLibrary("wnfslib");
54
- System.loadLibrary("gojni");
55
- }
56
-
57
-
58
- public static final String NAME = "FulaModule";
59
- fulamobile.Client fula;
60
-
61
- Client client;
62
- Config fulaConfig;
63
- String appDir;
64
- String fulaStorePath;
65
- String privateForest;
66
- land.fx.wnfslib.Config rootConfig;
67
- SharedPreferenceHelper sharedPref;
68
- SecretKey secretKeyGlobal;
69
- String identityEncryptedGlobal;
70
- static String PRIVATE_KEY_STORE_PEERID = "PRIVATE_KEY";
71
-
72
- public static class Client implements land.fx.wnfslib.Datastore {
73
-
74
- private final fulamobile.Client internalClient;
75
-
76
- Client(fulamobile.Client clientInput) {
77
- this.internalClient = clientInput;
78
- }
79
-
80
- @NonNull
81
- @Override
82
- public byte[] get(@NonNull byte[] cid) {
83
- try {
84
- Log.d("ReactNative", Arrays.toString(cid));
85
- return this.internalClient.get(cid);
86
- } catch (Exception e) {
87
- e.printStackTrace();
88
- }
89
- Log.d("ReactNative","Error get");
90
- return cid;
91
- }
92
-
93
- @NonNull
94
- @Override
95
- public byte[] put(@NonNull byte[] data, long codec) {
96
- try {
97
- //Log.d("ReactNative", "data="+ Arrays.toString(data) +" ;codec="+codec);
98
- return this.internalClient.put(data, codec);
99
- } catch (Exception e) {
100
- Log.d("ReactNative", "put Error="+e.getMessage());
101
- e.printStackTrace();
102
- }
103
- Log.d("ReactNative","Error put");
104
- return data;
105
- }
106
- }
107
-
108
- public FulaModule(ReactApplicationContext reactContext) {
109
- super(reactContext);
110
- appDir = reactContext.getFilesDir().toString();
111
- fulaStorePath = appDir + "/fula";
112
- File storeDir = new File(fulaStorePath);
113
- sharedPref = SharedPreferenceHelper.getInstance(reactContext.getApplicationContext());
114
- boolean success = true;
115
- if (!storeDir.exists()) {
116
- success = storeDir.mkdirs();
117
- }
118
- if (success) {
119
- Log.d(NAME, "Fula store folder created");
120
- } else {
121
- Log.d(NAME, "Unable to create fula store folder!");
122
- }
123
- }
124
-
125
- @Override
126
- @NonNull
127
- public java.lang.String getName() {
128
- return NAME;
129
- }
130
-
131
-
132
- private byte[] toByte(@NonNull String input) {
133
- return input.getBytes(StandardCharsets.UTF_8);
134
- }
135
-
136
- private byte[] decToByte(@NonNull String input) {
137
- String[] parts = input.split(",");
138
- byte[] output = new byte[parts.length];
139
- for (int i = 0; i < parts.length; i++) {
140
- output[i] = Byte.parseByte(parts[i]);
141
- }
142
- return output;
143
- }
144
-
145
- @NonNull
146
- @Contract("_ -> new")
147
- public String toString(byte[] input) {
148
- return new String(input, StandardCharsets.UTF_8);
149
- }
150
-
151
- @NonNull
152
- private static int[] stringArrToIntArr(@NonNull String[] s) {
153
- int[] result = new int[s.length];
154
- for (int i = 0; i < s.length; i++) {
155
- result[i] = Integer.parseInt(s[i]);
156
- }
157
- return result;
158
- }
159
-
160
- @NonNull
161
- @Contract(pure = true)
162
- private static byte[] convertIntToByte(@NonNull int[] input) {
163
- byte[] result = new byte[input.length];
164
- for (int i = 0; i < input.length; i++) {
165
- byte b = (byte) input[i];
166
- result[i] = b;
167
- }
168
- return result;
169
- }
170
-
171
- @NonNull
172
- private byte[] convertStringToByte(@NonNull String data) {
173
- String[] keyInt_S = data.split(",");
174
- int[] keyInt = stringArrToIntArr(keyInt_S);
175
-
176
- return convertIntToByte(keyInt);
177
- }
178
-
179
- @ReactMethod
180
- public void checkConnection(int timeout, Promise promise) {
181
- Log.d("ReactNative", "checkConnection started");
182
- ThreadUtils.runOnExecutor(() -> {
183
- if (this.fula != null) {
184
- try {
185
- boolean connectionStatus = this.checkConnectionInternal(timeout);
186
- Log.d("ReactNative", "checkConnection ended " + connectionStatus);
187
- promise.resolve(connectionStatus);
188
- }
189
- catch (Exception e) {
190
- Log.d("ReactNative", "checkConnection failed with Error: " + e.getMessage());
191
- promise.resolve(false);
192
- }
193
- } else {
194
- Log.d("ReactNative", "checkConnection failed with Error: " + "fula is null");
195
- promise.resolve(false);
196
- }
197
- });
198
- }
199
-
200
- @ReactMethod
201
- public void newClient(String identityString, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh, Promise promise) {
202
- Log.d("ReactNative", "newClient started");
203
- ThreadUtils.runOnExecutor(() -> {
204
- try {
205
- Log.d("ReactNative", "newClient storePath= " + storePath + " bloxAddr= " + bloxAddr + " exchange= " + exchange + " autoFlush= " + autoFlush + " useRelay= " + useRelay + " refresh= " + refresh);
206
- byte[] identity = toByte(identityString);
207
- Log.d("ReactNative", "newClient identity= " + identityString);
208
- this.newClientInternal(identity, storePath, bloxAddr, exchange, autoFlush, useRelay, refresh);
209
- //String objString = Arrays.toString(obj);
210
- String peerId = this.fula.id();
211
- Log.d("ReactNative", "newClient peerId= " + peerId);
212
- promise.resolve(peerId);
213
- } catch (Exception e) {
214
- Log.d("ReactNative", "newClient failed with Error: " + e.getMessage());
215
- promise.reject("Error", e.getMessage());
216
- }
217
- });
218
- }
219
-
220
- @ReactMethod
221
- public void isReady(boolean filesystemCheck, Promise promise) {
222
- Log.d("ReactNative", "isReady started");
223
- ThreadUtils.runOnExecutor(() -> {
224
- boolean initialized = false;
225
- try {
226
- if (this.fula != null && this.fula.id() != null) {
227
- if (filesystemCheck) {
228
- if (this.client != null && this.rootConfig != null && !this.rootConfig.getCid().isEmpty()) {
229
- initialized = true;
230
- Log.d("ReactNative", "isReady is true with filesystem check");
231
- }
232
- } else {
233
- Log.d("ReactNative", "isReady is true without filesystem check");
234
- initialized = true;
235
- }
236
- }
237
- promise.resolve(initialized);
238
- } catch (Exception e) {
239
- Log.d("ReactNative", "isReady failed with Error: " + e.getMessage());
240
- promise.reject("Error", e.getMessage());
241
- }
242
- });
243
- }
244
-
245
- @ReactMethod
246
- public void init(String identityString, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootConfig, boolean useRelay, boolean refresh, Promise promise) {
247
- Log.d("ReactNative", "init started");
248
- ThreadUtils.runOnExecutor(() -> {
249
- try {
250
- WritableMap resultData = new WritableNativeMap();
251
- Log.d("ReactNative", "init storePath= " + storePath);
252
- byte[] identity = toByte(identityString);
253
- Log.d("ReactNative", "init identity= " + identityString);
254
- String[] obj = this.initInternal(identity, storePath, bloxAddr, exchange, autoFlush, rootConfig, useRelay, refresh);
255
- Log.d("ReactNative", "init object created: [ " + obj[0] + ", " + obj[1] + ", " + obj[2] + " ]");
256
- resultData.putString("peerId", obj[0]);
257
- resultData.putString("rootCid", obj[1]);
258
- resultData.putString("private_ref", obj[2]);
259
- promise.resolve(resultData);
260
- } catch (Exception e) {
261
- Log.d("ReactNative", "init failed with Error: " + e.getMessage());
262
- promise.reject("Error", e.getMessage());
263
- }
264
- });
265
- }
266
-
267
- @ReactMethod
268
- public void logout(String identityString, String storePath, Promise promise) {
269
- Log.d("ReactNative", "logout started");
270
- ThreadUtils.runOnExecutor(() -> {
271
- try {
272
- byte[] identity = toByte(identityString);
273
- boolean obj = this.logoutInternal(identity, storePath);
274
- Log.d("ReactNative", "logout completed");
275
- promise.resolve(obj);
276
- } catch (Exception e) {
277
- Log.d("ReactNative", "logout failed with Error: " + e.getMessage());
278
- promise.reject("Error", e.getMessage());
279
- }
280
- });
281
- }
282
-
283
- private boolean checkConnectionInternal(int timeout) throws Exception {
284
- try {
285
- Log.d("ReactNative", "checkConnectionInternal started");
286
- if (this.fula != null) {
287
- try {
288
- Log.d("ReactNative", "connectToBlox started");
289
-
290
- AtomicBoolean connectionStatus = new AtomicBoolean(false);
291
- ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
292
- Future<?> future = executor.submit(() -> {
293
- try {
294
- this.fula.connectToBlox();
295
- connectionStatus.set(true);
296
- Log.d("ReactNative", "checkConnectionInternal succeeded ");
297
- } catch (Exception e) {
298
- Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
299
- }
300
- });
301
-
302
- try {
303
- future.get(timeout, TimeUnit.SECONDS);
304
- } catch (TimeoutException te) {
305
- // If the timeout occurs, shut down the executor and return false
306
- executor.shutdownNow();
307
- return false;
308
- } finally {
309
- // If the future task is done, we can shut down the executor
310
- if (future.isDone()) {
311
- executor.shutdown();
312
- }
313
- }
314
-
315
- return connectionStatus.get();
316
- } catch (Exception e) {
317
- Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
318
- return false;
319
- }
320
- } else {
321
- Log.d("ReactNative", "checkConnectionInternal failed because fula is not initialized ");
322
- return false;
323
- }
324
- } catch (Exception e) {
325
- Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
326
- throw (e);
327
- }
328
- }
329
-
330
- @ReactMethod
331
- private void checkFailedActions(boolean retry, int timeout, Promise promise) throws Exception {
332
- try {
333
- if (this.fula != null) {
334
- if (!retry) {
335
- Log.d("ReactNative", "checkFailedActions without retry");
336
- fulamobile.LinkIterator failedLinks = this.fula.listFailedPushes();
337
- if (failedLinks.hasNext()) {
338
- Log.d("ReactNative", "checkFailedActions found: "+Arrays.toString(failedLinks.next()));
339
- promise.resolve(true);
340
- } else {
341
- promise.resolve(false);
342
- }
343
- } else {
344
- Log.d("ReactNative", "checkFailedActions with retry");
345
- boolean retryResults = this.retryFailedActionsInternal(timeout);
346
- promise.resolve(!retryResults);
347
- }
348
- } else {
349
- throw new Exception("Fula is not initialized");
350
- }
351
- } catch (Exception e) {
352
- Log.d("ReactNative", "checkFailedActions failed with Error: " + e.getMessage());
353
- throw (e);
354
- }
355
- }
356
-
357
- private boolean retryFailedActionsInternal(int timeout) throws Exception {
358
- try {
359
- Log.d("ReactNative", "retryFailedActionsInternal started");
360
- if (this.fula != null) {
361
- //Fula is initialized
362
- try {
363
- boolean connectionCheck = this.checkConnectionInternal(timeout);
364
- if(connectionCheck) {
365
- try {
366
- Log.d("ReactNative", "retryFailedPushes started");
367
- this.fula.retryFailedPushes();
368
- Log.d("ReactNative", "flush started");
369
- this.fula.flush();
370
- return true;
371
- }
372
- catch (Exception e) {
373
- this.fula.flush();
374
- Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
375
- return false;
376
- }
377
- //Blox online
378
- /*fulamobile.LinkIterator failedLinks = this.fula.listFailedPushes();
379
- if (failedLinks.hasNext()) {
380
- Log.d("ReactNative", "Failed links");
381
- //Failed list is not empty. iterate in the list
382
- while (failedLinks.hasNext()) {
383
- //Get the missing key
384
- byte[] failedNode = failedLinks.next();
385
- try {
386
- //Push to Blox
387
- Log.d("ReactNative", "Pushing Failed links "+Arrays.toString(failedNode));
388
- this.pushInternal(failedNode);
389
- Log.d("ReactNative", "Failed links pushed");
390
- }
391
- catch (Exception e) {
392
- Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
393
- }
394
- }
395
- //check if list is empty now and all are pushed
396
- Log.d("ReactNative", "Pushing finished");
397
- fulamobile.LinkIterator failedLinks_after = this.fula.listFailedPushes();
398
- if(failedLinks_after.hasNext()) {
399
- //Some pushes failed
400
- byte[] first_failed = failedLinks_after.next();
401
- Log.d("ReactNative", "Failed links are not empty "+Arrays.toString(first_failed));
402
- return false;
403
- } else {
404
- //All pushes successful
405
- return true;
406
- }
407
- } else {
408
- Log.d("ReactNative", "No Failed links");
409
- //Failed list is empty
410
- return true;
411
- }*/
412
- } else {
413
- Log.d("ReactNative", "retryFailedActions failed because blox is offline");
414
- //Blox Offline
415
- return false;
416
- }
417
- }
418
- catch (Exception e) {
419
- Log.d("ReactNative", "retryFailedActions failed with Error: " + e.getMessage());
420
- return false;
421
- }
422
- } else {
423
- Log.d("ReactNative", "retryFailedActions failed because fula is not initialized");
424
- //Fula is not initialized
425
- return false;
426
- }
427
- } catch (Exception e) {
428
- Log.d("ReactNative", "retryFailedActions failed with Error: " + e.getMessage());
429
- throw (e);
430
- }
431
- }
432
-
433
- @NonNull
434
- private byte[] createPeerIdentity(byte[] identity) throws GeneralSecurityException, IOException {
435
- try {
436
- // 1: First: create public key from provided private key
437
- // 2: Should read the local keychain store (if it is key-value, key is public key above,
438
- // 3: if found, decrypt using the private key
439
- // 4: If not found or decryption not successful, generate an identity
440
- // 5: then encrypt and store in keychain
441
- byte[] libp2pId;
442
- String encryptedLibp2pId = sharedPref.getValue(PRIVATE_KEY_STORE_PEERID);
443
- byte[] encryptionPair;
444
- SecretKey encryptionSecretKey;
445
- try {
446
- encryptionSecretKey = Cryptography.generateKey(identity);
447
- Log.d("ReactNative", "encryptionSecretKey generated from privateKey");
448
- } catch (Exception e) {
449
- Log.d("ReactNative", "Failed to generate key for encryption: " + e.getMessage());
450
- throw new GeneralSecurityException("Failed to generate key encryption", e);
451
- }
452
-
453
- if (encryptedLibp2pId == null || !encryptedLibp2pId.startsWith("FULA_ENC_V3:")) {
454
- Log.d("ReactNative", "encryptedLibp2pId is not correct. creating new one " + encryptedLibp2pId);
455
-
456
- try {
457
- libp2pId = Fulamobile.generateEd25519KeyFromString(toString(identity));
458
- } catch (Exception e) {
459
- Log.d("ReactNative", "Failed to generate libp2pId: " + e.getMessage());
460
- throw new GeneralSecurityException("Failed to generate libp2pId", e);
461
- }
462
- encryptedLibp2pId = "FULA_ENC_V3:" + Cryptography.encryptMsg(StaticHelper.bytesToBase64(libp2pId), encryptionSecretKey);
463
- sharedPref.add(PRIVATE_KEY_STORE_PEERID, encryptedLibp2pId);
464
- } else {
465
- Log.d("ReactNative", "encryptedLibp2pId is correct. decrypting " + encryptedLibp2pId);
466
- }
467
-
468
- try {
469
- String decryptedLibp2pId = Cryptography.decryptMsg(encryptedLibp2pId.replace("FULA_ENC_V3:", ""), encryptionSecretKey);
470
-
471
- return StaticHelper.base64ToBytes(decryptedLibp2pId);
472
- } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
473
- Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e.getMessage());
474
- throw (e);
475
- }
476
-
477
- } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
478
- Log.d("ReactNative", "createPeerIdentity failed with Error: " + e.getMessage());
479
- throw (e);
480
- }
481
- }
482
-
483
- private void createNewRootConfig(FulaModule.Client iClient, byte[] identity) throws Exception {
484
- this.privateForest = Fs.createPrivateForest(iClient);
485
- Log.d("ReactNative", "privateForest is created: " + this.privateForest);
486
- this.rootConfig = Fs.createRootDir(iClient, this.privateForest, identity);
487
- if (this.fula != null) {
488
- this.fula.flush();
489
- }
490
- Log.d("ReactNative", "new rootConfig is created: cid=" + this.rootConfig.getCid()+" & private_ref="+this.rootConfig.getPrivate_ref());
491
-
492
- this.encrypt_and_store_config();
493
- }
494
-
495
- private String getPrivateRef(FulaModule.Client iClient, byte[] wnfsKey, String rootCid) throws Exception {
496
- Log.d("ReactNative", "getPrivateRef called: rootCid=" + rootCid);
497
- String privateRef = Fs.getPrivateRef(iClient, wnfsKey, rootCid);
498
- Log.d("ReactNative", "getPrivateRef completed: privateRef=" + privateRef);
499
- return privateRef;
500
- }
501
-
502
- private boolean encrypt_and_store_config() throws Exception {
503
- try {
504
- if(this.identityEncryptedGlobal != null && !this.identityEncryptedGlobal.isEmpty()) {
505
- String cid_encrypted = Cryptography.encryptMsg(this.rootConfig.getCid(), this.secretKeyGlobal);
506
- String private_ref_encrypted = Cryptography.encryptMsg(this.rootConfig.getPrivate_ref(), this.secretKeyGlobal);
507
-
508
- sharedPref.add("FULA_ENC_V3:cid_encrypted_" + this.identityEncryptedGlobal, cid_encrypted);
509
- sharedPref.add("FULA_ENC_V3:private_ref_encrypted_" + this.identityEncryptedGlobal, private_ref_encrypted);
510
- return true;
511
- } else {
512
- return false;
513
- }
514
- } catch (Exception e) {
515
- Log.d("ReactNative", "encrypt_and_store_config failed with Error: " + e.getMessage());
516
- throw (e);
517
- }
518
- }
519
-
520
- private boolean logoutInternal(byte[] identity, String storePath) throws Exception {
521
- try {
522
- if (this.fula != null) {
523
- this.fula.flush();
524
- }
525
- SecretKey secretKey = Cryptography.generateKey(identity);
526
-
527
- String identity_encrypted = Cryptography.encryptMsg(Arrays.toString(identity), secretKey);
528
- sharedPref.remove("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
529
- sharedPref.remove("FULA_ENC_V3:private_ref_encrypted_"+identity_encrypted);
530
-
531
- //TODO: Should also remove peerid @Mahdi
532
-
533
- sharedPref.remove("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
534
- sharedPref.remove("FULA_ENC_V3:private_ref_encrypted_"+ identity_encrypted);
535
-
536
- this.rootConfig = null;
537
- this.secretKeyGlobal = null;
538
- this.identityEncryptedGlobal = null;
539
-
540
- if (storePath == null || storePath.trim().isEmpty()) {
541
- storePath = this.fulaStorePath;
542
- }
543
-
544
- File file = new File(storePath);
545
- FileUtils.deleteDirectory(file);
546
- return true;
547
-
548
- } catch (Exception e) {
549
- Log.d("ReactNative", "logout internal failed with Error: " + e.getMessage());
550
- throw (e);
551
- }
552
- }
553
-
554
- public fulamobile.Client getFulaClient() {
555
- return this.fula;
556
- }
557
-
558
- @NonNull
559
- private byte[] newClientInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh) throws GeneralSecurityException, IOException {
560
- byte[] peerIdentity = null;
561
- try {
562
- fulaConfig = new Config();
563
- if (storePath == null || storePath.trim().isEmpty()) {
564
- fulaConfig.setStorePath(this.fulaStorePath);
565
- } else {
566
- fulaConfig.setStorePath(storePath);
567
- }
568
- Log.d("ReactNative", "newClientInternal storePath is set: " + fulaConfig.getStorePath());
569
-
570
- peerIdentity = this.createPeerIdentity(identity);
571
- fulaConfig.setIdentity(peerIdentity);
572
- Log.d("ReactNative", "peerIdentity is set: " + toString(fulaConfig.getIdentity()));
573
- fulaConfig.setBloxAddr(bloxAddr);
574
- Log.d("ReactNative", "bloxAddr is set: " + fulaConfig.getBloxAddr());
575
- fulaConfig.setExchange(exchange);
576
- fulaConfig.setSyncWrites(autoFlush);
577
- if (useRelay) {
578
- fulaConfig.setAllowTransientConnection(true);
579
- fulaConfig.setForceReachabilityPrivate(true);
580
- }
581
- if (this.fula == null || refresh) {
582
- Log.d("ReactNative", "Creating a new Fula instance");
583
- try {
584
- shutdownInternal();
585
- this.fula = Fulamobile.newClient(fulaConfig);
586
- if (this.fula != null) {
587
- this.fula.flush();
588
- }
589
- } catch (Exception e) {
590
- Log.d("ReactNative", "Failed to create new Fula instance: " + e.getMessage());
591
- throw new IOException("Failed to create new Fula instance", e);
592
- }
593
- }
594
- } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
595
- Log.d("ReactNative", "newclientInternal failed with Error: " + e.getMessage());
596
- throw (e);
597
- }
598
- return peerIdentity;
599
- }
600
-
601
-
602
- @NonNull
603
- private String[] initInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootCid, boolean useRelay, boolean refresh) throws Exception {
604
- try {
605
- if (this.fula == null || refresh) {
606
- this.newClientInternal(identity, storePath, bloxAddr, exchange, autoFlush, useRelay, refresh);
607
- }
608
- if(this.client == null || refresh) {
609
- this.client = new Client(this.fula);
610
- Log.d("ReactNative", "fula initialized: " + this.fula.id());
611
- }
612
-
613
- SecretKey secretKey = Cryptography.generateKey(identity);
614
- String identity_encrypted =Cryptography.encryptMsg(Arrays.toString(identity), secretKey);
615
- this.identityEncryptedGlobal = identity_encrypted;
616
- this.secretKeyGlobal = secretKey;
617
-
618
- if (this.rootConfig == null || this.rootConfig.getCid().isEmpty() || this.rootConfig.getPrivate_ref().isEmpty()) {
619
- Log.d("ReactNative", "this.rootCid is empty.");
620
- //Load from keystore
621
-
622
- String cid_encrypted_fetched = sharedPref.getValue("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
623
- String private_ref_encrypted_fetched = sharedPref.getValue("FULA_ENC_V3:private_ref_encrypted_"+identity_encrypted);
624
- Log.d("ReactNative", "Here1");
625
- String cid = "";
626
- String private_ref = "";
627
- if(cid_encrypted_fetched != null && !cid_encrypted_fetched.isEmpty()) {
628
- Log.d("ReactNative", "decrypting cid="+cid_encrypted_fetched+" with secret="+secretKey.toString());
629
- cid = Cryptography.decryptMsg(cid_encrypted_fetched, secretKey);
630
- }
631
- if(private_ref_encrypted_fetched != null && !private_ref_encrypted_fetched.isEmpty()) {
632
- Log.d("ReactNative", "decrypting private_ref="+private_ref_encrypted_fetched+" with secret="+secretKey.toString());
633
- private_ref = Cryptography.decryptMsg(private_ref_encrypted_fetched, secretKey);
634
- }
635
- Log.d("ReactNative", "Here2");
636
- //Log.d("ReactNative", "Attempted to fetch cid from keystore; cid="+cid+" & private_ref="+private_ref);
637
- if((cid == null || cid.isEmpty()) || (private_ref == null || private_ref.isEmpty()) ){
638
- Log.d("ReactNative", "cid or PrivateRef was not found");
639
- if(rootCid != null && !rootCid.isEmpty()){
640
- Log.d("ReactNative", "Re-setting cid from input: "+rootCid);
641
- cid = rootCid;
642
- }
643
- if((private_ref == null || private_ref.isEmpty()) && (cid != null && !cid.isEmpty())){
644
- Log.d("ReactNative", "Re-fetching privateRef from wnfs: cid="+cid);
645
- private_ref = this.getPrivateRef(this.client, identity, cid);
646
- Log.d("ReactNative", "Re-fetching privateRef from wnfs: "+private_ref);
647
- }
648
- if(cid == null || cid.isEmpty() || private_ref == null || private_ref.isEmpty()) {
649
- Log.d("ReactNative", "Tried to recover cid and privateRef but was not successful. Creating new ones");
650
- this.createNewRootConfig(this.client, identity);
651
- } else {
652
- Log.d("ReactNative", "Tried to recover cid and privateRef and was successful. cid:"+cid+" & private_ref="+private_ref);
653
- this.rootConfig = new land.fx.wnfslib.Config(cid, private_ref);
654
- this.encrypt_and_store_config();
655
- }
656
- } else if(cid != null && !cid.isEmpty() && private_ref != null && !private_ref.isEmpty()) {
657
- Log.d("ReactNative", "Found cid and private ref in keychain store");
658
- if(cid != null && !cid.isEmpty() && private_ref != null && !private_ref.isEmpty()) {
659
- Log.d("ReactNative", "Recovered cid and private ref from keychain store. cid="+cid+" & private_ref="+private_ref);
660
- this.rootConfig = new land.fx.wnfslib.Config(cid, private_ref);
661
- } else{
662
- Log.d("ReactNative", "Found but Could not recover cid and private_ref from keychain store");
663
- this.createNewRootConfig(this.client, identity);
664
- }
665
- } else{
666
- Log.d("ReactNative", "This cid and private_ref generation should never happen!!!");
667
- //Create new root and store cid and private_ref
668
- this.createNewRootConfig(this.client, identity);
669
- }
670
-
671
-
672
- Log.d("ReactNative", "creating rootConfig completed");
673
-
674
- /*
675
- byte[] testbyte = convertStringToByte("-104,40,24,-93,24,100,24,114,24,111,24,111,24,116,24,-126,24,-126,0,0,24,-128,24,103,24,118,24,101,24,114,24,115,24,105,24,111,24,110,24,101,24,48,24,46,24,49,24,46,24,48,24,105,24,115,24,116,24,114,24,117,24,99,24,116,24,117,24,114,24,101,24,100,24,104,24,97,24,109,24,116");
676
- long testcodec = 85;
677
- byte[] testputcid = this.client.put(testbyte, testcodec);
678
- Log.d("ReactNative", "client.put test done"+ Arrays.toString(testputcid));
679
- byte[] testfetchedcid = convertStringToByte("1,113,18,32,-6,-63,-128,79,-102,-89,57,77,-8,67,-98,8,-81,40,-87,123,122,29,-52,-124,-60,-53,100,105,125,123,-5,-99,41,106,-124,-64");
680
- byte[] testfetchedbytes = this.client.get(testfetchedcid);
681
- Log.d("ReactNative", "client.get test done"+ Arrays.toString(testfetchedbytes));
682
- */
683
-
684
-
685
- Log.d("ReactNative", "rootConfig is created: cid=" + this.rootConfig.getCid()+ "& private_ref="+this
686
- .rootConfig.getPrivate_ref());
687
- } else {
688
- Log.d("ReactNative", "rootConfig existed: cid=" + this.rootConfig.getCid()+ " & private_ref="+this.rootConfig.getPrivate_ref());
689
- }
690
- String peerId = this.fula.id();
691
- String[] obj = new String[3];
692
- obj[0] = peerId;
693
- obj[1] = this.rootConfig.getCid();
694
- obj[2] = this.rootConfig.getPrivate_ref();
695
- Log.d("ReactNative", "initInternal is completed successfully");
696
- if (this.fula != null) {
697
- this.fula.flush();
698
- }
699
- return obj;
700
- } catch (Exception e) {
701
- Log.d("ReactNative", "init internal failed with Error: " + e.getMessage());
702
- throw (e);
703
- }
704
- }
705
-
706
- @ReactMethod
707
- public void mkdir(String path, Promise promise) {
708
- ThreadUtils.runOnExecutor(() -> {
709
- Log.d("ReactNative", "mkdir: path = " + path);
710
- try {
711
- land.fx.wnfslib.Config config = Fs.mkdir(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path);
712
- if(config != null) {
713
- this.rootConfig = config;
714
- this.encrypt_and_store_config();
715
- if (this.fula != null) {
716
- this.fula.flush();
717
- }
718
- promise.resolve(config.getCid());
719
- } else {
720
- Log.d("ReactNative", "mkdir Error: config is null");
721
- promise.reject(new Exception("mkdir Error: config is null"));
722
- }
723
- } catch (Exception e) {
724
- Log.d("get", e.getMessage());
725
- promise.reject(e);
726
- }
727
- });
728
- }
729
-
730
- @ReactMethod
731
- public void writeFile(String fulaTargetFilename, String localFilename, Promise promise) {
732
- /*
733
- // reads content of the file form localFilename (should include full absolute path to local file with read permission
734
- // writes content to the specified location by fulaTargetFilename in Fula filesystem
735
- // fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
736
- // localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
737
- // Returns: new cid of the root after this file is placed in the tree
738
- */
739
- ThreadUtils.runOnExecutor(() -> {
740
- Log.d("ReactNative", "writeFile to : path = " + fulaTargetFilename + ", from: " + localFilename);
741
- try {
742
- land.fx.wnfslib.Config config = Fs.writeFileFromPath(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), fulaTargetFilename, localFilename);
743
- if(config != null) {
744
- this.rootConfig = config;
745
- this.encrypt_and_store_config();
746
- if (this.fula != null) {
747
- this.fula.flush();
748
- }
749
- promise.resolve(config.getCid());
750
- } else {
751
- Log.d("ReactNative", "writeFile Error: config is null");
752
- promise.reject(new Exception("writeFile Error: config is null"));
753
- }
754
- } catch (Exception e) {
755
- Log.d("get", e.getMessage());
756
- promise.reject(e);
757
- }
758
- });
759
- }
760
-
761
- @ReactMethod
762
- public void writeFileContent(String path, String contentString, Promise promise) {
763
- ThreadUtils.runOnExecutor(() -> {
764
- Log.d("ReactNative", "writeFile: contentString = " + contentString);
765
- Log.d("ReactNative", "writeFile: path = " + path);
766
- try {
767
- byte[] content = this.convertStringToByte(contentString);
768
- land.fx.wnfslib.Config config = Fs.writeFile(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path, content);
769
- this.rootConfig = config;
770
- this.encrypt_and_store_config();
771
- if (this.fula != null) {
772
- this.fula.flush();
773
- }
774
- promise.resolve(config.getCid());
775
- } catch (Exception e) {
776
- Log.d("get", e.getMessage());
777
- promise.reject(e);
778
- }
779
- });
780
- }
781
-
782
- @ReactMethod
783
- public void ls(String path, Promise promise) {
784
- ThreadUtils.runOnExecutor(() -> {
785
- Log.d("ReactNative", "ls: path = " + path);
786
- try {
787
- byte[] res = Fs.ls(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path);
788
-
789
- //JSONArray jsonArray = new JSONArray(res);
790
- String s = new String(res, StandardCharsets.UTF_8);
791
- Log.d("ReactNative", "ls: res = " + s);
792
- promise.resolve(s);
793
- } catch (Exception e) {
794
- Log.d("get", e.getMessage());
795
- promise.reject(e);
796
- }
797
- });
798
- }
799
-
800
- @ReactMethod
801
- public void rm(String path, Promise promise) {
802
- ThreadUtils.runOnExecutor(() -> {
803
- Log.d("ReactNative", "rm: path = " + path);
804
- try {
805
- land.fx.wnfslib.Config config = Fs.rm(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path);
806
- if(config != null) {
807
- this.rootConfig = config;
808
- this.encrypt_and_store_config();
809
- if (this.fula != null) {
810
- this.fula.flush();
811
- }
812
- promise.resolve(config.getCid());
813
- } else {
814
- Log.d("ReactNative", "rm Error: config is null");
815
- promise.reject(new Exception("rm Error: config is null"));
816
- }
817
- } catch (Exception e) {
818
- Log.d("get", e.getMessage());
819
- promise.reject(e);
820
- }
821
- });
822
- }
823
-
824
- @ReactMethod
825
- public void cp(String sourcePath, String targetPath, Promise promise) {
826
- ThreadUtils.runOnExecutor(() -> {
827
- Log.d("ReactNative", "rm: sourcePath = " + sourcePath);
828
- try {
829
- land.fx.wnfslib.Config config = Fs.cp(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), sourcePath, targetPath);
830
- if(config != null) {
831
- this.rootConfig = config;
832
- this.encrypt_and_store_config();
833
- if (this.fula != null) {
834
- this.fula.flush();
835
- }
836
- promise.resolve(config.getCid());
837
- } else {
838
- Log.d("ReactNative", "cp Error: config is null");
839
- promise.reject(new Exception("cp Error: config is null"));
840
- }
841
- } catch (Exception e) {
842
- Log.d("get", e.getMessage());
843
- promise.reject(e);
844
- }
845
- });
846
- }
847
-
848
- @ReactMethod
849
- public void mv(String sourcePath, String targetPath, Promise promise) {
850
- ThreadUtils.runOnExecutor(() -> {
851
- Log.d("ReactNative", "rm: sourcePath = " + sourcePath);
852
- try {
853
- land.fx.wnfslib.Config config = Fs.mv(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), sourcePath, targetPath);
854
- if(config != null) {
855
- this.rootConfig = config;
856
- this.encrypt_and_store_config();
857
- if (this.fula != null) {
858
- this.fula.flush();
859
- }
860
- promise.resolve(config.getCid());
861
- } else {
862
- Log.d("ReactNative", "mv Error: config is null");
863
- promise.reject(new Exception("mv Error: config is null"));
864
- }
865
- } catch (Exception e) {
866
- Log.d("get", e.getMessage());
867
- promise.reject(e);
868
- }
869
- });
870
- }
871
-
872
- @ReactMethod
873
- public void readFile(String fulaTargetFilename, String localFilename, Promise promise) {
874
- /*
875
- // reads content of the file form localFilename (should include full absolute path to local file with read permission
876
- // writes content to the specified location by fulaTargetFilename in Fula filesystem
877
- // fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
878
- // localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
879
- // Returns: new cid of the root after this file is placed in the tree
880
- */
881
- ThreadUtils.runOnExecutor(() -> {
882
- Log.d("ReactNative", "readFile: fulaTargetFilename = " + fulaTargetFilename);
883
- try {
884
- String path = Fs.readFilestreamToPath(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), fulaTargetFilename, localFilename);
885
- promise.resolve(path);
886
- } catch (Exception e) {
887
- Log.d("get", e.getMessage());
888
- promise.reject(e);
889
- }
890
- });
891
- }
892
-
893
- @ReactMethod
894
- public void readFileContent(String path, Promise promise) {
895
- ThreadUtils.runOnExecutor(() -> {
896
- Log.d("ReactNative", "readFileContent: path = " + path);
897
- try {
898
- byte[] res = Fs.readFile(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path);
899
- String resString = toString(res);
900
- promise.resolve(resString);
901
- } catch (Exception e) {
902
- Log.d("get", e.getMessage());
903
- promise.reject(e);
904
- }
905
- });
906
- }
907
-
908
- @ReactMethod
909
- public void get(String keyString, Promise promise) {
910
- ThreadUtils.runOnExecutor(() -> {
911
- Log.d("ReactNative", "get: keyString = " + keyString);
912
- try {
913
- byte[] key = this.convertStringToByte(keyString);
914
- byte[] value = this.getInternal(key);
915
- String valueString = toString(value);
916
- promise.resolve(valueString);
917
- } catch (Exception e) {
918
- Log.d("get", e.getMessage());
919
- promise.reject(e);
920
- }
921
- });
922
- }
923
-
924
- @NonNull
925
- private byte[] getInternal(byte[] key) throws Exception {
926
- try {
927
- Log.d("ReactNative", "getInternal: key.toString() = " + toString(key));
928
- Log.d("ReactNative", "getInternal: key.toString().bytes = " + Arrays.toString(key));
929
- byte[] value = this.fula.get(key);
930
- Log.d("ReactNative", "getInternal: value.toString() = " + toString(value));
931
- return value;
932
- } catch (Exception e) {
933
- Log.d("ReactNative", "getInternal: error = " + e.getMessage());
934
- Log.d("getInternal", e.getMessage());
935
- throw (e);
936
- }
937
- }
938
-
939
- @ReactMethod
940
- public void has(String keyString, Promise promise) {
941
- ThreadUtils.runOnExecutor(() -> {
942
- Log.d("ReactNative", "has: keyString = " + keyString);
943
- try {
944
- byte[] key = this.convertStringToByte(keyString);
945
- boolean result = this.hasInternal(key);
946
- promise.resolve(result);
947
- } catch (Exception e) {
948
- Log.d("get", e.getMessage());
949
- promise.reject(e);
950
- }
951
- });
952
- }
953
-
954
- private boolean hasInternal(byte[] key) throws Exception {
955
- try {
956
- boolean res = this.fula.has(key);
957
- return res;
958
- } catch (Exception e) {
959
- Log.d("hasInternal", e.getMessage());
960
- throw (e);
961
- }
962
- }
963
-
964
- private void pullInternal(byte[] key) throws Exception {
965
- try {
966
- this.fula.pull(key);
967
- } catch (Exception e) {
968
- Log.d("pullInternal", e.getMessage());
969
- throw (e);
970
- }
971
- }
972
-
973
- @ReactMethod
974
- public void push(Promise promise) {
975
- ThreadUtils.runOnExecutor(() -> {
976
- Log.d("ReactNative", "push started");
977
- try {
978
- this.pushInternal(this.convertStringToByte(this.rootConfig.getCid()));
979
- promise.resolve(this.rootConfig.getCid());
980
- } catch (Exception e) {
981
- Log.d("get", e.getMessage());
982
- promise.reject(e);
983
- }
984
- });
985
- }
986
-
987
- private void pushInternal(byte[] key) throws Exception {
988
- try {
989
- if (this.fula != null && this.fula.has(key)) {
990
- this.fula.push(key);
991
- this.fula.flush();
992
- } else {
993
- Log.d("ReactNative", "pushInternal error: key wasn't found or fula is not initialized");
994
- throw new Exception("key wasn't found in local storage");
995
- }
996
- } catch (Exception e) {
997
- Log.d("ReactNative", "pushInternal"+ e.getMessage());
998
- throw (e);
999
- }
1000
- }
1001
-
1002
- @ReactMethod
1003
- public void put(String valueString, String codecString, Promise promise) {
1004
- ThreadUtils.runOnExecutor(() -> {
1005
- Log.d("ReactNative", "put: codecString = " + codecString);
1006
- Log.d("ReactNative", "put: valueString = " + valueString);
1007
- try {
1008
- //byte[] codec = this.convertStringToByte(CodecString);
1009
- long codec = Long.parseLong(codecString);
1010
-
1011
-
1012
- Log.d("ReactNative", "put: codec = " + codec);
1013
- byte[] value = toByte(valueString);
1014
-
1015
- Log.d("ReactNative", "put: value.toString() = " + toString(value));
1016
- byte[] key = this.putInternal(value, codec);
1017
- Log.d("ReactNative", "put: key.toString() = " + toString(key));
1018
- promise.resolve(toString(key));
1019
- } catch (Exception e) {
1020
- Log.d("ReactNative", "put: error = " + e.getMessage());
1021
- promise.reject(e);
1022
- }
1023
- });
1024
- }
1025
-
1026
- @NonNull
1027
- private byte[] putInternal(byte[] value, long codec) throws Exception {
1028
- try {
1029
- if(this.fula != null) {
1030
- byte[] key = this.fula.put(value, codec);
1031
- this.fula.flush();
1032
- return key;
1033
- } else {
1034
- Log.d("ReactNative", "putInternal Error: fula is not initialized");
1035
- throw (new Exception("putInternal Error: fula is not initialized"));
1036
- }
1037
- } catch (Exception e) {
1038
- Log.d("ReactNative", "putInternal"+ e.getMessage());
1039
- throw (e);
1040
- }
1041
- }
1042
-
1043
- @ReactMethod
1044
- public void setAuth(String peerIdString, boolean allow, Promise promise) {
1045
- ThreadUtils.runOnExecutor(() -> {
1046
- Log.d("ReactNative", "setAuth: peerIdString = " + peerIdString);
1047
- try {
1048
- if (this.fula != null && this.fula.id() != null && this.fulaConfig != null && this.fulaConfig.getBloxAddr() != null) {
1049
- String bloxAddr = this.fulaConfig.getBloxAddr();
1050
- Log.d("ReactNative", "setAuth: bloxAddr = '" + bloxAddr+"'"+ " peerIdString = '" + peerIdString+"'");
1051
- int index = bloxAddr.lastIndexOf("/");
1052
- String bloxPeerId = bloxAddr.substring(index + 1);
1053
- this.fula.setAuth(bloxPeerId, peerIdString, allow);
1054
- promise.resolve(true);
1055
- } else {
1056
- Log.d("ReactNative", "setAuth error: fula is not initialized");
1057
- throw new Exception("fula is not initialized");
1058
- }
1059
- promise.resolve(false);
1060
- } catch (Exception e) {
1061
- Log.d("get", e.getMessage());
1062
- promise.reject(e);
1063
- }
1064
- });
1065
- }
1066
-
1067
- private void shutdownInternal() throws Exception {
1068
- try {
1069
- if(this.fula != null) {
1070
- this.fula.shutdown();
1071
- this.fula = null;
1072
- this.client = null;
1073
- }
1074
- } catch (Exception e) {
1075
- Log.d("ReactNative", "shutdownInternal"+ e.getMessage());
1076
- throw (e);
1077
- }
1078
- }
1079
-
1080
- @ReactMethod
1081
- public void shutdown(Promise promise) {
1082
- ThreadUtils.runOnExecutor(() -> {
1083
- try {
1084
- shutdownInternal();
1085
- promise.resolve(true);
1086
- } catch (Exception e) {
1087
- promise.reject(e);
1088
- Log.d("ReactNative", "shutdown"+ e.getMessage());
1089
- }
1090
- });
1091
- }
1092
-
1093
- ///////////////////////////////////////////////////////////
1094
- ///////////////////////////////////////////////////////////
1095
- ///////////////////////////////////////////////////////////
1096
- ///////////////////////////////////////////////////////////
1097
- //////////////////////ANYTHING BELOW IS FOR BLOCKCHAIN/////
1098
- ///////////////////////////////////////////////////////////
1099
- @ReactMethod
1100
- public void createAccount(String seedString, Promise promise) {
1101
- ThreadUtils.runOnExecutor(() -> {
1102
- Log.d("ReactNative", "createAccount: seedString = " + seedString);
1103
- try {
1104
- if (this.fula == null || this.fula.id() == null || this.fula.id().isEmpty()) {
1105
- promise.reject(new Error("Fula client is not initialized"));
1106
- } else {
1107
-
1108
- if (!seedString.startsWith("/")) {
1109
- promise.reject(new Error("seed should start with /"));
1110
- }
1111
- byte[] result = this.fula.seeded(seedString);
1112
- String resultString = toString(result);
1113
- promise.resolve(resultString);
1114
- }
1115
- } catch (Exception e) {
1116
- Log.d("get", e.getMessage());
1117
- promise.reject(e);
1118
- }
1119
- });
1120
- }
1121
-
1122
- @ReactMethod
1123
- public void checkAccountExists(String accountString, Promise promise) {
1124
- ThreadUtils.runOnExecutor(() -> {
1125
- Log.d("ReactNative", "checkAccountExists: accountString = " + accountString);
1126
- try {
1127
- byte[] result = this.fula.accountExists(accountString);
1128
- String resultString = toString(result);
1129
- promise.resolve(resultString);
1130
- } catch (Exception e) {
1131
- Log.d("get", e.getMessage());
1132
- promise.reject(e);
1133
- }
1134
- });
1135
- }
1136
-
1137
- @ReactMethod
1138
- public void createPool(String seedString, String poolName, Promise promise) {
1139
- ThreadUtils.runOnExecutor(() -> {
1140
- Log.d("ReactNative", "createPool: seedString = " + seedString + "; poolName = " + poolName);
1141
- try {
1142
- byte[] result = this.fula.poolCreate(seedString, poolName);
1143
- String resultString = toString(result);
1144
- promise.resolve(resultString);
1145
- } catch (Exception e) {
1146
- Log.d("get", e.getMessage());
1147
- promise.reject(e);
1148
- }
1149
- });
1150
- }
1151
-
1152
- @ReactMethod
1153
- public void listPools(Promise promise) {
1154
- ThreadUtils.runOnExecutor(() -> {
1155
- Log.d("ReactNative", "listPools");
1156
- try {
1157
- byte[] result = this.fula.poolList();
1158
- String resultString = toString(result);
1159
- promise.resolve(resultString);
1160
- } catch (Exception e) {
1161
- Log.d("get", e.getMessage());
1162
- promise.reject(e);
1163
- }
1164
- });
1165
- }
1166
-
1167
- @ReactMethod
1168
- public void joinPool(String seedString, long poolID, Promise promise) {
1169
- ThreadUtils.runOnExecutor(() -> {
1170
- Log.d("ReactNative", "joinPool: seedString = " + seedString + "; poolID = " + poolID);
1171
- try {
1172
- byte[] result = this.fula.poolJoin(seedString, poolID);
1173
- String resultString = toString(result);
1174
- promise.resolve(resultString);
1175
- } catch (Exception e) {
1176
- Log.d("get", e.getMessage());
1177
- promise.reject(e);
1178
- }
1179
- });
1180
- }
1181
-
1182
- @ReactMethod
1183
- public void cancelPoolJoin(String seedString, long poolID, Promise promise) {
1184
- ThreadUtils.runOnExecutor(() -> {
1185
- Log.d("ReactNative", "cancelPoolJoin: seedString = " + seedString + "; poolID = " + poolID);
1186
- try {
1187
- byte[] result = this.fula.poolCancelJoin(seedString, poolID);
1188
- String resultString = toString(result);
1189
- promise.resolve(resultString);
1190
- } catch (Exception e) {
1191
- Log.d("get", e.getMessage());
1192
- promise.reject(e);
1193
- }
1194
- });
1195
- }
1196
-
1197
- @ReactMethod
1198
- public void listPoolJoinRequests(long poolID, Promise promise) {
1199
- ThreadUtils.runOnExecutor(() -> {
1200
- Log.d("ReactNative", "listPoolJoinRequests: poolID = " + poolID);
1201
- try {
1202
- byte[] result = this.fula.poolRequests(poolID);
1203
- String resultString = toString(result);
1204
- promise.resolve(resultString);
1205
- } catch (Exception e) {
1206
- Log.d("get", e.getMessage());
1207
- promise.reject(e);
1208
- }
1209
- });
1210
- }
1211
-
1212
- @ReactMethod
1213
- public void votePoolJoinRequest(String seedString, long poolID, String accountString, boolean accept, Promise promise) {
1214
- ThreadUtils.runOnExecutor(() -> {
1215
- Log.d("ReactNative", "votePoolJoinRequest: seedString = " + seedString + "; poolID = " + poolID + "; accountString = " + accountString + "; accept = " + accept);
1216
- try {
1217
- byte[] result = this.fula.poolVote(seedString, poolID, accountString, accept);
1218
- String resultString = toString(result);
1219
- promise.resolve(resultString);
1220
- } catch (Exception e) {
1221
- Log.d("get", e.getMessage());
1222
- promise.reject(e);
1223
- }
1224
- });
1225
- }
1226
-
1227
- @ReactMethod
1228
- public void leavePool(String seedString, long poolID, Promise promise) {
1229
- ThreadUtils.runOnExecutor(() -> {
1230
- Log.d("ReactNative", "leavePool: seedString = " + seedString + "; poolID = " + poolID);
1231
- try {
1232
- byte[] result = this.fula.poolLeave(seedString, poolID);
1233
- String resultString = toString(result);
1234
- promise.resolve(resultString);
1235
- } catch (Exception e) {
1236
- Log.d("get", e.getMessage());
1237
- promise.reject(e);
1238
- }
1239
- });
1240
- }
1241
-
1242
- @ReactMethod
1243
- public void newReplicationRequest(String seedString, long poolID, long replicationFactor, String cid, Promise promise) {
1244
- ThreadUtils.runOnExecutor(() -> {
1245
- Log.d("ReactNative", "newReplicationRequest: seedString = " + seedString + "; poolID = " + poolID + "; replicationFactor = " + replicationFactor + "; cid = " + cid);
1246
- try {
1247
- byte[] result = this.fula.manifestUpload(seedString, poolID, replicationFactor, cid);
1248
- String resultString = toString(result);
1249
- promise.resolve(resultString);
1250
- } catch (Exception e) {
1251
- Log.d("get", e.getMessage());
1252
- promise.reject(e);
1253
- }
1254
- });
1255
- }
1256
-
1257
- @ReactMethod
1258
- public void newStoreRequest(String seedString, long poolID, String uploader, String cid, Promise promise) {
1259
- ThreadUtils.runOnExecutor(() -> {
1260
- Log.d("ReactNative", "newStoreRequest: seedString = " + seedString + "; poolID = " + poolID + "; uploader = " + uploader + "; cid = " + cid);
1261
- try {
1262
- byte[] result = this.fula.manifestStore(seedString, poolID, uploader, cid);
1263
- String resultString = toString(result);
1264
- promise.resolve(resultString);
1265
- } catch (Exception e) {
1266
- Log.d("get", e.getMessage());
1267
- promise.reject(e);
1268
- }
1269
- });
1270
- }
1271
-
1272
- @ReactMethod
1273
- public void listAvailableReplicationRequests(long poolID, Promise promise) {
1274
- ThreadUtils.runOnExecutor(() -> {
1275
- Log.d("ReactNative", "listAvailableReplicationRequests: poolID = " + poolID);
1276
- try {
1277
- byte[] result = this.fula.manifestAvailable(poolID);
1278
- String resultString = toString(result);
1279
- promise.resolve(resultString);
1280
- } catch (Exception e) {
1281
- Log.d("get", e.getMessage());
1282
- promise.reject(e);
1283
- }
1284
- });
1285
- }
1286
-
1287
- @ReactMethod
1288
- public void removeReplicationRequest(String seedString, long poolID, String cid, Promise promise) {
1289
- ThreadUtils.runOnExecutor(() -> {
1290
- Log.d("ReactNative", "newReplicationRequest: seedString = " + seedString + "; poolID = " + poolID + "; cid = " + cid);
1291
- try {
1292
- byte[] result = this.fula.manifestRemove(seedString, poolID, cid);
1293
- String resultString = toString(result);
1294
- promise.resolve(resultString);
1295
- } catch (Exception e) {
1296
- Log.d("get", e.getMessage());
1297
- promise.reject(e);
1298
- }
1299
- });
1300
- }
1301
-
1302
- @ReactMethod
1303
- public void removeStorer(String seedString, String storage, long poolID, String cid, Promise promise) {
1304
- ThreadUtils.runOnExecutor(() -> {
1305
- Log.d("ReactNative", "removeStorer: seedString = " + seedString + "; storage = " + storage + "; poolID = " + poolID + "; cid = " + cid);
1306
- try {
1307
- byte[] result = this.fula.manifestRemoveStorer(seedString, storage, poolID, cid);
1308
- String resultString = toString(result);
1309
- promise.resolve(resultString);
1310
- } catch (Exception e) {
1311
- Log.d("get", e.getMessage());
1312
- promise.reject(e);
1313
- }
1314
- });
1315
- }
1316
-
1317
- @ReactMethod
1318
- public void removeStoredReplication(String seedString, String uploader, long poolID, String cid, Promise promise) {
1319
- ThreadUtils.runOnExecutor(() -> {
1320
- Log.d("ReactNative", "removeStoredReplication: seedString = " + seedString + "; uploader = " + uploader + "; poolID = " + poolID + "; cid = " + cid);
1321
- try {
1322
- byte[] result = this.fula.manifestRemoveStored(seedString, uploader, poolID, cid);
1323
- String resultString = toString(result);
1324
- promise.resolve(resultString);
1325
- } catch (Exception e) {
1326
- Log.d("get", e.getMessage());
1327
- promise.reject(e);
1328
- }
1329
- });
1330
- }
1331
-
1332
- ////////////////////////////////////////////////////////////////
1333
- ///////////////// Blox Hardware Methods ////////////////////////
1334
- ////////////////////////////////////////////////////////////////
1335
-
1336
- @ReactMethod
1337
- public void bloxFreeSpace(Promise promise) {
1338
- ThreadUtils.runOnExecutor(() -> {
1339
- Log.d("ReactNative", "bloxFreeSpace");
1340
- try {
1341
- byte[] result = this.fula.bloxFreeSpace();
1342
- String resultString = toString(result);
1343
- Log.d("ReactNative", "result string="+resultString);
1344
- promise.resolve(resultString);
1345
- } catch (Exception e) {
1346
- Log.d("ReactNative", e.getMessage());
1347
- promise.reject(e);
1348
- }
1349
- });
1350
- }
1351
-
1352
- @ReactMethod
1353
- public void wifiRemoveall(Promise promise) {
1354
- ThreadUtils.runOnExecutor(() -> {
1355
- Log.d("ReactNative", "wifiRemoveall");
1356
- try {
1357
- byte[] result = this.fula.wifiRemoveall();
1358
- String resultString = toString(result);
1359
- Log.d("ReactNative", "result string="+resultString);
1360
- promise.resolve(resultString);
1361
- } catch (Exception e) {
1362
- Log.d("ReactNative", e.getMessage());
1363
- promise.reject(e);
1364
- }
1365
- });
1366
- }
1367
-
1368
- @ReactMethod
1369
- public void reboot(Promise promise) {
1370
- ThreadUtils.runOnExecutor(() -> {
1371
- Log.d("ReactNative", "reboot");
1372
- try {
1373
- byte[] result = this.fula.reboot();
1374
- String resultString = toString(result);
1375
- Log.d("ReactNative", "result string="+resultString);
1376
- promise.resolve(resultString);
1377
- } catch (Exception e) {
1378
- Log.d("ReactNative", e.getMessage());
1379
- promise.reject(e);
1380
- }
1381
- });
1382
- }
1383
-
1384
- }
1
+ package land.fx.fula;
2
+
3
+ import android.util.Log;
4
+
5
+ import androidx.annotation.NonNull;
6
+
7
+ import com.facebook.react.bridge.Promise;
8
+ import com.facebook.react.bridge.ReactApplicationContext;
9
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
10
+ import com.facebook.react.bridge.ReactMethod;
11
+ import com.facebook.react.bridge.WritableMap;
12
+ import com.facebook.react.bridge.WritableNativeMap;
13
+ import com.facebook.react.module.annotations.ReactModule;
14
+ import com.facebook.react.bridge.Arguments;
15
+ import com.facebook.react.bridge.WritableArray;
16
+ import com.facebook.react.bridge.ReadableArray;
17
+
18
+
19
+ import org.apache.commons.io.FileUtils;
20
+ import org.jetbrains.annotations.Contract;
21
+
22
+ import java.io.File;
23
+ import java.io.IOException;
24
+ import java.nio.charset.StandardCharsets;
25
+ import java.security.GeneralSecurityException;
26
+ import java.security.InvalidAlgorithmParameterException;
27
+ import java.security.InvalidKeyException;
28
+ import java.security.NoSuchAlgorithmException;
29
+ import java.util.Arrays;
30
+ import java.util.ArrayList;
31
+
32
+ import javax.crypto.BadPaddingException;
33
+ import javax.crypto.IllegalBlockSizeException;
34
+ import javax.crypto.NoSuchPaddingException;
35
+ import javax.crypto.SecretKey;
36
+
37
+ import java.util.concurrent.Executors;
38
+ import java.util.concurrent.ScheduledExecutorService;
39
+ import java.util.concurrent.TimeUnit;
40
+ import java.util.concurrent.atomic.AtomicBoolean;
41
+ import java.util.concurrent.Future;
42
+ import java.util.concurrent.TimeoutException;
43
+
44
+ import fulamobile.Config;
45
+ import fulamobile.Fulamobile;
46
+
47
+ import land.fx.wnfslib.Fs;
48
+
49
+ @ReactModule(name = FulaModule.NAME)
50
+ public class FulaModule extends ReactContextBaseJavaModule {
51
+
52
+
53
+ @Override
54
+ public void initialize() {
55
+ System.loadLibrary("wnfslib");
56
+ System.loadLibrary("gojni");
57
+ }
58
+
59
+
60
+ public static final String NAME = "FulaModule";
61
+ fulamobile.Client fula;
62
+
63
+ Client client;
64
+ Config fulaConfig;
65
+ String appDir;
66
+ String fulaStorePath;
67
+ String privateForest;
68
+ land.fx.wnfslib.Config rootConfig;
69
+ SharedPreferenceHelper sharedPref;
70
+ SecretKey secretKeyGlobal;
71
+ String identityEncryptedGlobal;
72
+ static String PRIVATE_KEY_STORE_PEERID = "PRIVATE_KEY";
73
+
74
+ public static class Client implements land.fx.wnfslib.Datastore {
75
+
76
+ private final fulamobile.Client internalClient;
77
+
78
+ Client(fulamobile.Client clientInput) {
79
+ this.internalClient = clientInput;
80
+ }
81
+
82
+ @NonNull
83
+ @Override
84
+ public byte[] get(@NonNull byte[] cid) {
85
+ try {
86
+ Log.d("ReactNative", Arrays.toString(cid));
87
+ return this.internalClient.get(cid);
88
+ } catch (Exception e) {
89
+ e.printStackTrace();
90
+ }
91
+ Log.d("ReactNative","Error get");
92
+ return cid;
93
+ }
94
+
95
+ @NonNull
96
+ @Override
97
+ public byte[] put(@NonNull byte[] data, long codec) {
98
+ try {
99
+ //Log.d("ReactNative", "data="+ Arrays.toString(data) +" ;codec="+codec);
100
+ return this.internalClient.put(data, codec);
101
+ } catch (Exception e) {
102
+ Log.d("ReactNative", "put Error="+e.getMessage());
103
+ e.printStackTrace();
104
+ }
105
+ Log.d("ReactNative","Error put");
106
+ return data;
107
+ }
108
+ }
109
+
110
+ public FulaModule(ReactApplicationContext reactContext) {
111
+ super(reactContext);
112
+ appDir = reactContext.getFilesDir().toString();
113
+ fulaStorePath = appDir + "/fula";
114
+ File storeDir = new File(fulaStorePath);
115
+ sharedPref = SharedPreferenceHelper.getInstance(reactContext.getApplicationContext());
116
+ boolean success = true;
117
+ if (!storeDir.exists()) {
118
+ success = storeDir.mkdirs();
119
+ }
120
+ if (success) {
121
+ Log.d(NAME, "Fula store folder created");
122
+ } else {
123
+ Log.d(NAME, "Unable to create fula store folder!");
124
+ }
125
+ }
126
+
127
+ @Override
128
+ @NonNull
129
+ public java.lang.String getName() {
130
+ return NAME;
131
+ }
132
+
133
+
134
+ private byte[] toByte(@NonNull String input) {
135
+ return input.getBytes(StandardCharsets.UTF_8);
136
+ }
137
+
138
+ private byte[] decToByte(@NonNull String input) {
139
+ String[] parts = input.split(",");
140
+ byte[] output = new byte[parts.length];
141
+ for (int i = 0; i < parts.length; i++) {
142
+ output[i] = Byte.parseByte(parts[i]);
143
+ }
144
+ return output;
145
+ }
146
+
147
+ @NonNull
148
+ @Contract("_ -> new")
149
+ public String toString(byte[] input) {
150
+ return new String(input, StandardCharsets.UTF_8);
151
+ }
152
+
153
+ @NonNull
154
+ private static int[] stringArrToIntArr(@NonNull String[] s) {
155
+ int[] result = new int[s.length];
156
+ for (int i = 0; i < s.length; i++) {
157
+ result[i] = Integer.parseInt(s[i]);
158
+ }
159
+ return result;
160
+ }
161
+
162
+ @NonNull
163
+ @Contract(pure = true)
164
+ private static byte[] convertIntToByte(@NonNull int[] input) {
165
+ byte[] result = new byte[input.length];
166
+ for (int i = 0; i < input.length; i++) {
167
+ byte b = (byte) input[i];
168
+ result[i] = b;
169
+ }
170
+ return result;
171
+ }
172
+
173
+ @NonNull
174
+ private byte[] convertStringToByte(@NonNull String data) {
175
+ String[] keyInt_S = data.split(",");
176
+ int[] keyInt = stringArrToIntArr(keyInt_S);
177
+
178
+ return convertIntToByte(keyInt);
179
+ }
180
+
181
+ @ReactMethod
182
+ public void checkConnection(int timeout, Promise promise) {
183
+ Log.d("ReactNative", "checkConnection started");
184
+ ThreadUtils.runOnExecutor(() -> {
185
+ if (this.fula != null) {
186
+ try {
187
+ boolean connectionStatus = this.checkConnectionInternal(timeout);
188
+ Log.d("ReactNative", "checkConnection ended " + connectionStatus);
189
+ promise.resolve(connectionStatus);
190
+ }
191
+ catch (Exception e) {
192
+ Log.d("ReactNative", "checkConnection failed with Error: " + e.getMessage());
193
+ promise.resolve(false);
194
+ }
195
+ } else {
196
+ Log.d("ReactNative", "checkConnection failed with Error: " + "fula is null");
197
+ promise.resolve(false);
198
+ }
199
+ });
200
+ }
201
+
202
+ @ReactMethod
203
+ public void newClient(String identityString, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh, Promise promise) {
204
+ Log.d("ReactNative", "newClient started");
205
+ ThreadUtils.runOnExecutor(() -> {
206
+ try {
207
+ Log.d("ReactNative", "newClient storePath= " + storePath + " bloxAddr= " + bloxAddr + " exchange= " + exchange + " autoFlush= " + autoFlush + " useRelay= " + useRelay + " refresh= " + refresh);
208
+ byte[] identity = toByte(identityString);
209
+ Log.d("ReactNative", "newClient identity= " + identityString);
210
+ this.newClientInternal(identity, storePath, bloxAddr, exchange, autoFlush, useRelay, refresh);
211
+ //String objString = Arrays.toString(obj);
212
+ String peerId = this.fula.id();
213
+ Log.d("ReactNative", "newClient peerId= " + peerId);
214
+ promise.resolve(peerId);
215
+ } catch (Exception e) {
216
+ Log.d("ReactNative", "newClient failed with Error: " + e.getMessage());
217
+ promise.reject("Error", e.getMessage());
218
+ }
219
+ });
220
+ }
221
+
222
+ @ReactMethod
223
+ public void isReady(boolean filesystemCheck, Promise promise) {
224
+ Log.d("ReactNative", "isReady started");
225
+ ThreadUtils.runOnExecutor(() -> {
226
+ boolean initialized = false;
227
+ try {
228
+ if (this.fula != null && this.fula.id() != null) {
229
+ if (filesystemCheck) {
230
+ if (this.client != null && this.rootConfig != null && !this.rootConfig.getCid().isEmpty()) {
231
+ initialized = true;
232
+ Log.d("ReactNative", "isReady is true with filesystem check");
233
+ }
234
+ } else {
235
+ Log.d("ReactNative", "isReady is true without filesystem check");
236
+ initialized = true;
237
+ }
238
+ }
239
+ promise.resolve(initialized);
240
+ } catch (Exception e) {
241
+ Log.d("ReactNative", "isReady failed with Error: " + e.getMessage());
242
+ promise.reject("Error", e.getMessage());
243
+ }
244
+ });
245
+ }
246
+
247
+ @ReactMethod
248
+ public void init(String identityString, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootConfig, boolean useRelay, boolean refresh, Promise promise) {
249
+ Log.d("ReactNative", "init started");
250
+ ThreadUtils.runOnExecutor(() -> {
251
+ try {
252
+ WritableMap resultData = new WritableNativeMap();
253
+ Log.d("ReactNative", "init storePath= " + storePath);
254
+ byte[] identity = toByte(identityString);
255
+ Log.d("ReactNative", "init identity= " + identityString);
256
+ String[] obj = this.initInternal(identity, storePath, bloxAddr, exchange, autoFlush, rootConfig, useRelay, refresh);
257
+ Log.d("ReactNative", "init object created: [ " + obj[0] + ", " + obj[1] + ", " + obj[2] + " ]");
258
+ resultData.putString("peerId", obj[0]);
259
+ resultData.putString("rootCid", obj[1]);
260
+ resultData.putString("private_ref", obj[2]);
261
+ promise.resolve(resultData);
262
+ } catch (Exception e) {
263
+ Log.d("ReactNative", "init failed with Error: " + e.getMessage());
264
+ promise.reject("Error", e.getMessage());
265
+ }
266
+ });
267
+ }
268
+
269
+ @ReactMethod
270
+ public void logout(String identityString, String storePath, Promise promise) {
271
+ Log.d("ReactNative", "logout started");
272
+ ThreadUtils.runOnExecutor(() -> {
273
+ try {
274
+ byte[] identity = toByte(identityString);
275
+ boolean obj = this.logoutInternal(identity, storePath);
276
+ Log.d("ReactNative", "logout completed");
277
+ promise.resolve(obj);
278
+ } catch (Exception e) {
279
+ Log.d("ReactNative", "logout failed with Error: " + e.getMessage());
280
+ promise.reject("Error", e.getMessage());
281
+ }
282
+ });
283
+ }
284
+
285
+ private boolean checkConnectionInternal(int timeout) throws Exception {
286
+ try {
287
+ Log.d("ReactNative", "checkConnectionInternal started");
288
+ if (this.fula != null) {
289
+ try {
290
+ Log.d("ReactNative", "connectToBlox started");
291
+
292
+ AtomicBoolean connectionStatus = new AtomicBoolean(false);
293
+ ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
294
+ Future<?> future = executor.submit(() -> {
295
+ try {
296
+ this.fula.connectToBlox();
297
+ connectionStatus.set(true);
298
+ Log.d("ReactNative", "checkConnectionInternal succeeded ");
299
+ } catch (Exception e) {
300
+ Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
301
+ }
302
+ });
303
+
304
+ try {
305
+ future.get(timeout, TimeUnit.SECONDS);
306
+ } catch (TimeoutException te) {
307
+ // If the timeout occurs, shut down the executor and return false
308
+ executor.shutdownNow();
309
+ return false;
310
+ } finally {
311
+ // If the future task is done, we can shut down the executor
312
+ if (future.isDone()) {
313
+ executor.shutdown();
314
+ }
315
+ }
316
+
317
+ return connectionStatus.get();
318
+ } catch (Exception e) {
319
+ Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
320
+ return false;
321
+ }
322
+ } else {
323
+ Log.d("ReactNative", "checkConnectionInternal failed because fula is not initialized ");
324
+ return false;
325
+ }
326
+ } catch (Exception e) {
327
+ Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
328
+ throw (e);
329
+ }
330
+ }
331
+
332
+ @ReactMethod
333
+ public void checkFailedActions(boolean retry, int timeout, Promise promise) throws Exception {
334
+ try {
335
+ if (this.fula != null) {
336
+ if (!retry) {
337
+ Log.d("ReactNative", "checkFailedActions without retry");
338
+ fulamobile.LinkIterator failedLinks = this.fula.listFailedPushes();
339
+ if (failedLinks.hasNext()) {
340
+ Log.d("ReactNative", "checkFailedActions found: "+Arrays.toString(failedLinks.next()));
341
+ promise.resolve(true);
342
+ } else {
343
+ promise.resolve(false);
344
+ }
345
+ } else {
346
+ Log.d("ReactNative", "checkFailedActions with retry");
347
+ boolean retryResults = this.retryFailedActionsInternal(timeout);
348
+ promise.resolve(!retryResults);
349
+ }
350
+ } else {
351
+ throw new Exception("Fula is not initialized");
352
+ }
353
+ } catch (Exception e) {
354
+ Log.d("ReactNative", "checkFailedActions failed with Error: " + e.getMessage());
355
+ throw (e);
356
+ }
357
+ }
358
+
359
+ @ReactMethod
360
+ private void listFailedActions(ReadableArray cids, Promise promise) throws Exception {
361
+ try {
362
+ if (this.fula != null) {
363
+ Log.d("ReactNative", "listFailedActions");
364
+ fulamobile.StringIterator failedLinks = this.fula.listFailedPushesAsString();
365
+ ArrayList<String> failedLinksList = new ArrayList<>();
366
+ while (failedLinks.hasNext()) {
367
+ failedLinksList.add(failedLinks.next());
368
+ }
369
+ if (cids.size() > 0) {
370
+ // If cids array is provided, filter the failedLinksList
371
+ ArrayList<String> cidsList = new ArrayList<>();
372
+ for (int i = 0; i < cids.size(); i++) {
373
+ cidsList.add(cids.getString(i));
374
+ }
375
+ cidsList.retainAll(failedLinksList); // Keep only the elements in both cidsList and failedLinksList
376
+ if (!cidsList.isEmpty()) {
377
+ // If there are any matching cids, return them
378
+ WritableArray cidsArray = Arguments.createArray();
379
+ for (String cid : cidsList) {
380
+ cidsArray.pushString(cid);
381
+ }
382
+ promise.resolve(cidsArray);
383
+ } else {
384
+ // If there are no matching cids, return false
385
+ promise.resolve(false);
386
+ }
387
+ } else if (!failedLinksList.isEmpty()) {
388
+ // If cids array is not provided, return the whole list
389
+ Log.d("ReactNative", "listFailedActions found: "+ failedLinksList);
390
+ WritableArray failedLinksArray = Arguments.createArray();
391
+ for (String link : failedLinksList) {
392
+ failedLinksArray.pushString(link);
393
+ }
394
+ promise.resolve(failedLinksArray);
395
+ } else {
396
+ promise.resolve(false);
397
+ }
398
+ } else {
399
+ throw new Exception("listFailedActions: Fula is not initialized");
400
+ }
401
+ } catch (Exception e) {
402
+ Log.d("ReactNative", "listFailedActions failed with Error: " + e.getMessage());
403
+ throw (e);
404
+ }
405
+ }
406
+
407
+
408
+
409
+
410
+ private boolean retryFailedActionsInternal(int timeout) throws Exception {
411
+ try {
412
+ Log.d("ReactNative", "retryFailedActionsInternal started");
413
+ if (this.fula != null) {
414
+ //Fula is initialized
415
+ try {
416
+ boolean connectionCheck = this.checkConnectionInternal(timeout);
417
+ if(connectionCheck) {
418
+ try {
419
+ Log.d("ReactNative", "retryFailedPushes started");
420
+ this.fula.retryFailedPushes();
421
+ Log.d("ReactNative", "flush started");
422
+ this.fula.flush();
423
+ return true;
424
+ }
425
+ catch (Exception e) {
426
+ this.fula.flush();
427
+ Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
428
+ return false;
429
+ }
430
+ //Blox online
431
+ /*fulamobile.LinkIterator failedLinks = this.fula.listFailedPushes();
432
+ if (failedLinks.hasNext()) {
433
+ Log.d("ReactNative", "Failed links");
434
+ //Failed list is not empty. iterate in the list
435
+ while (failedLinks.hasNext()) {
436
+ //Get the missing key
437
+ byte[] failedNode = failedLinks.next();
438
+ try {
439
+ //Push to Blox
440
+ Log.d("ReactNative", "Pushing Failed links "+Arrays.toString(failedNode));
441
+ this.pushInternal(failedNode);
442
+ Log.d("ReactNative", "Failed links pushed");
443
+ }
444
+ catch (Exception e) {
445
+ Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
446
+ }
447
+ }
448
+ //check if list is empty now and all are pushed
449
+ Log.d("ReactNative", "Pushing finished");
450
+ fulamobile.LinkIterator failedLinks_after = this.fula.listFailedPushes();
451
+ if(failedLinks_after.hasNext()) {
452
+ //Some pushes failed
453
+ byte[] first_failed = failedLinks_after.next();
454
+ Log.d("ReactNative", "Failed links are not empty "+Arrays.toString(first_failed));
455
+ return false;
456
+ } else {
457
+ //All pushes successful
458
+ return true;
459
+ }
460
+ } else {
461
+ Log.d("ReactNative", "No Failed links");
462
+ //Failed list is empty
463
+ return true;
464
+ }*/
465
+ } else {
466
+ Log.d("ReactNative", "retryFailedActionsInternal failed because blox is offline");
467
+ //Blox Offline
468
+ return false;
469
+ }
470
+ }
471
+ catch (Exception e) {
472
+ Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
473
+ return false;
474
+ }
475
+ } else {
476
+ Log.d("ReactNative", "retryFailedActionsInternal failed because fula is not initialized");
477
+ //Fula is not initialized
478
+ return false;
479
+ }
480
+ } catch (Exception e) {
481
+ Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
482
+ throw (e);
483
+ }
484
+ }
485
+
486
+ @NonNull
487
+ private byte[] createPeerIdentity(byte[] identity) throws GeneralSecurityException, IOException {
488
+ try {
489
+ // 1: First: create public key from provided private key
490
+ // 2: Should read the local keychain store (if it is key-value, key is public key above,
491
+ // 3: if found, decrypt using the private key
492
+ // 4: If not found or decryption not successful, generate an identity
493
+ // 5: then encrypt and store in keychain
494
+ byte[] libp2pId;
495
+ String encryptedLibp2pId = sharedPref.getValue(PRIVATE_KEY_STORE_PEERID);
496
+ byte[] encryptionPair;
497
+ SecretKey encryptionSecretKey;
498
+ try {
499
+ encryptionSecretKey = Cryptography.generateKey(identity);
500
+ Log.d("ReactNative", "encryptionSecretKey generated from privateKey");
501
+ } catch (Exception e) {
502
+ Log.d("ReactNative", "Failed to generate key for encryption: " + e.getMessage());
503
+ throw new GeneralSecurityException("Failed to generate key encryption", e);
504
+ }
505
+
506
+ if (encryptedLibp2pId == null || !encryptedLibp2pId.startsWith("FULA_ENC_V3:")) {
507
+ Log.d("ReactNative", "encryptedLibp2pId is not correct. creating new one " + encryptedLibp2pId);
508
+
509
+ try {
510
+ libp2pId = Fulamobile.generateEd25519KeyFromString(toString(identity));
511
+ } catch (Exception e) {
512
+ Log.d("ReactNative", "Failed to generate libp2pId: " + e.getMessage());
513
+ throw new GeneralSecurityException("Failed to generate libp2pId", e);
514
+ }
515
+ encryptedLibp2pId = "FULA_ENC_V3:" + Cryptography.encryptMsg(StaticHelper.bytesToBase64(libp2pId), encryptionSecretKey);
516
+ sharedPref.add(PRIVATE_KEY_STORE_PEERID, encryptedLibp2pId);
517
+ } else {
518
+ Log.d("ReactNative", "encryptedLibp2pId is correct. decrypting " + encryptedLibp2pId);
519
+ }
520
+
521
+ try {
522
+ String decryptedLibp2pId = Cryptography.decryptMsg(encryptedLibp2pId.replace("FULA_ENC_V3:", ""), encryptionSecretKey);
523
+
524
+ return StaticHelper.base64ToBytes(decryptedLibp2pId);
525
+ } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
526
+ Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e.getMessage());
527
+ throw (e);
528
+ }
529
+
530
+ } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
531
+ Log.d("ReactNative", "createPeerIdentity failed with Error: " + e.getMessage());
532
+ throw (e);
533
+ }
534
+ }
535
+
536
+ private void createNewRootConfig(FulaModule.Client iClient, byte[] identity) throws Exception {
537
+ this.privateForest = Fs.createPrivateForest(iClient);
538
+ Log.d("ReactNative", "privateForest is created: " + this.privateForest);
539
+ this.rootConfig = Fs.createRootDir(iClient, this.privateForest, identity);
540
+ if (this.fula != null) {
541
+ this.fula.flush();
542
+ }
543
+ Log.d("ReactNative", "new rootConfig is created: cid=" + this.rootConfig.getCid()+" & private_ref="+this.rootConfig.getPrivate_ref());
544
+
545
+ this.encrypt_and_store_config();
546
+ }
547
+
548
+ private String getPrivateRef(FulaModule.Client iClient, byte[] wnfsKey, String rootCid) throws Exception {
549
+ Log.d("ReactNative", "getPrivateRef called: rootCid=" + rootCid);
550
+ String privateRef = Fs.getPrivateRef(iClient, wnfsKey, rootCid);
551
+ Log.d("ReactNative", "getPrivateRef completed: privateRef=" + privateRef);
552
+ return privateRef;
553
+ }
554
+
555
+ private boolean encrypt_and_store_config() throws Exception {
556
+ try {
557
+ if(this.identityEncryptedGlobal != null && !this.identityEncryptedGlobal.isEmpty()) {
558
+ String cid_encrypted = Cryptography.encryptMsg(this.rootConfig.getCid(), this.secretKeyGlobal);
559
+ String private_ref_encrypted = Cryptography.encryptMsg(this.rootConfig.getPrivate_ref(), this.secretKeyGlobal);
560
+
561
+ sharedPref.add("FULA_ENC_V3:cid_encrypted_" + this.identityEncryptedGlobal, cid_encrypted);
562
+ sharedPref.add("FULA_ENC_V3:private_ref_encrypted_" + this.identityEncryptedGlobal, private_ref_encrypted);
563
+ return true;
564
+ } else {
565
+ return false;
566
+ }
567
+ } catch (Exception e) {
568
+ Log.d("ReactNative", "encrypt_and_store_config failed with Error: " + e.getMessage());
569
+ throw (e);
570
+ }
571
+ }
572
+
573
+ private boolean logoutInternal(byte[] identity, String storePath) throws Exception {
574
+ try {
575
+ if (this.fula != null) {
576
+ this.fula.flush();
577
+ }
578
+ SecretKey secretKey = Cryptography.generateKey(identity);
579
+
580
+ String identity_encrypted = Cryptography.encryptMsg(Arrays.toString(identity), secretKey);
581
+ sharedPref.remove("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
582
+ sharedPref.remove("FULA_ENC_V3:private_ref_encrypted_"+identity_encrypted);
583
+
584
+ //TODO: Should also remove peerid @Mahdi
585
+
586
+ sharedPref.remove("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
587
+ sharedPref.remove("FULA_ENC_V3:private_ref_encrypted_"+ identity_encrypted);
588
+
589
+ this.rootConfig = null;
590
+ this.secretKeyGlobal = null;
591
+ this.identityEncryptedGlobal = null;
592
+
593
+ if (storePath == null || storePath.trim().isEmpty()) {
594
+ storePath = this.fulaStorePath;
595
+ }
596
+
597
+ File file = new File(storePath);
598
+ FileUtils.deleteDirectory(file);
599
+ return true;
600
+
601
+ } catch (Exception e) {
602
+ Log.d("ReactNative", "logout internal failed with Error: " + e.getMessage());
603
+ throw (e);
604
+ }
605
+ }
606
+
607
+ public fulamobile.Client getFulaClient() {
608
+ return this.fula;
609
+ }
610
+
611
+ @NonNull
612
+ private byte[] newClientInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh) throws GeneralSecurityException, IOException {
613
+ byte[] peerIdentity = null;
614
+ try {
615
+ fulaConfig = new Config();
616
+ if (storePath == null || storePath.trim().isEmpty()) {
617
+ fulaConfig.setStorePath(this.fulaStorePath);
618
+ } else {
619
+ fulaConfig.setStorePath(storePath);
620
+ }
621
+ Log.d("ReactNative", "newClientInternal storePath is set: " + fulaConfig.getStorePath());
622
+
623
+ peerIdentity = this.createPeerIdentity(identity);
624
+ fulaConfig.setIdentity(peerIdentity);
625
+ Log.d("ReactNative", "peerIdentity is set: " + toString(fulaConfig.getIdentity()));
626
+ fulaConfig.setBloxAddr(bloxAddr);
627
+ Log.d("ReactNative", "bloxAddr is set: " + fulaConfig.getBloxAddr());
628
+ fulaConfig.setExchange(exchange);
629
+ fulaConfig.setSyncWrites(autoFlush);
630
+ if (useRelay) {
631
+ fulaConfig.setAllowTransientConnection(true);
632
+ fulaConfig.setForceReachabilityPrivate(true);
633
+ }
634
+ if (this.fula == null || refresh) {
635
+ Log.d("ReactNative", "Creating a new Fula instance");
636
+ try {
637
+ shutdownInternal();
638
+ this.fula = Fulamobile.newClient(fulaConfig);
639
+ if (this.fula != null) {
640
+ this.fula.flush();
641
+ }
642
+ } catch (Exception e) {
643
+ Log.d("ReactNative", "Failed to create new Fula instance: " + e.getMessage());
644
+ throw new IOException("Failed to create new Fula instance", e);
645
+ }
646
+ }
647
+ } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
648
+ Log.d("ReactNative", "newclientInternal failed with Error: " + e.getMessage());
649
+ throw (e);
650
+ }
651
+ return peerIdentity;
652
+ }
653
+
654
+
655
+ @NonNull
656
+ private String[] initInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootCid, boolean useRelay, boolean refresh) throws Exception {
657
+ try {
658
+ if (this.fula == null || refresh) {
659
+ this.newClientInternal(identity, storePath, bloxAddr, exchange, autoFlush, useRelay, refresh);
660
+ }
661
+ if(this.client == null || refresh) {
662
+ this.client = new Client(this.fula);
663
+ Log.d("ReactNative", "fula initialized: " + this.fula.id());
664
+ }
665
+
666
+ SecretKey secretKey = Cryptography.generateKey(identity);
667
+ String identity_encrypted =Cryptography.encryptMsg(Arrays.toString(identity), secretKey);
668
+ this.identityEncryptedGlobal = identity_encrypted;
669
+ this.secretKeyGlobal = secretKey;
670
+
671
+ if (this.rootConfig == null || this.rootConfig.getCid().isEmpty() || this.rootConfig.getPrivate_ref().isEmpty()) {
672
+ Log.d("ReactNative", "this.rootCid is empty.");
673
+ //Load from keystore
674
+
675
+ String cid_encrypted_fetched = sharedPref.getValue("FULA_ENC_V3:cid_encrypted_"+ identity_encrypted);
676
+ String private_ref_encrypted_fetched = sharedPref.getValue("FULA_ENC_V3:private_ref_encrypted_"+identity_encrypted);
677
+ Log.d("ReactNative", "Here1");
678
+ String cid = "";
679
+ String private_ref = "";
680
+ if(cid_encrypted_fetched != null && !cid_encrypted_fetched.isEmpty()) {
681
+ Log.d("ReactNative", "decrypting cid="+cid_encrypted_fetched+" with secret="+secretKey.toString());
682
+ cid = Cryptography.decryptMsg(cid_encrypted_fetched, secretKey);
683
+ }
684
+ if(private_ref_encrypted_fetched != null && !private_ref_encrypted_fetched.isEmpty()) {
685
+ Log.d("ReactNative", "decrypting private_ref="+private_ref_encrypted_fetched+" with secret="+secretKey.toString());
686
+ private_ref = Cryptography.decryptMsg(private_ref_encrypted_fetched, secretKey);
687
+ }
688
+ Log.d("ReactNative", "Here2");
689
+ //Log.d("ReactNative", "Attempted to fetch cid from keystore; cid="+cid+" & private_ref="+private_ref);
690
+ if((cid == null || cid.isEmpty()) || (private_ref == null || private_ref.isEmpty()) ){
691
+ Log.d("ReactNative", "cid or PrivateRef was not found");
692
+ if(rootCid != null && !rootCid.isEmpty()){
693
+ Log.d("ReactNative", "Re-setting cid from input: "+rootCid);
694
+ cid = rootCid;
695
+ }
696
+ if((private_ref == null || private_ref.isEmpty()) && (cid != null && !cid.isEmpty())){
697
+ Log.d("ReactNative", "Re-fetching privateRef from wnfs: cid="+cid);
698
+ private_ref = this.getPrivateRef(this.client, identity, cid);
699
+ Log.d("ReactNative", "Re-fetching privateRef from wnfs: "+private_ref);
700
+ }
701
+ if(cid == null || cid.isEmpty() || private_ref == null || private_ref.isEmpty()) {
702
+ Log.d("ReactNative", "Tried to recover cid and privateRef but was not successful. Creating new ones");
703
+ this.createNewRootConfig(this.client, identity);
704
+ } else {
705
+ Log.d("ReactNative", "Tried to recover cid and privateRef and was successful. cid:"+cid+" & private_ref="+private_ref);
706
+ this.rootConfig = new land.fx.wnfslib.Config(cid, private_ref);
707
+ this.encrypt_and_store_config();
708
+ }
709
+ } else if(cid != null && !cid.isEmpty() && private_ref != null && !private_ref.isEmpty()) {
710
+ Log.d("ReactNative", "Found cid and private ref in keychain store");
711
+ if(cid != null && !cid.isEmpty() && private_ref != null && !private_ref.isEmpty()) {
712
+ Log.d("ReactNative", "Recovered cid and private ref from keychain store. cid="+cid+" & private_ref="+private_ref);
713
+ this.rootConfig = new land.fx.wnfslib.Config(cid, private_ref);
714
+ } else{
715
+ Log.d("ReactNative", "Found but Could not recover cid and private_ref from keychain store");
716
+ this.createNewRootConfig(this.client, identity);
717
+ }
718
+ } else{
719
+ Log.d("ReactNative", "This cid and private_ref generation should never happen!!!");
720
+ //Create new root and store cid and private_ref
721
+ this.createNewRootConfig(this.client, identity);
722
+ }
723
+
724
+
725
+ Log.d("ReactNative", "creating rootConfig completed");
726
+
727
+ /*
728
+ byte[] testbyte = convertStringToByte("-104,40,24,-93,24,100,24,114,24,111,24,111,24,116,24,-126,24,-126,0,0,24,-128,24,103,24,118,24,101,24,114,24,115,24,105,24,111,24,110,24,101,24,48,24,46,24,49,24,46,24,48,24,105,24,115,24,116,24,114,24,117,24,99,24,116,24,117,24,114,24,101,24,100,24,104,24,97,24,109,24,116");
729
+ long testcodec = 85;
730
+ byte[] testputcid = this.client.put(testbyte, testcodec);
731
+ Log.d("ReactNative", "client.put test done"+ Arrays.toString(testputcid));
732
+ byte[] testfetchedcid = convertStringToByte("1,113,18,32,-6,-63,-128,79,-102,-89,57,77,-8,67,-98,8,-81,40,-87,123,122,29,-52,-124,-60,-53,100,105,125,123,-5,-99,41,106,-124,-64");
733
+ byte[] testfetchedbytes = this.client.get(testfetchedcid);
734
+ Log.d("ReactNative", "client.get test done"+ Arrays.toString(testfetchedbytes));
735
+ */
736
+
737
+
738
+ Log.d("ReactNative", "rootConfig is created: cid=" + this.rootConfig.getCid()+ "& private_ref="+this
739
+ .rootConfig.getPrivate_ref());
740
+ } else {
741
+ Log.d("ReactNative", "rootConfig existed: cid=" + this.rootConfig.getCid()+ " & private_ref="+this.rootConfig.getPrivate_ref());
742
+ }
743
+ String peerId = this.fula.id();
744
+ String[] obj = new String[3];
745
+ obj[0] = peerId;
746
+ obj[1] = this.rootConfig.getCid();
747
+ obj[2] = this.rootConfig.getPrivate_ref();
748
+ Log.d("ReactNative", "initInternal is completed successfully");
749
+ if (this.fula != null) {
750
+ this.fula.flush();
751
+ }
752
+ return obj;
753
+ } catch (Exception e) {
754
+ Log.d("ReactNative", "init internal failed with Error: " + e.getMessage());
755
+ throw (e);
756
+ }
757
+ }
758
+
759
+ @ReactMethod
760
+ public void mkdir(String path, Promise promise) {
761
+ ThreadUtils.runOnExecutor(() -> {
762
+ Log.d("ReactNative", "mkdir: path = " + path);
763
+ try {
764
+ land.fx.wnfslib.Config config = Fs.mkdir(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path);
765
+ if(config != null) {
766
+ this.rootConfig = config;
767
+ this.encrypt_and_store_config();
768
+ if (this.fula != null) {
769
+ this.fula.flush();
770
+ }
771
+ promise.resolve(config.getCid());
772
+ } else {
773
+ Log.d("ReactNative", "mkdir Error: config is null");
774
+ promise.reject(new Exception("mkdir Error: config is null"));
775
+ }
776
+ } catch (Exception e) {
777
+ Log.d("get", e.getMessage());
778
+ promise.reject(e);
779
+ }
780
+ });
781
+ }
782
+
783
+ @ReactMethod
784
+ public void writeFile(String fulaTargetFilename, String localFilename, Promise promise) {
785
+ /*
786
+ // reads content of the file form localFilename (should include full absolute path to local file with read permission
787
+ // writes content to the specified location by fulaTargetFilename in Fula filesystem
788
+ // fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
789
+ // localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
790
+ // Returns: new cid of the root after this file is placed in the tree
791
+ */
792
+ ThreadUtils.runOnExecutor(() -> {
793
+ Log.d("ReactNative", "writeFile to : path = " + fulaTargetFilename + ", from: " + localFilename);
794
+ try {
795
+ if (this.client != null) {
796
+ Log.d("ReactNative", "writeFileFromPath started: this.rootConfig.getCid=" + this.rootConfig.getCid()+ ", fulaTargetFilename="+fulaTargetFilename + ", localFilename="+localFilename);
797
+ land.fx.wnfslib.Config config = Fs.writeFileFromPath(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), fulaTargetFilename, localFilename);
798
+ if(config != null) {
799
+ this.rootConfig = config;
800
+ this.encrypt_and_store_config();
801
+ if (this.fula != null) {
802
+ this.fula.flush();
803
+ promise.resolve(config.getCid());
804
+ } else {
805
+ Log.d("ReactNative", "writeFile Error: fula is null");
806
+ promise.reject(new Exception("writeFile Error: fula is null"));
807
+ }
808
+ } else {
809
+ Log.d("ReactNative", "writeFile Error: config is null");
810
+ promise.reject(new Exception("writeFile Error: config is null"));
811
+ }
812
+ } else {
813
+ Log.d("ReactNative", "writeFile Error: client is null");
814
+ promise.reject(new Exception("writeFile Error: client is null"));
815
+ }
816
+ } catch (Exception e) {
817
+ Log.d("get", e.getMessage());
818
+ promise.reject(e);
819
+ }
820
+ });
821
+ }
822
+
823
+ @ReactMethod
824
+ public void writeFileContent(String path, String contentString, Promise promise) {
825
+ ThreadUtils.runOnExecutor(() -> {
826
+ Log.d("ReactNative", "writeFile: contentString = " + contentString);
827
+ Log.d("ReactNative", "writeFile: path = " + path);
828
+ try {
829
+ byte[] content = this.convertStringToByte(contentString);
830
+ land.fx.wnfslib.Config config = Fs.writeFile(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path, content);
831
+ this.rootConfig = config;
832
+ this.encrypt_and_store_config();
833
+ if (this.fula != null) {
834
+ this.fula.flush();
835
+ }
836
+ promise.resolve(config.getCid());
837
+ } catch (Exception e) {
838
+ Log.d("get", e.getMessage());
839
+ promise.reject(e);
840
+ }
841
+ });
842
+ }
843
+
844
+ @ReactMethod
845
+ public void ls(String path, Promise promise) {
846
+ ThreadUtils.runOnExecutor(() -> {
847
+ Log.d("ReactNative", "ls: path = " + path);
848
+ try {
849
+ byte[] res = Fs.ls(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path);
850
+
851
+ //JSONArray jsonArray = new JSONArray(res);
852
+ String s = new String(res, StandardCharsets.UTF_8);
853
+ Log.d("ReactNative", "ls: res = " + s);
854
+ promise.resolve(s);
855
+ } catch (Exception e) {
856
+ Log.d("get", e.getMessage());
857
+ promise.reject(e);
858
+ }
859
+ });
860
+ }
861
+
862
+ @ReactMethod
863
+ public void rm(String path, Promise promise) {
864
+ ThreadUtils.runOnExecutor(() -> {
865
+ Log.d("ReactNative", "rm: path = " + path);
866
+ try {
867
+ land.fx.wnfslib.Config config = Fs.rm(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path);
868
+ if(config != null) {
869
+ this.rootConfig = config;
870
+ this.encrypt_and_store_config();
871
+ if (this.fula != null) {
872
+ this.fula.flush();
873
+ }
874
+ promise.resolve(config.getCid());
875
+ } else {
876
+ Log.d("ReactNative", "rm Error: config is null");
877
+ promise.reject(new Exception("rm Error: config is null"));
878
+ }
879
+ } catch (Exception e) {
880
+ Log.d("get", e.getMessage());
881
+ promise.reject(e);
882
+ }
883
+ });
884
+ }
885
+
886
+ @ReactMethod
887
+ public void cp(String sourcePath, String targetPath, Promise promise) {
888
+ ThreadUtils.runOnExecutor(() -> {
889
+ Log.d("ReactNative", "rm: sourcePath = " + sourcePath);
890
+ try {
891
+ land.fx.wnfslib.Config config = Fs.cp(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), sourcePath, targetPath);
892
+ if(config != null) {
893
+ this.rootConfig = config;
894
+ this.encrypt_and_store_config();
895
+ if (this.fula != null) {
896
+ this.fula.flush();
897
+ }
898
+ promise.resolve(config.getCid());
899
+ } else {
900
+ Log.d("ReactNative", "cp Error: config is null");
901
+ promise.reject(new Exception("cp Error: config is null"));
902
+ }
903
+ } catch (Exception e) {
904
+ Log.d("get", e.getMessage());
905
+ promise.reject(e);
906
+ }
907
+ });
908
+ }
909
+
910
+ @ReactMethod
911
+ public void mv(String sourcePath, String targetPath, Promise promise) {
912
+ ThreadUtils.runOnExecutor(() -> {
913
+ Log.d("ReactNative", "rm: sourcePath = " + sourcePath);
914
+ try {
915
+ land.fx.wnfslib.Config config = Fs.mv(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), sourcePath, targetPath);
916
+ if(config != null) {
917
+ this.rootConfig = config;
918
+ this.encrypt_and_store_config();
919
+ if (this.fula != null) {
920
+ this.fula.flush();
921
+ }
922
+ promise.resolve(config.getCid());
923
+ } else {
924
+ Log.d("ReactNative", "mv Error: config is null");
925
+ promise.reject(new Exception("mv Error: config is null"));
926
+ }
927
+ } catch (Exception e) {
928
+ Log.d("get", e.getMessage());
929
+ promise.reject(e);
930
+ }
931
+ });
932
+ }
933
+
934
+ @ReactMethod
935
+ public void readFile(String fulaTargetFilename, String localFilename, Promise promise) {
936
+ /*
937
+ // reads content of the file form localFilename (should include full absolute path to local file with read permission
938
+ // writes content to the specified location by fulaTargetFilename in Fula filesystem
939
+ // fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
940
+ // localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
941
+ // Returns: new cid of the root after this file is placed in the tree
942
+ */
943
+ ThreadUtils.runOnExecutor(() -> {
944
+ Log.d("ReactNative", "readFile: fulaTargetFilename = " + fulaTargetFilename);
945
+ try {
946
+ String path = Fs.readFilestreamToPath(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), fulaTargetFilename, localFilename);
947
+ promise.resolve(path);
948
+ } catch (Exception e) {
949
+ Log.d("get", e.getMessage());
950
+ promise.reject(e);
951
+ }
952
+ });
953
+ }
954
+
955
+ @ReactMethod
956
+ public void readFileContent(String path, Promise promise) {
957
+ ThreadUtils.runOnExecutor(() -> {
958
+ Log.d("ReactNative", "readFileContent: path = " + path);
959
+ try {
960
+ byte[] res = Fs.readFile(this.client, this.rootConfig.getCid(), this.rootConfig.getPrivate_ref(), path);
961
+ String resString = toString(res);
962
+ promise.resolve(resString);
963
+ } catch (Exception e) {
964
+ Log.d("get", e.getMessage());
965
+ promise.reject(e);
966
+ }
967
+ });
968
+ }
969
+
970
+ @ReactMethod
971
+ public void get(String keyString, Promise promise) {
972
+ ThreadUtils.runOnExecutor(() -> {
973
+ Log.d("ReactNative", "get: keyString = " + keyString);
974
+ try {
975
+ byte[] key = this.convertStringToByte(keyString);
976
+ byte[] value = this.getInternal(key);
977
+ String valueString = toString(value);
978
+ promise.resolve(valueString);
979
+ } catch (Exception e) {
980
+ Log.d("get", e.getMessage());
981
+ promise.reject(e);
982
+ }
983
+ });
984
+ }
985
+
986
+ @NonNull
987
+ private byte[] getInternal(byte[] key) throws Exception {
988
+ try {
989
+ Log.d("ReactNative", "getInternal: key.toString() = " + toString(key));
990
+ Log.d("ReactNative", "getInternal: key.toString().bytes = " + Arrays.toString(key));
991
+ byte[] value = this.fula.get(key);
992
+ Log.d("ReactNative", "getInternal: value.toString() = " + toString(value));
993
+ return value;
994
+ } catch (Exception e) {
995
+ Log.d("ReactNative", "getInternal: error = " + e.getMessage());
996
+ Log.d("getInternal", e.getMessage());
997
+ throw (e);
998
+ }
999
+ }
1000
+
1001
+ @ReactMethod
1002
+ public void has(String keyString, Promise promise) {
1003
+ ThreadUtils.runOnExecutor(() -> {
1004
+ Log.d("ReactNative", "has: keyString = " + keyString);
1005
+ try {
1006
+ byte[] key = this.convertStringToByte(keyString);
1007
+ boolean result = this.hasInternal(key);
1008
+ promise.resolve(result);
1009
+ } catch (Exception e) {
1010
+ Log.d("get", e.getMessage());
1011
+ promise.reject(e);
1012
+ }
1013
+ });
1014
+ }
1015
+
1016
+ private boolean hasInternal(byte[] key) throws Exception {
1017
+ try {
1018
+ boolean res = this.fula.has(key);
1019
+ return res;
1020
+ } catch (Exception e) {
1021
+ Log.d("hasInternal", e.getMessage());
1022
+ throw (e);
1023
+ }
1024
+ }
1025
+
1026
+ private void pullInternal(byte[] key) throws Exception {
1027
+ try {
1028
+ this.fula.pull(key);
1029
+ } catch (Exception e) {
1030
+ Log.d("pullInternal", e.getMessage());
1031
+ throw (e);
1032
+ }
1033
+ }
1034
+
1035
+ @ReactMethod
1036
+ public void push(Promise promise) {
1037
+ ThreadUtils.runOnExecutor(() -> {
1038
+ Log.d("ReactNative", "push started");
1039
+ try {
1040
+ this.pushInternal(this.convertStringToByte(this.rootConfig.getCid()));
1041
+ promise.resolve(this.rootConfig.getCid());
1042
+ } catch (Exception e) {
1043
+ Log.d("get", e.getMessage());
1044
+ promise.reject(e);
1045
+ }
1046
+ });
1047
+ }
1048
+
1049
+ private void pushInternal(byte[] key) throws Exception {
1050
+ try {
1051
+ if (this.fula != null && this.fula.has(key)) {
1052
+ this.fula.push(key);
1053
+ this.fula.flush();
1054
+ } else {
1055
+ Log.d("ReactNative", "pushInternal error: key wasn't found or fula is not initialized");
1056
+ throw new Exception("key wasn't found in local storage");
1057
+ }
1058
+ } catch (Exception e) {
1059
+ Log.d("ReactNative", "pushInternal"+ e.getMessage());
1060
+ throw (e);
1061
+ }
1062
+ }
1063
+
1064
+ @ReactMethod
1065
+ public void put(String valueString, String codecString, Promise promise) {
1066
+ ThreadUtils.runOnExecutor(() -> {
1067
+ Log.d("ReactNative", "put: codecString = " + codecString);
1068
+ Log.d("ReactNative", "put: valueString = " + valueString);
1069
+ try {
1070
+ //byte[] codec = this.convertStringToByte(CodecString);
1071
+ long codec = Long.parseLong(codecString);
1072
+
1073
+
1074
+ Log.d("ReactNative", "put: codec = " + codec);
1075
+ byte[] value = toByte(valueString);
1076
+
1077
+ Log.d("ReactNative", "put: value.toString() = " + toString(value));
1078
+ byte[] key = this.putInternal(value, codec);
1079
+ Log.d("ReactNative", "put: key.toString() = " + toString(key));
1080
+ promise.resolve(toString(key));
1081
+ } catch (Exception e) {
1082
+ Log.d("ReactNative", "put: error = " + e.getMessage());
1083
+ promise.reject(e);
1084
+ }
1085
+ });
1086
+ }
1087
+
1088
+ @NonNull
1089
+ private byte[] putInternal(byte[] value, long codec) throws Exception {
1090
+ try {
1091
+ if(this.fula != null) {
1092
+ byte[] key = this.fula.put(value, codec);
1093
+ this.fula.flush();
1094
+ return key;
1095
+ } else {
1096
+ Log.d("ReactNative", "putInternal Error: fula is not initialized");
1097
+ throw (new Exception("putInternal Error: fula is not initialized"));
1098
+ }
1099
+ } catch (Exception e) {
1100
+ Log.d("ReactNative", "putInternal"+ e.getMessage());
1101
+ throw (e);
1102
+ }
1103
+ }
1104
+
1105
+ @ReactMethod
1106
+ public void setAuth(String peerIdString, boolean allow, Promise promise) {
1107
+ ThreadUtils.runOnExecutor(() -> {
1108
+ Log.d("ReactNative", "setAuth: peerIdString = " + peerIdString);
1109
+ try {
1110
+ if (this.fula != null && this.fula.id() != null && this.fulaConfig != null && this.fulaConfig.getBloxAddr() != null) {
1111
+ String bloxAddr = this.fulaConfig.getBloxAddr();
1112
+ Log.d("ReactNative", "setAuth: bloxAddr = '" + bloxAddr+"'"+ " peerIdString = '" + peerIdString+"'");
1113
+ int index = bloxAddr.lastIndexOf("/");
1114
+ String bloxPeerId = bloxAddr.substring(index + 1);
1115
+ this.fula.setAuth(bloxPeerId, peerIdString, allow);
1116
+ promise.resolve(true);
1117
+ } else {
1118
+ Log.d("ReactNative", "setAuth error: fula is not initialized");
1119
+ throw new Exception("fula is not initialized");
1120
+ }
1121
+ promise.resolve(false);
1122
+ } catch (Exception e) {
1123
+ Log.d("get", e.getMessage());
1124
+ promise.reject(e);
1125
+ }
1126
+ });
1127
+ }
1128
+
1129
+ private void shutdownInternal() throws Exception {
1130
+ try {
1131
+ if(this.fula != null) {
1132
+ this.fula.shutdown();
1133
+ this.fula = null;
1134
+ this.client = null;
1135
+ }
1136
+ } catch (Exception e) {
1137
+ Log.d("ReactNative", "shutdownInternal"+ e.getMessage());
1138
+ throw (e);
1139
+ }
1140
+ }
1141
+
1142
+ @ReactMethod
1143
+ public void shutdown(Promise promise) {
1144
+ ThreadUtils.runOnExecutor(() -> {
1145
+ try {
1146
+ shutdownInternal();
1147
+ promise.resolve(true);
1148
+ } catch (Exception e) {
1149
+ promise.reject(e);
1150
+ Log.d("ReactNative", "shutdown"+ e.getMessage());
1151
+ }
1152
+ });
1153
+ }
1154
+
1155
+ ///////////////////////////////////////////////////////////
1156
+ ///////////////////////////////////////////////////////////
1157
+ ///////////////////////////////////////////////////////////
1158
+ ///////////////////////////////////////////////////////////
1159
+ //////////////////////ANYTHING BELOW IS FOR BLOCKCHAIN/////
1160
+ ///////////////////////////////////////////////////////////
1161
+ @ReactMethod
1162
+ public void createAccount(String seedString, Promise promise) {
1163
+ ThreadUtils.runOnExecutor(() -> {
1164
+ Log.d("ReactNative", "createAccount: seedString = " + seedString);
1165
+ try {
1166
+ if (this.fula == null || this.fula.id() == null || this.fula.id().isEmpty()) {
1167
+ promise.reject(new Error("Fula client is not initialized"));
1168
+ } else {
1169
+
1170
+ if (!seedString.startsWith("/")) {
1171
+ promise.reject(new Error("seed should start with /"));
1172
+ }
1173
+ byte[] result = this.fula.seeded(seedString);
1174
+ String resultString = toString(result);
1175
+ promise.resolve(resultString);
1176
+ }
1177
+ } catch (Exception e) {
1178
+ Log.d("get", e.getMessage());
1179
+ promise.reject(e);
1180
+ }
1181
+ });
1182
+ }
1183
+
1184
+ @ReactMethod
1185
+ public void checkAccountExists(String accountString, Promise promise) {
1186
+ ThreadUtils.runOnExecutor(() -> {
1187
+ Log.d("ReactNative", "checkAccountExists: accountString = " + accountString);
1188
+ try {
1189
+ byte[] result = this.fula.accountExists(accountString);
1190
+ String resultString = toString(result);
1191
+ promise.resolve(resultString);
1192
+ } catch (Exception e) {
1193
+ Log.d("get", e.getMessage());
1194
+ promise.reject(e);
1195
+ }
1196
+ });
1197
+ }
1198
+
1199
+ @ReactMethod
1200
+ public void createPool(String seedString, String poolName, Promise promise) {
1201
+ ThreadUtils.runOnExecutor(() -> {
1202
+ Log.d("ReactNative", "createPool: seedString = " + seedString + "; poolName = " + poolName);
1203
+ try {
1204
+ byte[] result = this.fula.poolCreate(seedString, poolName);
1205
+ String resultString = toString(result);
1206
+ promise.resolve(resultString);
1207
+ } catch (Exception e) {
1208
+ Log.d("get", e.getMessage());
1209
+ promise.reject(e);
1210
+ }
1211
+ });
1212
+ }
1213
+
1214
+ @ReactMethod
1215
+ public void listPools(Promise promise) {
1216
+ ThreadUtils.runOnExecutor(() -> {
1217
+ Log.d("ReactNative", "listPools");
1218
+ try {
1219
+ byte[] result = this.fula.poolList();
1220
+ String resultString = toString(result);
1221
+ promise.resolve(resultString);
1222
+ } catch (Exception e) {
1223
+ Log.d("get", e.getMessage());
1224
+ promise.reject(e);
1225
+ }
1226
+ });
1227
+ }
1228
+
1229
+ @ReactMethod
1230
+ public void joinPool(String seedString, long poolID, Promise promise) {
1231
+ ThreadUtils.runOnExecutor(() -> {
1232
+ Log.d("ReactNative", "joinPool: seedString = " + seedString + "; poolID = " + poolID);
1233
+ try {
1234
+ byte[] result = this.fula.poolJoin(seedString, poolID);
1235
+ String resultString = toString(result);
1236
+ promise.resolve(resultString);
1237
+ } catch (Exception e) {
1238
+ Log.d("get", e.getMessage());
1239
+ promise.reject(e);
1240
+ }
1241
+ });
1242
+ }
1243
+
1244
+ @ReactMethod
1245
+ public void cancelPoolJoin(String seedString, long poolID, Promise promise) {
1246
+ ThreadUtils.runOnExecutor(() -> {
1247
+ Log.d("ReactNative", "cancelPoolJoin: seedString = " + seedString + "; poolID = " + poolID);
1248
+ try {
1249
+ byte[] result = this.fula.poolCancelJoin(seedString, poolID);
1250
+ String resultString = toString(result);
1251
+ promise.resolve(resultString);
1252
+ } catch (Exception e) {
1253
+ Log.d("get", e.getMessage());
1254
+ promise.reject(e);
1255
+ }
1256
+ });
1257
+ }
1258
+
1259
+ @ReactMethod
1260
+ public void listPoolJoinRequests(long poolID, Promise promise) {
1261
+ ThreadUtils.runOnExecutor(() -> {
1262
+ Log.d("ReactNative", "listPoolJoinRequests: poolID = " + poolID);
1263
+ try {
1264
+ byte[] result = this.fula.poolRequests(poolID);
1265
+ String resultString = toString(result);
1266
+ promise.resolve(resultString);
1267
+ } catch (Exception e) {
1268
+ Log.d("get", e.getMessage());
1269
+ promise.reject(e);
1270
+ }
1271
+ });
1272
+ }
1273
+
1274
+ @ReactMethod
1275
+ public void votePoolJoinRequest(String seedString, long poolID, String accountString, boolean accept, Promise promise) {
1276
+ ThreadUtils.runOnExecutor(() -> {
1277
+ Log.d("ReactNative", "votePoolJoinRequest: seedString = " + seedString + "; poolID = " + poolID + "; accountString = " + accountString + "; accept = " + accept);
1278
+ try {
1279
+ byte[] result = this.fula.poolVote(seedString, poolID, accountString, accept);
1280
+ String resultString = toString(result);
1281
+ promise.resolve(resultString);
1282
+ } catch (Exception e) {
1283
+ Log.d("get", e.getMessage());
1284
+ promise.reject(e);
1285
+ }
1286
+ });
1287
+ }
1288
+
1289
+ @ReactMethod
1290
+ public void leavePool(String seedString, long poolID, Promise promise) {
1291
+ ThreadUtils.runOnExecutor(() -> {
1292
+ Log.d("ReactNative", "leavePool: seedString = " + seedString + "; poolID = " + poolID);
1293
+ try {
1294
+ byte[] result = this.fula.poolLeave(seedString, poolID);
1295
+ String resultString = toString(result);
1296
+ promise.resolve(resultString);
1297
+ } catch (Exception e) {
1298
+ Log.d("get", e.getMessage());
1299
+ promise.reject(e);
1300
+ }
1301
+ });
1302
+ }
1303
+
1304
+ @ReactMethod
1305
+ public void newReplicationRequest(String seedString, long poolID, long replicationFactor, String cid, Promise promise) {
1306
+ ThreadUtils.runOnExecutor(() -> {
1307
+ Log.d("ReactNative", "newReplicationRequest: seedString = " + seedString + "; poolID = " + poolID + "; replicationFactor = " + replicationFactor + "; cid = " + cid);
1308
+ try {
1309
+ byte[] result = this.fula.manifestUpload(seedString, poolID, replicationFactor, cid);
1310
+ String resultString = toString(result);
1311
+ promise.resolve(resultString);
1312
+ } catch (Exception e) {
1313
+ Log.d("get", e.getMessage());
1314
+ promise.reject(e);
1315
+ }
1316
+ });
1317
+ }
1318
+
1319
+ @ReactMethod
1320
+ public void newStoreRequest(String seedString, long poolID, String uploader, String cid, Promise promise) {
1321
+ ThreadUtils.runOnExecutor(() -> {
1322
+ Log.d("ReactNative", "newStoreRequest: seedString = " + seedString + "; poolID = " + poolID + "; uploader = " + uploader + "; cid = " + cid);
1323
+ try {
1324
+ byte[] result = this.fula.manifestStore(seedString, poolID, uploader, cid);
1325
+ String resultString = toString(result);
1326
+ promise.resolve(resultString);
1327
+ } catch (Exception e) {
1328
+ Log.d("get", e.getMessage());
1329
+ promise.reject(e);
1330
+ }
1331
+ });
1332
+ }
1333
+
1334
+ @ReactMethod
1335
+ public void listAvailableReplicationRequests(long poolID, Promise promise) {
1336
+ ThreadUtils.runOnExecutor(() -> {
1337
+ Log.d("ReactNative", "listAvailableReplicationRequests: poolID = " + poolID);
1338
+ try {
1339
+ byte[] result = this.fula.manifestAvailable(poolID);
1340
+ String resultString = toString(result);
1341
+ promise.resolve(resultString);
1342
+ } catch (Exception e) {
1343
+ Log.d("get", e.getMessage());
1344
+ promise.reject(e);
1345
+ }
1346
+ });
1347
+ }
1348
+
1349
+ @ReactMethod
1350
+ public void removeReplicationRequest(String seedString, long poolID, String cid, Promise promise) {
1351
+ ThreadUtils.runOnExecutor(() -> {
1352
+ Log.d("ReactNative", "newReplicationRequest: seedString = " + seedString + "; poolID = " + poolID + "; cid = " + cid);
1353
+ try {
1354
+ byte[] result = this.fula.manifestRemove(seedString, poolID, cid);
1355
+ String resultString = toString(result);
1356
+ promise.resolve(resultString);
1357
+ } catch (Exception e) {
1358
+ Log.d("get", e.getMessage());
1359
+ promise.reject(e);
1360
+ }
1361
+ });
1362
+ }
1363
+
1364
+ @ReactMethod
1365
+ public void removeStorer(String seedString, String storage, long poolID, String cid, Promise promise) {
1366
+ ThreadUtils.runOnExecutor(() -> {
1367
+ Log.d("ReactNative", "removeStorer: seedString = " + seedString + "; storage = " + storage + "; poolID = " + poolID + "; cid = " + cid);
1368
+ try {
1369
+ byte[] result = this.fula.manifestRemoveStorer(seedString, storage, poolID, cid);
1370
+ String resultString = toString(result);
1371
+ promise.resolve(resultString);
1372
+ } catch (Exception e) {
1373
+ Log.d("get", e.getMessage());
1374
+ promise.reject(e);
1375
+ }
1376
+ });
1377
+ }
1378
+
1379
+ @ReactMethod
1380
+ public void removeStoredReplication(String seedString, String uploader, long poolID, String cid, Promise promise) {
1381
+ ThreadUtils.runOnExecutor(() -> {
1382
+ Log.d("ReactNative", "removeStoredReplication: seedString = " + seedString + "; uploader = " + uploader + "; poolID = " + poolID + "; cid = " + cid);
1383
+ try {
1384
+ byte[] result = this.fula.manifestRemoveStored(seedString, uploader, poolID, cid);
1385
+ String resultString = toString(result);
1386
+ promise.resolve(resultString);
1387
+ } catch (Exception e) {
1388
+ Log.d("get", e.getMessage());
1389
+ promise.reject(e);
1390
+ }
1391
+ });
1392
+ }
1393
+
1394
+ ////////////////////////////////////////////////////////////////
1395
+ ///////////////// Blox Hardware Methods ////////////////////////
1396
+ ////////////////////////////////////////////////////////////////
1397
+
1398
+ @ReactMethod
1399
+ public void bloxFreeSpace(Promise promise) {
1400
+ ThreadUtils.runOnExecutor(() -> {
1401
+ Log.d("ReactNative", "bloxFreeSpace");
1402
+ try {
1403
+ byte[] result = this.fula.bloxFreeSpace();
1404
+ String resultString = toString(result);
1405
+ Log.d("ReactNative", "result string="+resultString);
1406
+ promise.resolve(resultString);
1407
+ } catch (Exception e) {
1408
+ Log.d("ReactNative", e.getMessage());
1409
+ promise.reject(e);
1410
+ }
1411
+ });
1412
+ }
1413
+
1414
+ @ReactMethod
1415
+ public void wifiRemoveall(Promise promise) {
1416
+ ThreadUtils.runOnExecutor(() -> {
1417
+ Log.d("ReactNative", "wifiRemoveall");
1418
+ try {
1419
+ byte[] result = this.fula.wifiRemoveall();
1420
+ String resultString = toString(result);
1421
+ Log.d("ReactNative", "result string="+resultString);
1422
+ promise.resolve(resultString);
1423
+ } catch (Exception e) {
1424
+ Log.d("ReactNative", e.getMessage());
1425
+ promise.reject(e);
1426
+ }
1427
+ });
1428
+ }
1429
+
1430
+ @ReactMethod
1431
+ public void reboot(Promise promise) {
1432
+ ThreadUtils.runOnExecutor(() -> {
1433
+ Log.d("ReactNative", "reboot");
1434
+ try {
1435
+ byte[] result = this.fula.reboot();
1436
+ String resultString = toString(result);
1437
+ Log.d("ReactNative", "result string="+resultString);
1438
+ promise.resolve(resultString);
1439
+ } catch (Exception e) {
1440
+ Log.d("ReactNative", e.getMessage());
1441
+ promise.reject(e);
1442
+ }
1443
+ });
1444
+ }
1445
+
1446
+ @ReactMethod
1447
+ public void testData(String identityString, String bloxAddr, Promise promise) {
1448
+ try {
1449
+ byte[] identity = toByte(identityString);
1450
+ byte[] peerIdByte = this.newClientInternal(identity, "", bloxAddr, "", true, true, true);
1451
+
1452
+ String peerIdReturned = Arrays.toString(peerIdByte);
1453
+ Log.d("ReactNative", "newClient peerIdReturned= " + peerIdReturned);
1454
+ String peerId = this.fula.id();
1455
+ Log.d("ReactNative", "newClient peerId= " + peerId);
1456
+ byte[] bytes = {1, 85, 18, 32, 11, -31, 75, -78, -109, 11, -111, 97, -47, -78, -22, 84, 39, -117, -64, -70, -91, 55, -23, -80, 116, -123, -97, -26, 126, -70, -76, 35, 54, -106, 55, -9};
1457
+
1458
+ byte[] key = this.fula.put(bytes, 85);
1459
+ Log.d("ReactNative", "testData put result string="+Arrays.toString(key));
1460
+
1461
+ byte[] value = this.fula.get(key);
1462
+ Log.d("ReactNative", "testData get result string="+Arrays.toString(value));
1463
+
1464
+ this.fula.push(key);
1465
+ //this.fula.flush();
1466
+
1467
+ byte[] fetchedVal = this.fula.get(key);
1468
+ this.fula.pull(key);
1469
+
1470
+ promise.resolve(Arrays.toString(fetchedVal));
1471
+ } catch (Exception e) {
1472
+ Log.d("ReactNative", "ERROR:" + e.getMessage());
1473
+ promise.reject(e);
1474
+ }
1475
+ }
1476
+
1477
+ }