@functionland/react-native-fula 1.55.12 → 1.55.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +2 -2
- package/android/gradle.properties +2 -2
- package/android/src/main/java/land/fx/fula/FulaModule.java +2057 -1991
- package/ios/Fula.mm +10 -0
- package/ios/Fula.swift +2281 -2207
- package/ios/Fula.xcodeproj/project.pbxproj +2 -2
- package/lib/commonjs/index.js +1 -2
- package/lib/commonjs/interfaces/fulaNativeModule.js.map +1 -1
- package/lib/commonjs/protocols/blockchain.js +67 -1
- package/lib/commonjs/protocols/blockchain.js.map +1 -1
- package/lib/module/interfaces/fulaNativeModule.js.map +1 -1
- package/lib/module/protocols/blockchain.js +64 -0
- package/lib/module/protocols/blockchain.js.map +1 -1
- package/package.json +1 -1
- package/react-native-fula.podspec +47 -47
- package/src/interfaces/fulaNativeModule.ts +177 -175
- package/src/protocols/blockchain.ts +72 -0
|
@@ -1,1991 +1,2057 @@
|
|
|
1
|
-
package land.fx.fula;
|
|
2
|
-
|
|
3
|
-
import android.util.Log;
|
|
4
|
-
|
|
5
|
-
import androidx.annotation.NonNull;
|
|
6
|
-
|
|
7
|
-
import android.os.Handler;
|
|
8
|
-
import android.os.Looper;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import com.facebook.react.bridge.Promise;
|
|
12
|
-
import com.facebook.react.bridge.Callback;
|
|
13
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
14
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
15
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
16
|
-
import com.facebook.react.bridge.WritableMap;
|
|
17
|
-
import com.facebook.react.bridge.WritableNativeMap;
|
|
18
|
-
import com.facebook.react.module.annotations.ReactModule;
|
|
19
|
-
import com.facebook.react.bridge.Arguments;
|
|
20
|
-
import com.facebook.react.bridge.WritableArray;
|
|
21
|
-
import com.facebook.react.bridge.ReadableArray;
|
|
22
|
-
import com.facebook.react.bridge.LifecycleEventListener;
|
|
23
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
import org.apache.commons.io.FileUtils;
|
|
27
|
-
import org.jetbrains.annotations.Contract;
|
|
28
|
-
|
|
29
|
-
import java.io.File;
|
|
30
|
-
import java.io.IOException;
|
|
31
|
-
import java.nio.charset.StandardCharsets;
|
|
32
|
-
import java.security.GeneralSecurityException;
|
|
33
|
-
import java.security.InvalidAlgorithmParameterException;
|
|
34
|
-
import java.security.InvalidKeyException;
|
|
35
|
-
import java.security.NoSuchAlgorithmException;
|
|
36
|
-
import java.security.MessageDigest;
|
|
37
|
-
import java.util.Arrays;
|
|
38
|
-
import java.util.ArrayList;
|
|
39
|
-
|
|
40
|
-
import javax.crypto.BadPaddingException;
|
|
41
|
-
import javax.crypto.IllegalBlockSizeException;
|
|
42
|
-
import javax.crypto.NoSuchPaddingException;
|
|
43
|
-
import javax.crypto.SecretKey;
|
|
44
|
-
|
|
45
|
-
import java.util.concurrent.Executors;
|
|
46
|
-
import java.util.concurrent.ScheduledExecutorService;
|
|
47
|
-
import java.util.concurrent.TimeUnit;
|
|
48
|
-
import java.util.concurrent.atomic.AtomicBoolean;
|
|
49
|
-
import java.util.concurrent.Future;
|
|
50
|
-
import java.util.concurrent.TimeoutException;
|
|
51
|
-
|
|
52
|
-
import fulamobile.Config;
|
|
53
|
-
import fulamobile.Fulamobile;
|
|
54
|
-
|
|
55
|
-
import land.fx.wnfslib.Fs;
|
|
56
|
-
import java.nio.file.Files;
|
|
57
|
-
import java.nio.file.Path;
|
|
58
|
-
import java.nio.file.Paths;
|
|
59
|
-
|
|
60
|
-
@ReactModule(name = FulaModule.NAME)
|
|
61
|
-
public class FulaModule extends ReactContextBaseJavaModule {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@Override
|
|
65
|
-
public void initialize() {
|
|
66
|
-
System.loadLibrary("wnfslib");
|
|
67
|
-
System.loadLibrary("gojni");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
public static final String NAME = "FulaModule";
|
|
72
|
-
private final ReactApplicationContext reactContext;
|
|
73
|
-
fulamobile.Client fula;
|
|
74
|
-
|
|
75
|
-
Client client;
|
|
76
|
-
Config fulaConfig;
|
|
77
|
-
|
|
78
|
-
String appName;
|
|
79
|
-
String appDir;
|
|
80
|
-
String fulaStorePath;
|
|
81
|
-
land.fx.wnfslib.Config rootConfig;
|
|
82
|
-
SharedPreferenceHelper sharedPref;
|
|
83
|
-
SecretKey secretKeyGlobal;
|
|
84
|
-
String identityEncryptedGlobal;
|
|
85
|
-
static String PRIVATE_KEY_STORE_PEERID = "PRIVATE_KEY";
|
|
86
|
-
|
|
87
|
-
public static class Client implements land.fx.wnfslib.Datastore {
|
|
88
|
-
|
|
89
|
-
private final fulamobile.Client internalClient;
|
|
90
|
-
|
|
91
|
-
Client(fulamobile.Client clientInput) {
|
|
92
|
-
this.internalClient = clientInput;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
@NonNull
|
|
96
|
-
@Override
|
|
97
|
-
public byte[] get(@NonNull byte[] cid) {
|
|
98
|
-
try {
|
|
99
|
-
Log.d("ReactNative", Arrays.toString(cid));
|
|
100
|
-
return this.internalClient.get(cid);
|
|
101
|
-
} catch (Exception e) {
|
|
102
|
-
e.printStackTrace();
|
|
103
|
-
}
|
|
104
|
-
Log.d("ReactNative","Error get");
|
|
105
|
-
return cid;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
@NonNull
|
|
109
|
-
@Override
|
|
110
|
-
public byte[] put(@NonNull byte[] cid, byte[] data) {
|
|
111
|
-
try {
|
|
112
|
-
long codec = (long)cid[1] & 0xFF;
|
|
113
|
-
byte[] put_cid = this.internalClient.put(data, codec);
|
|
114
|
-
//Log.d("ReactNative", "data="+ Arrays.toString(data) +" ;codec="+codec);
|
|
115
|
-
return put_cid;
|
|
116
|
-
} catch (Exception e) {
|
|
117
|
-
Log.d("ReactNative", "put Error="+e.getMessage());
|
|
118
|
-
e.printStackTrace();
|
|
119
|
-
}
|
|
120
|
-
Log.d("ReactNative","Error put");
|
|
121
|
-
return data;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
public FulaModule(ReactApplicationContext reactContext) {
|
|
126
|
-
super(reactContext);
|
|
127
|
-
this.reactContext = reactContext;
|
|
128
|
-
appName = reactContext.getPackageName();
|
|
129
|
-
appDir = reactContext.getFilesDir().toString();
|
|
130
|
-
fulaStorePath = appDir + "/fula";
|
|
131
|
-
File storeDir = new File(fulaStorePath);
|
|
132
|
-
sharedPref = SharedPreferenceHelper.getInstance(reactContext.getApplicationContext());
|
|
133
|
-
boolean success = true;
|
|
134
|
-
if (!storeDir.exists()) {
|
|
135
|
-
success = storeDir.mkdirs();
|
|
136
|
-
}
|
|
137
|
-
if (success) {
|
|
138
|
-
Log.d("ReactNative", "Fula store folder created for " + appName + " at " + fulaStorePath);
|
|
139
|
-
} else {
|
|
140
|
-
Log.d("ReactNative", "Unable to create fula store folder for " + appName + " at " + fulaStorePath);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
@Override
|
|
145
|
-
@NonNull
|
|
146
|
-
public java.lang.String getName() {
|
|
147
|
-
return NAME;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
private byte[] toByte(@NonNull String input) {
|
|
152
|
-
return input.getBytes(StandardCharsets.UTF_8);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private byte[] decToByte(@NonNull String input) {
|
|
156
|
-
String[] parts = input.split(",");
|
|
157
|
-
byte[] output = new byte[parts.length];
|
|
158
|
-
for (int i = 0; i < parts.length; i++) {
|
|
159
|
-
output[i] = Byte.parseByte(parts[i]);
|
|
160
|
-
}
|
|
161
|
-
return output;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
@NonNull
|
|
165
|
-
@Contract("_ -> new")
|
|
166
|
-
public String toString(byte[] input) {
|
|
167
|
-
return new String(input, StandardCharsets.UTF_8);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
@NonNull
|
|
171
|
-
private static int[] stringArrToIntArr(@NonNull String[] s) {
|
|
172
|
-
int[] result = new int[s.length];
|
|
173
|
-
for (int i = 0; i < s.length; i++) {
|
|
174
|
-
result[i] = Integer.parseInt(s[i]);
|
|
175
|
-
}
|
|
176
|
-
return result;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
@NonNull
|
|
180
|
-
@Contract(pure = true)
|
|
181
|
-
private static byte[] convertIntToByte(@NonNull int[] input) {
|
|
182
|
-
byte[] result = new byte[input.length];
|
|
183
|
-
for (int i = 0; i < input.length; i++) {
|
|
184
|
-
byte b = (byte) input[i];
|
|
185
|
-
result[i] = b;
|
|
186
|
-
}
|
|
187
|
-
return result;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
@NonNull
|
|
191
|
-
private byte[] convertStringToByte(@NonNull String data) {
|
|
192
|
-
String[] keyInt_S = data.split(",");
|
|
193
|
-
int[] keyInt = stringArrToIntArr(keyInt_S);
|
|
194
|
-
|
|
195
|
-
return convertIntToByte(keyInt);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
@ReactMethod
|
|
199
|
-
public void registerLifecycleListener(Promise promise) {
|
|
200
|
-
getReactApplicationContext().addLifecycleEventListener(new LifecycleEventListener() {
|
|
201
|
-
@Override
|
|
202
|
-
public void onHostResume() {
|
|
203
|
-
// App is in the foreground
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
@Override
|
|
207
|
-
public void onHostPause() {
|
|
208
|
-
// App is in the background
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
@Override
|
|
212
|
-
public void onHostDestroy() {
|
|
213
|
-
// Attempt to shut down Fula cleanly
|
|
214
|
-
try {
|
|
215
|
-
Log.e("ReactNative", "shutting down Fula onHostDestroy");
|
|
216
|
-
shutdownInternal();
|
|
217
|
-
} catch (Exception e) {
|
|
218
|
-
Log.e("ReactNative", "Error shutting down Fula", e);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
promise.resolve(true);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
@ReactMethod
|
|
226
|
-
public void checkConnection(int timeout, Promise promise) {
|
|
227
|
-
Log.d("ReactNative", "checkConnection started");
|
|
228
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
229
|
-
if (this.fula != null) {
|
|
230
|
-
try {
|
|
231
|
-
boolean connectionStatus = this.checkConnectionInternal(timeout);
|
|
232
|
-
Log.d("ReactNative", "checkConnection ended " + connectionStatus);
|
|
233
|
-
promise.resolve(connectionStatus);
|
|
234
|
-
}
|
|
235
|
-
catch (Exception e) {
|
|
236
|
-
Log.d("ReactNative", "checkConnection failed with Error: " + e.getMessage());
|
|
237
|
-
promise.resolve(false);
|
|
238
|
-
}
|
|
239
|
-
} else {
|
|
240
|
-
Log.d("ReactNative", "checkConnection failed with Error: " + "fula is null");
|
|
241
|
-
promise.resolve(false);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
@ReactMethod
|
|
247
|
-
public void newClient(String identityString, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh, Promise promise) {
|
|
248
|
-
Log.d("ReactNative", "newClient started");
|
|
249
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
250
|
-
try {
|
|
251
|
-
Log.d("ReactNative", "newClient storePath= " + storePath + " bloxAddr= " + bloxAddr + " exchange= " + exchange + " autoFlush= " + autoFlush + " useRelay= " + useRelay + " refresh= " + refresh);
|
|
252
|
-
byte[] identity = toByte(identityString);
|
|
253
|
-
Log.d("ReactNative", "newClient identity= " + identityString);
|
|
254
|
-
this.newClientInternal(identity, storePath, bloxAddr, exchange, autoFlush, useRelay, refresh);
|
|
255
|
-
//String objString = Arrays.toString(obj);
|
|
256
|
-
String peerId = this.fula.id();
|
|
257
|
-
Log.d("ReactNative", "newClient peerId= " + peerId);
|
|
258
|
-
promise.resolve(peerId);
|
|
259
|
-
} catch (Exception e) {
|
|
260
|
-
Log.d("ReactNative", "newClient failed with Error: " + e.getMessage());
|
|
261
|
-
promise.reject("Error", e.getMessage());
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
@ReactMethod
|
|
267
|
-
public void deleteDsLock() {
|
|
268
|
-
String lockFilePath = fulaConfig.getStorePath() + "/LOCK";
|
|
269
|
-
Path lockFile = Paths.get(lockFilePath);
|
|
270
|
-
try {
|
|
271
|
-
if (Files.exists(lockFile)) {
|
|
272
|
-
Files.delete(lockFile);
|
|
273
|
-
Log.d("ReactNative", "Lock file deleted successfully.");
|
|
274
|
-
} else {
|
|
275
|
-
Log.d("ReactNative", "Lock file does not exist.");
|
|
276
|
-
}
|
|
277
|
-
} catch (Exception e) {
|
|
278
|
-
Log.d("ReactNative", "Failed to delete lock file: " + e.getMessage());
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
@ReactMethod
|
|
283
|
-
public void isReady(boolean filesystemCheck, Promise promise) {
|
|
284
|
-
Log.d("ReactNative", "isReady started");
|
|
285
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
286
|
-
boolean initialized = false;
|
|
287
|
-
try {
|
|
288
|
-
if (this.fula != null && this.fula.id() != null) {
|
|
289
|
-
if (filesystemCheck) {
|
|
290
|
-
if (this.client != null && this.rootConfig != null && !this.rootConfig.getCid().isEmpty()) {
|
|
291
|
-
initialized = true;
|
|
292
|
-
Log.d("ReactNative", "isReady is true with filesystem check");
|
|
293
|
-
}
|
|
294
|
-
} else {
|
|
295
|
-
Log.d("ReactNative", "isReady is true without filesystem check");
|
|
296
|
-
initialized = true;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
promise.resolve(initialized);
|
|
300
|
-
} catch (Exception e) {
|
|
301
|
-
Log.d("ReactNative", "isReady failed with Error: " + e.getMessage());
|
|
302
|
-
promise.reject("Error", e.getMessage());
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
@ReactMethod
|
|
308
|
-
public void initFula(String identityString, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootConfig, boolean useRelay, boolean refresh, Promise promise) {
|
|
309
|
-
Log.d("ReactNative", "init started");
|
|
310
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
311
|
-
try {
|
|
312
|
-
WritableMap resultData = new WritableNativeMap();
|
|
313
|
-
Log.d("ReactNative", "init storePath= " + storePath);
|
|
314
|
-
byte[] identity = toByte(identityString);
|
|
315
|
-
Log.d("ReactNative", "init identity= " + identityString);
|
|
316
|
-
String[] obj = this.initInternal(identity, storePath, bloxAddr, exchange, autoFlush, rootConfig, useRelay, refresh);
|
|
317
|
-
Log.d("ReactNative", "init object created: [ " + obj[0] + ", " + obj[1] + " ]");
|
|
318
|
-
resultData.putString("peerId", obj[0]);
|
|
319
|
-
resultData.putString("rootCid", obj[1]);
|
|
320
|
-
promise.resolve(resultData);
|
|
321
|
-
} catch (Exception e) {
|
|
322
|
-
Log.d("ReactNative", "init failed with Error: " + e.getMessage());
|
|
323
|
-
promise.reject("Error", e.getMessage());
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
@ReactMethod
|
|
329
|
-
public void logout(String identityString, String storePath, Promise promise) {
|
|
330
|
-
Log.d("ReactNative", "logout started");
|
|
331
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
332
|
-
try {
|
|
333
|
-
byte[] identity = toByte(identityString);
|
|
334
|
-
boolean obj = this.logoutInternal(identity, storePath);
|
|
335
|
-
Log.d("ReactNative", "logout completed");
|
|
336
|
-
promise.resolve(obj);
|
|
337
|
-
} catch (Exception e) {
|
|
338
|
-
Log.d("ReactNative", "logout failed with Error: " + e.getMessage());
|
|
339
|
-
promise.reject("Error", e.getMessage());
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
private boolean checkConnectionInternal(int timeout) throws Exception {
|
|
345
|
-
try {
|
|
346
|
-
Log.d("ReactNative", "checkConnectionInternal started");
|
|
347
|
-
if (this.fula != null) {
|
|
348
|
-
try {
|
|
349
|
-
Log.d("ReactNative", "connectToBlox started");
|
|
350
|
-
|
|
351
|
-
AtomicBoolean connectionStatus = new AtomicBoolean(false);
|
|
352
|
-
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
|
353
|
-
Future<?> future = executor.submit(() -> {
|
|
354
|
-
try {
|
|
355
|
-
this.fula.connectToBlox();
|
|
356
|
-
connectionStatus.set(true);
|
|
357
|
-
Log.d("ReactNative", "checkConnectionInternal succeeded ");
|
|
358
|
-
} catch (Exception e) {
|
|
359
|
-
Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
try {
|
|
364
|
-
future.get(timeout, TimeUnit.SECONDS);
|
|
365
|
-
} catch (TimeoutException te) {
|
|
366
|
-
// If the timeout occurs, shut down the executor and return false
|
|
367
|
-
executor.shutdownNow();
|
|
368
|
-
return false;
|
|
369
|
-
} finally {
|
|
370
|
-
// If the future task is done, we can shut down the executor
|
|
371
|
-
if (future.isDone()) {
|
|
372
|
-
executor.shutdown();
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
return connectionStatus.get();
|
|
377
|
-
} catch (Exception e) {
|
|
378
|
-
Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
|
|
379
|
-
return false;
|
|
380
|
-
}
|
|
381
|
-
} else {
|
|
382
|
-
Log.d("ReactNative", "checkConnectionInternal failed because fula is not initialized ");
|
|
383
|
-
return false;
|
|
384
|
-
}
|
|
385
|
-
} catch (Exception e) {
|
|
386
|
-
Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
|
|
387
|
-
throw (e);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
@ReactMethod
|
|
392
|
-
public void checkFailedActions(boolean retry, int timeout, Promise promise) throws Exception {
|
|
393
|
-
try {
|
|
394
|
-
if (this.fula != null) {
|
|
395
|
-
if (!retry) {
|
|
396
|
-
Log.d("ReactNative", "checkFailedActions without retry");
|
|
397
|
-
fulamobile.LinkIterator failedLinks = this.fula.listFailedPushes();
|
|
398
|
-
if (failedLinks.hasNext()) {
|
|
399
|
-
Log.d("ReactNative", "checkFailedActions found: "+Arrays.toString(failedLinks.next()));
|
|
400
|
-
promise.resolve(true);
|
|
401
|
-
} else {
|
|
402
|
-
promise.resolve(false);
|
|
403
|
-
}
|
|
404
|
-
} else {
|
|
405
|
-
Log.d("ReactNative", "checkFailedActions with retry");
|
|
406
|
-
boolean retryResults = this.retryFailedActionsInternal(timeout);
|
|
407
|
-
promise.resolve(!retryResults);
|
|
408
|
-
}
|
|
409
|
-
} else {
|
|
410
|
-
throw new Exception("Fula is not initialized");
|
|
411
|
-
}
|
|
412
|
-
} catch (Exception e) {
|
|
413
|
-
Log.d("ReactNative", "checkFailedActions failed with Error: " + e.getMessage());
|
|
414
|
-
throw (e);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
@ReactMethod
|
|
419
|
-
private void listFailedActions(ReadableArray cids, Promise promise) throws Exception {
|
|
420
|
-
try {
|
|
421
|
-
if (this.fula != null) {
|
|
422
|
-
Log.d("ReactNative", "listFailedActions");
|
|
423
|
-
fulamobile.StringIterator failedLinks = this.fula.listFailedPushesAsString();
|
|
424
|
-
ArrayList<String> failedLinksList = new ArrayList<>();
|
|
425
|
-
while (failedLinks.hasNext()) {
|
|
426
|
-
failedLinksList.add(failedLinks.next());
|
|
427
|
-
}
|
|
428
|
-
if (cids.size() > 0) {
|
|
429
|
-
// If cids array is provided, filter the failedLinksList
|
|
430
|
-
ArrayList<String> cidsList = new ArrayList<>();
|
|
431
|
-
for (int i = 0; i < cids.size(); i++) {
|
|
432
|
-
cidsList.add(cids.getString(i));
|
|
433
|
-
}
|
|
434
|
-
cidsList.retainAll(failedLinksList); // Keep only the elements in both cidsList and failedLinksList
|
|
435
|
-
if (!cidsList.isEmpty()) {
|
|
436
|
-
// If there are any matching cids, return them
|
|
437
|
-
WritableArray cidsArray = Arguments.createArray();
|
|
438
|
-
for (String cid : cidsList) {
|
|
439
|
-
cidsArray.pushString(cid);
|
|
440
|
-
}
|
|
441
|
-
promise.resolve(cidsArray);
|
|
442
|
-
} else {
|
|
443
|
-
// If there are no matching cids, return false
|
|
444
|
-
promise.resolve(false);
|
|
445
|
-
}
|
|
446
|
-
} else if (!failedLinksList.isEmpty()) {
|
|
447
|
-
// If cids array is not provided, return the whole list
|
|
448
|
-
Log.d("ReactNative", "listFailedActions found: "+ failedLinksList);
|
|
449
|
-
WritableArray failedLinksArray = Arguments.createArray();
|
|
450
|
-
for (String link : failedLinksList) {
|
|
451
|
-
failedLinksArray.pushString(link);
|
|
452
|
-
}
|
|
453
|
-
promise.resolve(failedLinksArray);
|
|
454
|
-
} else {
|
|
455
|
-
promise.resolve(false);
|
|
456
|
-
}
|
|
457
|
-
} else {
|
|
458
|
-
throw new Exception("listFailedActions: Fula is not initialized");
|
|
459
|
-
}
|
|
460
|
-
} catch (Exception e) {
|
|
461
|
-
Log.d("ReactNative", "listFailedActions failed with Error: " + e.getMessage());
|
|
462
|
-
throw (e);
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
private boolean retryFailedActionsInternal(int timeout) throws Exception {
|
|
470
|
-
try {
|
|
471
|
-
Log.d("ReactNative", "retryFailedActionsInternal started");
|
|
472
|
-
if (this.fula != null) {
|
|
473
|
-
//Fula is initialized
|
|
474
|
-
try {
|
|
475
|
-
boolean connectionCheck = this.checkConnectionInternal(timeout);
|
|
476
|
-
if(connectionCheck) {
|
|
477
|
-
try {
|
|
478
|
-
Log.d("ReactNative", "retryFailedPushes started");
|
|
479
|
-
this.fula.retryFailedPushes();
|
|
480
|
-
Log.d("ReactNative", "flush started");
|
|
481
|
-
this.fula.flush();
|
|
482
|
-
return true;
|
|
483
|
-
}
|
|
484
|
-
catch (Exception e) {
|
|
485
|
-
this.fula.flush();
|
|
486
|
-
Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
|
|
487
|
-
return false;
|
|
488
|
-
}
|
|
489
|
-
//Blox online
|
|
490
|
-
/*fulamobile.LinkIterator failedLinks = this.fula.listFailedPushes();
|
|
491
|
-
if (failedLinks.hasNext()) {
|
|
492
|
-
Log.d("ReactNative", "Failed links");
|
|
493
|
-
//Failed list is not empty. iterate in the list
|
|
494
|
-
while (failedLinks.hasNext()) {
|
|
495
|
-
//Get the missing key
|
|
496
|
-
byte[] failedNode = failedLinks.next();
|
|
497
|
-
try {
|
|
498
|
-
//Push to Blox
|
|
499
|
-
Log.d("ReactNative", "Pushing Failed links "+Arrays.toString(failedNode));
|
|
500
|
-
this.pushInternal(failedNode);
|
|
501
|
-
Log.d("ReactNative", "Failed links pushed");
|
|
502
|
-
}
|
|
503
|
-
catch (Exception e) {
|
|
504
|
-
Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
//check if list is empty now and all are pushed
|
|
508
|
-
Log.d("ReactNative", "Pushing finished");
|
|
509
|
-
fulamobile.LinkIterator failedLinks_after = this.fula.listFailedPushes();
|
|
510
|
-
if(failedLinks_after.hasNext()) {
|
|
511
|
-
//Some pushes failed
|
|
512
|
-
byte[] first_failed = failedLinks_after.next();
|
|
513
|
-
Log.d("ReactNative", "Failed links are not empty "+Arrays.toString(first_failed));
|
|
514
|
-
return false;
|
|
515
|
-
} else {
|
|
516
|
-
//All pushes successful
|
|
517
|
-
return true;
|
|
518
|
-
}
|
|
519
|
-
} else {
|
|
520
|
-
Log.d("ReactNative", "No Failed links");
|
|
521
|
-
//Failed list is empty
|
|
522
|
-
return true;
|
|
523
|
-
}*/
|
|
524
|
-
} else {
|
|
525
|
-
Log.d("ReactNative", "retryFailedActionsInternal failed because blox is offline");
|
|
526
|
-
//Blox Offline
|
|
527
|
-
return false;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
catch (Exception e) {
|
|
531
|
-
Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
|
|
532
|
-
return false;
|
|
533
|
-
}
|
|
534
|
-
} else {
|
|
535
|
-
Log.d("ReactNative", "retryFailedActionsInternal failed because fula is not initialized");
|
|
536
|
-
//Fula is not initialized
|
|
537
|
-
return false;
|
|
538
|
-
}
|
|
539
|
-
} catch (Exception e) {
|
|
540
|
-
Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
|
|
541
|
-
throw (e);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
@NonNull
|
|
546
|
-
private byte[] createPeerIdentity(byte[] identity) throws GeneralSecurityException, IOException {
|
|
547
|
-
try {
|
|
548
|
-
// 1: First: create public key from provided private key
|
|
549
|
-
// 2: Should read the local keychain store (if it is key-value, key is public key above,
|
|
550
|
-
// 3: if found, decrypt using the private key
|
|
551
|
-
// 4: If not found or decryption not successful, generate an identity
|
|
552
|
-
// 5: then encrypt and store in keychain
|
|
553
|
-
byte[] libp2pId;
|
|
554
|
-
String encryptedLibp2pId = sharedPref.getValue(PRIVATE_KEY_STORE_PEERID);
|
|
555
|
-
byte[] encryptionPair;
|
|
556
|
-
SecretKey encryptionSecretKey;
|
|
557
|
-
try {
|
|
558
|
-
encryptionSecretKey = Cryptography.generateKey(identity);
|
|
559
|
-
Log.d("ReactNative", "encryptionSecretKey generated from privateKey");
|
|
560
|
-
} catch (Exception e) {
|
|
561
|
-
Log.d("ReactNative", "Failed to generate key for encryption: " + e.getMessage());
|
|
562
|
-
throw new GeneralSecurityException("Failed to generate key encryption", e);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
if (encryptedLibp2pId == null || !encryptedLibp2pId.startsWith("FULA_" +
|
|
566
|
-
"ENC_V4:")) {
|
|
567
|
-
Log.d("ReactNative", "encryptedLibp2pId is not correct or empty. creating new one " + encryptedLibp2pId);
|
|
568
|
-
encryptedLibp2pId = createEncryptedLibp2pId(identity, encryptionSecretKey);
|
|
569
|
-
} else {
|
|
570
|
-
Log.d("ReactNative", "encryptedLibp2pId is correct. decrypting " + encryptedLibp2pId);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
try {
|
|
574
|
-
String decryptedLibp2pId = decryptLibp2pIdentity(encryptedLibp2pId, encryptionSecretKey);
|
|
575
|
-
return StaticHelper.base64ToBytes(decryptedLibp2pId);
|
|
576
|
-
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
577
|
-
Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e.getMessage());
|
|
578
|
-
Log.d("ReactNative", "creating new encrpyted identity");
|
|
579
|
-
try {
|
|
580
|
-
encryptedLibp2pId = createEncryptedLibp2pId(identity, encryptionSecretKey);
|
|
581
|
-
String decryptedLibp2pId = decryptLibp2pIdentity(encryptedLibp2pId, encryptionSecretKey);
|
|
582
|
-
return StaticHelper.base64ToBytes(decryptedLibp2pId);
|
|
583
|
-
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e2) {
|
|
584
|
-
Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e2.getMessage());
|
|
585
|
-
Log.d("ReactNative", "creating new encrpyted identity");
|
|
586
|
-
throw(e2);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
591
|
-
Log.d("ReactNative", "createPeerIdentity failed with Error: " + e.getMessage());
|
|
592
|
-
throw (e);
|
|
593
|
-
} catch (Exception e) {
|
|
594
|
-
throw new RuntimeException(e);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
private String decryptLibp2pIdentity(String encryptedLibp2pId, SecretKey encryptionSecretKey) throws Exception {
|
|
599
|
-
try {
|
|
600
|
-
String decryptedLibp2pId = Cryptography.decryptMsg(encryptedLibp2pId.replace("FULA_ENC_V4:", ""), encryptionSecretKey);
|
|
601
|
-
|
|
602
|
-
return decryptedLibp2pId;
|
|
603
|
-
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
604
|
-
Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e.getMessage());
|
|
605
|
-
Log.d("ReactNative", "creating new encrpyted identity");
|
|
606
|
-
throw new GeneralSecurityException("decryptLibp2pIdentity Failed to decrypt libp2pId", e);
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
private String createEncryptedLibp2pId(byte[] identity, SecretKey encryptionSecretKey) throws Exception {
|
|
611
|
-
byte[] libp2pId;
|
|
612
|
-
String encryptedLibp2pId;
|
|
613
|
-
try {
|
|
614
|
-
Log.d("ReactNative", "createEncryptedLibp2pId started");
|
|
615
|
-
|
|
616
|
-
try {
|
|
617
|
-
libp2pId = Fulamobile.generateEd25519KeyFromString(toString(identity));
|
|
618
|
-
} catch (Exception e) {
|
|
619
|
-
Log.d("ReactNative", " createEncryptedLibp2pId Failed to generate libp2pId: " + e.getMessage());
|
|
620
|
-
throw new GeneralSecurityException("createEncryptedLibp2pId Failed to generate libp2pId", e);
|
|
621
|
-
}
|
|
622
|
-
encryptedLibp2pId = "FULA_ENC_V4:" + Cryptography.encryptMsg(StaticHelper.bytesToBase64(libp2pId), encryptionSecretKey, null);
|
|
623
|
-
sharedPref.add(PRIVATE_KEY_STORE_PEERID, encryptedLibp2pId);
|
|
624
|
-
return encryptedLibp2pId;
|
|
625
|
-
}
|
|
626
|
-
catch (Exception e) {
|
|
627
|
-
Log.d("ReactNative", "createEncryptedLibp2pId failed with Error: " + e.getMessage());
|
|
628
|
-
throw new GeneralSecurityException("createEncryptedLibp2pId Failed to generate libp2pId at hte first level", e);
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
private void createNewRootConfig(FulaModule.Client iClient, byte[] identity) throws Exception {
|
|
633
|
-
byte[] hash32 = getSHA256Hash(identity);
|
|
634
|
-
this.rootConfig = Fs.init(iClient, hash32);
|
|
635
|
-
Log.d("ReactNative", "rootConfig is created " + this.rootConfig.getCid());
|
|
636
|
-
if (this.fula != null) {
|
|
637
|
-
this.fula.flush();
|
|
638
|
-
}
|
|
639
|
-
this.encrypt_and_store_config();
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
public static byte[] getSHA256Hash(byte[] input) throws NoSuchAlgorithmException {
|
|
643
|
-
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
|
644
|
-
return md.digest(input);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
private static String bytesToHex(byte[] bytes) {
|
|
648
|
-
StringBuilder result = new StringBuilder();
|
|
649
|
-
for (byte b : bytes) {
|
|
650
|
-
result.append(String.format("%02x", b));
|
|
651
|
-
}
|
|
652
|
-
return result.toString();
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
private void reloadFS(FulaModule.Client iClient, byte[] wnfsKey, String rootCid) throws Exception {
|
|
656
|
-
Log.d("ReactNative", "reloadFS called: rootCid=" + rootCid);
|
|
657
|
-
byte[] hash32 = getSHA256Hash(wnfsKey);
|
|
658
|
-
Log.d("ReactNative", "wnfsKey=" + bytesToHex(wnfsKey) + "; hash32 = " + bytesToHex(hash32));
|
|
659
|
-
Fs.loadWithWNFSKey(iClient, hash32, rootCid);
|
|
660
|
-
Log.d("ReactNative", "reloadFS completed");
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
private boolean encrypt_and_store_config() throws Exception {
|
|
664
|
-
try {
|
|
665
|
-
if(this.identityEncryptedGlobal != null && !this.identityEncryptedGlobal.isEmpty()) {
|
|
666
|
-
Log.d("ReactNative", "encrypt_and_store_config started");
|
|
667
|
-
|
|
668
|
-
String cid_encrypted = Cryptography.encryptMsg(this.rootConfig.getCid(), this.secretKeyGlobal, null);
|
|
669
|
-
|
|
670
|
-
sharedPref.add("FULA_ENC_V4:cid_encrypted_" + this.identityEncryptedGlobal, cid_encrypted);
|
|
671
|
-
return true;
|
|
672
|
-
} else {
|
|
673
|
-
Log.d("ReactNative", "encrypt_and_store_config failed because identityEncryptedGlobal is empty");
|
|
674
|
-
return false;
|
|
675
|
-
}
|
|
676
|
-
} catch (Exception e) {
|
|
677
|
-
Log.d("ReactNative", "encrypt_and_store_config failed with Error: " + e.getMessage());
|
|
678
|
-
throw (e);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
private boolean logoutInternal(byte[] identity, String storePath) throws Exception {
|
|
683
|
-
try {
|
|
684
|
-
if (this.fula != null) {
|
|
685
|
-
this.fula.flush();
|
|
686
|
-
}
|
|
687
|
-
SecretKey secretKey = Cryptography.generateKey(identity);
|
|
688
|
-
byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B };
|
|
689
|
-
String identity_encrypted = Cryptography.encryptMsg(Arrays.toString(identity), secretKey, iv);
|
|
690
|
-
sharedPref.remove("FULA_ENC_V4:cid_encrypted_"+ identity_encrypted);
|
|
691
|
-
|
|
692
|
-
//TODO: Should also remove peerid @Mahdi
|
|
693
|
-
|
|
694
|
-
sharedPref.remove("FULA_ENC_V4:cid_encrypted_"+ identity_encrypted);
|
|
695
|
-
|
|
696
|
-
this.rootConfig = null;
|
|
697
|
-
this.secretKeyGlobal = null;
|
|
698
|
-
this.identityEncryptedGlobal = null;
|
|
699
|
-
|
|
700
|
-
if (storePath == null || storePath.trim().isEmpty()) {
|
|
701
|
-
storePath = this.fulaStorePath;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
File file = new File(storePath);
|
|
705
|
-
FileUtils.deleteDirectory(file);
|
|
706
|
-
return true;
|
|
707
|
-
|
|
708
|
-
} catch (Exception e) {
|
|
709
|
-
Log.d("ReactNative", "logout internal failed with Error: " + e.getMessage());
|
|
710
|
-
throw (e);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
public fulamobile.Client getFulaClient() {
|
|
715
|
-
return this.fula;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
@NonNull
|
|
719
|
-
private byte[] newClientInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh) throws GeneralSecurityException, IOException {
|
|
720
|
-
byte[] peerIdentity = null;
|
|
721
|
-
try {
|
|
722
|
-
fulaConfig = new Config();
|
|
723
|
-
if (storePath == null || storePath.trim().isEmpty()) {
|
|
724
|
-
fulaConfig.setStorePath(this.fulaStorePath);
|
|
725
|
-
} else {
|
|
726
|
-
fulaConfig.setStorePath(storePath);
|
|
727
|
-
}
|
|
728
|
-
Log.d("ReactNative", "newClientInternal storePath is set: " + fulaConfig.getStorePath());
|
|
729
|
-
|
|
730
|
-
peerIdentity = this.createPeerIdentity(identity);
|
|
731
|
-
fulaConfig.setIdentity(peerIdentity);
|
|
732
|
-
Log.d("ReactNative", "peerIdentity is set: " + toString(fulaConfig.getIdentity()));
|
|
733
|
-
fulaConfig.setBloxAddr(bloxAddr);
|
|
734
|
-
Log.d("ReactNative", "bloxAddr is set: " + fulaConfig.getBloxAddr());
|
|
735
|
-
fulaConfig.setExchange(exchange);
|
|
736
|
-
fulaConfig.setSyncWrites(autoFlush);
|
|
737
|
-
if (useRelay) {
|
|
738
|
-
fulaConfig.setAllowTransientConnection(true);
|
|
739
|
-
fulaConfig.setForceReachabilityPrivate(true);
|
|
740
|
-
}
|
|
741
|
-
if (this.fula == null || refresh) {
|
|
742
|
-
Log.d("ReactNative", "Creating a new Fula instance");
|
|
743
|
-
try {
|
|
744
|
-
shutdownInternal();
|
|
745
|
-
Log.d("ReactNative", "Creating a new Fula instance with config");
|
|
746
|
-
this.fula = Fulamobile.newClient(fulaConfig);
|
|
747
|
-
if (this.fula != null) {
|
|
748
|
-
this.fula.flush();
|
|
749
|
-
}
|
|
750
|
-
} catch (Exception e) {
|
|
751
|
-
Log.d("ReactNative", "Failed to create new Fula instance: " + e.getMessage());
|
|
752
|
-
throw new IOException("Failed to create new Fula instance", e);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
756
|
-
Log.d("ReactNative", "newclientInternal failed with Error: " + e.getMessage());
|
|
757
|
-
throw (e);
|
|
758
|
-
}
|
|
759
|
-
return peerIdentity;
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
@NonNull
|
|
764
|
-
private String[] initInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootCid, boolean useRelay, boolean refresh) throws Exception {
|
|
765
|
-
try {
|
|
766
|
-
if (this.fula == null || refresh) {
|
|
767
|
-
this.newClientInternal(identity, storePath, bloxAddr, exchange, autoFlush, useRelay, refresh);
|
|
768
|
-
}
|
|
769
|
-
if(this.client == null || refresh) {
|
|
770
|
-
this.client = new Client(this.fula);
|
|
771
|
-
Log.d("ReactNative", "fula initialized: " + this.fula.id());
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
SecretKey secretKey = Cryptography.generateKey(identity);
|
|
775
|
-
Log.d("ReactNative", "secretKey generated: " + secretKey.toString());
|
|
776
|
-
byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B };
|
|
777
|
-
String identity_encrypted =Cryptography.encryptMsg(Arrays.toString(identity), secretKey, iv);
|
|
778
|
-
Log.d("ReactNative", "identity_encrypted generated: " + identity_encrypted + " for identity: " + Arrays.toString(identity));
|
|
779
|
-
this.identityEncryptedGlobal = identity_encrypted;
|
|
780
|
-
this.secretKeyGlobal = secretKey;
|
|
781
|
-
|
|
782
|
-
if ( this.rootConfig == null || this.rootConfig.getCid().isEmpty() ) {
|
|
783
|
-
Log.d("ReactNative", "this.rootCid is empty.");
|
|
784
|
-
//Load from keystore
|
|
785
|
-
|
|
786
|
-
String cid_encrypted_fetched = sharedPref.getValue("FULA_ENC_V4:cid_encrypted_"+ identity_encrypted);
|
|
787
|
-
Log.d("ReactNative", "Here1");
|
|
788
|
-
String cid = "";
|
|
789
|
-
if(cid_encrypted_fetched != null && !cid_encrypted_fetched.isEmpty()) {
|
|
790
|
-
Log.d("ReactNative", "decrypting cid="+cid_encrypted_fetched+" with secret="+secretKey.toString());
|
|
791
|
-
cid = Cryptography.decryptMsg(cid_encrypted_fetched, secretKey);
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
Log.d("ReactNative", "Here2");
|
|
795
|
-
//Log.d("ReactNative", "Attempted to fetch cid from keystore; cid="+cid);
|
|
796
|
-
if(cid == null || cid.isEmpty()) {
|
|
797
|
-
Log.d("ReactNative", "cid was not found");
|
|
798
|
-
if(rootCid != null && !rootCid.isEmpty()){
|
|
799
|
-
Log.d("ReactNative", "Re-setting cid from input: "+rootCid);
|
|
800
|
-
cid = rootCid;
|
|
801
|
-
this.rootConfig = new land.fx.wnfslib.Config(cid);
|
|
802
|
-
this.reloadFS(this.client, identity, cid);
|
|
803
|
-
this.encrypt_and_store_config();
|
|
804
|
-
}
|
|
805
|
-
if(cid == null || cid.isEmpty()) {
|
|
806
|
-
Log.d("ReactNative", "Tried to recover cid but was not successful. Creating new ones");
|
|
807
|
-
this.createNewRootConfig(this.client, identity);
|
|
808
|
-
} else {
|
|
809
|
-
this.rootConfig = new land.fx.wnfslib.Config(cid);
|
|
810
|
-
this.reloadFS(this.client, identity, cid);
|
|
811
|
-
this.encrypt_and_store_config();
|
|
812
|
-
}
|
|
813
|
-
} else {
|
|
814
|
-
Log.d("ReactNative", "Recovered cid and private ref from keychain store. cid="+cid +" and cid from input was: "+rootCid);
|
|
815
|
-
this.rootConfig = new land.fx.wnfslib.Config(cid);
|
|
816
|
-
this.reloadFS(this.client, identity, cid);
|
|
817
|
-
this.encrypt_and_store_config();
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
Log.d("ReactNative", "creating rootConfig completed");
|
|
821
|
-
|
|
822
|
-
Log.d("ReactNative", "rootConfig is created: cid=" + this.rootConfig.getCid());
|
|
823
|
-
} else {
|
|
824
|
-
Log.d("ReactNative", "rootConfig existed: cid=" + this.rootConfig.getCid());
|
|
825
|
-
}
|
|
826
|
-
String peerId = this.fula.id();
|
|
827
|
-
String[] obj = new String[2];
|
|
828
|
-
obj[0] = peerId;
|
|
829
|
-
obj[1] = this.rootConfig.getCid();
|
|
830
|
-
Log.d("ReactNative", "initInternal is completed successfully");
|
|
831
|
-
if (this.fula != null) {
|
|
832
|
-
this.fula.flush();
|
|
833
|
-
}
|
|
834
|
-
return obj;
|
|
835
|
-
} catch (Exception e) {
|
|
836
|
-
Log.d("ReactNative", "init internal failed with Error: " + e.getMessage());
|
|
837
|
-
throw (e);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
@ReactMethod
|
|
842
|
-
public void mkdir(String path, Promise promise) {
|
|
843
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
844
|
-
Log.d("ReactNative", "mkdir started with: path = " + path + " rootConfig.getCid() = " + this.rootConfig.getCid());
|
|
845
|
-
try {
|
|
846
|
-
land.fx.wnfslib.Config config = Fs.mkdir(this.client, this.rootConfig.getCid(), path);
|
|
847
|
-
if(config != null) {
|
|
848
|
-
this.rootConfig = config;
|
|
849
|
-
this.encrypt_and_store_config();
|
|
850
|
-
if (this.fula != null) {
|
|
851
|
-
this.fula.flush();
|
|
852
|
-
}
|
|
853
|
-
String rootCid = this.rootConfig.getCid();
|
|
854
|
-
Log.d("ReactNative", "mkdir completed successfully with rootCid = " + rootCid);
|
|
855
|
-
promise.resolve(rootCid);
|
|
856
|
-
} else {
|
|
857
|
-
Log.d("ReactNative", "mkdir Error: config is null");
|
|
858
|
-
promise.reject(new Exception("mkdir Error: config is null"));
|
|
859
|
-
}
|
|
860
|
-
} catch (Exception e) {
|
|
861
|
-
Log.d("get", e.getMessage());
|
|
862
|
-
promise.reject(e);
|
|
863
|
-
}
|
|
864
|
-
});
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
@ReactMethod
|
|
868
|
-
public void writeFile(String fulaTargetFilename, String localFilename, Promise promise) {
|
|
869
|
-
/*
|
|
870
|
-
// reads content of the file form localFilename (should include full absolute path to local file with read permission
|
|
871
|
-
// writes content to the specified location by fulaTargetFilename in Fula filesystem
|
|
872
|
-
// fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
|
|
873
|
-
// localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
|
|
874
|
-
// Returns: new cid of the root after this file is placed in the tree
|
|
875
|
-
*/
|
|
876
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
877
|
-
Log.d("ReactNative", "writeFile to : path = " + fulaTargetFilename + ", from: " + localFilename);
|
|
878
|
-
try {
|
|
879
|
-
if (this.client != null) {
|
|
880
|
-
Log.d("ReactNative", "writeFileFromPath started: this.rootConfig.getCid=" + this.rootConfig.getCid()+ ", fulaTargetFilename="+fulaTargetFilename + ", localFilename="+localFilename);
|
|
881
|
-
land.fx.wnfslib.Config config = Fs.writeFileStreamFromPath(this.client, this.rootConfig.getCid(), fulaTargetFilename, localFilename);
|
|
882
|
-
if(config != null) {
|
|
883
|
-
this.rootConfig = config;
|
|
884
|
-
this.encrypt_and_store_config();
|
|
885
|
-
if (this.fula != null) {
|
|
886
|
-
this.fula.flush();
|
|
887
|
-
String rootCid = this.rootConfig.getCid();
|
|
888
|
-
Log.d("ReactNative", "writeFileFromPath completed: this.rootConfig.getCid=" + rootCid);
|
|
889
|
-
promise.resolve(rootCid);
|
|
890
|
-
} else {
|
|
891
|
-
Log.d("ReactNative", "writeFile Error: fula is null");
|
|
892
|
-
promise.reject(new Exception("writeFile Error: fula is null"));
|
|
893
|
-
}
|
|
894
|
-
} else {
|
|
895
|
-
Log.d("ReactNative", "writeFile Error: config is null");
|
|
896
|
-
promise.reject(new Exception("writeFile Error: config is null"));
|
|
897
|
-
}
|
|
898
|
-
} else {
|
|
899
|
-
Log.d("ReactNative", "writeFile Error: client is null");
|
|
900
|
-
promise.reject(new Exception("writeFile Error: client is null"));
|
|
901
|
-
}
|
|
902
|
-
} catch (Exception e) {
|
|
903
|
-
Log.d("get", e.getMessage());
|
|
904
|
-
promise.reject(e);
|
|
905
|
-
}
|
|
906
|
-
});
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
@ReactMethod
|
|
910
|
-
public void writeFileContent(String path, String contentString, Promise promise) {
|
|
911
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
912
|
-
Log.d("ReactNative", "writeFile: contentString = " + contentString);
|
|
913
|
-
Log.d("ReactNative", "writeFile: path = " + path);
|
|
914
|
-
try {
|
|
915
|
-
byte[] content = this.convertStringToByte(contentString);
|
|
916
|
-
land.fx.wnfslib.Config config = Fs.writeFile(this.client, this.rootConfig.getCid(), path, content);
|
|
917
|
-
this.rootConfig = config;
|
|
918
|
-
this.encrypt_and_store_config();
|
|
919
|
-
if (this.fula != null) {
|
|
920
|
-
this.fula.flush();
|
|
921
|
-
}
|
|
922
|
-
promise.resolve(config.getCid());
|
|
923
|
-
} catch (Exception e) {
|
|
924
|
-
Log.d("get", e.getMessage());
|
|
925
|
-
promise.reject(e);
|
|
926
|
-
}
|
|
927
|
-
});
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
@ReactMethod
|
|
931
|
-
public void ls(String path, Promise promise) {
|
|
932
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
933
|
-
Log.d("ReactNative", "ls: path = " + path + "rootCid= " + this.rootConfig.getCid());
|
|
934
|
-
try {
|
|
935
|
-
byte[] res = Fs.ls(this.client, this.rootConfig.getCid(), path);
|
|
936
|
-
|
|
937
|
-
String s = new String(res, StandardCharsets.UTF_8);
|
|
938
|
-
Log.d("ReactNative", "ls: res = " + s);
|
|
939
|
-
promise.resolve(s);
|
|
940
|
-
} catch (Exception e) {
|
|
941
|
-
Log.d("ReactNative", e.getMessage());
|
|
942
|
-
promise.reject(e);
|
|
943
|
-
}
|
|
944
|
-
});
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
@ReactMethod
|
|
948
|
-
public void rm(String path, Promise promise) {
|
|
949
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
950
|
-
Log.d("ReactNative", "rm: path = " + path + ", beginning rootCid=" + this.rootConfig.getCid());
|
|
951
|
-
try {
|
|
952
|
-
land.fx.wnfslib.Config config = Fs.rm(this.client, this.rootConfig.getCid(), path);
|
|
953
|
-
if(config != null) {
|
|
954
|
-
this.rootConfig = config;
|
|
955
|
-
this.encrypt_and_store_config();
|
|
956
|
-
if (this.fula != null) {
|
|
957
|
-
this.fula.flush();
|
|
958
|
-
}
|
|
959
|
-
String rootCid = config.getCid();
|
|
960
|
-
Log.d("ReactNative", "rm: returned rootCid = " + rootCid);
|
|
961
|
-
promise.resolve(rootCid);
|
|
962
|
-
} else {
|
|
963
|
-
Log.d("ReactNative", "rm Error: config is null");
|
|
964
|
-
promise.reject(new Exception("rm Error: config is null"));
|
|
965
|
-
}
|
|
966
|
-
} catch (Exception e) {
|
|
967
|
-
Log.d("ReactNative", e.getMessage());
|
|
968
|
-
promise.reject(e);
|
|
969
|
-
}
|
|
970
|
-
});
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
@ReactMethod
|
|
974
|
-
public void cp(String sourcePath, String targetPath, Promise promise) {
|
|
975
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
976
|
-
Log.d("ReactNative", "rm: sourcePath = " + sourcePath);
|
|
977
|
-
try {
|
|
978
|
-
land.fx.wnfslib.Config config = Fs.cp(this.client, this.rootConfig.getCid(), sourcePath, targetPath);
|
|
979
|
-
if(config != null) {
|
|
980
|
-
this.rootConfig = config;
|
|
981
|
-
this.encrypt_and_store_config();
|
|
982
|
-
if (this.fula != null) {
|
|
983
|
-
this.fula.flush();
|
|
984
|
-
}
|
|
985
|
-
promise.resolve(config.getCid());
|
|
986
|
-
} else {
|
|
987
|
-
Log.d("ReactNative", "cp Error: config is null");
|
|
988
|
-
promise.reject(new Exception("cp Error: config is null"));
|
|
989
|
-
}
|
|
990
|
-
} catch (Exception e) {
|
|
991
|
-
Log.d("ReactNative", e.getMessage());
|
|
992
|
-
promise.reject(e);
|
|
993
|
-
}
|
|
994
|
-
});
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
@ReactMethod
|
|
998
|
-
public void mv(String sourcePath, String targetPath, Promise promise) {
|
|
999
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1000
|
-
Log.d("ReactNative", "rm: sourcePath = " + sourcePath);
|
|
1001
|
-
try {
|
|
1002
|
-
land.fx.wnfslib.Config config = Fs.mv(this.client, this.rootConfig.getCid(), sourcePath, targetPath);
|
|
1003
|
-
if(config != null) {
|
|
1004
|
-
this.rootConfig = config;
|
|
1005
|
-
this.encrypt_and_store_config();
|
|
1006
|
-
if (this.fula != null) {
|
|
1007
|
-
this.fula.flush();
|
|
1008
|
-
}
|
|
1009
|
-
promise.resolve(config.getCid());
|
|
1010
|
-
} else {
|
|
1011
|
-
Log.d("ReactNative", "mv Error: config is null");
|
|
1012
|
-
promise.reject(new Exception("mv Error: config is null"));
|
|
1013
|
-
}
|
|
1014
|
-
} catch (Exception e) {
|
|
1015
|
-
Log.d("ReactNative", e.getMessage());
|
|
1016
|
-
promise.reject(e);
|
|
1017
|
-
}
|
|
1018
|
-
});
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
@ReactMethod
|
|
1022
|
-
public void readFile(String fulaTargetFilename, String localFilename, Promise promise) {
|
|
1023
|
-
/*
|
|
1024
|
-
// reads content of the file form localFilename (should include full absolute path to local file with read permission
|
|
1025
|
-
// writes content to the specified location by fulaTargetFilename in Fula filesystem
|
|
1026
|
-
// fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
|
|
1027
|
-
// localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
|
|
1028
|
-
// Returns: new cid of the root after this file is placed in the tree
|
|
1029
|
-
*/
|
|
1030
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1031
|
-
Log.d("ReactNative", "readFile: fulaTargetFilename = " + fulaTargetFilename);
|
|
1032
|
-
try {
|
|
1033
|
-
Log.d("ReactNative", "readFile: localFilename = " + localFilename + " fulaTargetFilename = " + fulaTargetFilename + " beginning rootCid = " + this.rootConfig.getCid());
|
|
1034
|
-
String path = Fs.readFilestreamToPath(this.client, this.rootConfig.getCid(), fulaTargetFilename, localFilename);
|
|
1035
|
-
promise.resolve(path);
|
|
1036
|
-
} catch (Exception e) {
|
|
1037
|
-
Log.d("ReactNative", e.getMessage());
|
|
1038
|
-
promise.reject(e);
|
|
1039
|
-
}
|
|
1040
|
-
});
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
@ReactMethod
|
|
1044
|
-
public void readFileContent(String path, Promise promise) {
|
|
1045
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1046
|
-
Log.d("ReactNative", "readFileContent: path = " + path);
|
|
1047
|
-
try {
|
|
1048
|
-
byte[] res = Fs.readFile(this.client, this.rootConfig.getCid(), path);
|
|
1049
|
-
String resString = toString(res);
|
|
1050
|
-
promise.resolve(resString);
|
|
1051
|
-
} catch (Exception e) {
|
|
1052
|
-
Log.d("ReactNative", e.getMessage());
|
|
1053
|
-
promise.reject(e);
|
|
1054
|
-
}
|
|
1055
|
-
});
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
@ReactMethod
|
|
1059
|
-
public void get(String keyString, Promise promise) {
|
|
1060
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1061
|
-
Log.d("ReactNative", "get: keyString = " + keyString);
|
|
1062
|
-
try {
|
|
1063
|
-
byte[] key = this.convertStringToByte(keyString);
|
|
1064
|
-
byte[] value = this.getInternal(key);
|
|
1065
|
-
String valueString = toString(value);
|
|
1066
|
-
promise.resolve(valueString);
|
|
1067
|
-
} catch (Exception e) {
|
|
1068
|
-
Log.d("ReactNative", e.getMessage());
|
|
1069
|
-
promise.reject(e);
|
|
1070
|
-
}
|
|
1071
|
-
});
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
@NonNull
|
|
1075
|
-
private byte[] getInternal(byte[] key) throws Exception {
|
|
1076
|
-
try {
|
|
1077
|
-
Log.d("ReactNative", "getInternal: key.toString() = " + toString(key));
|
|
1078
|
-
Log.d("ReactNative", "getInternal: key.toString().bytes = " + Arrays.toString(key));
|
|
1079
|
-
byte[] value = this.fula.get(key);
|
|
1080
|
-
Log.d("ReactNative", "getInternal: value.toString() = " + toString(value));
|
|
1081
|
-
return value;
|
|
1082
|
-
} catch (Exception e) {
|
|
1083
|
-
Log.d("ReactNative", "getInternal: error = " + e.getMessage());
|
|
1084
|
-
Log.d("getInternal", e.getMessage());
|
|
1085
|
-
throw (e);
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
@ReactMethod
|
|
1090
|
-
public void has(String keyString, Promise promise) {
|
|
1091
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1092
|
-
Log.d("ReactNative", "has: keyString = " + keyString);
|
|
1093
|
-
try {
|
|
1094
|
-
byte[] key = this.convertStringToByte(keyString);
|
|
1095
|
-
boolean result = this.hasInternal(key);
|
|
1096
|
-
promise.resolve(result);
|
|
1097
|
-
} catch (Exception e) {
|
|
1098
|
-
Log.d("ReactNative", e.getMessage());
|
|
1099
|
-
promise.reject(e);
|
|
1100
|
-
}
|
|
1101
|
-
});
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
private boolean hasInternal(byte[] key) throws Exception {
|
|
1105
|
-
try {
|
|
1106
|
-
boolean res = this.fula.has(key);
|
|
1107
|
-
return res;
|
|
1108
|
-
} catch (Exception e) {
|
|
1109
|
-
Log.d("ReactNative", e.getMessage());
|
|
1110
|
-
throw (e);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
private void pullInternal(byte[] key) throws Exception {
|
|
1115
|
-
try {
|
|
1116
|
-
this.fula.pull(key);
|
|
1117
|
-
} catch (Exception e) {
|
|
1118
|
-
Log.d("ReactNative", e.getMessage());
|
|
1119
|
-
throw (e);
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
@ReactMethod
|
|
1124
|
-
public void push(Promise promise) {
|
|
1125
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1126
|
-
Log.d("ReactNative", "push started");
|
|
1127
|
-
try {
|
|
1128
|
-
this.pushInternal(this.convertStringToByte(this.rootConfig.getCid()));
|
|
1129
|
-
promise.resolve(this.rootConfig.getCid());
|
|
1130
|
-
} catch (Exception e) {
|
|
1131
|
-
Log.d("ReactNative", e.getMessage());
|
|
1132
|
-
promise.reject(e);
|
|
1133
|
-
}
|
|
1134
|
-
});
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
private void pushInternal(byte[] key) throws Exception {
|
|
1138
|
-
try {
|
|
1139
|
-
if (this.fula != null && this.fula.has(key)) {
|
|
1140
|
-
this.fula.push(key);
|
|
1141
|
-
this.fula.flush();
|
|
1142
|
-
} else {
|
|
1143
|
-
Log.d("ReactNative", "pushInternal error: key wasn't found or fula is not initialized");
|
|
1144
|
-
throw new Exception("key wasn't found in local storage");
|
|
1145
|
-
}
|
|
1146
|
-
} catch (Exception e) {
|
|
1147
|
-
Log.d("ReactNative", "pushInternal"+ e.getMessage());
|
|
1148
|
-
throw (e);
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
@ReactMethod
|
|
1153
|
-
public void put(String valueString, String codecString, Promise promise) {
|
|
1154
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1155
|
-
Log.d("ReactNative", "put: codecString = " + codecString);
|
|
1156
|
-
Log.d("ReactNative", "put: valueString = " + valueString);
|
|
1157
|
-
try {
|
|
1158
|
-
//byte[] codec = this.convertStringToByte(CodecString);
|
|
1159
|
-
long codec = Long.parseLong(codecString);
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
Log.d("ReactNative", "put: codec = " + codec);
|
|
1163
|
-
byte[] value = toByte(valueString);
|
|
1164
|
-
|
|
1165
|
-
Log.d("ReactNative", "put: value.toString() = " + toString(value));
|
|
1166
|
-
byte[] key = this.putInternal(value, codec);
|
|
1167
|
-
Log.d("ReactNative", "put: key.toString() = " + toString(key));
|
|
1168
|
-
promise.resolve(toString(key));
|
|
1169
|
-
} catch (Exception e) {
|
|
1170
|
-
Log.d("ReactNative", "put: error = " + e.getMessage());
|
|
1171
|
-
promise.reject(e);
|
|
1172
|
-
}
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
@NonNull
|
|
1177
|
-
private byte[] putInternal(byte[] value, long codec) throws Exception {
|
|
1178
|
-
try {
|
|
1179
|
-
if(this.fula != null) {
|
|
1180
|
-
byte[] key = this.fula.put(value, codec);
|
|
1181
|
-
this.fula.flush();
|
|
1182
|
-
return key;
|
|
1183
|
-
} else {
|
|
1184
|
-
Log.d("ReactNative", "putInternal Error: fula is not initialized");
|
|
1185
|
-
throw (new Exception("putInternal Error: fula is not initialized"));
|
|
1186
|
-
}
|
|
1187
|
-
} catch (Exception e) {
|
|
1188
|
-
Log.d("ReactNative", "putInternal"+ e.getMessage());
|
|
1189
|
-
throw (e);
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
@ReactMethod
|
|
1194
|
-
public void setAuth(String peerIdString, boolean allow, Promise promise) {
|
|
1195
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1196
|
-
Log.d("ReactNative", "setAuth: peerIdString = " + peerIdString);
|
|
1197
|
-
try {
|
|
1198
|
-
if (this.fula != null && this.fula.id() != null && this.fulaConfig != null && this.fulaConfig.getBloxAddr() != null) {
|
|
1199
|
-
String bloxAddr = this.fulaConfig.getBloxAddr();
|
|
1200
|
-
Log.d("ReactNative", "setAuth: bloxAddr = '" + bloxAddr+"'"+ " peerIdString = '" + peerIdString+"'");
|
|
1201
|
-
int index = bloxAddr.lastIndexOf("/");
|
|
1202
|
-
String bloxPeerId = bloxAddr.substring(index + 1);
|
|
1203
|
-
this.fula.setAuth(bloxPeerId, peerIdString, allow);
|
|
1204
|
-
promise.resolve(true);
|
|
1205
|
-
} else {
|
|
1206
|
-
Log.d("ReactNative", "setAuth error: fula is not initialized");
|
|
1207
|
-
throw new Exception("fula is not initialized");
|
|
1208
|
-
}
|
|
1209
|
-
promise.resolve(false);
|
|
1210
|
-
} catch (Exception e) {
|
|
1211
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1212
|
-
promise.reject(e);
|
|
1213
|
-
}
|
|
1214
|
-
});
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
private void shutdownInternal() throws Exception {
|
|
1218
|
-
try {
|
|
1219
|
-
if(this.fula != null) {
|
|
1220
|
-
this.fula.shutdown();
|
|
1221
|
-
this.fula = null;
|
|
1222
|
-
this.client = null;
|
|
1223
|
-
Log.d("ReactNative", "shutdownInternal done");
|
|
1224
|
-
|
|
1225
|
-
}
|
|
1226
|
-
} catch (Exception e) {
|
|
1227
|
-
Log.d("ReactNative", "shutdownInternal error: "+ e.getMessage());
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
@ReactMethod
|
|
1232
|
-
public void shutdown(Promise promise) {
|
|
1233
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1234
|
-
try {
|
|
1235
|
-
shutdownInternal();
|
|
1236
|
-
promise.resolve(true);
|
|
1237
|
-
} catch (Exception e) {
|
|
1238
|
-
promise.reject(e);
|
|
1239
|
-
Log.d("ReactNative", "shutdown"+ e.getMessage());
|
|
1240
|
-
}
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
///////////////////////////////////////////////////////////
|
|
1245
|
-
///////////////////////////////////////////////////////////
|
|
1246
|
-
///////////////////////////////////////////////////////////
|
|
1247
|
-
///////////////////////////////////////////////////////////
|
|
1248
|
-
//////////////////////ANYTHING BELOW IS FOR BLOCKCHAIN/////
|
|
1249
|
-
///////////////////////////////////////////////////////////
|
|
1250
|
-
@ReactMethod
|
|
1251
|
-
public void getAccount(Promise promise) {
|
|
1252
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1253
|
-
Log.d("ReactNative", "getAccount called ");
|
|
1254
|
-
try {
|
|
1255
|
-
byte[] result = this.fula.getAccount();
|
|
1256
|
-
String resultString = toString(result);
|
|
1257
|
-
promise.resolve(resultString);
|
|
1258
|
-
} catch (Exception e) {
|
|
1259
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1260
|
-
promise.reject(e);
|
|
1261
|
-
}
|
|
1262
|
-
});
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
@ReactMethod
|
|
1266
|
-
public void accountFund(String accountString, Promise promise) {
|
|
1267
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1268
|
-
Log.d("ReactNative", "accountFund: accountString = " + accountString);
|
|
1269
|
-
try {
|
|
1270
|
-
byte[] result = this.fula.accountFund(accountString);
|
|
1271
|
-
String resultString = toString(result);
|
|
1272
|
-
promise.resolve(resultString);
|
|
1273
|
-
} catch (Exception e) {
|
|
1274
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1275
|
-
promise.reject(e);
|
|
1276
|
-
}
|
|
1277
|
-
});
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
|
-
@ReactMethod
|
|
1281
|
-
public void assetsBalance(String account, String assetId, String classId, Promise promise) {
|
|
1282
|
-
long assetIdLong = Long.parseLong(assetId);
|
|
1283
|
-
long classIdLong = Long.parseLong(classId);
|
|
1284
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1285
|
-
Log.d("ReactNative", "assetsBalance called ");
|
|
1286
|
-
try {
|
|
1287
|
-
byte[] result = this.fula.assetsBalance(account, assetIdLong, classIdLong);
|
|
1288
|
-
String resultString = toString(result);
|
|
1289
|
-
promise.resolve(resultString);
|
|
1290
|
-
} catch (Exception e) {
|
|
1291
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1292
|
-
promise.reject(e);
|
|
1293
|
-
}
|
|
1294
|
-
});
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
@ReactMethod
|
|
1298
|
-
public void transferToFula(String amount, String wallet, String chain, Promise promise) {
|
|
1299
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1300
|
-
Log.d("ReactNative", "transferToFula called ");
|
|
1301
|
-
try {
|
|
1302
|
-
byte[] result = this.fula.transferToFula(amount, wallet, chain);
|
|
1303
|
-
String resultString = toString(result);
|
|
1304
|
-
promise.resolve(resultString);
|
|
1305
|
-
} catch (Exception e) {
|
|
1306
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1307
|
-
promise.reject(e);
|
|
1308
|
-
}
|
|
1309
|
-
});
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
@ReactMethod
|
|
1313
|
-
public void checkAccountExists(String accountString, Promise promise) {
|
|
1314
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1315
|
-
Log.d("ReactNative", "checkAccountExists: accountString = " + accountString);
|
|
1316
|
-
try {
|
|
1317
|
-
byte[] result = this.fula.accountExists(accountString);
|
|
1318
|
-
String resultString = toString(result);
|
|
1319
|
-
promise.resolve(resultString);
|
|
1320
|
-
} catch (Exception e) {
|
|
1321
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1322
|
-
promise.reject(e);
|
|
1323
|
-
}
|
|
1324
|
-
});
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
|
-
@ReactMethod
|
|
1328
|
-
public void listPools(Promise promise) {
|
|
1329
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1330
|
-
Log.d("ReactNative", "listPools");
|
|
1331
|
-
try {
|
|
1332
|
-
byte[] result = this.fula.poolList();
|
|
1333
|
-
String resultString = toString(result);
|
|
1334
|
-
promise.resolve(resultString);
|
|
1335
|
-
} catch (Exception e) {
|
|
1336
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1337
|
-
promise.reject(e);
|
|
1338
|
-
}
|
|
1339
|
-
});
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1342
|
-
@ReactMethod
|
|
1343
|
-
public void joinPool(String poolID, Promise promise) {
|
|
1344
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1345
|
-
long poolIdLong = Long.parseLong(poolID);
|
|
1346
|
-
Log.d("ReactNative", "joinPool: poolID = " + poolIdLong);
|
|
1347
|
-
try {
|
|
1348
|
-
byte[] result = this.fula.poolJoin(poolIdLong);
|
|
1349
|
-
String resultString = toString(result);
|
|
1350
|
-
promise.resolve(resultString);
|
|
1351
|
-
} catch (Exception e) {
|
|
1352
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1353
|
-
promise.reject(e);
|
|
1354
|
-
}
|
|
1355
|
-
});
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
@ReactMethod
|
|
1359
|
-
public void cancelPoolJoin(String poolID, Promise promise) {
|
|
1360
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1361
|
-
long poolIdLong = Long.parseLong(poolID);
|
|
1362
|
-
Log.d("ReactNative", "cancelPoolJoin: poolID = " + poolIdLong);
|
|
1363
|
-
try {
|
|
1364
|
-
byte[] result = this.fula.poolCancelJoin(poolIdLong);
|
|
1365
|
-
String resultString = toString(result);
|
|
1366
|
-
promise.resolve(resultString);
|
|
1367
|
-
} catch (Exception e) {
|
|
1368
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1369
|
-
promise.reject(e);
|
|
1370
|
-
}
|
|
1371
|
-
});
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
@ReactMethod
|
|
1375
|
-
public void listPoolJoinRequests(String poolIDStr, Promise promise) {
|
|
1376
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1377
|
-
Log.d("ReactNative", "listPoolJoinRequests: poolID = " + poolIDStr);
|
|
1378
|
-
try {
|
|
1379
|
-
long poolID = Long.parseLong(poolIDStr);
|
|
1380
|
-
byte[] result = this.fula.poolRequests(poolID);
|
|
1381
|
-
String resultString = toString(result);
|
|
1382
|
-
promise.resolve(resultString);
|
|
1383
|
-
} catch (Exception e) {
|
|
1384
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1385
|
-
promise.reject(e);
|
|
1386
|
-
}
|
|
1387
|
-
});
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
@ReactMethod
|
|
1391
|
-
public void leavePool(String poolID, Promise promise) {
|
|
1392
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1393
|
-
long poolIdLong = Long.parseLong(poolID);
|
|
1394
|
-
Log.d("ReactNative", "leavePool: poolID = " + poolIdLong);
|
|
1395
|
-
try {
|
|
1396
|
-
byte[] result = this.fula.poolLeave(poolIdLong);
|
|
1397
|
-
String resultString = toString(result);
|
|
1398
|
-
promise.resolve(resultString);
|
|
1399
|
-
} catch (Exception e) {
|
|
1400
|
-
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1401
|
-
promise.reject(e);
|
|
1402
|
-
}
|
|
1403
|
-
});
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
@ReactMethod
|
|
1407
|
-
public void
|
|
1408
|
-
ThreadUtils.runOnExecutor(() -> {
|
|
1409
|
-
Log.d("ReactNative", "
|
|
1410
|
-
try {
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
} else {
|
|
1511
|
-
throw new Exception("
|
|
1512
|
-
}
|
|
1513
|
-
} catch (Exception e) {
|
|
1514
|
-
Log.d("ReactNative", "
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
Log.d("ReactNative", "
|
|
1766
|
-
promise.
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
@ReactMethod
|
|
1898
|
-
public void
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
})
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
.
|
|
1984
|
-
.
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1
|
+
package land.fx.fula;
|
|
2
|
+
|
|
3
|
+
import android.util.Log;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
|
|
7
|
+
import android.os.Handler;
|
|
8
|
+
import android.os.Looper;
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
import com.facebook.react.bridge.Promise;
|
|
12
|
+
import com.facebook.react.bridge.Callback;
|
|
13
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
14
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
15
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
16
|
+
import com.facebook.react.bridge.WritableMap;
|
|
17
|
+
import com.facebook.react.bridge.WritableNativeMap;
|
|
18
|
+
import com.facebook.react.module.annotations.ReactModule;
|
|
19
|
+
import com.facebook.react.bridge.Arguments;
|
|
20
|
+
import com.facebook.react.bridge.WritableArray;
|
|
21
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
22
|
+
import com.facebook.react.bridge.LifecycleEventListener;
|
|
23
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
import org.apache.commons.io.FileUtils;
|
|
27
|
+
import org.jetbrains.annotations.Contract;
|
|
28
|
+
|
|
29
|
+
import java.io.File;
|
|
30
|
+
import java.io.IOException;
|
|
31
|
+
import java.nio.charset.StandardCharsets;
|
|
32
|
+
import java.security.GeneralSecurityException;
|
|
33
|
+
import java.security.InvalidAlgorithmParameterException;
|
|
34
|
+
import java.security.InvalidKeyException;
|
|
35
|
+
import java.security.NoSuchAlgorithmException;
|
|
36
|
+
import java.security.MessageDigest;
|
|
37
|
+
import java.util.Arrays;
|
|
38
|
+
import java.util.ArrayList;
|
|
39
|
+
|
|
40
|
+
import javax.crypto.BadPaddingException;
|
|
41
|
+
import javax.crypto.IllegalBlockSizeException;
|
|
42
|
+
import javax.crypto.NoSuchPaddingException;
|
|
43
|
+
import javax.crypto.SecretKey;
|
|
44
|
+
|
|
45
|
+
import java.util.concurrent.Executors;
|
|
46
|
+
import java.util.concurrent.ScheduledExecutorService;
|
|
47
|
+
import java.util.concurrent.TimeUnit;
|
|
48
|
+
import java.util.concurrent.atomic.AtomicBoolean;
|
|
49
|
+
import java.util.concurrent.Future;
|
|
50
|
+
import java.util.concurrent.TimeoutException;
|
|
51
|
+
|
|
52
|
+
import fulamobile.Config;
|
|
53
|
+
import fulamobile.Fulamobile;
|
|
54
|
+
|
|
55
|
+
import land.fx.wnfslib.Fs;
|
|
56
|
+
import java.nio.file.Files;
|
|
57
|
+
import java.nio.file.Path;
|
|
58
|
+
import java.nio.file.Paths;
|
|
59
|
+
|
|
60
|
+
@ReactModule(name = FulaModule.NAME)
|
|
61
|
+
public class FulaModule extends ReactContextBaseJavaModule {
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@Override
|
|
65
|
+
public void initialize() {
|
|
66
|
+
System.loadLibrary("wnfslib");
|
|
67
|
+
System.loadLibrary("gojni");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
public static final String NAME = "FulaModule";
|
|
72
|
+
private final ReactApplicationContext reactContext;
|
|
73
|
+
fulamobile.Client fula;
|
|
74
|
+
|
|
75
|
+
Client client;
|
|
76
|
+
Config fulaConfig;
|
|
77
|
+
|
|
78
|
+
String appName;
|
|
79
|
+
String appDir;
|
|
80
|
+
String fulaStorePath;
|
|
81
|
+
land.fx.wnfslib.Config rootConfig;
|
|
82
|
+
SharedPreferenceHelper sharedPref;
|
|
83
|
+
SecretKey secretKeyGlobal;
|
|
84
|
+
String identityEncryptedGlobal;
|
|
85
|
+
static String PRIVATE_KEY_STORE_PEERID = "PRIVATE_KEY";
|
|
86
|
+
|
|
87
|
+
public static class Client implements land.fx.wnfslib.Datastore {
|
|
88
|
+
|
|
89
|
+
private final fulamobile.Client internalClient;
|
|
90
|
+
|
|
91
|
+
Client(fulamobile.Client clientInput) {
|
|
92
|
+
this.internalClient = clientInput;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@NonNull
|
|
96
|
+
@Override
|
|
97
|
+
public byte[] get(@NonNull byte[] cid) {
|
|
98
|
+
try {
|
|
99
|
+
Log.d("ReactNative", Arrays.toString(cid));
|
|
100
|
+
return this.internalClient.get(cid);
|
|
101
|
+
} catch (Exception e) {
|
|
102
|
+
e.printStackTrace();
|
|
103
|
+
}
|
|
104
|
+
Log.d("ReactNative","Error get");
|
|
105
|
+
return cid;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@NonNull
|
|
109
|
+
@Override
|
|
110
|
+
public byte[] put(@NonNull byte[] cid, byte[] data) {
|
|
111
|
+
try {
|
|
112
|
+
long codec = (long)cid[1] & 0xFF;
|
|
113
|
+
byte[] put_cid = this.internalClient.put(data, codec);
|
|
114
|
+
//Log.d("ReactNative", "data="+ Arrays.toString(data) +" ;codec="+codec);
|
|
115
|
+
return put_cid;
|
|
116
|
+
} catch (Exception e) {
|
|
117
|
+
Log.d("ReactNative", "put Error="+e.getMessage());
|
|
118
|
+
e.printStackTrace();
|
|
119
|
+
}
|
|
120
|
+
Log.d("ReactNative","Error put");
|
|
121
|
+
return data;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public FulaModule(ReactApplicationContext reactContext) {
|
|
126
|
+
super(reactContext);
|
|
127
|
+
this.reactContext = reactContext;
|
|
128
|
+
appName = reactContext.getPackageName();
|
|
129
|
+
appDir = reactContext.getFilesDir().toString();
|
|
130
|
+
fulaStorePath = appDir + "/fula";
|
|
131
|
+
File storeDir = new File(fulaStorePath);
|
|
132
|
+
sharedPref = SharedPreferenceHelper.getInstance(reactContext.getApplicationContext());
|
|
133
|
+
boolean success = true;
|
|
134
|
+
if (!storeDir.exists()) {
|
|
135
|
+
success = storeDir.mkdirs();
|
|
136
|
+
}
|
|
137
|
+
if (success) {
|
|
138
|
+
Log.d("ReactNative", "Fula store folder created for " + appName + " at " + fulaStorePath);
|
|
139
|
+
} else {
|
|
140
|
+
Log.d("ReactNative", "Unable to create fula store folder for " + appName + " at " + fulaStorePath);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@Override
|
|
145
|
+
@NonNull
|
|
146
|
+
public java.lang.String getName() {
|
|
147
|
+
return NAME;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
private byte[] toByte(@NonNull String input) {
|
|
152
|
+
return input.getBytes(StandardCharsets.UTF_8);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private byte[] decToByte(@NonNull String input) {
|
|
156
|
+
String[] parts = input.split(",");
|
|
157
|
+
byte[] output = new byte[parts.length];
|
|
158
|
+
for (int i = 0; i < parts.length; i++) {
|
|
159
|
+
output[i] = Byte.parseByte(parts[i]);
|
|
160
|
+
}
|
|
161
|
+
return output;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@NonNull
|
|
165
|
+
@Contract("_ -> new")
|
|
166
|
+
public String toString(byte[] input) {
|
|
167
|
+
return new String(input, StandardCharsets.UTF_8);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@NonNull
|
|
171
|
+
private static int[] stringArrToIntArr(@NonNull String[] s) {
|
|
172
|
+
int[] result = new int[s.length];
|
|
173
|
+
for (int i = 0; i < s.length; i++) {
|
|
174
|
+
result[i] = Integer.parseInt(s[i]);
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@NonNull
|
|
180
|
+
@Contract(pure = true)
|
|
181
|
+
private static byte[] convertIntToByte(@NonNull int[] input) {
|
|
182
|
+
byte[] result = new byte[input.length];
|
|
183
|
+
for (int i = 0; i < input.length; i++) {
|
|
184
|
+
byte b = (byte) input[i];
|
|
185
|
+
result[i] = b;
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@NonNull
|
|
191
|
+
private byte[] convertStringToByte(@NonNull String data) {
|
|
192
|
+
String[] keyInt_S = data.split(",");
|
|
193
|
+
int[] keyInt = stringArrToIntArr(keyInt_S);
|
|
194
|
+
|
|
195
|
+
return convertIntToByte(keyInt);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@ReactMethod
|
|
199
|
+
public void registerLifecycleListener(Promise promise) {
|
|
200
|
+
getReactApplicationContext().addLifecycleEventListener(new LifecycleEventListener() {
|
|
201
|
+
@Override
|
|
202
|
+
public void onHostResume() {
|
|
203
|
+
// App is in the foreground
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@Override
|
|
207
|
+
public void onHostPause() {
|
|
208
|
+
// App is in the background
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
@Override
|
|
212
|
+
public void onHostDestroy() {
|
|
213
|
+
// Attempt to shut down Fula cleanly
|
|
214
|
+
try {
|
|
215
|
+
Log.e("ReactNative", "shutting down Fula onHostDestroy");
|
|
216
|
+
shutdownInternal();
|
|
217
|
+
} catch (Exception e) {
|
|
218
|
+
Log.e("ReactNative", "Error shutting down Fula", e);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
promise.resolve(true);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
@ReactMethod
|
|
226
|
+
public void checkConnection(int timeout, Promise promise) {
|
|
227
|
+
Log.d("ReactNative", "checkConnection started");
|
|
228
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
229
|
+
if (this.fula != null) {
|
|
230
|
+
try {
|
|
231
|
+
boolean connectionStatus = this.checkConnectionInternal(timeout);
|
|
232
|
+
Log.d("ReactNative", "checkConnection ended " + connectionStatus);
|
|
233
|
+
promise.resolve(connectionStatus);
|
|
234
|
+
}
|
|
235
|
+
catch (Exception e) {
|
|
236
|
+
Log.d("ReactNative", "checkConnection failed with Error: " + e.getMessage());
|
|
237
|
+
promise.resolve(false);
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
Log.d("ReactNative", "checkConnection failed with Error: " + "fula is null");
|
|
241
|
+
promise.resolve(false);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
@ReactMethod
|
|
247
|
+
public void newClient(String identityString, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh, Promise promise) {
|
|
248
|
+
Log.d("ReactNative", "newClient started");
|
|
249
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
250
|
+
try {
|
|
251
|
+
Log.d("ReactNative", "newClient storePath= " + storePath + " bloxAddr= " + bloxAddr + " exchange= " + exchange + " autoFlush= " + autoFlush + " useRelay= " + useRelay + " refresh= " + refresh);
|
|
252
|
+
byte[] identity = toByte(identityString);
|
|
253
|
+
Log.d("ReactNative", "newClient identity= " + identityString);
|
|
254
|
+
this.newClientInternal(identity, storePath, bloxAddr, exchange, autoFlush, useRelay, refresh);
|
|
255
|
+
//String objString = Arrays.toString(obj);
|
|
256
|
+
String peerId = this.fula.id();
|
|
257
|
+
Log.d("ReactNative", "newClient peerId= " + peerId);
|
|
258
|
+
promise.resolve(peerId);
|
|
259
|
+
} catch (Exception e) {
|
|
260
|
+
Log.d("ReactNative", "newClient failed with Error: " + e.getMessage());
|
|
261
|
+
promise.reject("Error", e.getMessage());
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@ReactMethod
|
|
267
|
+
public void deleteDsLock() {
|
|
268
|
+
String lockFilePath = fulaConfig.getStorePath() + "/LOCK";
|
|
269
|
+
Path lockFile = Paths.get(lockFilePath);
|
|
270
|
+
try {
|
|
271
|
+
if (Files.exists(lockFile)) {
|
|
272
|
+
Files.delete(lockFile);
|
|
273
|
+
Log.d("ReactNative", "Lock file deleted successfully.");
|
|
274
|
+
} else {
|
|
275
|
+
Log.d("ReactNative", "Lock file does not exist.");
|
|
276
|
+
}
|
|
277
|
+
} catch (Exception e) {
|
|
278
|
+
Log.d("ReactNative", "Failed to delete lock file: " + e.getMessage());
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@ReactMethod
|
|
283
|
+
public void isReady(boolean filesystemCheck, Promise promise) {
|
|
284
|
+
Log.d("ReactNative", "isReady started");
|
|
285
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
286
|
+
boolean initialized = false;
|
|
287
|
+
try {
|
|
288
|
+
if (this.fula != null && this.fula.id() != null) {
|
|
289
|
+
if (filesystemCheck) {
|
|
290
|
+
if (this.client != null && this.rootConfig != null && !this.rootConfig.getCid().isEmpty()) {
|
|
291
|
+
initialized = true;
|
|
292
|
+
Log.d("ReactNative", "isReady is true with filesystem check");
|
|
293
|
+
}
|
|
294
|
+
} else {
|
|
295
|
+
Log.d("ReactNative", "isReady is true without filesystem check");
|
|
296
|
+
initialized = true;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
promise.resolve(initialized);
|
|
300
|
+
} catch (Exception e) {
|
|
301
|
+
Log.d("ReactNative", "isReady failed with Error: " + e.getMessage());
|
|
302
|
+
promise.reject("Error", e.getMessage());
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
@ReactMethod
|
|
308
|
+
public void initFula(String identityString, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootConfig, boolean useRelay, boolean refresh, Promise promise) {
|
|
309
|
+
Log.d("ReactNative", "init started");
|
|
310
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
311
|
+
try {
|
|
312
|
+
WritableMap resultData = new WritableNativeMap();
|
|
313
|
+
Log.d("ReactNative", "init storePath= " + storePath);
|
|
314
|
+
byte[] identity = toByte(identityString);
|
|
315
|
+
Log.d("ReactNative", "init identity= " + identityString);
|
|
316
|
+
String[] obj = this.initInternal(identity, storePath, bloxAddr, exchange, autoFlush, rootConfig, useRelay, refresh);
|
|
317
|
+
Log.d("ReactNative", "init object created: [ " + obj[0] + ", " + obj[1] + " ]");
|
|
318
|
+
resultData.putString("peerId", obj[0]);
|
|
319
|
+
resultData.putString("rootCid", obj[1]);
|
|
320
|
+
promise.resolve(resultData);
|
|
321
|
+
} catch (Exception e) {
|
|
322
|
+
Log.d("ReactNative", "init failed with Error: " + e.getMessage());
|
|
323
|
+
promise.reject("Error", e.getMessage());
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
@ReactMethod
|
|
329
|
+
public void logout(String identityString, String storePath, Promise promise) {
|
|
330
|
+
Log.d("ReactNative", "logout started");
|
|
331
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
332
|
+
try {
|
|
333
|
+
byte[] identity = toByte(identityString);
|
|
334
|
+
boolean obj = this.logoutInternal(identity, storePath);
|
|
335
|
+
Log.d("ReactNative", "logout completed");
|
|
336
|
+
promise.resolve(obj);
|
|
337
|
+
} catch (Exception e) {
|
|
338
|
+
Log.d("ReactNative", "logout failed with Error: " + e.getMessage());
|
|
339
|
+
promise.reject("Error", e.getMessage());
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private boolean checkConnectionInternal(int timeout) throws Exception {
|
|
345
|
+
try {
|
|
346
|
+
Log.d("ReactNative", "checkConnectionInternal started");
|
|
347
|
+
if (this.fula != null) {
|
|
348
|
+
try {
|
|
349
|
+
Log.d("ReactNative", "connectToBlox started");
|
|
350
|
+
|
|
351
|
+
AtomicBoolean connectionStatus = new AtomicBoolean(false);
|
|
352
|
+
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
|
353
|
+
Future<?> future = executor.submit(() -> {
|
|
354
|
+
try {
|
|
355
|
+
this.fula.connectToBlox();
|
|
356
|
+
connectionStatus.set(true);
|
|
357
|
+
Log.d("ReactNative", "checkConnectionInternal succeeded ");
|
|
358
|
+
} catch (Exception e) {
|
|
359
|
+
Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
future.get(timeout, TimeUnit.SECONDS);
|
|
365
|
+
} catch (TimeoutException te) {
|
|
366
|
+
// If the timeout occurs, shut down the executor and return false
|
|
367
|
+
executor.shutdownNow();
|
|
368
|
+
return false;
|
|
369
|
+
} finally {
|
|
370
|
+
// If the future task is done, we can shut down the executor
|
|
371
|
+
if (future.isDone()) {
|
|
372
|
+
executor.shutdown();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return connectionStatus.get();
|
|
377
|
+
} catch (Exception e) {
|
|
378
|
+
Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
} else {
|
|
382
|
+
Log.d("ReactNative", "checkConnectionInternal failed because fula is not initialized ");
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
} catch (Exception e) {
|
|
386
|
+
Log.d("ReactNative", "checkConnectionInternal failed with Error: " + e.getMessage());
|
|
387
|
+
throw (e);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
@ReactMethod
|
|
392
|
+
public void checkFailedActions(boolean retry, int timeout, Promise promise) throws Exception {
|
|
393
|
+
try {
|
|
394
|
+
if (this.fula != null) {
|
|
395
|
+
if (!retry) {
|
|
396
|
+
Log.d("ReactNative", "checkFailedActions without retry");
|
|
397
|
+
fulamobile.LinkIterator failedLinks = this.fula.listFailedPushes();
|
|
398
|
+
if (failedLinks.hasNext()) {
|
|
399
|
+
Log.d("ReactNative", "checkFailedActions found: "+Arrays.toString(failedLinks.next()));
|
|
400
|
+
promise.resolve(true);
|
|
401
|
+
} else {
|
|
402
|
+
promise.resolve(false);
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
Log.d("ReactNative", "checkFailedActions with retry");
|
|
406
|
+
boolean retryResults = this.retryFailedActionsInternal(timeout);
|
|
407
|
+
promise.resolve(!retryResults);
|
|
408
|
+
}
|
|
409
|
+
} else {
|
|
410
|
+
throw new Exception("Fula is not initialized");
|
|
411
|
+
}
|
|
412
|
+
} catch (Exception e) {
|
|
413
|
+
Log.d("ReactNative", "checkFailedActions failed with Error: " + e.getMessage());
|
|
414
|
+
throw (e);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@ReactMethod
|
|
419
|
+
private void listFailedActions(ReadableArray cids, Promise promise) throws Exception {
|
|
420
|
+
try {
|
|
421
|
+
if (this.fula != null) {
|
|
422
|
+
Log.d("ReactNative", "listFailedActions");
|
|
423
|
+
fulamobile.StringIterator failedLinks = this.fula.listFailedPushesAsString();
|
|
424
|
+
ArrayList<String> failedLinksList = new ArrayList<>();
|
|
425
|
+
while (failedLinks.hasNext()) {
|
|
426
|
+
failedLinksList.add(failedLinks.next());
|
|
427
|
+
}
|
|
428
|
+
if (cids.size() > 0) {
|
|
429
|
+
// If cids array is provided, filter the failedLinksList
|
|
430
|
+
ArrayList<String> cidsList = new ArrayList<>();
|
|
431
|
+
for (int i = 0; i < cids.size(); i++) {
|
|
432
|
+
cidsList.add(cids.getString(i));
|
|
433
|
+
}
|
|
434
|
+
cidsList.retainAll(failedLinksList); // Keep only the elements in both cidsList and failedLinksList
|
|
435
|
+
if (!cidsList.isEmpty()) {
|
|
436
|
+
// If there are any matching cids, return them
|
|
437
|
+
WritableArray cidsArray = Arguments.createArray();
|
|
438
|
+
for (String cid : cidsList) {
|
|
439
|
+
cidsArray.pushString(cid);
|
|
440
|
+
}
|
|
441
|
+
promise.resolve(cidsArray);
|
|
442
|
+
} else {
|
|
443
|
+
// If there are no matching cids, return false
|
|
444
|
+
promise.resolve(false);
|
|
445
|
+
}
|
|
446
|
+
} else if (!failedLinksList.isEmpty()) {
|
|
447
|
+
// If cids array is not provided, return the whole list
|
|
448
|
+
Log.d("ReactNative", "listFailedActions found: "+ failedLinksList);
|
|
449
|
+
WritableArray failedLinksArray = Arguments.createArray();
|
|
450
|
+
for (String link : failedLinksList) {
|
|
451
|
+
failedLinksArray.pushString(link);
|
|
452
|
+
}
|
|
453
|
+
promise.resolve(failedLinksArray);
|
|
454
|
+
} else {
|
|
455
|
+
promise.resolve(false);
|
|
456
|
+
}
|
|
457
|
+
} else {
|
|
458
|
+
throw new Exception("listFailedActions: Fula is not initialized");
|
|
459
|
+
}
|
|
460
|
+
} catch (Exception e) {
|
|
461
|
+
Log.d("ReactNative", "listFailedActions failed with Error: " + e.getMessage());
|
|
462
|
+
throw (e);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
private boolean retryFailedActionsInternal(int timeout) throws Exception {
|
|
470
|
+
try {
|
|
471
|
+
Log.d("ReactNative", "retryFailedActionsInternal started");
|
|
472
|
+
if (this.fula != null) {
|
|
473
|
+
//Fula is initialized
|
|
474
|
+
try {
|
|
475
|
+
boolean connectionCheck = this.checkConnectionInternal(timeout);
|
|
476
|
+
if(connectionCheck) {
|
|
477
|
+
try {
|
|
478
|
+
Log.d("ReactNative", "retryFailedPushes started");
|
|
479
|
+
this.fula.retryFailedPushes();
|
|
480
|
+
Log.d("ReactNative", "flush started");
|
|
481
|
+
this.fula.flush();
|
|
482
|
+
return true;
|
|
483
|
+
}
|
|
484
|
+
catch (Exception e) {
|
|
485
|
+
this.fula.flush();
|
|
486
|
+
Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
//Blox online
|
|
490
|
+
/*fulamobile.LinkIterator failedLinks = this.fula.listFailedPushes();
|
|
491
|
+
if (failedLinks.hasNext()) {
|
|
492
|
+
Log.d("ReactNative", "Failed links");
|
|
493
|
+
//Failed list is not empty. iterate in the list
|
|
494
|
+
while (failedLinks.hasNext()) {
|
|
495
|
+
//Get the missing key
|
|
496
|
+
byte[] failedNode = failedLinks.next();
|
|
497
|
+
try {
|
|
498
|
+
//Push to Blox
|
|
499
|
+
Log.d("ReactNative", "Pushing Failed links "+Arrays.toString(failedNode));
|
|
500
|
+
this.pushInternal(failedNode);
|
|
501
|
+
Log.d("ReactNative", "Failed links pushed");
|
|
502
|
+
}
|
|
503
|
+
catch (Exception e) {
|
|
504
|
+
Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
//check if list is empty now and all are pushed
|
|
508
|
+
Log.d("ReactNative", "Pushing finished");
|
|
509
|
+
fulamobile.LinkIterator failedLinks_after = this.fula.listFailedPushes();
|
|
510
|
+
if(failedLinks_after.hasNext()) {
|
|
511
|
+
//Some pushes failed
|
|
512
|
+
byte[] first_failed = failedLinks_after.next();
|
|
513
|
+
Log.d("ReactNative", "Failed links are not empty "+Arrays.toString(first_failed));
|
|
514
|
+
return false;
|
|
515
|
+
} else {
|
|
516
|
+
//All pushes successful
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
} else {
|
|
520
|
+
Log.d("ReactNative", "No Failed links");
|
|
521
|
+
//Failed list is empty
|
|
522
|
+
return true;
|
|
523
|
+
}*/
|
|
524
|
+
} else {
|
|
525
|
+
Log.d("ReactNative", "retryFailedActionsInternal failed because blox is offline");
|
|
526
|
+
//Blox Offline
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
catch (Exception e) {
|
|
531
|
+
Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
} else {
|
|
535
|
+
Log.d("ReactNative", "retryFailedActionsInternal failed because fula is not initialized");
|
|
536
|
+
//Fula is not initialized
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
} catch (Exception e) {
|
|
540
|
+
Log.d("ReactNative", "retryFailedActionsInternal failed with Error: " + e.getMessage());
|
|
541
|
+
throw (e);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
@NonNull
|
|
546
|
+
private byte[] createPeerIdentity(byte[] identity) throws GeneralSecurityException, IOException {
|
|
547
|
+
try {
|
|
548
|
+
// 1: First: create public key from provided private key
|
|
549
|
+
// 2: Should read the local keychain store (if it is key-value, key is public key above,
|
|
550
|
+
// 3: if found, decrypt using the private key
|
|
551
|
+
// 4: If not found or decryption not successful, generate an identity
|
|
552
|
+
// 5: then encrypt and store in keychain
|
|
553
|
+
byte[] libp2pId;
|
|
554
|
+
String encryptedLibp2pId = sharedPref.getValue(PRIVATE_KEY_STORE_PEERID);
|
|
555
|
+
byte[] encryptionPair;
|
|
556
|
+
SecretKey encryptionSecretKey;
|
|
557
|
+
try {
|
|
558
|
+
encryptionSecretKey = Cryptography.generateKey(identity);
|
|
559
|
+
Log.d("ReactNative", "encryptionSecretKey generated from privateKey");
|
|
560
|
+
} catch (Exception e) {
|
|
561
|
+
Log.d("ReactNative", "Failed to generate key for encryption: " + e.getMessage());
|
|
562
|
+
throw new GeneralSecurityException("Failed to generate key encryption", e);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
if (encryptedLibp2pId == null || !encryptedLibp2pId.startsWith("FULA_" +
|
|
566
|
+
"ENC_V4:")) {
|
|
567
|
+
Log.d("ReactNative", "encryptedLibp2pId is not correct or empty. creating new one " + encryptedLibp2pId);
|
|
568
|
+
encryptedLibp2pId = createEncryptedLibp2pId(identity, encryptionSecretKey);
|
|
569
|
+
} else {
|
|
570
|
+
Log.d("ReactNative", "encryptedLibp2pId is correct. decrypting " + encryptedLibp2pId);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
try {
|
|
574
|
+
String decryptedLibp2pId = decryptLibp2pIdentity(encryptedLibp2pId, encryptionSecretKey);
|
|
575
|
+
return StaticHelper.base64ToBytes(decryptedLibp2pId);
|
|
576
|
+
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
577
|
+
Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e.getMessage());
|
|
578
|
+
Log.d("ReactNative", "creating new encrpyted identity");
|
|
579
|
+
try {
|
|
580
|
+
encryptedLibp2pId = createEncryptedLibp2pId(identity, encryptionSecretKey);
|
|
581
|
+
String decryptedLibp2pId = decryptLibp2pIdentity(encryptedLibp2pId, encryptionSecretKey);
|
|
582
|
+
return StaticHelper.base64ToBytes(decryptedLibp2pId);
|
|
583
|
+
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e2) {
|
|
584
|
+
Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e2.getMessage());
|
|
585
|
+
Log.d("ReactNative", "creating new encrpyted identity");
|
|
586
|
+
throw(e2);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
591
|
+
Log.d("ReactNative", "createPeerIdentity failed with Error: " + e.getMessage());
|
|
592
|
+
throw (e);
|
|
593
|
+
} catch (Exception e) {
|
|
594
|
+
throw new RuntimeException(e);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
private String decryptLibp2pIdentity(String encryptedLibp2pId, SecretKey encryptionSecretKey) throws Exception {
|
|
599
|
+
try {
|
|
600
|
+
String decryptedLibp2pId = Cryptography.decryptMsg(encryptedLibp2pId.replace("FULA_ENC_V4:", ""), encryptionSecretKey);
|
|
601
|
+
|
|
602
|
+
return decryptedLibp2pId;
|
|
603
|
+
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
604
|
+
Log.d("ReactNative", "createPeerIdentity decryptMsg failed with Error: " + e.getMessage());
|
|
605
|
+
Log.d("ReactNative", "creating new encrpyted identity");
|
|
606
|
+
throw new GeneralSecurityException("decryptLibp2pIdentity Failed to decrypt libp2pId", e);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
private String createEncryptedLibp2pId(byte[] identity, SecretKey encryptionSecretKey) throws Exception {
|
|
611
|
+
byte[] libp2pId;
|
|
612
|
+
String encryptedLibp2pId;
|
|
613
|
+
try {
|
|
614
|
+
Log.d("ReactNative", "createEncryptedLibp2pId started");
|
|
615
|
+
|
|
616
|
+
try {
|
|
617
|
+
libp2pId = Fulamobile.generateEd25519KeyFromString(toString(identity));
|
|
618
|
+
} catch (Exception e) {
|
|
619
|
+
Log.d("ReactNative", " createEncryptedLibp2pId Failed to generate libp2pId: " + e.getMessage());
|
|
620
|
+
throw new GeneralSecurityException("createEncryptedLibp2pId Failed to generate libp2pId", e);
|
|
621
|
+
}
|
|
622
|
+
encryptedLibp2pId = "FULA_ENC_V4:" + Cryptography.encryptMsg(StaticHelper.bytesToBase64(libp2pId), encryptionSecretKey, null);
|
|
623
|
+
sharedPref.add(PRIVATE_KEY_STORE_PEERID, encryptedLibp2pId);
|
|
624
|
+
return encryptedLibp2pId;
|
|
625
|
+
}
|
|
626
|
+
catch (Exception e) {
|
|
627
|
+
Log.d("ReactNative", "createEncryptedLibp2pId failed with Error: " + e.getMessage());
|
|
628
|
+
throw new GeneralSecurityException("createEncryptedLibp2pId Failed to generate libp2pId at hte first level", e);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
private void createNewRootConfig(FulaModule.Client iClient, byte[] identity) throws Exception {
|
|
633
|
+
byte[] hash32 = getSHA256Hash(identity);
|
|
634
|
+
this.rootConfig = Fs.init(iClient, hash32);
|
|
635
|
+
Log.d("ReactNative", "rootConfig is created " + this.rootConfig.getCid());
|
|
636
|
+
if (this.fula != null) {
|
|
637
|
+
this.fula.flush();
|
|
638
|
+
}
|
|
639
|
+
this.encrypt_and_store_config();
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
public static byte[] getSHA256Hash(byte[] input) throws NoSuchAlgorithmException {
|
|
643
|
+
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
|
644
|
+
return md.digest(input);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
private static String bytesToHex(byte[] bytes) {
|
|
648
|
+
StringBuilder result = new StringBuilder();
|
|
649
|
+
for (byte b : bytes) {
|
|
650
|
+
result.append(String.format("%02x", b));
|
|
651
|
+
}
|
|
652
|
+
return result.toString();
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
private void reloadFS(FulaModule.Client iClient, byte[] wnfsKey, String rootCid) throws Exception {
|
|
656
|
+
Log.d("ReactNative", "reloadFS called: rootCid=" + rootCid);
|
|
657
|
+
byte[] hash32 = getSHA256Hash(wnfsKey);
|
|
658
|
+
Log.d("ReactNative", "wnfsKey=" + bytesToHex(wnfsKey) + "; hash32 = " + bytesToHex(hash32));
|
|
659
|
+
Fs.loadWithWNFSKey(iClient, hash32, rootCid);
|
|
660
|
+
Log.d("ReactNative", "reloadFS completed");
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
private boolean encrypt_and_store_config() throws Exception {
|
|
664
|
+
try {
|
|
665
|
+
if(this.identityEncryptedGlobal != null && !this.identityEncryptedGlobal.isEmpty()) {
|
|
666
|
+
Log.d("ReactNative", "encrypt_and_store_config started");
|
|
667
|
+
|
|
668
|
+
String cid_encrypted = Cryptography.encryptMsg(this.rootConfig.getCid(), this.secretKeyGlobal, null);
|
|
669
|
+
|
|
670
|
+
sharedPref.add("FULA_ENC_V4:cid_encrypted_" + this.identityEncryptedGlobal, cid_encrypted);
|
|
671
|
+
return true;
|
|
672
|
+
} else {
|
|
673
|
+
Log.d("ReactNative", "encrypt_and_store_config failed because identityEncryptedGlobal is empty");
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
} catch (Exception e) {
|
|
677
|
+
Log.d("ReactNative", "encrypt_and_store_config failed with Error: " + e.getMessage());
|
|
678
|
+
throw (e);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
private boolean logoutInternal(byte[] identity, String storePath) throws Exception {
|
|
683
|
+
try {
|
|
684
|
+
if (this.fula != null) {
|
|
685
|
+
this.fula.flush();
|
|
686
|
+
}
|
|
687
|
+
SecretKey secretKey = Cryptography.generateKey(identity);
|
|
688
|
+
byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B };
|
|
689
|
+
String identity_encrypted = Cryptography.encryptMsg(Arrays.toString(identity), secretKey, iv);
|
|
690
|
+
sharedPref.remove("FULA_ENC_V4:cid_encrypted_"+ identity_encrypted);
|
|
691
|
+
|
|
692
|
+
//TODO: Should also remove peerid @Mahdi
|
|
693
|
+
|
|
694
|
+
sharedPref.remove("FULA_ENC_V4:cid_encrypted_"+ identity_encrypted);
|
|
695
|
+
|
|
696
|
+
this.rootConfig = null;
|
|
697
|
+
this.secretKeyGlobal = null;
|
|
698
|
+
this.identityEncryptedGlobal = null;
|
|
699
|
+
|
|
700
|
+
if (storePath == null || storePath.trim().isEmpty()) {
|
|
701
|
+
storePath = this.fulaStorePath;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
File file = new File(storePath);
|
|
705
|
+
FileUtils.deleteDirectory(file);
|
|
706
|
+
return true;
|
|
707
|
+
|
|
708
|
+
} catch (Exception e) {
|
|
709
|
+
Log.d("ReactNative", "logout internal failed with Error: " + e.getMessage());
|
|
710
|
+
throw (e);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
public fulamobile.Client getFulaClient() {
|
|
715
|
+
return this.fula;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
@NonNull
|
|
719
|
+
private byte[] newClientInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, boolean useRelay, boolean refresh) throws GeneralSecurityException, IOException {
|
|
720
|
+
byte[] peerIdentity = null;
|
|
721
|
+
try {
|
|
722
|
+
fulaConfig = new Config();
|
|
723
|
+
if (storePath == null || storePath.trim().isEmpty()) {
|
|
724
|
+
fulaConfig.setStorePath(this.fulaStorePath);
|
|
725
|
+
} else {
|
|
726
|
+
fulaConfig.setStorePath(storePath);
|
|
727
|
+
}
|
|
728
|
+
Log.d("ReactNative", "newClientInternal storePath is set: " + fulaConfig.getStorePath());
|
|
729
|
+
|
|
730
|
+
peerIdentity = this.createPeerIdentity(identity);
|
|
731
|
+
fulaConfig.setIdentity(peerIdentity);
|
|
732
|
+
Log.d("ReactNative", "peerIdentity is set: " + toString(fulaConfig.getIdentity()));
|
|
733
|
+
fulaConfig.setBloxAddr(bloxAddr);
|
|
734
|
+
Log.d("ReactNative", "bloxAddr is set: " + fulaConfig.getBloxAddr());
|
|
735
|
+
fulaConfig.setExchange(exchange);
|
|
736
|
+
fulaConfig.setSyncWrites(autoFlush);
|
|
737
|
+
if (useRelay) {
|
|
738
|
+
fulaConfig.setAllowTransientConnection(true);
|
|
739
|
+
fulaConfig.setForceReachabilityPrivate(true);
|
|
740
|
+
}
|
|
741
|
+
if (this.fula == null || refresh) {
|
|
742
|
+
Log.d("ReactNative", "Creating a new Fula instance");
|
|
743
|
+
try {
|
|
744
|
+
shutdownInternal();
|
|
745
|
+
Log.d("ReactNative", "Creating a new Fula instance with config");
|
|
746
|
+
this.fula = Fulamobile.newClient(fulaConfig);
|
|
747
|
+
if (this.fula != null) {
|
|
748
|
+
this.fula.flush();
|
|
749
|
+
}
|
|
750
|
+
} catch (Exception e) {
|
|
751
|
+
Log.d("ReactNative", "Failed to create new Fula instance: " + e.getMessage());
|
|
752
|
+
throw new IOException("Failed to create new Fula instance", e);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
|
|
756
|
+
Log.d("ReactNative", "newclientInternal failed with Error: " + e.getMessage());
|
|
757
|
+
throw (e);
|
|
758
|
+
}
|
|
759
|
+
return peerIdentity;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
@NonNull
|
|
764
|
+
private String[] initInternal(byte[] identity, String storePath, String bloxAddr, String exchange, boolean autoFlush, String rootCid, boolean useRelay, boolean refresh) throws Exception {
|
|
765
|
+
try {
|
|
766
|
+
if (this.fula == null || refresh) {
|
|
767
|
+
this.newClientInternal(identity, storePath, bloxAddr, exchange, autoFlush, useRelay, refresh);
|
|
768
|
+
}
|
|
769
|
+
if(this.client == null || refresh) {
|
|
770
|
+
this.client = new Client(this.fula);
|
|
771
|
+
Log.d("ReactNative", "fula initialized: " + this.fula.id());
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
SecretKey secretKey = Cryptography.generateKey(identity);
|
|
775
|
+
Log.d("ReactNative", "secretKey generated: " + secretKey.toString());
|
|
776
|
+
byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B };
|
|
777
|
+
String identity_encrypted =Cryptography.encryptMsg(Arrays.toString(identity), secretKey, iv);
|
|
778
|
+
Log.d("ReactNative", "identity_encrypted generated: " + identity_encrypted + " for identity: " + Arrays.toString(identity));
|
|
779
|
+
this.identityEncryptedGlobal = identity_encrypted;
|
|
780
|
+
this.secretKeyGlobal = secretKey;
|
|
781
|
+
|
|
782
|
+
if ( this.rootConfig == null || this.rootConfig.getCid().isEmpty() ) {
|
|
783
|
+
Log.d("ReactNative", "this.rootCid is empty.");
|
|
784
|
+
//Load from keystore
|
|
785
|
+
|
|
786
|
+
String cid_encrypted_fetched = sharedPref.getValue("FULA_ENC_V4:cid_encrypted_"+ identity_encrypted);
|
|
787
|
+
Log.d("ReactNative", "Here1");
|
|
788
|
+
String cid = "";
|
|
789
|
+
if(cid_encrypted_fetched != null && !cid_encrypted_fetched.isEmpty()) {
|
|
790
|
+
Log.d("ReactNative", "decrypting cid="+cid_encrypted_fetched+" with secret="+secretKey.toString());
|
|
791
|
+
cid = Cryptography.decryptMsg(cid_encrypted_fetched, secretKey);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
Log.d("ReactNative", "Here2");
|
|
795
|
+
//Log.d("ReactNative", "Attempted to fetch cid from keystore; cid="+cid);
|
|
796
|
+
if(cid == null || cid.isEmpty()) {
|
|
797
|
+
Log.d("ReactNative", "cid was not found");
|
|
798
|
+
if(rootCid != null && !rootCid.isEmpty()){
|
|
799
|
+
Log.d("ReactNative", "Re-setting cid from input: "+rootCid);
|
|
800
|
+
cid = rootCid;
|
|
801
|
+
this.rootConfig = new land.fx.wnfslib.Config(cid);
|
|
802
|
+
this.reloadFS(this.client, identity, cid);
|
|
803
|
+
this.encrypt_and_store_config();
|
|
804
|
+
}
|
|
805
|
+
if(cid == null || cid.isEmpty()) {
|
|
806
|
+
Log.d("ReactNative", "Tried to recover cid but was not successful. Creating new ones");
|
|
807
|
+
this.createNewRootConfig(this.client, identity);
|
|
808
|
+
} else {
|
|
809
|
+
this.rootConfig = new land.fx.wnfslib.Config(cid);
|
|
810
|
+
this.reloadFS(this.client, identity, cid);
|
|
811
|
+
this.encrypt_and_store_config();
|
|
812
|
+
}
|
|
813
|
+
} else {
|
|
814
|
+
Log.d("ReactNative", "Recovered cid and private ref from keychain store. cid="+cid +" and cid from input was: "+rootCid);
|
|
815
|
+
this.rootConfig = new land.fx.wnfslib.Config(cid);
|
|
816
|
+
this.reloadFS(this.client, identity, cid);
|
|
817
|
+
this.encrypt_and_store_config();
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
Log.d("ReactNative", "creating rootConfig completed");
|
|
821
|
+
|
|
822
|
+
Log.d("ReactNative", "rootConfig is created: cid=" + this.rootConfig.getCid());
|
|
823
|
+
} else {
|
|
824
|
+
Log.d("ReactNative", "rootConfig existed: cid=" + this.rootConfig.getCid());
|
|
825
|
+
}
|
|
826
|
+
String peerId = this.fula.id();
|
|
827
|
+
String[] obj = new String[2];
|
|
828
|
+
obj[0] = peerId;
|
|
829
|
+
obj[1] = this.rootConfig.getCid();
|
|
830
|
+
Log.d("ReactNative", "initInternal is completed successfully");
|
|
831
|
+
if (this.fula != null) {
|
|
832
|
+
this.fula.flush();
|
|
833
|
+
}
|
|
834
|
+
return obj;
|
|
835
|
+
} catch (Exception e) {
|
|
836
|
+
Log.d("ReactNative", "init internal failed with Error: " + e.getMessage());
|
|
837
|
+
throw (e);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
@ReactMethod
|
|
842
|
+
public void mkdir(String path, Promise promise) {
|
|
843
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
844
|
+
Log.d("ReactNative", "mkdir started with: path = " + path + " rootConfig.getCid() = " + this.rootConfig.getCid());
|
|
845
|
+
try {
|
|
846
|
+
land.fx.wnfslib.Config config = Fs.mkdir(this.client, this.rootConfig.getCid(), path);
|
|
847
|
+
if(config != null) {
|
|
848
|
+
this.rootConfig = config;
|
|
849
|
+
this.encrypt_and_store_config();
|
|
850
|
+
if (this.fula != null) {
|
|
851
|
+
this.fula.flush();
|
|
852
|
+
}
|
|
853
|
+
String rootCid = this.rootConfig.getCid();
|
|
854
|
+
Log.d("ReactNative", "mkdir completed successfully with rootCid = " + rootCid);
|
|
855
|
+
promise.resolve(rootCid);
|
|
856
|
+
} else {
|
|
857
|
+
Log.d("ReactNative", "mkdir Error: config is null");
|
|
858
|
+
promise.reject(new Exception("mkdir Error: config is null"));
|
|
859
|
+
}
|
|
860
|
+
} catch (Exception e) {
|
|
861
|
+
Log.d("get", e.getMessage());
|
|
862
|
+
promise.reject(e);
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
@ReactMethod
|
|
868
|
+
public void writeFile(String fulaTargetFilename, String localFilename, Promise promise) {
|
|
869
|
+
/*
|
|
870
|
+
// reads content of the file form localFilename (should include full absolute path to local file with read permission
|
|
871
|
+
// writes content to the specified location by fulaTargetFilename in Fula filesystem
|
|
872
|
+
// fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
|
|
873
|
+
// localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
|
|
874
|
+
// Returns: new cid of the root after this file is placed in the tree
|
|
875
|
+
*/
|
|
876
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
877
|
+
Log.d("ReactNative", "writeFile to : path = " + fulaTargetFilename + ", from: " + localFilename);
|
|
878
|
+
try {
|
|
879
|
+
if (this.client != null) {
|
|
880
|
+
Log.d("ReactNative", "writeFileFromPath started: this.rootConfig.getCid=" + this.rootConfig.getCid()+ ", fulaTargetFilename="+fulaTargetFilename + ", localFilename="+localFilename);
|
|
881
|
+
land.fx.wnfslib.Config config = Fs.writeFileStreamFromPath(this.client, this.rootConfig.getCid(), fulaTargetFilename, localFilename);
|
|
882
|
+
if(config != null) {
|
|
883
|
+
this.rootConfig = config;
|
|
884
|
+
this.encrypt_and_store_config();
|
|
885
|
+
if (this.fula != null) {
|
|
886
|
+
this.fula.flush();
|
|
887
|
+
String rootCid = this.rootConfig.getCid();
|
|
888
|
+
Log.d("ReactNative", "writeFileFromPath completed: this.rootConfig.getCid=" + rootCid);
|
|
889
|
+
promise.resolve(rootCid);
|
|
890
|
+
} else {
|
|
891
|
+
Log.d("ReactNative", "writeFile Error: fula is null");
|
|
892
|
+
promise.reject(new Exception("writeFile Error: fula is null"));
|
|
893
|
+
}
|
|
894
|
+
} else {
|
|
895
|
+
Log.d("ReactNative", "writeFile Error: config is null");
|
|
896
|
+
promise.reject(new Exception("writeFile Error: config is null"));
|
|
897
|
+
}
|
|
898
|
+
} else {
|
|
899
|
+
Log.d("ReactNative", "writeFile Error: client is null");
|
|
900
|
+
promise.reject(new Exception("writeFile Error: client is null"));
|
|
901
|
+
}
|
|
902
|
+
} catch (Exception e) {
|
|
903
|
+
Log.d("get", e.getMessage());
|
|
904
|
+
promise.reject(e);
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
@ReactMethod
|
|
910
|
+
public void writeFileContent(String path, String contentString, Promise promise) {
|
|
911
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
912
|
+
Log.d("ReactNative", "writeFile: contentString = " + contentString);
|
|
913
|
+
Log.d("ReactNative", "writeFile: path = " + path);
|
|
914
|
+
try {
|
|
915
|
+
byte[] content = this.convertStringToByte(contentString);
|
|
916
|
+
land.fx.wnfslib.Config config = Fs.writeFile(this.client, this.rootConfig.getCid(), path, content);
|
|
917
|
+
this.rootConfig = config;
|
|
918
|
+
this.encrypt_and_store_config();
|
|
919
|
+
if (this.fula != null) {
|
|
920
|
+
this.fula.flush();
|
|
921
|
+
}
|
|
922
|
+
promise.resolve(config.getCid());
|
|
923
|
+
} catch (Exception e) {
|
|
924
|
+
Log.d("get", e.getMessage());
|
|
925
|
+
promise.reject(e);
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
@ReactMethod
|
|
931
|
+
public void ls(String path, Promise promise) {
|
|
932
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
933
|
+
Log.d("ReactNative", "ls: path = " + path + "rootCid= " + this.rootConfig.getCid());
|
|
934
|
+
try {
|
|
935
|
+
byte[] res = Fs.ls(this.client, this.rootConfig.getCid(), path);
|
|
936
|
+
|
|
937
|
+
String s = new String(res, StandardCharsets.UTF_8);
|
|
938
|
+
Log.d("ReactNative", "ls: res = " + s);
|
|
939
|
+
promise.resolve(s);
|
|
940
|
+
} catch (Exception e) {
|
|
941
|
+
Log.d("ReactNative", e.getMessage());
|
|
942
|
+
promise.reject(e);
|
|
943
|
+
}
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
@ReactMethod
|
|
948
|
+
public void rm(String path, Promise promise) {
|
|
949
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
950
|
+
Log.d("ReactNative", "rm: path = " + path + ", beginning rootCid=" + this.rootConfig.getCid());
|
|
951
|
+
try {
|
|
952
|
+
land.fx.wnfslib.Config config = Fs.rm(this.client, this.rootConfig.getCid(), path);
|
|
953
|
+
if(config != null) {
|
|
954
|
+
this.rootConfig = config;
|
|
955
|
+
this.encrypt_and_store_config();
|
|
956
|
+
if (this.fula != null) {
|
|
957
|
+
this.fula.flush();
|
|
958
|
+
}
|
|
959
|
+
String rootCid = config.getCid();
|
|
960
|
+
Log.d("ReactNative", "rm: returned rootCid = " + rootCid);
|
|
961
|
+
promise.resolve(rootCid);
|
|
962
|
+
} else {
|
|
963
|
+
Log.d("ReactNative", "rm Error: config is null");
|
|
964
|
+
promise.reject(new Exception("rm Error: config is null"));
|
|
965
|
+
}
|
|
966
|
+
} catch (Exception e) {
|
|
967
|
+
Log.d("ReactNative", e.getMessage());
|
|
968
|
+
promise.reject(e);
|
|
969
|
+
}
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
@ReactMethod
|
|
974
|
+
public void cp(String sourcePath, String targetPath, Promise promise) {
|
|
975
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
976
|
+
Log.d("ReactNative", "rm: sourcePath = " + sourcePath);
|
|
977
|
+
try {
|
|
978
|
+
land.fx.wnfslib.Config config = Fs.cp(this.client, this.rootConfig.getCid(), sourcePath, targetPath);
|
|
979
|
+
if(config != null) {
|
|
980
|
+
this.rootConfig = config;
|
|
981
|
+
this.encrypt_and_store_config();
|
|
982
|
+
if (this.fula != null) {
|
|
983
|
+
this.fula.flush();
|
|
984
|
+
}
|
|
985
|
+
promise.resolve(config.getCid());
|
|
986
|
+
} else {
|
|
987
|
+
Log.d("ReactNative", "cp Error: config is null");
|
|
988
|
+
promise.reject(new Exception("cp Error: config is null"));
|
|
989
|
+
}
|
|
990
|
+
} catch (Exception e) {
|
|
991
|
+
Log.d("ReactNative", e.getMessage());
|
|
992
|
+
promise.reject(e);
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
@ReactMethod
|
|
998
|
+
public void mv(String sourcePath, String targetPath, Promise promise) {
|
|
999
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1000
|
+
Log.d("ReactNative", "rm: sourcePath = " + sourcePath);
|
|
1001
|
+
try {
|
|
1002
|
+
land.fx.wnfslib.Config config = Fs.mv(this.client, this.rootConfig.getCid(), sourcePath, targetPath);
|
|
1003
|
+
if(config != null) {
|
|
1004
|
+
this.rootConfig = config;
|
|
1005
|
+
this.encrypt_and_store_config();
|
|
1006
|
+
if (this.fula != null) {
|
|
1007
|
+
this.fula.flush();
|
|
1008
|
+
}
|
|
1009
|
+
promise.resolve(config.getCid());
|
|
1010
|
+
} else {
|
|
1011
|
+
Log.d("ReactNative", "mv Error: config is null");
|
|
1012
|
+
promise.reject(new Exception("mv Error: config is null"));
|
|
1013
|
+
}
|
|
1014
|
+
} catch (Exception e) {
|
|
1015
|
+
Log.d("ReactNative", e.getMessage());
|
|
1016
|
+
promise.reject(e);
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
@ReactMethod
|
|
1022
|
+
public void readFile(String fulaTargetFilename, String localFilename, Promise promise) {
|
|
1023
|
+
/*
|
|
1024
|
+
// reads content of the file form localFilename (should include full absolute path to local file with read permission
|
|
1025
|
+
// writes content to the specified location by fulaTargetFilename in Fula filesystem
|
|
1026
|
+
// fulaTargetFilename: a string including full path and filename of target file on Fula (e.g. root/pictures/cat.jpg)
|
|
1027
|
+
// localFilename: a string containing full path and filename of local file on hte device (e.g /usr/bin/cat.jpg)
|
|
1028
|
+
// Returns: new cid of the root after this file is placed in the tree
|
|
1029
|
+
*/
|
|
1030
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1031
|
+
Log.d("ReactNative", "readFile: fulaTargetFilename = " + fulaTargetFilename);
|
|
1032
|
+
try {
|
|
1033
|
+
Log.d("ReactNative", "readFile: localFilename = " + localFilename + " fulaTargetFilename = " + fulaTargetFilename + " beginning rootCid = " + this.rootConfig.getCid());
|
|
1034
|
+
String path = Fs.readFilestreamToPath(this.client, this.rootConfig.getCid(), fulaTargetFilename, localFilename);
|
|
1035
|
+
promise.resolve(path);
|
|
1036
|
+
} catch (Exception e) {
|
|
1037
|
+
Log.d("ReactNative", e.getMessage());
|
|
1038
|
+
promise.reject(e);
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
@ReactMethod
|
|
1044
|
+
public void readFileContent(String path, Promise promise) {
|
|
1045
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1046
|
+
Log.d("ReactNative", "readFileContent: path = " + path);
|
|
1047
|
+
try {
|
|
1048
|
+
byte[] res = Fs.readFile(this.client, this.rootConfig.getCid(), path);
|
|
1049
|
+
String resString = toString(res);
|
|
1050
|
+
promise.resolve(resString);
|
|
1051
|
+
} catch (Exception e) {
|
|
1052
|
+
Log.d("ReactNative", e.getMessage());
|
|
1053
|
+
promise.reject(e);
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
@ReactMethod
|
|
1059
|
+
public void get(String keyString, Promise promise) {
|
|
1060
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1061
|
+
Log.d("ReactNative", "get: keyString = " + keyString);
|
|
1062
|
+
try {
|
|
1063
|
+
byte[] key = this.convertStringToByte(keyString);
|
|
1064
|
+
byte[] value = this.getInternal(key);
|
|
1065
|
+
String valueString = toString(value);
|
|
1066
|
+
promise.resolve(valueString);
|
|
1067
|
+
} catch (Exception e) {
|
|
1068
|
+
Log.d("ReactNative", e.getMessage());
|
|
1069
|
+
promise.reject(e);
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
@NonNull
|
|
1075
|
+
private byte[] getInternal(byte[] key) throws Exception {
|
|
1076
|
+
try {
|
|
1077
|
+
Log.d("ReactNative", "getInternal: key.toString() = " + toString(key));
|
|
1078
|
+
Log.d("ReactNative", "getInternal: key.toString().bytes = " + Arrays.toString(key));
|
|
1079
|
+
byte[] value = this.fula.get(key);
|
|
1080
|
+
Log.d("ReactNative", "getInternal: value.toString() = " + toString(value));
|
|
1081
|
+
return value;
|
|
1082
|
+
} catch (Exception e) {
|
|
1083
|
+
Log.d("ReactNative", "getInternal: error = " + e.getMessage());
|
|
1084
|
+
Log.d("getInternal", e.getMessage());
|
|
1085
|
+
throw (e);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
@ReactMethod
|
|
1090
|
+
public void has(String keyString, Promise promise) {
|
|
1091
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1092
|
+
Log.d("ReactNative", "has: keyString = " + keyString);
|
|
1093
|
+
try {
|
|
1094
|
+
byte[] key = this.convertStringToByte(keyString);
|
|
1095
|
+
boolean result = this.hasInternal(key);
|
|
1096
|
+
promise.resolve(result);
|
|
1097
|
+
} catch (Exception e) {
|
|
1098
|
+
Log.d("ReactNative", e.getMessage());
|
|
1099
|
+
promise.reject(e);
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
private boolean hasInternal(byte[] key) throws Exception {
|
|
1105
|
+
try {
|
|
1106
|
+
boolean res = this.fula.has(key);
|
|
1107
|
+
return res;
|
|
1108
|
+
} catch (Exception e) {
|
|
1109
|
+
Log.d("ReactNative", e.getMessage());
|
|
1110
|
+
throw (e);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
private void pullInternal(byte[] key) throws Exception {
|
|
1115
|
+
try {
|
|
1116
|
+
this.fula.pull(key);
|
|
1117
|
+
} catch (Exception e) {
|
|
1118
|
+
Log.d("ReactNative", e.getMessage());
|
|
1119
|
+
throw (e);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
@ReactMethod
|
|
1124
|
+
public void push(Promise promise) {
|
|
1125
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1126
|
+
Log.d("ReactNative", "push started");
|
|
1127
|
+
try {
|
|
1128
|
+
this.pushInternal(this.convertStringToByte(this.rootConfig.getCid()));
|
|
1129
|
+
promise.resolve(this.rootConfig.getCid());
|
|
1130
|
+
} catch (Exception e) {
|
|
1131
|
+
Log.d("ReactNative", e.getMessage());
|
|
1132
|
+
promise.reject(e);
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
private void pushInternal(byte[] key) throws Exception {
|
|
1138
|
+
try {
|
|
1139
|
+
if (this.fula != null && this.fula.has(key)) {
|
|
1140
|
+
this.fula.push(key);
|
|
1141
|
+
this.fula.flush();
|
|
1142
|
+
} else {
|
|
1143
|
+
Log.d("ReactNative", "pushInternal error: key wasn't found or fula is not initialized");
|
|
1144
|
+
throw new Exception("key wasn't found in local storage");
|
|
1145
|
+
}
|
|
1146
|
+
} catch (Exception e) {
|
|
1147
|
+
Log.d("ReactNative", "pushInternal"+ e.getMessage());
|
|
1148
|
+
throw (e);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
@ReactMethod
|
|
1153
|
+
public void put(String valueString, String codecString, Promise promise) {
|
|
1154
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1155
|
+
Log.d("ReactNative", "put: codecString = " + codecString);
|
|
1156
|
+
Log.d("ReactNative", "put: valueString = " + valueString);
|
|
1157
|
+
try {
|
|
1158
|
+
//byte[] codec = this.convertStringToByte(CodecString);
|
|
1159
|
+
long codec = Long.parseLong(codecString);
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
Log.d("ReactNative", "put: codec = " + codec);
|
|
1163
|
+
byte[] value = toByte(valueString);
|
|
1164
|
+
|
|
1165
|
+
Log.d("ReactNative", "put: value.toString() = " + toString(value));
|
|
1166
|
+
byte[] key = this.putInternal(value, codec);
|
|
1167
|
+
Log.d("ReactNative", "put: key.toString() = " + toString(key));
|
|
1168
|
+
promise.resolve(toString(key));
|
|
1169
|
+
} catch (Exception e) {
|
|
1170
|
+
Log.d("ReactNative", "put: error = " + e.getMessage());
|
|
1171
|
+
promise.reject(e);
|
|
1172
|
+
}
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
@NonNull
|
|
1177
|
+
private byte[] putInternal(byte[] value, long codec) throws Exception {
|
|
1178
|
+
try {
|
|
1179
|
+
if(this.fula != null) {
|
|
1180
|
+
byte[] key = this.fula.put(value, codec);
|
|
1181
|
+
this.fula.flush();
|
|
1182
|
+
return key;
|
|
1183
|
+
} else {
|
|
1184
|
+
Log.d("ReactNative", "putInternal Error: fula is not initialized");
|
|
1185
|
+
throw (new Exception("putInternal Error: fula is not initialized"));
|
|
1186
|
+
}
|
|
1187
|
+
} catch (Exception e) {
|
|
1188
|
+
Log.d("ReactNative", "putInternal"+ e.getMessage());
|
|
1189
|
+
throw (e);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
@ReactMethod
|
|
1194
|
+
public void setAuth(String peerIdString, boolean allow, Promise promise) {
|
|
1195
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1196
|
+
Log.d("ReactNative", "setAuth: peerIdString = " + peerIdString);
|
|
1197
|
+
try {
|
|
1198
|
+
if (this.fula != null && this.fula.id() != null && this.fulaConfig != null && this.fulaConfig.getBloxAddr() != null) {
|
|
1199
|
+
String bloxAddr = this.fulaConfig.getBloxAddr();
|
|
1200
|
+
Log.d("ReactNative", "setAuth: bloxAddr = '" + bloxAddr+"'"+ " peerIdString = '" + peerIdString+"'");
|
|
1201
|
+
int index = bloxAddr.lastIndexOf("/");
|
|
1202
|
+
String bloxPeerId = bloxAddr.substring(index + 1);
|
|
1203
|
+
this.fula.setAuth(bloxPeerId, peerIdString, allow);
|
|
1204
|
+
promise.resolve(true);
|
|
1205
|
+
} else {
|
|
1206
|
+
Log.d("ReactNative", "setAuth error: fula is not initialized");
|
|
1207
|
+
throw new Exception("fula is not initialized");
|
|
1208
|
+
}
|
|
1209
|
+
promise.resolve(false);
|
|
1210
|
+
} catch (Exception e) {
|
|
1211
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1212
|
+
promise.reject(e);
|
|
1213
|
+
}
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
private void shutdownInternal() throws Exception {
|
|
1218
|
+
try {
|
|
1219
|
+
if(this.fula != null) {
|
|
1220
|
+
this.fula.shutdown();
|
|
1221
|
+
this.fula = null;
|
|
1222
|
+
this.client = null;
|
|
1223
|
+
Log.d("ReactNative", "shutdownInternal done");
|
|
1224
|
+
|
|
1225
|
+
}
|
|
1226
|
+
} catch (Exception e) {
|
|
1227
|
+
Log.d("ReactNative", "shutdownInternal error: "+ e.getMessage());
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
@ReactMethod
|
|
1232
|
+
public void shutdown(Promise promise) {
|
|
1233
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1234
|
+
try {
|
|
1235
|
+
shutdownInternal();
|
|
1236
|
+
promise.resolve(true);
|
|
1237
|
+
} catch (Exception e) {
|
|
1238
|
+
promise.reject(e);
|
|
1239
|
+
Log.d("ReactNative", "shutdown"+ e.getMessage());
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
///////////////////////////////////////////////////////////
|
|
1245
|
+
///////////////////////////////////////////////////////////
|
|
1246
|
+
///////////////////////////////////////////////////////////
|
|
1247
|
+
///////////////////////////////////////////////////////////
|
|
1248
|
+
//////////////////////ANYTHING BELOW IS FOR BLOCKCHAIN/////
|
|
1249
|
+
///////////////////////////////////////////////////////////
|
|
1250
|
+
@ReactMethod
|
|
1251
|
+
public void getAccount(Promise promise) {
|
|
1252
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1253
|
+
Log.d("ReactNative", "getAccount called ");
|
|
1254
|
+
try {
|
|
1255
|
+
byte[] result = this.fula.getAccount();
|
|
1256
|
+
String resultString = toString(result);
|
|
1257
|
+
promise.resolve(resultString);
|
|
1258
|
+
} catch (Exception e) {
|
|
1259
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1260
|
+
promise.reject(e);
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
@ReactMethod
|
|
1266
|
+
public void accountFund(String accountString, Promise promise) {
|
|
1267
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1268
|
+
Log.d("ReactNative", "accountFund: accountString = " + accountString);
|
|
1269
|
+
try {
|
|
1270
|
+
byte[] result = this.fula.accountFund(accountString);
|
|
1271
|
+
String resultString = toString(result);
|
|
1272
|
+
promise.resolve(resultString);
|
|
1273
|
+
} catch (Exception e) {
|
|
1274
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1275
|
+
promise.reject(e);
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
@ReactMethod
|
|
1281
|
+
public void assetsBalance(String account, String assetId, String classId, Promise promise) {
|
|
1282
|
+
long assetIdLong = Long.parseLong(assetId);
|
|
1283
|
+
long classIdLong = Long.parseLong(classId);
|
|
1284
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1285
|
+
Log.d("ReactNative", "assetsBalance called ");
|
|
1286
|
+
try {
|
|
1287
|
+
byte[] result = this.fula.assetsBalance(account, assetIdLong, classIdLong);
|
|
1288
|
+
String resultString = toString(result);
|
|
1289
|
+
promise.resolve(resultString);
|
|
1290
|
+
} catch (Exception e) {
|
|
1291
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1292
|
+
promise.reject(e);
|
|
1293
|
+
}
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
@ReactMethod
|
|
1298
|
+
public void transferToFula(String amount, String wallet, String chain, Promise promise) {
|
|
1299
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1300
|
+
Log.d("ReactNative", "transferToFula called ");
|
|
1301
|
+
try {
|
|
1302
|
+
byte[] result = this.fula.transferToFula(amount, wallet, chain);
|
|
1303
|
+
String resultString = toString(result);
|
|
1304
|
+
promise.resolve(resultString);
|
|
1305
|
+
} catch (Exception e) {
|
|
1306
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1307
|
+
promise.reject(e);
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
@ReactMethod
|
|
1313
|
+
public void checkAccountExists(String accountString, Promise promise) {
|
|
1314
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1315
|
+
Log.d("ReactNative", "checkAccountExists: accountString = " + accountString);
|
|
1316
|
+
try {
|
|
1317
|
+
byte[] result = this.fula.accountExists(accountString);
|
|
1318
|
+
String resultString = toString(result);
|
|
1319
|
+
promise.resolve(resultString);
|
|
1320
|
+
} catch (Exception e) {
|
|
1321
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1322
|
+
promise.reject(e);
|
|
1323
|
+
}
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
@ReactMethod
|
|
1328
|
+
public void listPools(Promise promise) {
|
|
1329
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1330
|
+
Log.d("ReactNative", "listPools");
|
|
1331
|
+
try {
|
|
1332
|
+
byte[] result = this.fula.poolList();
|
|
1333
|
+
String resultString = toString(result);
|
|
1334
|
+
promise.resolve(resultString);
|
|
1335
|
+
} catch (Exception e) {
|
|
1336
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1337
|
+
promise.reject(e);
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
@ReactMethod
|
|
1343
|
+
public void joinPool(String poolID, Promise promise) {
|
|
1344
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1345
|
+
long poolIdLong = Long.parseLong(poolID);
|
|
1346
|
+
Log.d("ReactNative", "joinPool: poolID = " + poolIdLong);
|
|
1347
|
+
try {
|
|
1348
|
+
byte[] result = this.fula.poolJoin(poolIdLong);
|
|
1349
|
+
String resultString = toString(result);
|
|
1350
|
+
promise.resolve(resultString);
|
|
1351
|
+
} catch (Exception e) {
|
|
1352
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1353
|
+
promise.reject(e);
|
|
1354
|
+
}
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
@ReactMethod
|
|
1359
|
+
public void cancelPoolJoin(String poolID, Promise promise) {
|
|
1360
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1361
|
+
long poolIdLong = Long.parseLong(poolID);
|
|
1362
|
+
Log.d("ReactNative", "cancelPoolJoin: poolID = " + poolIdLong);
|
|
1363
|
+
try {
|
|
1364
|
+
byte[] result = this.fula.poolCancelJoin(poolIdLong);
|
|
1365
|
+
String resultString = toString(result);
|
|
1366
|
+
promise.resolve(resultString);
|
|
1367
|
+
} catch (Exception e) {
|
|
1368
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1369
|
+
promise.reject(e);
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
@ReactMethod
|
|
1375
|
+
public void listPoolJoinRequests(String poolIDStr, Promise promise) {
|
|
1376
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1377
|
+
Log.d("ReactNative", "listPoolJoinRequests: poolID = " + poolIDStr);
|
|
1378
|
+
try {
|
|
1379
|
+
long poolID = Long.parseLong(poolIDStr);
|
|
1380
|
+
byte[] result = this.fula.poolRequests(poolID);
|
|
1381
|
+
String resultString = toString(result);
|
|
1382
|
+
promise.resolve(resultString);
|
|
1383
|
+
} catch (Exception e) {
|
|
1384
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1385
|
+
promise.reject(e);
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
@ReactMethod
|
|
1391
|
+
public void leavePool(String poolID, Promise promise) {
|
|
1392
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1393
|
+
long poolIdLong = Long.parseLong(poolID);
|
|
1394
|
+
Log.d("ReactNative", "leavePool: poolID = " + poolIdLong);
|
|
1395
|
+
try {
|
|
1396
|
+
byte[] result = this.fula.poolLeave(poolIdLong);
|
|
1397
|
+
String resultString = toString(result);
|
|
1398
|
+
promise.resolve(resultString);
|
|
1399
|
+
} catch (Exception e) {
|
|
1400
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1401
|
+
promise.reject(e);
|
|
1402
|
+
}
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
@ReactMethod
|
|
1407
|
+
public void joinPoolWithChain(String poolID, String chainName, Promise promise) {
|
|
1408
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1409
|
+
Log.d("ReactNative", "joinPoolWithChain: poolID = " + poolID + ", chainName = " + chainName);
|
|
1410
|
+
try {
|
|
1411
|
+
// Validate inputs
|
|
1412
|
+
if (poolID == null || poolID.trim().isEmpty()) {
|
|
1413
|
+
promise.reject("INVALID_POOL_ID", "Pool ID cannot be null or empty");
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
if (chainName == null || chainName.trim().isEmpty()) {
|
|
1417
|
+
promise.reject("INVALID_CHAIN_NAME", "Chain name cannot be null or empty");
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1420
|
+
if (this.fula == null) {
|
|
1421
|
+
promise.reject("FULA_NOT_INITIALIZED", "Fula client is not initialized");
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
long poolIdLong = Long.parseLong(poolID);
|
|
1426
|
+
byte[] result = this.fula.poolJoinWithChain(poolIdLong, chainName);
|
|
1427
|
+
String resultString = toString(result);
|
|
1428
|
+
promise.resolve(resultString);
|
|
1429
|
+
} catch (NumberFormatException e) {
|
|
1430
|
+
Log.d("ReactNative", "ERROR: Invalid poolID format: " + e.getMessage());
|
|
1431
|
+
promise.reject("INVALID_POOL_ID_FORMAT", "Pool ID must be a valid number: " + poolID, e);
|
|
1432
|
+
} catch (Exception e) {
|
|
1433
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1434
|
+
promise.reject("JOIN_POOL_WITH_CHAIN_ERROR", "Failed to join pool with chain: " + e.getMessage(), e);
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
@ReactMethod
|
|
1440
|
+
public void leavePoolWithChain(String poolID, String chainName, Promise promise) {
|
|
1441
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1442
|
+
Log.d("ReactNative", "leavePoolWithChain: poolID = " + poolID + ", chainName = " + chainName);
|
|
1443
|
+
try {
|
|
1444
|
+
// Validate inputs
|
|
1445
|
+
if (poolID == null || poolID.trim().isEmpty()) {
|
|
1446
|
+
promise.reject("INVALID_POOL_ID", "Pool ID cannot be null or empty");
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
if (chainName == null || chainName.trim().isEmpty()) {
|
|
1450
|
+
promise.reject("INVALID_CHAIN_NAME", "Chain name cannot be null or empty");
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
if (this.fula == null) {
|
|
1454
|
+
promise.reject("FULA_NOT_INITIALIZED", "Fula client is not initialized");
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
long poolIdLong = Long.parseLong(poolID);
|
|
1459
|
+
byte[] result = this.fula.poolLeaveWithChain(poolIdLong, chainName);
|
|
1460
|
+
String resultString = toString(result);
|
|
1461
|
+
promise.resolve(resultString);
|
|
1462
|
+
} catch (NumberFormatException e) {
|
|
1463
|
+
Log.d("ReactNative", "ERROR: Invalid poolID format: " + e.getMessage());
|
|
1464
|
+
promise.reject("INVALID_POOL_ID_FORMAT", "Pool ID must be a valid number: " + poolID, e);
|
|
1465
|
+
} catch (Exception e) {
|
|
1466
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1467
|
+
promise.reject("LEAVE_POOL_WITH_CHAIN_ERROR", "Failed to leave pool with chain: " + e.getMessage(), e);
|
|
1468
|
+
}
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
@ReactMethod
|
|
1473
|
+
public void listAvailableReplicationRequests(String poolIDStr, Promise promise) {
|
|
1474
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1475
|
+
Log.d("ReactNative", "listAvailableReplicationRequests: poolID = " + poolIDStr);
|
|
1476
|
+
try {
|
|
1477
|
+
long poolID = Long.parseLong(poolIDStr);
|
|
1478
|
+
byte[] result = this.fula.manifestAvailable(poolID);
|
|
1479
|
+
String resultString = toString(result);
|
|
1480
|
+
promise.resolve(resultString);
|
|
1481
|
+
} catch (Exception e) {
|
|
1482
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1483
|
+
promise.reject(e);
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
@ReactMethod
|
|
1489
|
+
private void listRecentCidsAsString(Promise promise) throws Exception {
|
|
1490
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1491
|
+
try {
|
|
1492
|
+
if (this.fula != null) {
|
|
1493
|
+
Log.d("ReactNative", "ListRecentCidsAsString");
|
|
1494
|
+
fulamobile.StringIterator recentLinks = this.fula.listRecentCidsAsString();
|
|
1495
|
+
ArrayList<String> recentLinksList = new ArrayList<>();
|
|
1496
|
+
while (recentLinks.hasNext()) {
|
|
1497
|
+
recentLinksList.add(recentLinks.next());
|
|
1498
|
+
}
|
|
1499
|
+
if (!recentLinksList.isEmpty()) {
|
|
1500
|
+
// return the whole list
|
|
1501
|
+
Log.d("ReactNative", "ListRecentCidsAsString found: "+ recentLinksList);
|
|
1502
|
+
WritableArray recentLinksArray = Arguments.createArray();
|
|
1503
|
+
for (String link : recentLinksList) {
|
|
1504
|
+
recentLinksArray.pushString(link);
|
|
1505
|
+
}
|
|
1506
|
+
promise.resolve(recentLinksArray);
|
|
1507
|
+
} else {
|
|
1508
|
+
promise.resolve(false);
|
|
1509
|
+
}
|
|
1510
|
+
} else {
|
|
1511
|
+
throw new Exception("ListRecentCidsAsString: Fula is not initialized");
|
|
1512
|
+
}
|
|
1513
|
+
} catch (Exception e) {
|
|
1514
|
+
Log.d("ReactNative", "ListRecentCidsAsString failed with Error: " + e.getMessage());
|
|
1515
|
+
try {
|
|
1516
|
+
throw (e);
|
|
1517
|
+
} catch (Exception ex) {
|
|
1518
|
+
throw new RuntimeException(ex);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
@ReactMethod
|
|
1525
|
+
private void listRecentCidsAsStringWithChildren(Promise promise) throws Exception {
|
|
1526
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1527
|
+
try {
|
|
1528
|
+
if (this.fula != null) {
|
|
1529
|
+
Log.d("ReactNative", "listRecentCidsAsStringWithChildren");
|
|
1530
|
+
fulamobile.StringIterator recentLinks = this.fula.listRecentCidsAsStringWithChildren();
|
|
1531
|
+
ArrayList<String> recentLinksList = new ArrayList<>();
|
|
1532
|
+
while (recentLinks.hasNext()) {
|
|
1533
|
+
recentLinksList.add(recentLinks.next());
|
|
1534
|
+
}
|
|
1535
|
+
if (!recentLinksList.isEmpty()) {
|
|
1536
|
+
// return the whole list
|
|
1537
|
+
Log.d("ReactNative", "listRecentCidsAsStringWithChildren found: "+ recentLinksList);
|
|
1538
|
+
WritableArray recentLinksArray = Arguments.createArray();
|
|
1539
|
+
for (String link : recentLinksList) {
|
|
1540
|
+
recentLinksArray.pushString(link);
|
|
1541
|
+
}
|
|
1542
|
+
promise.resolve(recentLinksArray);
|
|
1543
|
+
} else {
|
|
1544
|
+
promise.resolve(false);
|
|
1545
|
+
}
|
|
1546
|
+
} else {
|
|
1547
|
+
throw new Exception("listRecentCidsAsStringWithChildren: Fula is not initialized");
|
|
1548
|
+
}
|
|
1549
|
+
} catch (Exception e) {
|
|
1550
|
+
Log.d("ReactNative", "listRecentCidsAsStringWithChildren failed with Error: " + e.getMessage());
|
|
1551
|
+
try {
|
|
1552
|
+
throw (e);
|
|
1553
|
+
} catch (Exception ex) {
|
|
1554
|
+
throw new RuntimeException(ex);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
});
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
@ReactMethod
|
|
1561
|
+
public void clearCidsFromRecent(ReadableArray cidArray, Promise promise) {
|
|
1562
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1563
|
+
try {
|
|
1564
|
+
if (this.fula != null) {
|
|
1565
|
+
StringBuilder cidStrBuilder = new StringBuilder();
|
|
1566
|
+
for (int i = 0; i < cidArray.size(); i++) {
|
|
1567
|
+
if (i > 0) {
|
|
1568
|
+
cidStrBuilder.append("|");
|
|
1569
|
+
}
|
|
1570
|
+
cidStrBuilder.append(cidArray.getString(i));
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
byte[] cidsBytes = cidStrBuilder.toString().getBytes(StandardCharsets.UTF_8);
|
|
1574
|
+
this.fula.clearCidsFromRecent(cidsBytes);
|
|
1575
|
+
promise.resolve(true); // Indicate success
|
|
1576
|
+
} else {
|
|
1577
|
+
throw new Exception("clearCidsFromRecent: Fula is not initialized");
|
|
1578
|
+
}
|
|
1579
|
+
} catch (Exception e) {
|
|
1580
|
+
Log.d("ReactNative", "clearCidsFromRecent failed with Error: " + e.getMessage());
|
|
1581
|
+
promise.reject("Error", e.getMessage());
|
|
1582
|
+
}
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
@ReactMethod
|
|
1587
|
+
public void batchUploadManifest(ReadableArray cidArray, String poolIDStr, String replicationFactorStr, Promise promise) {
|
|
1588
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1589
|
+
try {
|
|
1590
|
+
long poolID = Long.parseLong(poolIDStr);
|
|
1591
|
+
long replicationFactor = Long.parseLong(replicationFactorStr);
|
|
1592
|
+
if (this.fula != null) {
|
|
1593
|
+
StringBuilder cidStrBuilder = new StringBuilder();
|
|
1594
|
+
for (int i = 0; i < cidArray.size(); i++) {
|
|
1595
|
+
if (i > 0) {
|
|
1596
|
+
cidStrBuilder.append("|");
|
|
1597
|
+
}
|
|
1598
|
+
cidStrBuilder.append(cidArray.getString(i));
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
byte[] cidsBytes = cidStrBuilder.toString().getBytes(StandardCharsets.UTF_8);
|
|
1602
|
+
this.fula.batchUploadManifest(cidsBytes, poolID, replicationFactor);
|
|
1603
|
+
promise.resolve(true); // Indicate success
|
|
1604
|
+
} else {
|
|
1605
|
+
throw new Exception("BatchUploadManifest: Fula is not initialized");
|
|
1606
|
+
}
|
|
1607
|
+
} catch (Exception e) {
|
|
1608
|
+
Log.d("ReactNative", "BatchUploadManifest failed with Error: " + e.getMessage());
|
|
1609
|
+
promise.reject("Error", e.getMessage());
|
|
1610
|
+
}
|
|
1611
|
+
});
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
@ReactMethod
|
|
1615
|
+
public void replicateInPool(ReadableArray cidArray, String account, String poolIDStr, Promise promise) {
|
|
1616
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1617
|
+
try {
|
|
1618
|
+
long poolID = Long.parseLong(poolIDStr);
|
|
1619
|
+
if (this.fula != null) {
|
|
1620
|
+
StringBuilder cidStrBuilder = new StringBuilder();
|
|
1621
|
+
for (int i = 0; i < cidArray.size(); i++) {
|
|
1622
|
+
if (i > 0) {
|
|
1623
|
+
cidStrBuilder.append("|");
|
|
1624
|
+
}
|
|
1625
|
+
cidStrBuilder.append(cidArray.getString(i));
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
byte[] cidsBytes = cidStrBuilder.toString().getBytes(StandardCharsets.UTF_8);
|
|
1629
|
+
byte[] res = this.fula.replicateInPool(cidsBytes, account, poolID);
|
|
1630
|
+
String receivedJsonString = new String(res, StandardCharsets.UTF_8);
|
|
1631
|
+
promise.resolve(receivedJsonString); // Indicate success
|
|
1632
|
+
} else {
|
|
1633
|
+
throw new Exception("replicateInPool: Fula is not initialized");
|
|
1634
|
+
}
|
|
1635
|
+
} catch (Exception e) {
|
|
1636
|
+
Log.d("ReactNative", "replicateInPool failed with Error: " + e.getMessage());
|
|
1637
|
+
promise.reject("Error", e.getMessage());
|
|
1638
|
+
}
|
|
1639
|
+
});
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
////////////////////////////////////////////////////////////////
|
|
1643
|
+
///////////////// Blox Hardware Methods ////////////////////////
|
|
1644
|
+
////////////////////////////////////////////////////////////////
|
|
1645
|
+
|
|
1646
|
+
@ReactMethod
|
|
1647
|
+
public void bloxFreeSpace(Promise promise) {
|
|
1648
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1649
|
+
Log.d("ReactNative", "bloxFreeSpace");
|
|
1650
|
+
try {
|
|
1651
|
+
byte[] result = this.fula.bloxFreeSpace();
|
|
1652
|
+
String resultString = toString(result);
|
|
1653
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1654
|
+
promise.resolve(resultString);
|
|
1655
|
+
} catch (Exception e) {
|
|
1656
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1657
|
+
promise.reject(e);
|
|
1658
|
+
}
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
@ReactMethod
|
|
1663
|
+
public void wifiRemoveall(Promise promise) {
|
|
1664
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1665
|
+
Log.d("ReactNative", "wifiRemoveall");
|
|
1666
|
+
try {
|
|
1667
|
+
byte[] result = this.fula.wifiRemoveall();
|
|
1668
|
+
String resultString = toString(result);
|
|
1669
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1670
|
+
promise.resolve(resultString);
|
|
1671
|
+
} catch (Exception e) {
|
|
1672
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1673
|
+
promise.reject(e);
|
|
1674
|
+
}
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
@ReactMethod
|
|
1679
|
+
public void fetchContainerLogs(String containerName, String tailCount, Promise promise) {
|
|
1680
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1681
|
+
Log.d("ReactNative", "fetchContainerLogs");
|
|
1682
|
+
try {
|
|
1683
|
+
byte[] result = this.fula.fetchContainerLogs(containerName, tailCount);
|
|
1684
|
+
String resultString = toString(result);
|
|
1685
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1686
|
+
promise.resolve(resultString);
|
|
1687
|
+
} catch (Exception e) {
|
|
1688
|
+
Log.d("ReactNative", "an error happened="+e.getMessage());
|
|
1689
|
+
promise.reject(e);
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
@ReactMethod
|
|
1695
|
+
public void findBestAndTargetInLogs(String containerName, String tailCount, Promise promise) {
|
|
1696
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1697
|
+
Log.d("ReactNative", "findBestAndTargetInLogs");
|
|
1698
|
+
try {
|
|
1699
|
+
byte[] result = this.fula.findBestAndTargetInLogs(containerName, tailCount);
|
|
1700
|
+
String resultString = toString(result);
|
|
1701
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1702
|
+
promise.resolve(resultString);
|
|
1703
|
+
} catch (Exception e) {
|
|
1704
|
+
Log.d("ReactNative", "an error happened="+e.getMessage());
|
|
1705
|
+
promise.reject(e);
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
@ReactMethod
|
|
1711
|
+
public void getFolderSize(String folderPath, Promise promise) {
|
|
1712
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1713
|
+
Log.d("ReactNative", "getFolderSize");
|
|
1714
|
+
try {
|
|
1715
|
+
byte[] result = this.fula.getFolderSize(folderPath);
|
|
1716
|
+
String resultString = toString(result);
|
|
1717
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1718
|
+
promise.resolve(resultString);
|
|
1719
|
+
} catch (Exception e) {
|
|
1720
|
+
Log.d("ReactNative", "an error happened="+e.getMessage());
|
|
1721
|
+
promise.reject(e);
|
|
1722
|
+
}
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
@ReactMethod
|
|
1727
|
+
public void getDatastoreSize(Promise promise) {
|
|
1728
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1729
|
+
Log.d("ReactNative", "getDatastoreSize");
|
|
1730
|
+
try {
|
|
1731
|
+
byte[] result = this.fula.getDatastoreSize();
|
|
1732
|
+
String resultString = toString(result);
|
|
1733
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1734
|
+
promise.resolve(resultString);
|
|
1735
|
+
} catch (Exception e) {
|
|
1736
|
+
Log.d("ReactNative", "an error happened="+e.getMessage());
|
|
1737
|
+
promise.reject(e);
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
@ReactMethod
|
|
1743
|
+
public void reboot(Promise promise) {
|
|
1744
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1745
|
+
Log.d("ReactNative", "reboot");
|
|
1746
|
+
try {
|
|
1747
|
+
byte[] result = this.fula.reboot();
|
|
1748
|
+
String resultString = toString(result);
|
|
1749
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1750
|
+
promise.resolve(resultString);
|
|
1751
|
+
} catch (Exception e) {
|
|
1752
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1753
|
+
promise.reject(e);
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
@ReactMethod
|
|
1759
|
+
public void partition(Promise promise) {
|
|
1760
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1761
|
+
Log.d("ReactNative", "partition");
|
|
1762
|
+
try {
|
|
1763
|
+
byte[] result = this.fula.partition();
|
|
1764
|
+
String resultString = toString(result);
|
|
1765
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1766
|
+
promise.resolve(resultString);
|
|
1767
|
+
} catch (Exception e) {
|
|
1768
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1769
|
+
promise.reject(e);
|
|
1770
|
+
}
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
@ReactMethod
|
|
1775
|
+
public void eraseBlData(Promise promise) {
|
|
1776
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1777
|
+
Log.d("ReactNative", "eraseBlData");
|
|
1778
|
+
try {
|
|
1779
|
+
byte[] result = this.fula.eraseBlData();
|
|
1780
|
+
String resultString = toString(result);
|
|
1781
|
+
Log.d("ReactNative", "result string="+resultString);
|
|
1782
|
+
promise.resolve(resultString);
|
|
1783
|
+
} catch (Exception e) {
|
|
1784
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1785
|
+
promise.reject(e);
|
|
1786
|
+
}
|
|
1787
|
+
});
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
@ReactMethod
|
|
1791
|
+
public void testData(String identityString, String bloxAddr, Promise promise) {
|
|
1792
|
+
try {
|
|
1793
|
+
byte[] identity = toByte(identityString);
|
|
1794
|
+
byte[] peerIdByte = this.newClientInternal(identity, "", bloxAddr, "", true, true, true);
|
|
1795
|
+
|
|
1796
|
+
String peerIdReturned = Arrays.toString(peerIdByte);
|
|
1797
|
+
Log.d("ReactNative", "newClient peerIdReturned= " + peerIdReturned);
|
|
1798
|
+
String peerId = this.fula.id();
|
|
1799
|
+
Log.d("ReactNative", "newClient peerId= " + peerId);
|
|
1800
|
+
byte[] bytes = {1, 85, 18, 32, 11, -31, 75, -78, -109, 11, -111, 97, -47, -78, -22, 84, 39, -117, -64, -70, -91, 55, -23, -80, 116, -123, -97, -26, 126, -70, -76, 35, 54, -106, 55, -9};
|
|
1801
|
+
|
|
1802
|
+
byte[] key = this.fula.put(bytes, 85);
|
|
1803
|
+
Log.d("ReactNative", "testData put result string="+Arrays.toString(key));
|
|
1804
|
+
|
|
1805
|
+
byte[] value = this.fula.get(key);
|
|
1806
|
+
Log.d("ReactNative", "testData get result string="+Arrays.toString(value));
|
|
1807
|
+
|
|
1808
|
+
this.fula.push(key);
|
|
1809
|
+
//this.fula.flush();
|
|
1810
|
+
|
|
1811
|
+
byte[] fetchedVal = this.fula.get(key);
|
|
1812
|
+
this.fula.pull(key);
|
|
1813
|
+
|
|
1814
|
+
promise.resolve(Arrays.toString(fetchedVal));
|
|
1815
|
+
} catch (Exception e) {
|
|
1816
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1817
|
+
promise.reject(e);
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
// Plugin Methods
|
|
1822
|
+
@ReactMethod
|
|
1823
|
+
public void listPlugins(Promise promise) {
|
|
1824
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1825
|
+
Log.d("ReactNative", "listPlugins");
|
|
1826
|
+
try {
|
|
1827
|
+
byte[] result = this.fula.listPlugins();
|
|
1828
|
+
String resultString = toString(result);
|
|
1829
|
+
promise.resolve(resultString);
|
|
1830
|
+
} catch (Exception e) {
|
|
1831
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1832
|
+
promise.reject(e);
|
|
1833
|
+
}
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
@ReactMethod
|
|
1838
|
+
public void listActivePlugins(Promise promise) {
|
|
1839
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1840
|
+
Log.d("ReactNative", "listActivePlugins");
|
|
1841
|
+
try {
|
|
1842
|
+
byte[] result = this.fula.listActivePlugins();
|
|
1843
|
+
String resultString = toString(result);
|
|
1844
|
+
promise.resolve(resultString);
|
|
1845
|
+
} catch (Exception e) {
|
|
1846
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1847
|
+
promise.reject(e);
|
|
1848
|
+
}
|
|
1849
|
+
});
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
@ReactMethod
|
|
1853
|
+
public void installPlugin(String pluginName, String params, Promise promise) {
|
|
1854
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1855
|
+
Log.d("ReactNative", "installPlugin: pluginName = " + pluginName + ", params = " + params);
|
|
1856
|
+
try {
|
|
1857
|
+
byte[] result = this.fula.installPlugin(pluginName, params);
|
|
1858
|
+
String resultString = toString(result);
|
|
1859
|
+
promise.resolve(resultString);
|
|
1860
|
+
} catch (Exception e) {
|
|
1861
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1862
|
+
promise.reject(e);
|
|
1863
|
+
}
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
@ReactMethod
|
|
1868
|
+
public void uninstallPlugin(String pluginName, Promise promise) {
|
|
1869
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1870
|
+
Log.d("ReactNative", "uninstallPlugin: pluginName = " + pluginName);
|
|
1871
|
+
try {
|
|
1872
|
+
byte[] result = this.fula.uninstallPlugin(pluginName);
|
|
1873
|
+
String resultString = toString(result);
|
|
1874
|
+
promise.resolve(resultString);
|
|
1875
|
+
} catch (Exception e) {
|
|
1876
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1877
|
+
promise.reject(e);
|
|
1878
|
+
}
|
|
1879
|
+
});
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
@ReactMethod
|
|
1883
|
+
public void showPluginStatus(String pluginName, int lines, Promise promise) {
|
|
1884
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1885
|
+
Log.d("ReactNative", "showPluginStatus: pluginName = " + pluginName + ", lines = " + lines);
|
|
1886
|
+
try {
|
|
1887
|
+
byte[] result = this.fula.showPluginStatus(pluginName, lines);
|
|
1888
|
+
String resultString = toString(result);
|
|
1889
|
+
promise.resolve(resultString);
|
|
1890
|
+
} catch (Exception e) {
|
|
1891
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1892
|
+
promise.reject(e);
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
@ReactMethod
|
|
1898
|
+
public void getInstallOutput(String pluginName, String params, Promise promise) {
|
|
1899
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1900
|
+
Log.d("ReactNative", "getInstallOutput: pluginName = " + pluginName + ", params = " + params);
|
|
1901
|
+
try {
|
|
1902
|
+
byte[] result = this.fula.getInstallOutput(pluginName, params);
|
|
1903
|
+
String resultString = toString(result);
|
|
1904
|
+
promise.resolve(resultString);
|
|
1905
|
+
} catch (Exception e) {
|
|
1906
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1907
|
+
promise.reject(e);
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
@ReactMethod
|
|
1913
|
+
public void getInstallStatus(String pluginName, Promise promise) {
|
|
1914
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1915
|
+
Log.d("ReactNative", "getInstallStatus: pluginName = " + pluginName);
|
|
1916
|
+
try {
|
|
1917
|
+
byte[] result = this.fula.getInstallStatus(pluginName);
|
|
1918
|
+
String resultString = toString(result);
|
|
1919
|
+
promise.resolve(resultString);
|
|
1920
|
+
} catch (Exception e) {
|
|
1921
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1922
|
+
promise.reject(e);
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
@ReactMethod
|
|
1928
|
+
public void updatePlugin(String pluginName, Promise promise) {
|
|
1929
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1930
|
+
Log.d("ReactNative", "updatePlugin: pluginName = " + pluginName);
|
|
1931
|
+
try {
|
|
1932
|
+
byte[] result = this.fula.updatePlugin(pluginName);
|
|
1933
|
+
String resultString = toString(result);
|
|
1934
|
+
promise.resolve(resultString);
|
|
1935
|
+
} catch (Exception e) {
|
|
1936
|
+
Log.d("ReactNative", "ERROR:" + e.getMessage());
|
|
1937
|
+
promise.reject(e);
|
|
1938
|
+
}
|
|
1939
|
+
});
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
// AI
|
|
1943
|
+
@ReactMethod
|
|
1944
|
+
public void chatWithAI(String aiModel, String userMessage, Promise promise) {
|
|
1945
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1946
|
+
Log.d("ReactNative", "chatWithAI: aiModel = " + aiModel + ", userMessage = " + userMessage);
|
|
1947
|
+
try {
|
|
1948
|
+
// Call the Go Mobile method, which returns a byte[]
|
|
1949
|
+
byte[] streamIDBytes = this.fula.chatWithAI(aiModel, userMessage);
|
|
1950
|
+
|
|
1951
|
+
// Convert byte[] to String (assuming UTF-8 encoding)
|
|
1952
|
+
String streamID = new String(streamIDBytes, "UTF-8");
|
|
1953
|
+
|
|
1954
|
+
// Resolve the promise with the stream ID
|
|
1955
|
+
promise.resolve(streamID);
|
|
1956
|
+
} catch (Exception e) {
|
|
1957
|
+
Log.d("ReactNative", "ERROR in chatWithAI: " + e.getMessage());
|
|
1958
|
+
promise.reject(e); // Reject the promise with the error
|
|
1959
|
+
}
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
@ReactMethod
|
|
1964
|
+
public void getChatChunk(String streamID, Promise promise) {
|
|
1965
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1966
|
+
Log.d("ReactNative", "getChatChunk: streamID = " + streamID);
|
|
1967
|
+
try {
|
|
1968
|
+
// Call the Go Mobile method, which returns a String
|
|
1969
|
+
String chunk = this.fula.getChatChunk(streamID);
|
|
1970
|
+
|
|
1971
|
+
// Handle null or empty response
|
|
1972
|
+
if (chunk == null || chunk.isEmpty()) {
|
|
1973
|
+
Log.d("ReactNative", "getChatChunk: No data received for streamID = " + streamID);
|
|
1974
|
+
promise.resolve(""); // Resolve with an empty string
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
// Resolve the promise with the chunk of data
|
|
1979
|
+
Log.d("ReactNative", "getChatChunk: Successfully received chunk for streamID = " + streamID);
|
|
1980
|
+
promise.resolve(chunk);
|
|
1981
|
+
} catch (Exception e) {
|
|
1982
|
+
// Log and reject the promise with the error
|
|
1983
|
+
Log.d("ReactNative", "ERROR in getChatChunk: " + e.getMessage());
|
|
1984
|
+
promise.reject(e);
|
|
1985
|
+
}
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
@ReactMethod
|
|
1990
|
+
public void streamChunks(String streamID, Promise promise) {
|
|
1991
|
+
if (streamID == null || streamID.trim().isEmpty()) {
|
|
1992
|
+
promise.reject("INVALID_ARGUMENT", "streamID cannot be null or empty");
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
ThreadUtils.runOnExecutor(() -> {
|
|
1997
|
+
try {
|
|
1998
|
+
fulamobile.StreamIterator iterator = this.fula.getStreamIterator(streamID);
|
|
1999
|
+
|
|
2000
|
+
if (iterator == null) {
|
|
2001
|
+
promise.reject("STREAM_ITERATOR_ERROR", "Failed to create StreamIterator");
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
// Start listening for chunks
|
|
2006
|
+
new Handler(Looper.getMainLooper()).post(() ->
|
|
2007
|
+
pollIterator(iterator, promise)
|
|
2008
|
+
);
|
|
2009
|
+
} catch (Exception e) {
|
|
2010
|
+
promise.reject("STREAM_ERROR", e.getMessage(), e);
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
private void pollIterator(fulamobile.StreamIterator iterator, Promise promise) {
|
|
2016
|
+
try {
|
|
2017
|
+
String chunk = iterator.next();
|
|
2018
|
+
if (chunk != null && !chunk.trim().isEmpty()) {
|
|
2019
|
+
emitEvent("onChunkReceived", chunk);
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
if (iterator.isComplete()) {
|
|
2023
|
+
emitEvent("onStreamingCompleted", null);
|
|
2024
|
+
promise.resolve(null);
|
|
2025
|
+
} else {
|
|
2026
|
+
new Handler(Looper.getMainLooper()).postDelayed(() ->
|
|
2027
|
+
pollIterator(iterator, promise)
|
|
2028
|
+
, 50); // Reduced delay for better responsiveness
|
|
2029
|
+
}
|
|
2030
|
+
} catch (Exception e) {
|
|
2031
|
+
if (e.getMessage() != null && e.getMessage().contains("EOF")) {
|
|
2032
|
+
emitEvent("onStreamingCompleted", null);
|
|
2033
|
+
promise.resolve(null);
|
|
2034
|
+
} else if (e.getMessage() != null && e.getMessage().contains("timeout")) {
|
|
2035
|
+
// Retry on timeout
|
|
2036
|
+
new Handler(Looper.getMainLooper()).post(() ->
|
|
2037
|
+
pollIterator(iterator, promise)
|
|
2038
|
+
);
|
|
2039
|
+
} else {
|
|
2040
|
+
emitEvent("onStreamError", e.getMessage());
|
|
2041
|
+
promise.reject("STREAM_ERROR", e.getMessage(), e);
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
private void emitEvent(String eventName, String data) {
|
|
2047
|
+
try {
|
|
2048
|
+
getReactApplicationContext()
|
|
2049
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
2050
|
+
.emit(eventName, data);
|
|
2051
|
+
} catch (Exception e) {
|
|
2052
|
+
Log.e("ReactNative", "Error emitting event: " + eventName, e);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
|
|
2057
|
+
}
|