@functionland/react-native-fula 1.1.9 → 1.2.1-rnf1

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