Compare commits

..
Author SHA1 Message Date
yqrashawn 2800719bfc fix: min pwd length for ::multiaccounts.db/password
https://github.com/status-im/status-go/compare/debfe1ca...debfe1ca

it's used in status-im.common.standard-authentication.enter-password
to decide if confirm button should be disabled

fix #18393

Signed-off-by: yqrashawn <namy.19@gmail.com>
2024-01-11 15:54:48 +08:00
82 changed files with 2924 additions and 3229 deletions
@@ -1,5 +0,0 @@
{:lint-as
{rewrite-clj.zip/subedit-> clojure.core/->
rewrite-clj.zip/subedit->> clojure.core/->>
rewrite-clj.zip/edit-> clojure.core/->
rewrite-clj.zip/edit->> clojure.core/->>}}
-1
View File
@@ -1 +0,0 @@
{:hooks {:analyze-call {taoensso.encore/defalias taoensso.encore/defalias}}}
@@ -1,16 +0,0 @@
(ns taoensso.encore
(:require
[clj-kondo.hooks-api :as hooks]))
(defn defalias [{:keys [node]}]
(let [[sym-raw src-raw] (rest (:children node))
src (if src-raw src-raw sym-raw)
sym (if src-raw
sym-raw
(symbol (name (hooks/sexpr src))))]
{:node (with-meta
(hooks/list-node
[(hooks/token-node 'def)
(hooks/token-node (hooks/sexpr sym))
(hooks/token-node (hooks/sexpr src))])
(meta src))}))
+18 -18
View File
@@ -1,26 +1,26 @@
;; -*- mode: clojure -*-
;; vi: ft=clojure
{:width 105
:remove {:fn-force-nl #{:noarg1-body}}
{:width 105
:style [;; community style
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#community
:community
:style
[;; community style https://github.com/kkinnear/zprint/blob/main/doc/reference.md#community
:community
;; no comma in map
:no-comma
;; no comma in map
:no-comma
:custom-justify
:custom-justify
;; respect all newlines
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-nl
:respect-nl
;; respect all newlines https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-nl
:respect-nl
;; respect blank line https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-bl
:respect-bl
;; hang multiline left-hand-thing https://github.com/kkinnear/zprint/issues/273
:multi-lhs-hang]
;; respect blank line
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-bl
:respect-bl
;; hang multiline left-hand-thing
;; https://github.com/kkinnear/zprint/issues/273
:multi-lhs-hang]
:fn-map
{"reg-sub" :arg1-pair
"h/describe" :arg1-body
@@ -50,9 +50,9 @@
"assoc-some" "assoc"
"conj-when" "conj"
"conj-some" "conj"}
:remove {:fn-force-nl #{:noarg1-body}}
:style-map
{:no-comma {:map {:comma? false}}
{:no-comma {:map {:comma? false}}
:custom-justify
{:doc "Justify everything using pre-1.1.2 approach"
:binding {:justify? true :justify {:max-variance 1000}}
+3 -3
View File
@@ -281,7 +281,7 @@ run-android: ##@run Build Android APK and start it on the device
SIMULATOR=iPhone 13
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
run-ios: export TARGET := ios
run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64
run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64,iossimulator/amd64
run-ios: ##@run Build iOS app and start it in a simulator/device
ifneq ("$(SIMULATOR)", "")
npx react-native run-ios --simulator="$(SIMULATOR)" | xcbeautify
@@ -294,7 +294,7 @@ show-ios-devices: ##@other shows connected ios device and its name
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
run-ios-device: export TARGET := ios
run-ios-device: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64
run-ios-device: export IOS_STATUS_GO_TARGETS := ios/arm64,iossimulator/amd64
run-ios-device: ##@run iOS app and start it on a connected device by its name
ifndef DEVICE_NAME
$(error Usage: make run-ios-device DEVICE_NAME=your-device-name)
@@ -329,7 +329,7 @@ lint-fix: ##@test Run code style checks and fix issues
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
clojure-lsp --ns-exclude-regex ".*/\.clj-kondo/.*|.*/src/status_im/core\.cljs|.*/src/test_helpers/component_tests_preload\.cljs$$" clean-ns && \
clojure-lsp --ns-exclude-regex ".*/src/status_im/core\.cljs|.*/src/test_helpers/component_tests_preload\.cljs$$" clean-ns && \
sh scripts/lint/trailing-newline.sh --fix && \
node_modules/.bin/prettier --write .
+1 -3
View File
@@ -78,9 +78,7 @@ pipeline {
}
stage('Upload') {
steps { script {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
env.DIAWI_URL = ios.uploadToDiawi()
}
env.DIAWI_URL = ios.uploadToDiawi()
env.PKG_URL = env.DIAWI_URL
jenkins.setBuildDesc(IPA: env.PKG_URL)
} }
+4 -35
View File
@@ -212,15 +212,16 @@ Properties must be set on view level
:bottom 0}
```
### Animated styles in the style file
### Apply animated styles in the style file
```clojure
;; bad
(defn circle
[]
(let [opacity (reanimated/use-shared-value 1)]
[reanimated/view {:style [{:opacity opacity}
style/circle-container]}]))
[reanimated/view {:style (reanimated/apply-animations-to-style
{:opacity opacity}
style/circle-container)}]))
;; good
(defn circle
@@ -229,38 +230,6 @@ Properties must be set on view level
[reanimated/view {:style (style/circle-container opacity)}]))
```
### Pass a vector of styles to Reanimated view
Prefer to pass a vector of styles to `react-native.reanimated/view` `:style`
prop instead of using `apply-animations-to-style` directly. For more details, check out Reanimated docs about [inline
styles](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/your-first-animation/#defining-a-shared-value)
and [useAnimatedStyle](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/animating-styles-and-props/#animating-styles).
```clojure
(defn f-view []
(let [scroll-x (reanimated/use-shared-value 0)
opacity (reanimated/interpolate scroll-x [0 45 50] [1 1 0])]
[reanimated/view
;; bad
{:style (reanimated/apply-animations-to-style
{:opacity opacity
:transform [{:translate-x scroll-x}]}
{:flex-direction :row})}
;; good
{:style [{:opacity opacity
:transform [{:translate-x scroll-x}]}
{:flex-direction :row}]}
;; other valid and good variants
{:style [{:opacity opacity}
{:transform [{:translate-x scroll-x}]}
{:flex-direction :row}]}
{:style {:opacity opacity
:transform [{:translate-x scroll-x}]
:flex-direction :row}}]))
```
### Don't use percents to define width/height
In ReactNative, all layouts use the [flexbox
@@ -1,345 +0,0 @@
package im.status.ethereum.module;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import statusgo.Statusgo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import org.json.JSONObject;
import org.json.JSONException;
import android.util.Log;
import android.content.Context;
import android.app.Activity;
public class AccountManager extends ReactContextBaseJavaModule {
private static final String TAG = "AccountManager";
private static final String gethLogFileName = "geth.log";
private ReactApplicationContext reactContext;
private Utils utils;
private LogManager logManager;
public AccountManager(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
this.utils = new Utils(reactContext);
this.logManager = new LogManager(reactContext);
}
@Override
public String getName() {
return "AccountManager";
}
private String getTestnetDataDir(final String absRootDirPath) {
return this.utils.pathCombine(absRootDirPath, "ethereum/testnet");
}
@ReactMethod
public void createAccountAndLogin(final String createAccountRequest) {
Log.d(TAG, "createAccountAndLogin");
String result = Statusgo.createAccountAndLogin(createAccountRequest);
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "createAccountAndLogin success: " + result);
Log.d(TAG, "Geth node started");
} else {
Log.e(TAG, "createAccountAndLogin failed: " + result);
}
}
@ReactMethod
public void restoreAccountAndLogin(final String restoreAccountRequest) {
Log.d(TAG, "restoreAccountAndLogin");
String result = Statusgo.restoreAccountAndLogin(restoreAccountRequest);
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "restoreAccountAndLogin success: " + result);
Log.d(TAG, "Geth node started");
} else {
Log.e(TAG, "restoreAccountAndLogin failed: " + result);
}
}
private String updateConfig(final String jsonConfigString, final String absRootDirPath, final String keystoreDirPath) throws JSONException {
final JSONObject jsonConfig = new JSONObject(jsonConfigString);
// retrieve parameters from app config, that will be applied onto the Go-side config later on
final String dataDirPath = jsonConfig.getString("DataDir");
final Boolean logEnabled = jsonConfig.getBoolean("LogEnabled");
final Context context = this.getReactApplicationContext();
final File gethLogFile = logEnabled ? this.logManager.prepareLogsFile(context) : null;
String gethLogDirPath = null;
if (gethLogFile != null) {
gethLogDirPath = gethLogFile.getParent();
}
Log.d(TAG, "log dir: " + gethLogDirPath + " log name: " + gethLogFileName);
jsonConfig.put("DataDir", dataDirPath);
jsonConfig.put("KeyStoreDir", keystoreDirPath);
jsonConfig.put("LogDir", gethLogDirPath);
jsonConfig.put("LogFile", gethLogFileName);
return jsonConfig.toString();
}
private static void prettyPrintConfig(final String config) {
Log.d(TAG, "startNode() with config (see below)");
String configOutput = config;
final int maxOutputLen = 4000;
Log.d(TAG, "********************** NODE CONFIG ****************************");
while (!configOutput.isEmpty()) {
Log.d(TAG, "Node config:" + configOutput.substring(0, Math.min(maxOutputLen, configOutput.length())));
if (configOutput.length() > maxOutputLen) {
configOutput = configOutput.substring(maxOutputLen);
} else {
break;
}
}
Log.d(TAG, "******************* ENDOF NODE CONFIG *************************");
}
private void copyDirectory(File sourceLocation, File targetLocation) throws IOException {
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists() && !targetLocation.mkdirs()) {
throw new IOException("Cannot create dir " + targetLocation.getAbsolutePath());
}
String[] children = sourceLocation.list();
for (int i = 0; i < children.length; i++) {
copyDirectory(new File(sourceLocation, children[i]), new File(targetLocation, children[i]));
}
} else {
File directory = targetLocation.getParentFile();
if (directory != null && !directory.exists() && !directory.mkdirs()) {
throw new IOException("Cannot create dir " + directory.getAbsolutePath());
}
InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}
private String prepareDirAndUpdateConfig(final String jsonConfigString, final String keyUID) {
final String absRootDirPath = this.utils.getNoBackupDirectory();
final String dataFolder = this.getTestnetDataDir(absRootDirPath);
Log.d(TAG, "Starting Geth node in folder: " + dataFolder);
try {
final File newFile = new File(dataFolder);
// todo handle error?
newFile.mkdir();
} catch (Exception e) {
Log.e(TAG, "error making folder: " + dataFolder, e);
}
final String ropstenFlagPath = this.utils.pathCombine(absRootDirPath, "ropsten_flag");
final File ropstenFlag = new File(ropstenFlagPath);
if (!ropstenFlag.exists()) {
try {
final String chaindDataFolderPath = this.utils.pathCombine(dataFolder, "StatusIM/lightchaindata");
final File lightChainFolder = new File(chaindDataFolderPath);
if (lightChainFolder.isDirectory()) {
String[] children = lightChainFolder.list();
for (int i = 0; i < children.length; i++) {
new File(lightChainFolder, children[i]).delete();
}
}
lightChainFolder.delete();
ropstenFlag.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
String testnetDataDir = dataFolder;
String oldKeystoreDir = this.utils.pathCombine(testnetDataDir, "keystore");
String newKeystoreDir = this.utils.pathCombine(absRootDirPath, "keystore");
final File oldKeystore = new File(oldKeystoreDir);
if (oldKeystore.exists()) {
try {
final File newKeystore = new File(newKeystoreDir);
copyDirectory(oldKeystore, newKeystore);
if (oldKeystore.isDirectory()) {
String[] children = oldKeystore.list();
for (int i = 0; i < children.length; i++) {
new File(oldKeystoreDir, children[i]).delete();
}
}
oldKeystore.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
final String multiaccountKeystoreDir = this.utils.pathCombine("/keystore", keyUID);
final String updatedJsonConfigString = this.updateConfig(jsonConfigString, absRootDirPath, multiaccountKeystoreDir);
prettyPrintConfig(updatedJsonConfigString);
return updatedJsonConfigString;
} catch (JSONException e) {
Log.e(TAG, "updateConfig failed: " + e.getMessage());
System.exit(1);
return "";
}
}
@ReactMethod
public void prepareDirAndUpdateConfig(final String keyUID, final String config, final Callback callback) {
Log.d(TAG, "prepareDirAndUpdateConfig");
String finalConfig = prepareDirAndUpdateConfig(config, keyUID);
callback.invoke(finalConfig);
}
@ReactMethod
public void saveAccountAndLoginWithKeycard(final String multiaccountData, final String password, final String settings, final String config, final String accountsData, final String chatKey) {
try {
Log.d(TAG, "saveAccountAndLoginWithKeycard");
String finalConfig = prepareDirAndUpdateConfig(config, this.utils.getKeyUID(multiaccountData));
String result = Statusgo.saveAccountAndLoginWithKeycard(multiaccountData, password, settings, finalConfig, accountsData, chatKey);
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "saveAccountAndLoginWithKeycard result: " + result);
Log.d(TAG, "Geth node started");
} else {
Log.e(TAG, "saveAccountAndLoginWithKeycard failed: " + result);
}
} catch (JSONException e) {
Log.e(TAG, "JSON conversion failed: " + e.getMessage());
}
}
@ReactMethod
public void loginWithKeycard(final String accountData, final String password, final String chatKey, final String nodeConfigJSON) {
Log.d(TAG, "loginWithKeycard");
this.utils.migrateKeyStoreDir(accountData, password);
String result = Statusgo.loginWithKeycard(accountData, password, chatKey, nodeConfigJSON);
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "LoginWithKeycard result: " + result);
} else {
Log.e(TAG, "LoginWithKeycard failed: " + result);
}
}
@ReactMethod
public void loginWithConfig(final String accountData, final String password, final String configJSON) {
Log.d(TAG, "loginWithConfig");
this.utils.migrateKeyStoreDir(accountData, password);
String result = Statusgo.loginWithConfig(accountData, password, configJSON);
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "LoginWithConfig result: " + result);
} else {
Log.e(TAG, "LoginWithConfig failed: " + result);
}
}
@ReactMethod
public void loginAccount(final String request) {
Log.d(TAG, "loginAccount");
String result = Statusgo.loginAccount(request);
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "loginAccount result: " + result);
} else {
Log.e(TAG, "loginAccount failed: " + result);
}
}
@ReactMethod
public void verify(final String address, final String password, final Callback callback) throws JSONException {
Activity currentActivity = getCurrentActivity();
final String absRootDirPath = this.utils.getNoBackupDirectory();
final String newKeystoreDir = this.utils.pathCombine(absRootDirPath, "keystore");
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.verifyAccountPassword(newKeystoreDir, address, password), callback);
}
@ReactMethod
public void verifyDatabasePassword(final String keyUID, final String password, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.verifyDatabasePassword(keyUID, password), callback);
}
@ReactMethod
private void openAccounts(final Callback callback) throws JSONException {
Log.d(TAG, "openAccounts");
final String rootDir = this.utils.getNoBackupDirectory();
Log.d(TAG, "[Opening accounts" + rootDir);
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.openAccounts(rootDir), callback);
}
//TODO : refactor logout usage to accept callback so that we can do this.utils.executeRunnableStatusGoMethod
@ReactMethod
public void logout() {
Log.d(TAG, "logout");
Runnable r = new Runnable() {
@Override
public void run() {
String result = Statusgo.logout();
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "Logout result: " + result);
} else {
Log.e(TAG, "Logout failed: " + result);
}
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountStoreAccount(final String json, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiAccountStoreAccount(json), callback);
}
@ReactMethod
public void multiAccountLoadAccount(final String json, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiAccountLoadAccount(json), callback);
}
@ReactMethod
public void multiAccountDeriveAddresses(final String json, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiAccountDeriveAddresses(json), callback);
}
@ReactMethod
public void multiAccountGenerateAndDeriveAddresses(final String json, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiAccountGenerateAndDeriveAddresses(json), callback);
}
@ReactMethod
public void multiAccountStoreDerived(final String json, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiAccountStoreDerivedAccounts(json), callback);
}
@ReactMethod
public void multiAccountImportMnemonic(final String json, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiAccountImportMnemonic(json), callback);
}
@ReactMethod
public void multiAccountImportPrivateKey(final String json, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiAccountImportPrivateKey(json), callback);
}
@ReactMethod
public void deleteMultiaccount(final String keyUID, final Callback callback) throws JSONException {
final String keyStoreDir = this.utils.getKeyStorePath(keyUID);
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.deleteMultiaccount(keyUID, keyStoreDir), callback);
}
}
@@ -1,66 +0,0 @@
package im.status.ethereum.module;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import statusgo.Statusgo;
import android.util.Log;
import java.io.File;
import android.os.Environment;
import android.content.Context;
public class DatabaseManager extends ReactContextBaseJavaModule {
private static final String TAG = "DatabaseManager";
private ReactApplicationContext reactContext;
private static final String exportDBFileName = "export.db";
private Utils utils;
public DatabaseManager(ReactApplicationContext reactContext) {
this.reactContext = reactContext;
this.utils = new Utils(reactContext);
}
@Override
public String getName() {
return "DatabaseManager";
}
private File getExportDBFile() {
final Context context = this.getReactApplicationContext();
// Environment.getExternalStoragePublicDirectory doesn't work as expected on Android Q
// https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)
final File pubDirectory = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
final File filename = new File(pubDirectory, exportDBFileName);
return filename;
}
@ReactMethod
public void exportUnencryptedDatabase(final String accountData, final String password, final Callback callback) {
Log.d(TAG, "login");
final File newFile = getExportDBFile();
this.utils.migrateKeyStoreDir(accountData, password);
String result = Statusgo.exportUnencryptedDatabase(accountData, password, newFile.getAbsolutePath());
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "Login result: " + result);
} else {
Log.e(TAG, "Login failed: " + result);
}
}
@ReactMethod
public void importUnencryptedDatabase(final String accountData, final String password) {
Log.d(TAG, "importUnencryptedDatabase");
final File newFile = getExportDBFile();
this.utils.migrateKeyStoreDir(accountData, password);
String result = Statusgo.importUnencryptedDatabase(accountData, password, newFile.getAbsolutePath());
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "import result: " + result);
} else {
Log.e(TAG, "import failed: " + result);
}
}
}
@@ -1,173 +0,0 @@
package im.status.ethereum.module;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.Callback;
import android.util.Log;
import statusgo.Statusgo;
import org.json.JSONException;
import java.util.function.Function;
import android.app.Activity;
import android.view.WindowManager;
import android.os.Build;
import android.view.Window;
import android.preference.PreferenceManager;
import android.content.SharedPreferences;
public class EncryptionUtils extends ReactContextBaseJavaModule {
private static final String TAG = "EncryptionUtils";
private ReactApplicationContext reactContext;
private Utils utils;
public EncryptionUtils(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
this.utils = new Utils(reactContext);
}
@Override
public String getName() {
return "EncryptionUtils";
}
@ReactMethod
private void initKeystore(final String keyUID, final Callback callback) throws JSONException {
Log.d(TAG, "initKeystore");
final String commonKeydir = this.utils.pathCombine(this.utils.getNoBackupDirectory(), "/keystore");
final String keydir = this.utils.pathCombine(commonKeydir, keyUID);
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.initKeystore(keydir), callback);
}
@ReactMethod
public void reEncryptDbAndKeystore(final String keyUID, final String password, final String newPassword, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.changeDatabasePassword(keyUID, password, newPassword), callback);
}
@ReactMethod
public void convertToKeycardAccount(final String keyUID, final String accountData, final String options, final String keycardUID, final String password,
final String newPassword, final Callback callback) throws JSONException {
final String keyStoreDir = this.utils.getKeyStorePath(keyUID);
this.utils.executeRunnableStatusGoMethod(() -> {
Statusgo.initKeystore(keyStoreDir);
return Statusgo.convertToKeycardAccount(accountData, options, keycardUID, password, newPassword);
}, callback);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String encodeTransfer(final String to, final String value) {
return Statusgo.encodeTransfer(to, value);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String decodeParameters(final String decodeParamJSON) {
return Statusgo.decodeParameters(decodeParamJSON);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String hexToNumber(final String hex) {
return Statusgo.hexToNumber(hex);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String numberToHex(final String numString) {
return Statusgo.numberToHex(numString);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String sha3(final String str) {
return Statusgo.sha3(str);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String utf8ToHex(final String str) {
return Statusgo.utf8ToHex(str);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String hexToUtf8(final String str) {
return Statusgo.hexToUtf8(str);
}
@ReactMethod
public void setBlankPreviewFlag(final Boolean blankPreview) {
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.reactContext);
sharedPrefs.edit().putBoolean("BLANK_PREVIEW", blankPreview).commit();
setSecureFlag();
}
private void setSecureFlag() {
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.reactContext);
final boolean setSecure = sharedPrefs.getBoolean("BLANK_PREVIEW", true);
final Activity activity = this.reactContext.getCurrentActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
final Window window = activity.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && setSecure) {
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
});
}
}
@ReactMethod
public void hashTransaction(final String txArgsJSON, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.hashTransaction(txArgsJSON), callback);
}
@ReactMethod
public void hashMessage(final String message, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.hashMessage(message), callback);
}
@ReactMethod
public void multiformatDeserializePublicKey(final String multiCodecKey, final String base58btc, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiformatDeserializePublicKey(multiCodecKey,base58btc), callback);
}
@ReactMethod
public void deserializeAndCompressKey(final String desktopKey, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.deserializeAndCompressKey(desktopKey), callback);
}
@ReactMethod
public void hashTypedData(final String data, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.hashTypedData(data), callback);
}
@ReactMethod
public void hashTypedDataV4(final String data, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.hashTypedDataV4(data), callback);
}
@ReactMethod
public void signMessage(final String rpcParams, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.signMessage(rpcParams), callback);
}
@ReactMethod
public void signTypedData(final String data, final String account, final String password, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.signTypedData(data, account, password), callback);
}
@ReactMethod
public void signTypedDataV4(final String data, final String account, final String password, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.signTypedDataV4(data, account, password), callback);
}
@ReactMethod
public void signGroupMembership(final String content, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.signGroupMembership(content), callback);
}
}
@@ -1,227 +0,0 @@
package im.status.ethereum.module;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.Callback;
import java.io.File;
import java.util.Stack;
import android.util.Log;
import android.net.Uri;
import java.io.OutputStreamWriter;
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import androidx.core.content.FileProvider;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipOutputStream;
import java.io.FileInputStream;
import java.util.zip.ZipEntry;
import org.json.JSONObject;
import statusgo.Statusgo;
import android.content.Context;
import org.json.JSONException;
public class LogManager extends ReactContextBaseJavaModule {
private static final String TAG = "LogManager";
private static final String gethLogFileName = "geth.log";
private static final String statusLogFileName = "Status.log";
private static final String logsZipFileName = "Status-debug-logs.zip";
private ReactApplicationContext reactContext;
private Utils utils;
public LogManager(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
this.utils = new Utils(reactContext);
}
@Override
public String getName() {
return "LogManager";
}
private File getLogsFile() {
final File pubDirectory = this.utils.getPublicStorageDirectory();
final File logFile = new File(pubDirectory, gethLogFileName);
return logFile;
}
public File prepareLogsFile(final Context context) {
final File logFile = this.utils.getLogsFile();
try {
logFile.setReadable(true);
File parent = logFile.getParentFile();
if (!parent.canWrite()) {
return null;
}
if (!parent.exists()) {
parent.mkdirs();
}
logFile.createNewFile();
logFile.setWritable(true);
Log.d(TAG, "Can write " + logFile.canWrite());
Uri gethLogUri = Uri.fromFile(logFile);
String gethLogFilePath = logFile.getAbsolutePath();
Log.d(TAG, gethLogFilePath);
return logFile;
} catch (Exception e) {
Log.d(TAG, "Can't create geth.log file! " + e.getMessage());
}
return null;
}
private void showErrorMessage(final String message) {
final Activity activity = getCurrentActivity();
new AlertDialog.Builder(activity)
.setTitle("Error")
.setMessage(message)
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, final int id) {
dialog.dismiss();
}
}).show();
}
private void dumpAdbLogsTo(final FileOutputStream statusLogStream) throws IOException {
final String filter = "logcat -d -b main ReactNativeJS:D StatusModule:D StatusService:D StatusNativeLogs:D *:S";
final java.lang.Process p = Runtime.getRuntime().exec(filter);
final java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(p.getInputStream()));
final java.io.BufferedWriter out = new java.io.BufferedWriter(new java.io.OutputStreamWriter(statusLogStream));
String line;
while ((line = in.readLine()) != null) {
out.write(line);
out.newLine();
}
out.close();
in.close();
}
private Boolean zip(File[] _files, File zipFile, Stack<String> errorList) {
final int BUFFER = 0x8000;
try {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(zipFile);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
byte data[] = new byte[BUFFER];
for (int i = 0; i < _files.length; i++) {
final File file = _files[i];
if (file == null || !file.exists()) {
continue;
}
Log.v("Compress", "Adding: " + file.getAbsolutePath());
try {
FileInputStream fi = new FileInputStream(file);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(file.getName());
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
errorList.push(e.getMessage());
}
}
out.close();
return true;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
return false;
}
}
@ReactMethod
public void sendLogs(final String dbJson, final String jsLogs, final Callback callback) {
Log.d(TAG, "sendLogs");
if (!this.utils.checkAvailability()) {
return;
}
final Context context = this.getReactApplicationContext();
final File logsTempDir = new File(context.getCacheDir(), "logs"); // This path needs to be in sync with android/app/src/main/res/xml/file_provider_paths.xml
logsTempDir.mkdir();
final File dbFile = new File(logsTempDir, "db.json");
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(dbFile));
outputStreamWriter.write(dbJson);
outputStreamWriter.close();
} catch (IOException e) {
Log.e(TAG, "File write failed: " + e.toString());
showErrorMessage(e.getLocalizedMessage());
}
final File zipFile = new File(logsTempDir, logsZipFileName);
final File statusLogFile = new File(logsTempDir, statusLogFileName);
final File gethLogFile = getLogsFile();
try {
if (zipFile.exists() || zipFile.createNewFile()) {
final long usableSpace = zipFile.getUsableSpace();
if (usableSpace < 20 * 1024 * 1024) {
final String message = String.format("Insufficient space available on device (%s) to write logs.\nPlease free up some space.", android.text.format.Formatter.formatShortFileSize(context, usableSpace));
Log.e(TAG, message);
showErrorMessage(message);
return;
}
}
dumpAdbLogsTo(new FileOutputStream(statusLogFile));
final Stack<String> errorList = new Stack<String>();
final Boolean zipped = zip(new File[]{dbFile, gethLogFile, statusLogFile}, zipFile, errorList);
if (zipped && zipFile.exists()) {
zipFile.setReadable(true, false);
Uri extUri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", zipFile);
callback.invoke(extUri.toString());
} else {
Log.d(TAG, "File " + zipFile.getAbsolutePath() + " does not exist");
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
showErrorMessage(e.getLocalizedMessage());
e.printStackTrace();
return;
} finally {
dbFile.delete();
statusLogFile.delete();
zipFile.deleteOnExit();
}
}
@ReactMethod
public void initLogging(final boolean enabled, final boolean mobileSystem, final String logLevel, final Callback callback) throws JSONException {
final JSONObject jsonConfig = new JSONObject();
jsonConfig.put("Enabled", enabled);
jsonConfig.put("MobileSystem", mobileSystem);
jsonConfig.put("Level", logLevel);
jsonConfig.put("File", getLogsFile().getAbsolutePath());
final String config = jsonConfig.toString();
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.initLogging(config), callback);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String logFileDirectory() {
return this.utils.getPublicStorageDirectory().getAbsolutePath();
}
}
@@ -1,78 +0,0 @@
package im.status.ethereum.module;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import org.json.JSONException;
import statusgo.Statusgo;
import org.json.JSONObject;
public class NetworkManager extends ReactContextBaseJavaModule {
private ReactApplicationContext reactContext;
private Utils utils;
public NetworkManager(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
this.utils = new Utils(reactContext);
}
@Override
public String getName() {
return "NetworkManager";
}
@ReactMethod
public void startSearchForLocalPairingPeers(final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.startSearchForLocalPairingPeers(), callback);
}
@ReactMethod
public void getConnectionStringForBootstrappingAnotherDevice(final String configJSON, final Callback callback) throws JSONException {
final JSONObject jsonConfig = new JSONObject(configJSON);
final JSONObject senderConfig = jsonConfig.getJSONObject("senderConfig");
final String keyUID = senderConfig.getString("keyUID");
final String keyStorePath = this.utils.getKeyStorePath(keyUID);
senderConfig.put("keystorePath", keyStorePath);
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.getConnectionStringForBootstrappingAnotherDevice(jsonConfig.toString()), callback);
}
@ReactMethod
public void inputConnectionStringForBootstrapping(final String connectionString, final String configJSON, final Callback callback) throws JSONException {
final JSONObject jsonConfig = new JSONObject(configJSON);
final JSONObject receiverConfig = jsonConfig.getJSONObject("receiverConfig");
final String keyStorePath = this.utils.pathCombine(this.utils.getNoBackupDirectory(), "/keystore");
receiverConfig.put("keystorePath", keyStorePath);
receiverConfig.getJSONObject("nodeConfig").put("rootDataDir", this.utils.getNoBackupDirectory());
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.inputConnectionStringForBootstrapping(connectionString, jsonConfig.toString()), callback);
}
@ReactMethod
public void sendTransactionWithSignature(final String txArgsJSON, final String signature, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.sendTransactionWithSignature(txArgsJSON, signature), callback);
}
@ReactMethod
public void sendTransaction(final String txArgsJSON, final String password, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.sendTransaction(txArgsJSON, password), callback);
}
@ReactMethod
public void callRPC(final String payload, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.callRPC(payload), callback);
}
@ReactMethod
public void callPrivateRPC(final String payload, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.callPrivateRPC(payload), callback);
}
@ReactMethod
public void recover(final String rpcParams, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.recover(rpcParams), callback);
}
}
@@ -30,13 +30,6 @@ public class StatusPackage implements ReactPackage {
List<NativeModule> modules = new ArrayList<>();
modules.add(new StatusModule(reactContext, this.rootedDevice));
modules.add(new AccountManager(reactContext));
modules.add(new EncryptionUtils(reactContext));
modules.add(new DatabaseManager(reactContext));
modules.add(new UIHelper(reactContext));
modules.add(new LogManager(reactContext));
modules.add(new Utils(reactContext));
modules.add(new NetworkManager(reactContext));
modules.add(new RNSelectableTextInputModule(reactContext));
return modules;
@@ -1,124 +0,0 @@
package im.status.ethereum.module;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import android.app.Activity;
import android.util.Log;
import android.os.Build;
import android.webkit.WebView;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebStorage;
import android.view.WindowManager;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.UIBlock;
import com.facebook.react.uimanager.NativeViewHierarchyManager;
import android.view.inputmethod.InputMethodManager;
import android.view.View;
import android.widget.EditText;
import android.content.Context;
public class UIHelper extends ReactContextBaseJavaModule {
private static final String TAG = "UIHelper";
private ReactApplicationContext reactContext;
public UIHelper(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public String getName() {
return "UIHelper";
}
@ReactMethod
public void setSoftInputMode(final int mode) {
Log.d(TAG, "setSoftInputMode");
final Activity activity = getCurrentActivity();
if (activity == null) {
return;
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.getWindow().setSoftInputMode(mode);
}
});
}
@SuppressWarnings("deprecation")
@ReactMethod
public void clearCookies() {
Log.d(TAG, "clearCookies");
final Activity activity = getCurrentActivity();
if (activity == null) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
CookieManager.getInstance().removeAllCookies(null);
CookieManager.getInstance().flush();
} else {
CookieSyncManager cookieSyncManager = CookieSyncManager.createInstance(activity);
cookieSyncManager.startSync();
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
cookieManager.removeSessionCookie();
cookieSyncManager.stopSync();
cookieSyncManager.sync();
}
}
@ReactMethod
public void toggleWebviewDebug(final boolean val) {
Log.d(TAG, "toggleWebviewDebug");
final Activity activity = getCurrentActivity();
if (activity == null) {
return;
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
WebView.setWebContentsDebuggingEnabled(val);
}
});
}
@ReactMethod
public void clearStorageAPIs() {
Log.d(TAG, "clearStorageAPIs");
final Activity activity = getCurrentActivity();
if (activity == null) {
return;
}
WebStorage storage = WebStorage.getInstance();
if (storage != null) {
storage.deleteAllData();
}
}
@ReactMethod
public void resetKeyboardInputCursor(final int reactTagToReset, final int selection) {
UIManagerModule uiManager = getReactApplicationContext().getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
InputMethodManager imm = (InputMethodManager) getReactApplicationContext().getBaseContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
View viewToReset = nativeViewHierarchyManager.resolveView(reactTagToReset);
imm.restartInput(viewToReset);
try {
EditText textView = (EditText) viewToReset;
textView.setSelection(selection);
} catch (Exception e) {}
}
}
});
}
}
@@ -1,155 +0,0 @@
package im.status.ethereum.module;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import android.util.Log;
import java.util.function.Supplier;
import java.io.File;
import android.content.Context;
import android.os.Environment;
import org.json.JSONObject;
import org.json.JSONException;
import statusgo.Statusgo;
public class Utils extends ReactContextBaseJavaModule {
private static final String gethLogFileName = "geth.log";
private static final String TAG = "Utils";
private ReactApplicationContext reactContext;
public Utils(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public String getName() {
return "Utils";
}
public String getNoBackupDirectory() {
return this.getReactApplicationContext().getNoBackupFilesDir().getAbsolutePath();
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String backupDisabledDataDir() {
return getNoBackupDirectory();
}
public File getPublicStorageDirectory() {
final Context context = this.getReactApplicationContext();
// Environment.getExternalStoragePublicDirectory doesn't work as expected on Android Q
// https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)
return context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
}
public File getLogsFile() {
final File pubDirectory = getPublicStorageDirectory();
final File logFile = new File(pubDirectory, gethLogFileName);
return logFile;
}
public String getKeyUID(final String json) throws JSONException {
final JSONObject jsonObj = new JSONObject(json);
return jsonObj.getString("key-uid");
}
public String pathCombine(final String path1, final String path2) {
// Replace this logic with Paths.get(path1, path2) once API level 26+ becomes the minimum supported API level
final File file = new File(path1, path2);
return file.getAbsolutePath();
}
public String getKeyStorePath(String keyUID) {
final String commonKeydir = pathCombine(getNoBackupDirectory(), "/keystore");
final String keydir = pathCombine(commonKeydir, keyUID);
return keydir;
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String keystoreDir() {
final String absRootDirPath = getNoBackupDirectory();
return pathCombine(absRootDirPath, "keystore");
}
public void migrateKeyStoreDir(final String accountData, final String password) {
try {
final String commonKeydir = pathCombine(getNoBackupDirectory(), "/keystore");
final String keydir = getKeyStorePath(getKeyUID(accountData));
Log.d(TAG, "before migrateKeyStoreDir " + keydir);
File keydirFile = new File(keydir);
if(!keydirFile.exists() || keydirFile.list().length == 0) {
Log.d(TAG, "migrateKeyStoreDir");
Statusgo.migrateKeyStoreDir(accountData, password, commonKeydir, keydir);
Statusgo.initKeystore(keydir);
}
} catch (JSONException e) {
Log.e(TAG, "JSON conversion failed: " + e.getMessage());
}
}
public boolean checkAvailability() {
// We wait at least 10s for getCurrentActivity to return a value,
// otherwise we give up
for (int attempts = 0; attempts < 100; attempts++) {
if (getCurrentActivity() != null) {
return true;
}
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
if (getCurrentActivity() != null) {
return true;
}
Log.d(TAG, "Activity doesn't exist");
return false;
}
}
Log.d(TAG, "Activity doesn't exist");
return false;
}
public void executeRunnableStatusGoMethod(Supplier<String> method, Callback callback) throws JSONException {
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable runnableTask = () -> {
String res = method.get();
callback.invoke(res);
};
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
}
@ReactMethod
public void validateMnemonic(final String seed, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.validateMnemonic(seed), callback);
}
public Boolean is24Hour() {
return android.text.format.DateFormat.is24HourFormat(this.reactContext.getApplicationContext());
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String checkAddressChecksum(final String address) {
return Statusgo.checkAddressChecksum(address);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String isAddress(final String address) {
return Statusgo.isAddress(address);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String toChecksumAddress(final String address) {
return Statusgo.toChecksumAddress(address);
}
}
@@ -1,9 +0,0 @@
#import <sys/utsname.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "Statusgo.h"
#import "RCTLog.h"
@interface AccountManager : NSObject <RCTBridgeModule>
@end
@@ -1,217 +0,0 @@
#import "AccountManager.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
#import "Statusgo.h"
#import "Utils.h"
@implementation AccountManager
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(createAccountAndLogin:(NSString *)request) {
#if DEBUG
NSLog(@"createAccountAndLogin() method called");
#endif
StatusgoCreateAccountAndLogin(request);
}
RCT_EXPORT_METHOD(restoreAccountAndLogin:(NSString *)request) {
#if DEBUG
NSLog(@"restoreAccountAndLogin() method called");
#endif
StatusgoRestoreAccountAndLogin(request);
}
-(NSString *) prepareDirAndUpdateConfig:(NSString *)config
withKeyUID:(NSString *)keyUID {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
NSURL *absTestnetFolderName = [rootUrl URLByAppendingPathComponent:@"ethereum/testnet"];
if (![fileManager fileExistsAtPath:absTestnetFolderName.path])
[fileManager createDirectoryAtPath:absTestnetFolderName.path withIntermediateDirectories:YES attributes:nil error:&error];
NSURL *flagFolderUrl = [rootUrl URLByAppendingPathComponent:@"ropsten_flag"];
if(![fileManager fileExistsAtPath:flagFolderUrl.path]){
NSLog(@"remove lightchaindata");
NSURL *absLightChainDataUrl = [absTestnetFolderName URLByAppendingPathComponent:@"StatusIM/lightchaindata"];
if([fileManager fileExistsAtPath:absLightChainDataUrl.path]) {
[fileManager removeItemAtPath:absLightChainDataUrl.path
error:nil];
}
[fileManager createDirectoryAtPath:flagFolderUrl.path
withIntermediateDirectories:NO
attributes:nil
error:&error];
}
NSLog(@"after remove lightchaindata");
NSString *keystore = @"keystore";
NSURL *absTestnetKeystoreUrl = [absTestnetFolderName URLByAppendingPathComponent:keystore];
NSURL *absKeystoreUrl = [rootUrl URLByAppendingPathComponent:keystore];
if([fileManager fileExistsAtPath:absTestnetKeystoreUrl.path]){
NSLog(@"copy keystore");
[fileManager copyItemAtPath:absTestnetKeystoreUrl.path toPath:absKeystoreUrl.path error:nil];
[fileManager removeItemAtPath:absTestnetKeystoreUrl.path error:nil];
}
NSLog(@"after lightChainData");
NSLog(@"preconfig: %@", config);
NSData *configData = [config dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *configJSON = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:nil];
NSString *relativeDataDir = [configJSON objectForKey:@"DataDir"];
NSString *absDataDir = [rootUrl.path stringByAppendingString:relativeDataDir];
NSURL *absDataDirUrl = [NSURL fileURLWithPath:absDataDir];
NSString *keystoreDir = [@"/keystore/" stringByAppendingString:keyUID];
[configJSON setValue:keystoreDir forKey:@"KeyStoreDir"];
[configJSON setValue:@"" forKey:@"LogDir"];
[configJSON setValue:@"geth.log" forKey:@"LogFile"];
NSString *resultingConfig = [Utils jsonStringWithPrettyPrint:NO fromDictionary:configJSON];
NSLog(@"node config %@", resultingConfig);
if(![fileManager fileExistsAtPath:absDataDir]) {
[fileManager createDirectoryAtPath:absDataDir
withIntermediateDirectories:YES attributes:nil error:nil];
}
NSLog(@"logUrlPath %@ rootDir %@", @"geth.log", rootUrl.path);
NSURL *absLogUrl = [absDataDirUrl URLByAppendingPathComponent:@"geth.log"];
if(![fileManager fileExistsAtPath:absLogUrl.path]) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:[NSNumber numberWithInt:511] forKey:NSFilePosixPermissions];
[fileManager createFileAtPath:absLogUrl.path contents:nil attributes:dict];
}
return resultingConfig;
}
RCT_EXPORT_METHOD(deleteMultiaccount:(NSString *)keyUID
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"DeleteMultiaccount() method called");
#endif
NSURL *multiaccountKeystoreDir = [Utils getKeyStoreDirForKeyUID:keyUID];
NSString *result = StatusgoDeleteMultiaccount(keyUID, multiaccountKeystoreDir.path);
callback(@[result]);
}
RCT_EXPORT_METHOD(prepareDirAndUpdateConfig:(NSString *)keyUID
config:(NSString *)config
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"PrepareDirAndUpdateConfig() method called");
#endif
NSString *updatedConfig = [self prepareDirAndUpdateConfig:config
withKeyUID:keyUID];
callback(@[updatedConfig]);
}
RCT_EXPORT_METHOD(saveAccountAndLoginWithKeycard:(NSString *)multiaccountData
password:(NSString *)password
settings:(NSString *)settings
config:(NSString *)config
accountsData:(NSString *)accountsData
chatKey:(NSString *)chatKey) {
#if DEBUG
NSLog(@"SaveAccountAndLoginWithKeycard() method called");
#endif
[Utils getExportDbFilePath];
NSString *keyUID = [Utils getKeyUID:multiaccountData];
NSString *finalConfig = [self prepareDirAndUpdateConfig:config
withKeyUID:keyUID];
NSString *result = StatusgoSaveAccountAndLoginWithKeycard(multiaccountData, password, settings, finalConfig, accountsData, chatKey);
NSLog(@"%@", result);
}
RCT_EXPORT_METHOD(loginWithKeycard:(NSString *)accountData
password:(NSString *)password
chatKey:(NSString *)chatKey
nodeConfigJSON:(NSString *)nodeConfigJSON) {
#if DEBUG
NSLog(@"LoginWithKeycard() method called");
#endif
[Utils getExportDbFilePath];
[Utils migrateKeystore:accountData password:password];
NSString *result = StatusgoLoginWithKeycard(accountData, password, chatKey, nodeConfigJSON);
NSLog(@"%@", result);
}
RCT_EXPORT_METHOD(loginWithConfig:(NSString *)accountData
password:(NSString *)password
configJSON:(NSString *)configJSON) {
#if DEBUG
NSLog(@"LoginWithConfig() method called");
#endif
[Utils getExportDbFilePath];
[Utils migrateKeystore:accountData password:password];
NSString *result = StatusgoLoginWithConfig(accountData, password, configJSON);
NSLog(@"%@", result);
}
RCT_EXPORT_METHOD(loginAccount:(NSString *)request) {
#if DEBUG
NSLog(@"LoginAccount() method called");
#endif
NSString *result = StatusgoLoginAccount(request);
NSLog(@"%@", result);
}
RCT_EXPORT_METHOD(verify:(NSString *)address
password:(NSString *)password
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"VerifyAccountPassword() method called");
#endif
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
NSURL *absKeystoreUrl = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSString *result = StatusgoVerifyAccountPassword(absKeystoreUrl.path, address, password);
callback(@[result]);
}
RCT_EXPORT_METHOD(verifyDatabasePassword:(NSString *)keyUID
password:(NSString *)password
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"VerifyDatabasePassword() method called");
#endif
NSString *result = StatusgoVerifyDatabasePassword(keyUID, password);
callback(@[result]);
}
RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"OpenAccounts() method called");
#endif
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
NSString *result = StatusgoOpenAccounts(rootUrl.path);
callback(@[result]);
}
RCT_EXPORT_METHOD(logout) {
#if DEBUG
NSLog(@"Logout() method called");
#endif
NSString *result = StatusgoLogout();
NSLog(@"%@", result);
}
@end
@@ -1,9 +0,0 @@
#import <sys/utsname.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "Statusgo.h"
#import "RCTLog.h"
@interface DatabaseManager : NSObject <RCTBridgeModule>
@end
@@ -1,33 +0,0 @@
#import "DatabaseManager.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
#import "Statusgo.h"
#import "Utils.h"
@implementation DatabaseManager
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(exportUnencryptedDatabase:(NSString *)accountData
password:(NSString *)password
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"exportUnencryptedDatabase() method called");
#endif
NSString *filePath = [Utils getExportDbFilePath];
StatusgoExportUnencryptedDatabase(accountData, password, filePath);
callback(@[filePath]);
}
RCT_EXPORT_METHOD(importUnencryptedDatabase:(NSString *)accountData
password:(NSString *)password) {
#if DEBUG
NSLog(@"importUnencryptedDatabase() method called");
#endif
"";
}
@end
@@ -1,9 +0,0 @@
#import <sys/utsname.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "Statusgo.h"
#import "RCTLog.h"
@interface EncryptionUtils : NSObject <RCTBridgeModule>
@end
@@ -1,200 +0,0 @@
#import "EncryptionUtils.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
#import "Statusgo.h"
#import "Utils.h"
@implementation EncryptionUtils
RCT_EXPORT_MODULE();
#pragma mark - InitKeystore method
RCT_EXPORT_METHOD(initKeystore:(NSString *)keyUID
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"initKeystore() method called");
#endif
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
NSURL *commonKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSURL *keystoreDir = [commonKeystoreDir URLByAppendingPathComponent:keyUID];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^(void)
{
NSString *res = StatusgoInitKeystore(keystoreDir.path);
NSLog(@"InitKeyStore result %@", res);
callback(@[]);
});
}
RCT_EXPORT_METHOD(reEncryptDbAndKeystore:(NSString *)keyUID
currentPassword:(NSString *)currentPassword
newPassword:(NSString *)newPassword
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"reEncryptDbAndKeystore() method called");
#endif
// changes password and re-encrypts keystore
NSString *result = StatusgoChangeDatabasePassword(keyUID, currentPassword, newPassword);
callback(@[result]);
}
RCT_EXPORT_METHOD(convertToKeycardAccount:(NSString *)keyUID
accountData:(NSString *)accountData
settings:(NSString *)settings
keycardUID:(NSString *)keycardUID
currentPassword:(NSString *)currentPassword
newPassword:(NSString *)newPassword
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"convertToKeycardAccount() method called");
#endif
NSURL *multiaccountKeystoreDir = [Utils getKeyStoreDirForKeyUID:keyUID];
StatusgoInitKeystore(multiaccountKeystoreDir.path);
NSString *result = StatusgoConvertToKeycardAccount(accountData, settings, keycardUID, currentPassword, newPassword);
callback(@[result]);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(encodeTransfer:(NSString *)to
value:(NSString *)value) {
return StatusgoEncodeTransfer(to,value);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(encodeFunctionCall:(NSString *)method
paramsJSON:(NSString *)paramsJSON) {
return StatusgoEncodeFunctionCall(method,paramsJSON);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(decodeParameters:(NSString *)decodeParamJSON) {
return StatusgoDecodeParameters(decodeParamJSON);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(hexToNumber:(NSString *)hex) {
return StatusgoHexToNumber(hex);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(numberToHex:(NSString *)numString) {
return StatusgoNumberToHex(numString);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(sha3:(NSString *)str) {
return StatusgoSha3(str);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(utf8ToHex:(NSString *)str) {
return StatusgoUtf8ToHex(str);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(hexToUtf8:(NSString *)str) {
return StatusgoHexToUtf8(str);
}
RCT_EXPORT_METHOD(setBlankPreviewFlag:(BOOL *)newValue)
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:newValue forKey:@"BLANK_PREVIEW"];
[userDefaults synchronize];
}
RCT_EXPORT_METHOD(hashTransaction:(NSString *)txArgsJSON
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"HashTransaction() method called");
#endif
NSString *result = StatusgoHashTransaction(txArgsJSON);
callback(@[result]);
}
RCT_EXPORT_METHOD(hashMessage:(NSString *)message
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"hashMessage() method called");
#endif
NSString *result = StatusgoHashMessage(message);
callback(@[result]);
}
RCT_EXPORT_METHOD(localPairingPreflightOutboundCheck:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"LocalPairingPreflightOutboundCheck() method called");
#endif
NSString *result = StatusgoLocalPairingPreflightOutboundCheck();
callback(@[result]);
}
RCT_EXPORT_METHOD(multiformatDeserializePublicKey:(NSString *)multiCodecKey
base58btc:(NSString *)base58btc
callback:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoMultiformatDeserializePublicKey(multiCodecKey,base58btc);
callback(@[result]);
}
RCT_EXPORT_METHOD(deserializeAndCompressKey:(NSString *)desktopKey
callback:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoDeserializeAndCompressKey(desktopKey);
callback(@[result]);
}
RCT_EXPORT_METHOD(hashTypedData:(NSString *)data
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"hashTypedData() method called");
#endif
NSString *result = StatusgoHashTypedData(data);
callback(@[result]);
}
RCT_EXPORT_METHOD(hashTypedDataV4:(NSString *)data
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"hashTypedDataV4() method called");
#endif
NSString *result = StatusgoHashTypedDataV4(data);
callback(@[result]);
}
#pragma mark - SignMessage
RCT_EXPORT_METHOD(signMessage:(NSString *)message
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"SignMessage() method called");
#endif
NSString *result = StatusgoSignMessage(message);
callback(@[result]);
}
#pragma mark - SignTypedData
RCT_EXPORT_METHOD(signTypedData:(NSString *)data
account:(NSString *)account
password:(NSString *)password
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"SignTypedData() method called");
#endif
NSString *result = StatusgoSignTypedData(data, account, password);
callback(@[result]);
}
#pragma mark - SignTypedDataV4
RCT_EXPORT_METHOD(signTypedDataV4:(NSString *)data
account:(NSString *)account
password:(NSString *)password
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"SignTypedDataV4() method called");
#endif
NSString *result = StatusgoSignTypedDataV4(data, account, password);
callback(@[result]);
}
@end
@@ -1,9 +0,0 @@
#import <sys/utsname.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "Statusgo.h"
#import "RCTLog.h"
@interface LogManager : NSObject <RCTBridgeModule>
@end
@@ -1,115 +0,0 @@
#import "LogManager.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
#import "Statusgo.h"
#import "Utils.h"
#import "SSZipArchive.h"
@implementation LogManager
RCT_EXPORT_MODULE();
#pragma mark - SendLogs method
RCT_EXPORT_METHOD(sendLogs:(NSString *)dbJson
jsLogs:(NSString *)jsLogs
callback:(RCTResponseSenderBlock)callback) {
// TODO: Implement SendLogs for iOS
#if DEBUG
NSLog(@"SendLogs() method called, not implemented");
#endif
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
NSURL *zipFile = [rootUrl URLByAppendingPathComponent:@"logs.zip"];
[fileManager removeItemAtPath:zipFile.path error:nil];
NSURL *logsFolderName = [rootUrl URLByAppendingPathComponent:@"logs"];
if (![fileManager fileExistsAtPath:logsFolderName.path])
[fileManager createDirectoryAtPath:logsFolderName.path withIntermediateDirectories:YES attributes:nil error:&error];
NSURL *dbFile = [logsFolderName URLByAppendingPathComponent:@"db.json"];
NSURL *jsLogsFile = [logsFolderName URLByAppendingPathComponent:@"Status.log"];
#if DEBUG
NSString *networkDirPath = @"ethereum/mainnet_rpc_dev";
#else
NSString *networkDirPath = @"ethereum/mainnet_rpc";
#endif
#if DEBUG
NSString *goerliNetworkDirPath = @"ethereum/goerli_rpc_dev";
#else
NSString *goerliNetworkDirPath = @"ethereum/goerli_rpc";
#endif
NSURL *networkDir = [rootUrl URLByAppendingPathComponent:networkDirPath];
NSURL *originalGethLogsFile = [networkDir URLByAppendingPathComponent:@"geth.log"];
NSURL *gethLogsFile = [logsFolderName URLByAppendingPathComponent:@"mainnet_geth.log"];
NSURL *goerliNetworkDir = [rootUrl URLByAppendingPathComponent:goerliNetworkDirPath];
NSURL *goerliGethLogsFile = [goerliNetworkDir URLByAppendingPathComponent:@"geth.log"];
NSURL *goerliLogsFile = [logsFolderName URLByAppendingPathComponent:@"goerli_geth.log"];
NSURL *mainGethLogsFile = [rootUrl URLByAppendingPathComponent:@"geth.log"];
NSURL *mainLogsFile = [logsFolderName URLByAppendingPathComponent:@"geth.log"];
[dbJson writeToFile:dbFile.path atomically:YES encoding:NSUTF8StringEncoding error:nil];
[jsLogs writeToFile:jsLogsFile.path atomically:YES encoding:NSUTF8StringEncoding error:nil];
//NSString* gethLogs = StatusgoExportNodeLogs();
//[gethLogs writeToFile:gethLogsFile.path atomically:YES encoding:NSUTF8StringEncoding error:nil];
[fileManager copyItemAtPath:originalGethLogsFile.path toPath:gethLogsFile.path error:nil];
[fileManager copyItemAtPath:goerliGethLogsFile.path toPath:goerliLogsFile.path error:nil];
[fileManager copyItemAtPath:mainGethLogsFile.path toPath:mainLogsFile.path error:nil];
[SSZipArchive createZipFileAtPath:zipFile.path withContentsOfDirectory:logsFolderName.path];
[fileManager removeItemAtPath:logsFolderName.path error:nil];
callback(@[zipFile.absoluteString]);
}
RCT_EXPORT_METHOD(initLogging:(BOOL)enabled
mobileSystem:(BOOL)mobileSystem
logLevel:(NSString *)logLevel
callback:(RCTResponseSenderBlock)callback)
{
NSString *logDirectory = [self logFileDirectory];
NSString *logFilePath = [logDirectory stringByAppendingPathComponent:@"geth.log"];
NSMutableDictionary *jsonConfig = [NSMutableDictionary dictionary];
jsonConfig[@"Enabled"] = @(enabled);
jsonConfig[@"MobileSystem"] = @(mobileSystem);
jsonConfig[@"Level"] = logLevel;
jsonConfig[@"File"] = logFilePath;
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonConfig options:0 error:&error];
if (error) {
// Handle JSON serialization error
callback(@[error.localizedDescription]);
return;
}
NSString *config = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// Call your native logging initialization method here
NSString *initResult = StatusgoInitLogging(config);
callback(@[initResult]);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(logFileDirectory) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
return rootUrl.path;
}
@end
@@ -1,9 +0,0 @@
#import <sys/utsname.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "Statusgo.h"
#import "RCTLog.h"
@interface NetworkManager : NSObject <RCTBridgeModule>
@end
@@ -1,109 +0,0 @@
#import "NetworkManager.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
#import "Statusgo.h"
#import "Utils.h"
@implementation NetworkManager
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(startSearchForLocalPairingPeers:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoStartSearchForLocalPairingPeers();
callback(@[result]);
}
RCT_EXPORT_METHOD(getConnectionStringForBootstrappingAnotherDevice:(NSString *)configJSON
callback:(RCTResponseSenderBlock)callback) {
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSMutableDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:&error];
NSMutableDictionary *senderConfig = configDict[@"senderConfig"];
NSString *keyUID = senderConfig[@"keyUID"];
NSURL *multiaccountKeystoreDir = [Utils getKeyStoreDirForKeyUID:keyUID];
NSString *keystoreDir = multiaccountKeystoreDir.path;
[senderConfig setValue:keystoreDir forKey:@"keystorePath"];
NSString *modifiedConfigJSON = [Utils jsonStringWithPrettyPrint:NO fromDictionary:configDict];
NSString *result = StatusgoGetConnectionStringForBootstrappingAnotherDevice(modifiedConfigJSON);
callback(@[result]);
}
RCT_EXPORT_METHOD(inputConnectionStringForBootstrapping:(NSString *)cs
configJSON:(NSString *)configJSON
callback:(RCTResponseSenderBlock)callback) {
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSMutableDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:&error];
NSMutableDictionary *receiverConfig = configDict[@"receiverConfig"];
NSMutableDictionary *nodeConfig = receiverConfig[@"nodeConfig"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *multiaccountKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSString *keystoreDir = multiaccountKeystoreDir.path;
NSString *rootDataDir = rootUrl.path;
[receiverConfig setValue:keystoreDir forKey:@"keystorePath"];
[nodeConfig setValue:rootDataDir forKey:@"rootDataDir"];
NSString *modifiedConfigJSON = [Utils jsonStringWithPrettyPrint:NO fromDictionary:configDict];
NSString *result = StatusgoInputConnectionStringForBootstrapping(cs, modifiedConfigJSON);
callback(@[result]);
}
RCT_EXPORT_METHOD(sendTransactionWithSignature:(NSString *)txArgsJSON
signature:(NSString *)signature
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"sendTransactionWithSignature() method called");
#endif
NSString *result = StatusgoSendTransactionWithSignature(txArgsJSON, signature);
callback(@[result]);
}
#pragma mark - SendTransaction
RCT_EXPORT_METHOD(sendTransaction:(NSString *)txArgsJSON
password:(NSString *)password
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"SendTransaction() method called");
#endif
NSString *result = StatusgoSendTransaction(txArgsJSON, password);
callback(@[result]);
}
RCT_EXPORT_METHOD(callRPC:(NSString *)payload
callback:(RCTResponseSenderBlock)callback) {
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *result = StatusgoCallRPC(payload);
dispatch_async(dispatch_get_main_queue(), ^{
callback(@[result]);
});
});
}
RCT_EXPORT_METHOD(callPrivateRPC:(NSString *)payload
callback:(RCTResponseSenderBlock)callback) {
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *result = StatusgoCallPrivateRPC(payload);
dispatch_async(dispatch_get_main_queue(), ^{
callback(@[result]);
});
});
}
#pragma mark - Recover
RCT_EXPORT_METHOD(recover:(NSString *)message
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"Recover() method called");
#endif
NSString *result = StatusgoRecover(message);
callback(@[result]);
}
@end
File diff suppressed because it is too large Load Diff
@@ -3,20 +3,13 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
206C9F3E1D474E910063E3E6 /* RCTStatus.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 206C9F3D1D474E910063E3E6 /* RCTStatus.h */; };
206C9F401D474E910063E3E6 /* RCTStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 206C9F3F1D474E910063E3E6 /* RCTStatus.m */; };
CE4E31B11D86951A0033ED64 /* Statusgo.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE4E31B01D86951A0033ED64 /* Statusgo.xcframework */; };
E92244EB2B485F2400915F4C /* UIHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E92244E92B485F2400915F4C /* UIHelper.m */; };
E967A3AC2B47BD5A00FB19B2 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = E967A3AB2B47BD5A00FB19B2 /* Utils.m */; };
E9BEF3602B470BF1001F6755 /* NetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E9BEF35E2B470BF1001F6755 /* NetworkManager.m */; };
E9C33AA62B4828A60074B1C5 /* DatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E9C33AA52B4828A60074B1C5 /* DatabaseManager.m */; };
E9DB08932B4858B400F51053 /* LogManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E9DB08912B4858B400F51053 /* LogManager.m */; };
E9F5C3322B483B6C001A7F40 /* EncryptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F5C3312B483B6C001A7F40 /* EncryptionUtils.m */; };
E9FC4ED12B47EEFF00E834DB /* AccountManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E9FC4ECF2B47EEFF00E834DB /* AccountManager.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -38,20 +31,6 @@
206C9F3D1D474E910063E3E6 /* RCTStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTStatus.h; sourceTree = "<group>"; };
206C9F3F1D474E910063E3E6 /* RCTStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTStatus.m; sourceTree = "<group>"; };
CE4E31B01D86951A0033ED64 /* Statusgo.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Statusgo.xcframework; sourceTree = "<group>"; };
E92244E92B485F2400915F4C /* UIHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIHelper.m; sourceTree = "<group>"; };
E92244EA2B485F2400915F4C /* UIHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIHelper.h; sourceTree = "<group>"; };
E967A3AA2B47BD5A00FB19B2 /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utils.h; sourceTree = "<group>"; };
E967A3AB2B47BD5A00FB19B2 /* Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utils.m; sourceTree = "<group>"; };
E9BEF35E2B470BF1001F6755 /* NetworkManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkManager.m; sourceTree = "<group>"; };
E9BEF35F2B470BF1001F6755 /* NetworkManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkManager.h; sourceTree = "<group>"; };
E9C33AA42B4828A60074B1C5 /* DatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseManager.h; sourceTree = "<group>"; };
E9C33AA52B4828A60074B1C5 /* DatabaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DatabaseManager.m; sourceTree = "<group>"; };
E9DB08912B4858B400F51053 /* LogManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LogManager.m; sourceTree = "<group>"; };
E9DB08922B4858B400F51053 /* LogManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogManager.h; sourceTree = "<group>"; };
E9F5C3302B483B6C001A7F40 /* EncryptionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncryptionUtils.h; sourceTree = "<group>"; };
E9F5C3312B483B6C001A7F40 /* EncryptionUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncryptionUtils.m; sourceTree = "<group>"; };
E9FC4ECF2B47EEFF00E834DB /* AccountManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AccountManager.m; sourceTree = "<group>"; };
E9FC4ED02B47EEFF00E834DB /* AccountManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccountManager.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -86,20 +65,6 @@
206C9F3C1D474E910063E3E6 /* Status */ = {
isa = PBXGroup;
children = (
E92244EA2B485F2400915F4C /* UIHelper.h */,
E92244E92B485F2400915F4C /* UIHelper.m */,
E9DB08922B4858B400F51053 /* LogManager.h */,
E9DB08912B4858B400F51053 /* LogManager.m */,
E9F5C3302B483B6C001A7F40 /* EncryptionUtils.h */,
E9F5C3312B483B6C001A7F40 /* EncryptionUtils.m */,
E9C33AA42B4828A60074B1C5 /* DatabaseManager.h */,
E9C33AA52B4828A60074B1C5 /* DatabaseManager.m */,
E9FC4ED02B47EEFF00E834DB /* AccountManager.h */,
E9FC4ECF2B47EEFF00E834DB /* AccountManager.m */,
E967A3AA2B47BD5A00FB19B2 /* Utils.h */,
E967A3AB2B47BD5A00FB19B2 /* Utils.m */,
E9BEF35F2B470BF1001F6755 /* NetworkManager.h */,
E9BEF35E2B470BF1001F6755 /* NetworkManager.m */,
206C9F3D1D474E910063E3E6 /* RCTStatus.h */,
206C9F3F1D474E910063E3E6 /* RCTStatus.m */,
);
@@ -162,14 +127,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E9DB08932B4858B400F51053 /* LogManager.m in Sources */,
E9F5C3322B483B6C001A7F40 /* EncryptionUtils.m in Sources */,
E967A3AC2B47BD5A00FB19B2 /* Utils.m in Sources */,
E92244EB2B485F2400915F4C /* UIHelper.m in Sources */,
E9BEF3602B470BF1001F6755 /* NetworkManager.m in Sources */,
206C9F401D474E910063E3E6 /* RCTStatus.m in Sources */,
E9C33AA62B4828A60074B1C5 /* DatabaseManager.m in Sources */,
E9FC4ED12B47EEFF00E834DB /* AccountManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1,8 +0,0 @@
#import <sys/utsname.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "RCTLog.h"
@interface UIHelper : NSObject <RCTBridgeModule>
@end
@@ -1,39 +0,0 @@
#import "UIHelper.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
@implementation UIHelper
RCT_EXPORT_MODULE();
#pragma mark - only android methods
RCT_EXPORT_METHOD(setSoftInputMode: (NSInteger) i) {
#if DEBUG
NSLog(@"setSoftInputMode() works only on Android");
#endif
}
RCT_EXPORT_METHOD(clearCookies) {
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies]) {
[storage deleteCookie:cookie];
}
}
RCT_EXPORT_METHOD(clearStorageAPIs) {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
for (NSString *string in array) {
NSLog(@"Removing %@", [path stringByAppendingPathComponent:string]);
if ([[string pathExtension] isEqualToString:@"localstorage"])
[[NSFileManager defaultManager] removeItemAtPath:[path stringByAppendingPathComponent:string] error:nil];
}
}
@end
@@ -1,16 +0,0 @@
#import <sys/utsname.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "Statusgo.h"
#import "RCTLog.h"
@interface Utils : NSObject <RCTBridgeModule>
+ (NSString *)jsonStringWithPrettyPrint:(BOOL)prettyPrint fromDictionary:(NSDictionary *)dictionary;
+ (NSString *)jsonStringWithPrettyPrint:(BOOL)prettyPrint fromArray:(NSArray *)array;
+ (NSURL *)getKeyStoreDirForKeyUID:(NSString *)keyUID;
+ (NSString *)getExportDbFilePath;
+ (NSString *)getKeyUID:(NSString *)jsonString;
+ (void)migrateKeystore:(NSString *)accountData password:(NSString *)password;
@end
@@ -1,128 +0,0 @@
#import "Utils.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
#import "Statusgo.h"
#import "Utils.h"
@implementation Utils
RCT_EXPORT_MODULE();
+ (NSString *)jsonStringWithPrettyPrint:(BOOL)prettyPrint fromDictionary:(NSDictionary *)dictionary {
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary
options:(NSJSONWritingOptions)(prettyPrint ? NSJSONWritingPrettyPrinted : 0)
error:&error];
if (!jsonData) {
NSLog(@"jsonStringWithPrettyPrint: error: %@", error.localizedDescription);
return @"{}";
} else {
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
}
+ (NSString *)jsonStringWithPrettyPrint:(BOOL)prettyPrint fromArray:(NSArray *)array {
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array
options:(NSJSONWritingOptions)(prettyPrint ? NSJSONWritingPrettyPrinted : 0)
error:&error];
if (!jsonData) {
NSLog(@"jsonStringWithPrettyPrint: error: %@", error.localizedDescription);
return @"[]";
} else {
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
}
+ (NSURL *)getKeyStoreDirForKeyUID:(NSString *)keyUID {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl = [[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *oldKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSURL *multiaccountKeystoreDir = [oldKeystoreDir URLByAppendingPathComponent:keyUID];
return multiaccountKeystoreDir;
}
+ (NSString *) getKeyUID:(NSString *)jsonString {
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:nil];
return [json valueForKey:@"key-uid"];
}
+ (NSString *) getExportDbFilePath {
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"export.db"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:filePath]) {
[fileManager removeItemAtPath:filePath error:nil];
}
return filePath;
}
+ (void) migrateKeystore:(NSString *)accountData
password:(NSString *)password {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
NSURL *keyUID = [self getKeyStoreDirForKeyUID:accountData];
NSURL *oldKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSURL *multiaccountKeystoreDir = [self getKeyStoreDirForKeyUID:keyUID.path];
NSArray *keys = [fileManager contentsOfDirectoryAtPath:multiaccountKeystoreDir.path error:nil];
if (keys.count == 0) {
NSString *migrationResult = StatusgoMigrateKeyStoreDir(accountData, password, oldKeystoreDir.path, multiaccountKeystoreDir.path);
NSLog(@"keystore migration result %@", migrationResult);
NSString *initKeystoreResult = StatusgoInitKeystore(multiaccountKeystoreDir.path);
NSLog(@"InitKeyStore result %@", initKeystoreResult);
}
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(backupDisabledDataDir) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
return rootUrl.path;
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(keystoreDir) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
NSURL *commonKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
return commonKeystoreDir.path;
}
RCT_EXPORT_METHOD(validateMnemonic:(NSString *)seed
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"validateMnemonic() method called");
#endif
NSString *result = StatusgoValidateMnemonic(seed);
callback(@[result]);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(checkAddressChecksum:(NSString *)address) {
return StatusgoCheckAddressChecksum(address);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toChecksumAddress:(NSString *)address) {
return StatusgoToChecksumAddress(address);
}
@end
+1 -1
View File
@@ -3,6 +3,6 @@ name: default: let
logEnvOverride = value:
builtins.trace "getEnvWithDefault ${name} (default: ${toString default}): ${value}" value;
in
if envOverride != "" && envOverride != default
if envOverride != ""
then logEnvOverride envOverride
else default
-6
View File
@@ -102,12 +102,6 @@
"rn-snoopy": "git+https://github.com/status-im/rn-snoopy.git#refs/tags/v2.0.2-status",
"shadow-cljs": "2.26.2"
},
"resolutions": {
"_comment": "This prevents random metro crashes till we upgrade to react-native 0.73.x",
"metro": "^0.79.1",
"metro-config": "^0.79.1",
"metro-core": "^0.79.1"
},
"binary": {
"module_name": "status_nodejs_addon",
"module_path": "./lib/binding/",
+1 -1
View File
@@ -2,7 +2,7 @@
set -eof pipefail
FILES=$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort <(git ls-files --deleted)) | grep --ignore-case -E '\.(java|cpp|nix|json|sh|md|js|clj|cljs|cljc|edn|kt|m)$')
FILES=$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort <(git ls-files --deleted)) | grep --ignore-case -E '\.(java|cpp|nix|json|sh|md|js|clj|cljs|cljc|edn)$')
N_FILES=$(echo "$FILES" | wc -l)
LINT_SHOULD_FIX=0
@@ -36,13 +36,6 @@
:always
(update :contacts conj (:id member))))
(defn decode-chat-id
[chat-id]
(let [community-id (subs chat-id 0 constants/community-id-length)
channel-id (subs chat-id constants/community-id-length)]
{:community-id community-id
:channel-id channel-id}))
(defn- unmarshal-members
[{:keys [members chat-type] :as chat}]
(cond
@@ -41,11 +41,3 @@
:timestamp 2}]
(testing "from-rpc"
(is (= expected-chat (chats/<-rpc chat))))))
(deftest decode-chat-id-test
(let [community-id "0x0322b9b84acb1631d6a31d41d9cf8e1938d352a624bc130de92869e025c7ca79c4"
channel-id "02081bc7-20e4-4362-99e2-37669c28cc08"
chat-id (str community-id channel-id)]
(is (= {:community-id community-id
:channel-id channel-id}
(chats/decode-chat-id chat-id)))))
+24 -15
View File
@@ -51,9 +51,9 @@
(rf/defn remove-members
{:events [:group-chats.ui/remove-members-pressed]}
[{{:group-chat/keys [deselected-members]} :db :as cofx} chat-id]
[{{:keys [current-chat-id] :group-chat/keys [deselected-members]} :db :as cofx}]
{:json-rpc/call [{:method "wakuext_removeMembersFromGroupChat"
:params [nil chat-id deselected-members]
:params [nil current-chat-id deselected-members]
:js-response true
:on-success #(re-frame/dispatch [:chat-updated % true])
:on-error #()}]})
@@ -97,19 +97,19 @@
(rf/defn add-members
"Add members to a group chat"
{:events [:group-chats.ui/add-members-pressed]}
[{{:group-chat/keys [selected-participants]} :db :as cofx} chat-id]
[{{:keys [current-chat-id] :group-chat/keys [selected-participants]} :db :as cofx}]
{:json-rpc/call [{:method "wakuext_addMembersToGroupChat"
:params [nil chat-id selected-participants]
:params [nil current-chat-id selected-participants]
:js-response true
:on-success #(re-frame/dispatch [:chat-updated % true])}]})
(rf/defn add-members-from-invitation
"Add members to a group chat"
{:events [:group-chats.ui/add-members-from-invitation]}
[{:keys [db]} id participant chat-id]
[{{:keys [current-chat-id] :as db} :db :as cofx} id participant]
{:db (assoc-in db [:group-chat/invitations id :state] constants/invitation-state-approved)
:json-rpc/call [{:method "wakuext_addMembersToGroupChat"
:params [nil chat-id [participant]]
:params [nil current-chat-id [participant]]
:js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]})
@@ -150,23 +150,23 @@
(rf/defn membership-retry
{:events [:group-chats.ui/membership-retry]}
[{:keys [db]} chat-id]
{:db (assoc-in db [:chat/memberships chat-id :retry?] true)})
[{{:keys [current-chat-id] :as db} :db}]
{:db (assoc-in db [:chat/memberships current-chat-id :retry?] true)})
(rf/defn membership-message
{:events [:group-chats.ui/update-membership-message]}
[{:keys [db]} message chat-id]
{:db (assoc-in db [:chat/memberships chat-id :message] message)})
[{{:keys [current-chat-id] :as db} :db} message]
{:db (assoc-in db [:chat/memberships current-chat-id :message] message)})
(rf/defn send-group-chat-membership-request
"Send group chat membership request"
{:events [:send-group-chat-membership-request]}
[{{:keys [chats] :as db} :db :as cofx} chat-id]
(let [{:keys [invitation-admin]} (get chats chat-id)
message (get-in db [:chat/memberships chat-id :message])]
{:db (assoc-in db [:chat/memberships chat-id] nil)
[{{:keys [current-chat-id chats] :as db} :db :as cofx}]
(let [{:keys [invitation-admin]} (get chats current-chat-id)
message (get-in db [:chat/memberships current-chat-id :message])]
{:db (assoc-in db [:chat/memberships current-chat-id] nil)
:json-rpc/call [{:method "wakuext_sendGroupChatInvitationRequest"
:params [nil chat-id invitation-admin message]
:params [nil current-chat-id invitation-admin message]
:js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}))
@@ -242,6 +242,15 @@
[{db :db}]
{:db (assoc db :group-chat/deselected-members #{})})
(rf/defn show-group-chat-profile
{:events [:show-group-chat-profile]}
[{:keys [db] :as cofx} chat-id]
(rf/merge cofx
{:db (-> db
(assoc :new-chat-name (get-in db [:chats chat-id :name]))
(assoc :current-chat-id chat-id))}
(navigation/navigate-to :group-chat-profile nil)))
(rf/defn ui-leave-chat-pressed
{:events [:group-chats.ui/leave-chat-pressed]}
[{:keys [db]} chat-id]
@@ -12,7 +12,7 @@
(def message-max-length 100)
(defn request-membership
[{:keys [state introduction-message] :as invitation} chat-id]
[{:keys [state introduction-message] :as invitation}]
(let [{:keys [message retry?]} @(re-frame/subscribe [:chats/current-chat-membership])
message-length (count message)]
[react/view {:margin-horizontal 16 :margin-top 10}
@@ -47,7 +47,7 @@
[react/text (i18n/label :t/introduce-yourself)]
[quo/text-input
{:placeholder (i18n/label :t/message)
:on-change-text #(re-frame/dispatch [:group-chats.ui/update-membership-message % chat-id])
:on-change-text #(re-frame/dispatch [:group-chats.ui/update-membership-message %])
:max-length (if platform/android?
message-max-length
(when (>= message-length message-max-length)
@@ -63,4 +63,4 @@
[chat-id invitation-admin]
(letsubs [invitations [:group-chat/invitations-by-chat-id chat-id]]
(when invitation-admin
[request-membership (first invitations) chat-id])))
[request-membership (first invitations)])))
@@ -6,6 +6,7 @@
[legacy.status-im.ui.components.typography :as typography]
[legacy.status-im.utils.utils :as utils]
[re-frame.core :as re-frame]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.common.json-rpc.events :as json-rpc]
[taoensso.timbre :as log]
@@ -85,28 +86,29 @@
(defn stats-table
[{:keys [total filtered-total stats]}]
[react/scroll-view
{:style {:padding-horizontal 8}}
[react/view
[react/view
{:style {:flex-direction :row
:justify-content :space-between
:margin-bottom 2}}
[legacy.status-im.ui.components.core/text {:style typography/font-semi-bold}
(i18n/label :t/rpc-usage-total)]
[legacy.status-im.ui.components.core/text {:style typography/font-semi-bold}
(i18n/label :t/rpc-usage-filtered-total {:filtered-total filtered-total :total total})]]
[react/view
{:style {:flex-direction :column
:flex 1}}
(when (seq stats)
(for [[k v] stats]
^{:key (str k v)}
[react/view
{:style {:flex-direction :row
:align-items :stretch}}
[legacy.status-im.ui.components.core/text {:style {:flex 7}} k]
[legacy.status-im.ui.components.core/text {:style {:flex 1}} v]]))]]])
rn/scroll-view
{:style {:padding-horizontal 8}}
rn/view
{:style {:flex-direction :row
:justify-content :space-between
:margin-bottom 2}}
[legacy.status-im.ui.components.core/text {:style typography/font-semi-bold}
(i18n/label :t/rpc-usage-total)]
[legacy.status-im.ui.components.core/text {:style typography/font-semi-bold}
(i18n/label :t/rpc-usage-filtered-total {:filtered-total filtered-total :total total})]
(when (seq stats)
(for [[k v] stats]
^{:key (str k v)}
[:<>
rn/view
{:style {:flex-direction :row
:align-items :center
:margin-vertical 10}}
[legacy.status-im.ui.components.core/text {:style {:flex 1}}
k]
[legacy.status-im.ui.components.core/text {:style {:margin-left 16}}
v]
[legacy.status-im.ui.components.core/separator]])))
(defn prepare-stats
[{:keys [stats]}]
@@ -123,32 +125,30 @@
[react/view
{:flex 1
:margin-horizontal 8}
[react/view
{:style {:flex-direction :column
:justify-content :space-between}}
[react/view
{:style {:flex-direction :row
:justify-content :space-between}}
[legacy.status-im.ui.components.core/button
{:on-press #(re-frame/dispatch [::reset])
:accessibility-label :rpc-usage-reset}
(i18n/label :t/rpc-usage-reset)]
[legacy.status-im.ui.components.core/button
{:on-press
#(react/copy-to-clipboard (prepare-stats stats))
:accessibility-label :rpc-usage-copy}
(i18n/label :t/rpc-usage-copy)]]
[legacy.status-im.ui.components.core/text-input
{:on-change-text #(re-frame/dispatch [::set-filter %])
:label (i18n/label :t/rpc-usage-filter-methods)
:placeholder (i18n/label :t/rpc-usage-filter)
:container-style {:margin-vertical 18}
:before {:icon :main-icons/search
:style {:padding-horizontal 8}}
:default-value methods-filter
:auto-capitalize :none
:show-cancel false
:auto-focus false}]]
rn/view
{:style {:flex-direction :row
:margin-vertical 8
:justify-content :space-between}}
[legacy.status-im.ui.components.core/button
{:on-press #(re-frame/dispatch [::reset])
:accessibility-label :rpc-usage-reset}
(i18n/label :t/rpc-usage-reset)]
[legacy.status-im.ui.components.core/button
{:on-press
#(react/copy-to-clipboard (prepare-stats stats))
:accessibility-label :rpc-usage-copy}
(i18n/label :t/rpc-usage-copy)]
[legacy.status-im.ui.components.core/text-input
{:on-change-text #(re-frame/dispatch [::set-filter %])
:label (i18n/label :t/rpc-usage-filter-methods)
:placeholder (i18n/label :t/rpc-usage-filter)
:container-style {:margin-vertical 18}
:before {:icon :main-icons/search
:style {:padding-horizontal 8}}
:default-value methods-filter
:auto-capitalize :none
:show-cancel false
:auto-focus false}]
[stats-table stats]]))
(defn usage-info
+84 -76
View File
@@ -31,81 +31,104 @@
(.pollSignal native-status signal-received-callback)
100))))
(def ui-helper
(def status
(clj->js
{:clearCookies identity
:clearStorageAPIs identity}))
{:openAccounts
(fn [callback]
(callback (.openAccounts native-status test-dir)))
:multiAccountStoreDerived
(fn [json callback]
(callback (.multiAccountStoreDerivedAccounts native-status json)))
:getNodeConfig (fn [] (types/clj->json {:WakuV2Config ""}))
:backupDisabledDataDir (fn [] (str test-dir "/backup"))
:keystoreDir (fn [] "")
:logFileDirectory (fn [] (str test-dir "/log"))
:clearCookies identity
:clearStorageAPIs identity
:setBlankPreviewFlag identity
:callPrivateRPC
(fn [payload callback]
(callback (.callPrivateRPC native-status payload)))
:createAccountAndLogin (fn [request] (.createAccountAndLogin native-status request))
:saveAccountAndLogin
(fn [multiaccount-data password settings config accounts-data]
(.saveAccountAndLogin native-status multiaccount-data password settings config accounts-data))
:logout
(fn [] (.logout native-status))
:multiAccountGenerateAndDeriveAddresses
(fn [json callback]
(callback (.multiAccountGenerateAndDeriveAddresses native-status json)))
:multiAccountImportMnemonic
(fn [json callback]
(callback (.multiAccountImportMnemonic native-status json)))
:multiAccountLoadAccount
(fn [json callback]
(callback (.multiAccountLoadAccount native-status json)))
:multiAccountDeriveAddresses
(fn [json callback]
(callback (.multiAccountDeriveAddresses native-status json)))
(def encryption-utils
(clj->js
{:sha3
(fn [s] (.sha3 native-status s))
:setBlankPreviewFlag
identity
:encodeTransfer
(fn [to-norm amount-hex]
(.encodeTransfer native-status to-norm amount-hex))
:hexToNumber
(fn [hex] (.hexToNumber native-status hex))
:decodeParameters
(fn [decode-param-json]
(.decodeParameters native-status decode-param-json))
:numberToHex
(fn [num-str] (.numberToHex native-status num-str))
:initKeystore
(fn [key-uid callback]
(callback (.initKeystore native-status
(str test-dir "/keystore/" key-uid))))
:multiformatDeserializePublicKey
(fn [public-key deserialization-key callback]
(callback (.multiformatDeserializePublicKey
native-status
public-key
deserialization-key)))}))
deserialization-key)))
(def account-manager
(clj->js
{:openAccounts
(fn [callback]
(callback (.openAccounts native-status test-dir)))
:createAccountAndLogin
(fn [request] (.createAccountAndLogin native-status request))
:logout
(fn [] (.logout native-status))
:multiAccountImportMnemonic
(fn [json callback]
(callback (.multiAccountImportMnemonic native-status json)))
:multiAccountLoadAccount
(fn [json callback]
(callback (.multiAccountLoadAccount native-status json)))
:multiAccountDeriveAddresses
(fn [json callback]
(callback (.multiAccountDeriveAddresses native-status json)))
:multiAccountGenerateAndDeriveAddresses
(fn [json callback]
(callback (.multiAccountGenerateAndDeriveAddresses native-status json)))
:multiAccountStoreDerived
(fn [json callback]
(callback (.multiAccountStoreDerivedAccounts native-status json)))}))
:initKeystore
(fn [key-uid callback]
(callback (.initKeystore native-status
(str test-dir "/keystore/" key-uid))))
:encodeTransfer
(fn [to-norm amount-hex]
(.encodeTransfer native-status to-norm amount-hex))
:encodeFunctionCall
(fn [method params-json]
(.encodeFunctionCall native-status method params-json))
:decodeParameters
(fn [decode-param-json]
(.decodeParameters native-status decode-param-json))
:hexToNumber
(fn [hex] (.hexToNumber native-status hex))
:numberToHex
(fn [num-str] (.numberToHex native-status num-str))
(def utils
(clj->js
{:backupDisabledDataDir
(fn [] (str test-dir "/backup"))
:keystoreDir (fn [] "")
:toChecksumAddress
(fn [address] (.toChecksumAddress native-status address))
:checkAddressChecksum
(fn [address] (.checkAddressChecksum native-status address))
:sha3
(fn [s] (.sha3 native-status s))
:toChecksumAddress
(fn [address] (.toChecksumAddress native-status address))
:isAddress
(fn [address] (.isAddress native-status address))
:fleets
(fn [] (.fleets native-status))
:validateMnemonic
(fn [json callback] (callback (.validateMnemonic native-status json)))
:isAddress
(fn [address] (.isAddress native-status address))}))
(def log-manager
(clj->js
{:logFileDirectory
(fn [] (str test-dir "/log"))
:startLocalNotifications identity
:initLogging
(fn [enabled mobile-system log-level callback]
(callback (.initLogging native-status
@@ -113,18 +136,3 @@
:MobileSystem mobile-system
:Level log-level
:File (str test-dir "/geth.log")}))))}))
(def network
(clj->js
{:callPrivateRPC
(fn [payload callback]
(callback (.callPrivateRPC native-status payload)))}))
(def status
(clj->js
{:getNodeConfig
(fn [] (types/clj->json {:WakuV2Config ""}))
:fleets
(fn [] (.fleets native-status))
:startLocalNotifications
identity}))
-6
View File
@@ -38,12 +38,6 @@
{:NativeModules {:RNGestureHandlerModule {:Direction (fn [])}
:PushNotifications {}
:Status utils.test/status
:EncryptionUtils utils.test/encryption-utils
:AccountManager utils.test/account-manager
:Utils utils.test/utils
:LogManager utils.test/log-manager
:NetworkManager utils.test/network
:UIHelper utils.test/ui-helper
:ReanimatedModule {:configureProps (fn [])}}
:View {}
+66 -105
View File
@@ -11,41 +11,6 @@
(when (exists? (.-NativeModules react-native))
(.-Status ^js (.-NativeModules react-native))))
(defn account-manager
[]
(when (exists? (.-NativeModules react-native))
(.-AccountManager ^js (.-NativeModules react-native))))
(defn encryption
[]
(when (exists? (.-NativeModules react-native))
(.-EncryptionUtils ^js (.-NativeModules react-native))))
(defn database
[]
(when (exists? (.-NativeModules react-native))
(.-DatabaseManager ^js (.-NativeModules react-native))))
(defn ui-helper
[]
(when (exists? (.-NativeModules react-native))
(.-UIHelper ^js (.-NativeModules react-native))))
(defn log-manager
[]
(when (exists? (.-NativeModules react-native))
(.-LogManager ^js (.-NativeModules react-native))))
(defn utils
[]
(when (exists? (.-NativeModules react-native))
(.-Utils ^js (.-NativeModules react-native))))
(defn network
[]
(when (exists? (.-NativeModules react-native))
(.-NetworkManager ^js (.-NativeModules react-native))))
(defn init
[handler]
(.addListener ^js (.-DeviceEventEmitter ^js react-native) "gethEvent" #(handler (.-jsonEvent ^js %))))
@@ -53,24 +18,24 @@
(defn clear-web-data
[]
(log/debug "[native-module] clear-web-data")
(when (ui-helper)
(.clearCookies ^js (ui-helper))
(.clearStorageAPIs ^js (ui-helper))))
(when (status)
(.clearCookies ^js (status))
(.clearStorageAPIs ^js (status))))
(defn init-keystore
[key-uid callback]
(log/debug "[native-module] init-keystore" key-uid)
(.initKeystore ^js (encryption) key-uid callback))
(.initKeystore ^js (status) key-uid callback))
(defn open-accounts
[callback]
(log/debug "[native-module] open-accounts")
(.openAccounts ^js (account-manager) #(callback (types/json->clj %))))
(.openAccounts ^js (status) #(callback (types/json->clj %))))
(defn prepare-dir-and-update-config
[key-uid config callback]
(log/debug "[native-module] prepare-dir-and-update-config")
(.prepareDirAndUpdateConfig ^js (account-manager)
(.prepareDirAndUpdateConfig ^js (status)
key-uid
config
#(callback (types/json->clj %))))
@@ -82,7 +47,7 @@
(init-keystore
key-uid
#(.saveAccountAndLoginWithKeycard
^js (account-manager)
^js (status)
multiaccount-data
password
settings
@@ -98,24 +63,24 @@
(let [config (if config (types/clj->json config) "")]
(init-keystore
key-uid
#(.loginWithConfig ^js (account-manager) account-data hashed-password config))))
#(.loginWithConfig ^js (status) account-data hashed-password config))))
(defn login-account
"NOTE: beware, the password has to be sha3 hashed"
[{:keys [keyUid] :as request}]
(log/debug "[native-module] loginAccount")
(log/debug "[native-module] loginWithConfig")
(clear-web-data)
(init-keystore
keyUid
#(.loginAccount ^js (account-manager) (types/clj->json request))))
#(.loginAccount ^js (status) (types/clj->json request))))
(defn create-account-and-login
[request]
(.createAccountAndLogin ^js (account-manager) (types/clj->json request)))
(.createAccountAndLogin ^js (status) (types/clj->json request)))
(defn restore-account-and-login
[request]
(.restoreAccountAndLogin ^js (account-manager) (types/clj->json request)))
(.restoreAccountAndLogin ^js (status) (types/clj->json request)))
(defn export-db
"NOTE: beware, the password has to be sha3 hashed"
@@ -124,7 +89,7 @@
(clear-web-data)
(init-keystore
key-uid
#(.exportUnencryptedDatabase ^js (database) account-data hashed-password callback)))
#(.exportUnencryptedDatabase ^js (status) account-data hashed-password callback)))
(defn import-db
"NOTE: beware, the password has to be sha3 hashed"
@@ -133,13 +98,13 @@
(clear-web-data)
(init-keystore
key-uid
#(.importUnencryptedDatabase ^js (database) account-data hashed-password)))
#(.importUnencryptedDatabase ^js (status) account-data hashed-password)))
(defn logout
[]
(log/debug "[native-module] logout")
(clear-web-data)
(.logout ^js (account-manager)))
(.logout ^js (status)))
(defn multiaccount-load-account
"NOTE: beware, the password has to be sha3 hashed
@@ -149,7 +114,7 @@
from memory"
[address hashed-password callback]
(log/debug "[native-module] multiaccount-load-account")
(.multiAccountLoadAccount ^js (account-manager)
(.multiAccountLoadAccount ^js (status)
(types/clj->json {:address address
:password hashed-password})
callback))
@@ -162,7 +127,7 @@
[account-id paths callback]
(log/debug "[native-module] multiaccount-derive-addresses")
(when (status)
(.multiAccountDeriveAddresses ^js (account-manager)
(.multiAccountDeriveAddresses ^js (status)
(types/clj->json {:accountID account-id
:paths paths})
callback)))
@@ -180,7 +145,7 @@
(when (status)
(init-keystore
key-uid
#(.multiAccountStoreAccount ^js (account-manager)
#(.multiAccountStoreAccount ^js (status)
(types/clj->json {:accountID account-id
:password hashed-password})
callback))))
@@ -193,7 +158,7 @@
account-id)
(init-keystore
key-uid
#(.multiAccountStoreDerived ^js (account-manager)
#(.multiAccountStoreDerived ^js (status)
(types/clj->json {:accountID account-id
:paths paths
:password hashed-password})
@@ -206,7 +171,7 @@
to store the key"
[n mnemonic-length paths callback]
(log/debug "[native-module] multiaccount-generate-and-derive-addresses")
(.multiAccountGenerateAndDeriveAddresses ^js (account-manager)
(.multiAccountGenerateAndDeriveAddresses ^js (status)
(types/clj->json {:n n
:mnemonicPhraseLength mnemonic-length
:bip39Passphrase ""
@@ -216,7 +181,7 @@
(defn multiaccount-import-mnemonic
[mnemonic password callback]
(log/debug "[native-module] multiaccount-import-mnemonic")
(.multiAccountImportMnemonic ^js (account-manager)
(.multiAccountImportMnemonic ^js (status)
(types/clj->json {:mnemonicPhrase mnemonic
;;NOTE this is not the multiaccount password
:Bip39Passphrase password})
@@ -225,7 +190,7 @@
(defn multiaccount-import-private-key
[private-key callback]
(log/debug "[native-module] multiaccount-import-private-key")
(.multiAccountImportPrivateKey ^js (account-manager)
(.multiAccountImportPrivateKey ^js (status)
(types/clj->json {:privateKey private-key})
callback))
@@ -233,13 +198,13 @@
"NOTE: beware, the password has to be sha3 hashed"
[address hashed-password callback]
(log/debug "[native-module] verify")
(.verify ^js (account-manager) address hashed-password callback))
(.verify ^js (status) address hashed-password callback))
(defn verify-database-password
"NOTE: beware, the password has to be sha3 hashed"
[key-uid hashed-password callback]
(log/debug "[native-module] verify-database-password")
(.verifyDatabasePassword ^js (account-manager) key-uid hashed-password callback))
(.verifyDatabasePassword ^js (status) key-uid hashed-password callback))
(defn login-with-keycard
[{:keys [key-uid multiaccount-data password chat-key node-config]}]
@@ -247,51 +212,47 @@
(clear-web-data)
(init-keystore
key-uid
#(.loginWithKeycard ^js (account-manager)
multiaccount-data
password
chat-key
(types/clj->json node-config))))
#(.loginWithKeycard ^js (status) multiaccount-data password chat-key (types/clj->json node-config))))
(defn set-soft-input-mode
[mode]
(log/debug "[native-module] set-soft-input-mode")
(.setSoftInputMode ^js (ui-helper) mode))
(.setSoftInputMode ^js (status) mode))
(defn call-rpc
[payload callback]
(log/debug "[native-module] call-rpc")
(.callRPC ^js (network) payload callback))
(.callRPC ^js (status) payload callback))
(defn call-private-rpc
[payload callback]
(.callPrivateRPC ^js (network) payload callback))
(.callPrivateRPC ^js (status) payload callback))
(defn hash-transaction
"used for keycard"
[rpcParams callback]
(log/debug "[native-module] hash-transaction")
(.hashTransaction ^js (encryption) rpcParams callback))
(.hashTransaction ^js (status) rpcParams callback))
(defn hash-message
"used for keycard"
[message callback]
(log/debug "[native-module] hash-message")
(.hashMessage ^js (encryption) message callback))
(.hashMessage ^js (status) message callback))
(defn start-searching-for-local-pairing-peers
"starts a UDP multicast beacon that both listens for and broadcasts to LAN peers"
[callback]
(log/info "[native-module] Start Searching for Local Pairing Peers"
{:fn :start-searching-for-local-pairing-peers})
(.startSearchForLocalPairingPeers ^js (network) callback))
(.startSearchForLocalPairingPeers ^js (status) callback))
(defn local-pairing-preflight-outbound-check
"Checks whether the device has allows connecting to the local server"
[callback]
(log/info "[native-module] Performing local pairing preflight check")
(when platform/ios?
(.localPairingPreflightOutboundCheck ^js (encryption) callback)))
(.localPairingPreflightOutboundCheck ^js (status) callback)))
(defn get-connection-string-for-bootstrapping-another-device
"Generates connection string form status-go for the purpose of local pairing on the sender end"
@@ -299,7 +260,7 @@
(log/info "[native-module] Fetching Connection String"
{:fn :get-connection-string-for-bootstrapping-another-device
:config-json config-json})
(.getConnectionStringForBootstrappingAnotherDevice ^js (network) config-json callback))
(.getConnectionStringForBootstrappingAnotherDevice ^js (status) config-json callback))
(defn input-connection-string-for-bootstrapping
"Provides connection string to status-go for the purpose of local pairing on the receiver end"
@@ -308,7 +269,7 @@
{:fn :input-connection-string-for-bootstrapping
:config-json config-json
:connection-string connection-string})
(.inputConnectionStringForBootstrapping ^js (network) connection-string config-json callback))
(.inputConnectionStringForBootstrapping ^js (status) connection-string config-json callback))
(defn deserialize-and-compress-key
"Provides a community id (public key) to status-go which is first deserialized
@@ -319,7 +280,7 @@
(log/info "[native-module] Deserializing and then compressing public key"
{:fn :deserialize-and-compress-key
:key input-key})
(.deserializeAndCompressKey ^js (encryption) input-key callback))
(.deserializeAndCompressKey ^js (status) input-key callback))
(defn compressed-key->public-key
"Provides compressed key to status-go and gets back the uncompressed public key via deserialization"
@@ -327,59 +288,59 @@
(log/info "[native-module] Deserializing compressed key"
{:fn :compressed-key->public-key
:public-key public-key})
(.multiformatDeserializePublicKey ^js (encryption) public-key deserialization-key callback))
(.multiformatDeserializePublicKey ^js (status) public-key deserialization-key callback))
(defn hash-typed-data
"used for keycard"
[data callback]
(log/debug "[native-module] hash-typed-data")
(.hashTypedData ^js (encryption) data callback))
(.hashTypedData ^js (status) data callback))
(defn hash-typed-data-v4
"used for keycard"
[data callback]
(log/debug "[native-module] hash-typed-data-v4")
(.hashTypedDataV4 ^js (encryption) data callback))
(.hashTypedDataV4 ^js (status) data callback))
(defn send-transaction-with-signature
"used for keycard"
[rpcParams sig callback]
(log/debug "[native-module] send-transaction-with-signature")
(.sendTransactionWithSignature ^js (network) rpcParams sig callback))
(.sendTransactionWithSignature ^js (status) rpcParams sig callback))
(defn sign-message
"NOTE: beware, the password in rpcParams has to be sha3 hashed"
[rpcParams callback]
(log/debug "[native-module] sign-message")
(.signMessage ^js (encryption) rpcParams callback))
(.signMessage ^js (status) rpcParams callback))
(defn recover-message
[rpcParams callback]
(log/debug "[native-module] recover")
(.recover ^js (network) rpcParams callback))
(.recover ^js (status) rpcParams callback))
(defn send-transaction
"NOTE: beware, the password has to be sha3 hashed"
[rpcParams hashed-password callback]
(log/debug "[native-module] send-transaction")
(.sendTransaction ^js (network) rpcParams hashed-password callback))
(.sendTransaction ^js (status) rpcParams hashed-password callback))
(defn sign-typed-data
"NOTE: beware, the password has to be sha3 hashed"
[data account hashed-password callback]
(log/debug "[native-module] sign-typed-data")
(.signTypedData ^js (encryption) data account hashed-password callback))
(.signTypedData ^js (status) data account hashed-password callback))
(defn sign-typed-data-v4
"NOTE: beware, the password has to be sha3 hashed"
[data account hashed-password callback]
(log/debug "[native-module] sign-typed-data-v4")
(.signTypedDataV4 ^js (encryption) data account hashed-password callback))
(.signTypedDataV4 ^js (status) data account hashed-password callback))
(defn send-logs
[dbJson js-logs callback]
(log/debug "[native-module] send-logs")
(.sendLogs ^js (log-manager) dbJson js-logs callback))
(.sendLogs ^js (status) dbJson js-logs callback))
(defn close-application
[]
@@ -404,7 +365,7 @@
(defn set-blank-preview-flag
[flag]
(log/debug "[native-module] set-blank-preview-flag")
(.setBlankPreviewFlag ^js (encryption) flag))
(.setBlankPreviewFlag ^js (status) flag))
(defn get-device-model-info
[]
@@ -432,7 +393,7 @@
(defn toggle-webview-debug
[on]
(log/debug "[native-module] toggle-webview-debug" on)
(.toggleWebviewDebug ^js (ui-helper) on))
(.toggleWebviewDebug ^js (status) on))
(defn rooted-device?
[callback]
@@ -455,72 +416,72 @@
(defn encode-transfer
[to-norm amount-hex]
(log/debug "[native-module] encode-transfer")
(.encodeTransfer ^js (encryption) to-norm amount-hex))
(.encodeTransfer ^js (status) to-norm amount-hex))
(defn decode-parameters
[bytes-string types]
(log/debug "[native-module] decode-parameters")
(let [json-str (.decodeParameters ^js (encryption)
(let [json-str (.decodeParameters ^js (status)
(types/clj->json {:bytesString bytes-string :types types}))]
(types/json->clj json-str)))
(defn hex-to-number
[hex]
(log/debug "[native-module] hex-to-number")
(let [json-str (.hexToNumber ^js (encryption) hex)]
(let [json-str (.hexToNumber ^js (status) hex)]
(types/json->clj json-str)))
(defn number-to-hex
[num]
(log/debug "[native-module] number-to-hex")
(.numberToHex ^js (encryption) (str num)))
(.numberToHex ^js (status) (str num)))
(defn sha3
[s]
(log/debug "[native-module] sha3")
(when s
(.sha3 ^js (encryption) (str s))))
(.sha3 ^js (status) (str s))))
(defn utf8-to-hex
[s]
(log/debug "[native-module] utf8-to-hex")
(.utf8ToHex ^js (encryption) s))
(.utf8ToHex ^js (status) s))
(defn hex-to-utf8
[s]
(log/debug "[native-module] hex-to-utf8")
(.hexToUtf8 ^js (encryption) s))
(.hexToUtf8 ^js (status) s))
(defn check-address-checksum
[address]
(log/debug "[native-module] check-address-checksum")
(let [result (.checkAddressChecksum ^js (utils) address)]
(let [result (.checkAddressChecksum ^js (status) address)]
(types/json->clj result)))
(defn address?
[address]
(log/debug "[native-module] address?")
(when address
(let [result (.isAddress ^js (utils) address)]
(let [result (.isAddress ^js (status) address)]
(types/json->clj result))))
(defn to-checksum-address
[address]
(log/debug "[native-module] to-checksum-address")
(.toChecksumAddress ^js (utils) address))
(.toChecksumAddress ^js (status) address))
(defn validate-mnemonic
"Validate that a mnemonic conforms to BIP39 dictionary/checksum standards"
[mnemonic callback]
(log/debug "[native-module] validate-mnemonic")
(.validateMnemonic ^js (utils) mnemonic callback))
(.validateMnemonic ^js (status) mnemonic callback))
(defn delete-multiaccount
"Delete multiaccount from database, deletes multiaccount's database and
key files."
[key-uid callback]
(log/debug "[native-module] delete-multiaccount")
(.deleteMultiaccount ^js (account-manager) key-uid callback))
(.deleteMultiaccount ^js (status) key-uid callback))
(defn delete-imported-key
"Delete imported key file."
@@ -532,7 +493,7 @@
[input selection]
(log/debug "[native-module] resetKeyboardInput")
(when platform/android?
(.resetKeyboardInputCursor ^js (ui-helper) input selection)))
(.resetKeyboardInputCursor ^js (status) input selection)))
;; passwords are hashed
(defn reset-password
@@ -540,12 +501,12 @@
(log/debug "[native-module] change-database-password")
(init-keystore
key-uid
#(.reEncryptDbAndKeystore ^js (encryption) key-uid current-password# new-password# callback)))
#(.reEncryptDbAndKeystore ^js (status) key-uid current-password# new-password# callback)))
(defn convert-to-keycard-account
[{:keys [key-uid] :as multiaccount-data} settings current-password# new-password callback]
(log/debug "[native-module] convert-to-keycard-account")
(.convertToKeycardAccount ^js (encryption)
(.convertToKeycardAccount ^js (status)
key-uid
(types/clj->json multiaccount-data)
(types/clj->json settings)
@@ -556,7 +517,7 @@
(defn backup-disabled-data-dir
[]
(.backupDisabledDataDir ^js (utils)))
(.backupDisabledDataDir ^js (status)))
(defn fleets
[]
@@ -564,12 +525,12 @@
(defn keystore-dir
[]
(.keystoreDir ^js (utils)))
(.keystoreDir ^js (status)))
(defn log-file-directory
[]
(.logFileDirectory ^js (log-manager)))
(.logFileDirectory ^js (status)))
(defn init-status-go-logging
[{:keys [enable? mobile-system? log-level callback]}]
(.initLogging ^js (log-manager) enable? mobile-system? log-level callback))
(.initLogging ^js (status) enable? mobile-system? log-level callback))
@@ -21,12 +21,7 @@
(def collectible-image
{:width 24
:height 24
:border-radius 8})
(def network
{:width 24
:height 24
:border-radius 12})
:border-radius 10})
(def token-image
{:border-radius 12})
@@ -22,7 +22,7 @@
:network
[rn/image
{:source image-source
:style style/network}]
:style style/token-image}]
:saved-address
[wallet-user-avatar/wallet-user-avatar
{:full-name label
@@ -24,7 +24,7 @@
:margin-right (if platform/ios? 6 4)
:color (colors/theme-colors colors/neutral-100 colors/white theme)
:padding 0
:flex 1
:text-align :center
:height "100%"}))
(defn divider
+1 -1
View File
@@ -349,7 +349,7 @@
[chat-id]
(entry {:icon :i/members
:label (i18n/label :t/group-details)
:on-press #(hide-sheet-and-dispatch [:navigate-to :group-chat-profile chat-id])
:on-press #(hide-sheet-and-dispatch [:show-group-chat-profile chat-id])
:danger? false
:accessibility-label :group-details
:sub-label nil
+7 -8
View File
@@ -58,16 +58,15 @@
(def picture-border-width 4)
(defn display-picture-container
[animation theme]
[animation]
(reanimated/apply-animations-to-style
{:transform [{:scale animation}]}
{:border-radius picture-diameter
:border-width picture-border-width
:border-color (colors/theme-colors colors/white colors/neutral-95 theme)
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
:position :absolute
:top (- (+ picture-radius picture-border-width))
:left (+ (/ picture-radius 2) picture-border-width)}))
{:border-radius picture-diameter
:border-width picture-border-width
:border-color (colors/theme-colors colors/white colors/neutral-95)
:position :absolute
:top (- (+ picture-radius picture-border-width))
:left (+ (/ picture-radius 2) picture-border-width)}))
(defn display-picture
[theme]
+1 -1
View File
@@ -89,7 +89,7 @@
js/undefined)
[scroll-height])
[reanimated/view
{:style (style/display-picture-container animation theme)}
{:style (style/display-picture-container animation)}
[rn/image
{:source cover
:style (style/display-picture theme)}]]))
+8 -3
View File
@@ -117,7 +117,7 @@
(def ^:const profile-pictures-visibility-everyone 2)
(def ^:const profile-pictures-visibility-none 3)
(def ^:const min-password-length 6)
(def ^:const min-password-length 10)
(def ^:const max-group-chat-participants 20)
(def ^:const default-number-of-messages 20)
(def ^:const default-number-of-pin-messages 3)
@@ -166,8 +166,6 @@
(def ^:const community-request-to-join-state-accepted 3)
(def ^:const community-request-to-join-state-cancelled 4)
(def ^:const community-id-length 68)
; BIP44 Wallet Root Key, the extended key from which any wallet can be derived
(def ^:const path-wallet-root "m/44'/60'/0'/0")
; EIP1581 Root Key, the extended key from which any whisper key/encryption key can be derived
@@ -337,6 +335,13 @@
(def ^:const local-pairing-action-sync-device 3)
(def ^:const local-pairing-action-pairing-installation 4)
(def ^:const serialization-key
"We pass this serialization key as a parameter to MultiformatSerializePublicKey
function at status-go, This key determines the output base of the serialization.
according to https://specs.status.im/spec/2#public-key-serialization we serialize
keys with base58btc encoding"
"z")
(def ^:const deserialization-key
"We pass this deserialization key as a parameter to MultiformatDeserializePublicKey
function at status-go, This key determines the output base of the deserialization.
@@ -20,20 +20,31 @@
:icon-only? true
:container-style {:margin-left 20}
:accessibility-label :back-button
:on-press #(rf/dispatch [:navigate-back])}
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:chat/close]))}
:i/arrow-left])
(defn options-button
[group]
[quo/button
{:type :grey
:size 32
:icon-only? true
:container-style {:margin-right 20}
:accessibility-label :options-button
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [actions/group-details-actions group])}])}
:i/options])
[]
(let [group (rf/sub [:chats/current-chat])]
[quo/button
{:type :grey
:size 32
:icon-only? true
:container-style {:margin-right 20}
:accessibility-label :options-button
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [actions/group-details-actions group])}])}
:i/options]))
(defn top-buttons
[]
[rn/view
{:style {:flex-direction :row
:padding-horizontal 20
:justify-content :space-between}}
[back-button] [options-button]])
(defn count-container
[amount accessibility-label]
@@ -89,8 +100,7 @@
[]
(let [selected-participants (rf/sub [:group-chat/selected-participants])
deselected-members (rf/sub [:group-chat/deselected-members])
chat-id (rf/sub [:get-screen-params :group-chat-profile])
{:keys [admins] :as group} (rf/sub [:chats/chat-by-id chat-id])
{:keys [admins] :as group} (rf/sub [:chats/current-chat])
admin? (get admins (rf/sub [:multiaccount/public-key]))]
[rn/view {:flex 1 :margin-top 20}
[rn/touchable-opacity
@@ -120,9 +130,9 @@
(rf/dispatch [:navigate-back])
(js/setTimeout (fn []
(rf/dispatch
[:group-chats.ui/remove-members-pressed chat-id]))
[:group-chats.ui/remove-members-pressed]))
500)
(rf/dispatch [:group-chats.ui/add-members-pressed chat-id]))
(rf/dispatch [:group-chats.ui/add-members-pressed]))
:disabled? (and (zero? (count selected-participants))
(zero? (count deselected-members)))}
(i18n/label :t/save)]]]))
@@ -141,79 +151,84 @@
:on-press show-profile-actions}})
item]))
(defn f-group-details
[]
(fn []
(rn/use-effect (fn []
#(rf/dispatch [:chat/close])))
(let [{:keys [admins chat-id chat-name color public?
muted contacts]} (rf/sub [:chats/current-chat])
members (rf/sub [:contacts/group-members-sections])
pinned-messages (rf/sub [:chats/pinned chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view
{:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo/header
{:left-component [back-button]
:right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}]
[rn/view
{:style {:flex-direction :row
:margin-top 24
:padding-horizontal 20}}
[quo/group-avatar
{:customization-color color
:size :size-32}]
[quo/text
{:weight :semi-bold
:size :heading-1
:style {:margin-horizontal 8}} chat-name]
[rn/view {:style {:margin-top 8}}
[quo/icon (if public? :i/world :i/privacy)
{:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :pinned-messages
:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id]))}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[quo/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages) :pinned-count]]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label :t/pinned-messages)]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :toggle-mute
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)
(when-not muted constants/mute-till-unmuted)])}
[quo/icon (if muted :i/muted :i/activity-center)
{:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if muted :unmute-group :mute-group))]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :manage-members
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch [:open-modal :group-add-manage-members]))}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[quo/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count contacts) :members-count]]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections members
:render-section-header-fn contacts-section-header
:render-data {:chat-id chat-id
:admin? admin?}
:render-fn contact-item-render}]])))
(defn group-details
[]
(let [chat-id (rf/sub [:get-screen-params :group-chat-profile])
{:keys [admins chat-id chat-name color public?
muted contacts]
:as group} (rf/sub [:chats/chat-by-id chat-id])
members (rf/sub [:contacts/group-members-sections chat-id])
pinned-messages (rf/sub [:chats/pinned chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view
{:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo/header
{:left-component [back-button]
:right-component [options-button group]
:background (colors/theme-colors colors/white colors/neutral-95)}]
[rn/view
{:style {:flex-direction :row
:margin-top 24
:padding-horizontal 20}}
[quo/group-avatar
{:customization-color color
:size :size-32}]
[quo/text
{:weight :semi-bold
:size :heading-1
:style {:margin-horizontal 8}} chat-name]
[rn/view {:style {:margin-top 8}}
[quo/icon (if public? :i/world :i/privacy)
{:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :pinned-messages
:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id]))}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[quo/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages) :pinned-count]]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label :t/pinned-messages)]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :toggle-mute
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)
(when-not muted constants/mute-till-unmuted)])}
[quo/icon (if muted :i/muted :i/activity-center)
{:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if muted :unmute-group :mute-group))]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :manage-members
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch [:open-modal :group-add-manage-members chat-id]))}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[quo/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count contacts) :members-count]]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections members
:render-section-header-fn contacts-section-header
:render-data {:chat-id chat-id
:admin? admin?}
:render-fn contact-item-render}]]))
[:f> f-group-details])
+1 -1
View File
@@ -48,7 +48,7 @@
(defn chats
[{:keys [theme selected-tab set-scroll-ref scroll-shared-value]}]
(let [unfiltered-items (rf/sub [:chats/chats-stack-items])
(let [unfiltered-items (rf/sub [:chats-stack-items])
items (filter-and-sort-items-by-tab selected-tab unfiltered-items)]
(if (empty? items)
[common.empty-state/view
@@ -46,7 +46,7 @@
[chat-id]
(let [pinned (rf/sub [:chats/pinned-sorted-list chat-id])
render-data (rf/sub [:chats/current-chat-message-list-view-context :in-pinned-view])
current-chat (rf/sub [:chats/chat-by-id chat-id])
current-chat (rf/sub [:chat-by-id chat-id])
{:keys [community-id]} current-chat
community (rf/sub [:communities/community community-id])
community-images (rf/sub [:community/images community-id])]
@@ -137,7 +137,7 @@
[chat-id cover-bg-color]
(let [latest-pin-text (rf/sub [:chats/last-pinned-message-text chat-id])
pins-count (rf/sub [:chats/pin-messages-count chat-id])
{:keys [muted muted-till chat-type]} (rf/sub [:chats/chat-by-id chat-id])
{:keys [muted muted-till chat-type]} (rf/sub [:chat-by-id chat-id])
community-channel? (= constants/community-chat-type chat-type)
muted? (and muted (some? muted-till))
mute-chat-label (if community-channel? :t/mute-channel :t/mute-chat)
@@ -101,22 +101,22 @@
:label (i18n/label :t/show-qr)})
(defn- action-share
[chat-id]
[]
{:icon :i/share
:accessibility-label :chat-share
:on-press #(rf/dispatch [:communities/share-community-channel-url-with-data chat-id])
:on-press not-implemented/alert
:label (i18n/label :t/share-channel)})
(defn actions
[{:keys [locked? chat-id]} inside-chat?]
(let [{:keys [muted muted-till chat-type]} (rf/sub [:chats/chat-by-id chat-id])]
(let [{:keys [muted muted-till chat-type]} (rf/sub [:chat-by-id chat-id])]
(cond
locked?
[quo/action-drawer
[[(action-invite-people)
(action-token-requirements)
(action-qr-code)
(action-share chat-id)]]]
(action-share)]]]
(and (not inside-chat?) (not locked?))
[quo/action-drawer
@@ -127,7 +127,7 @@
(action-pinned-messages)
(action-invite-people)
(action-qr-code)
(action-share chat-id)]]]
(action-share)]]]
(and inside-chat? (not locked?))
[quo/action-drawer
@@ -140,6 +140,6 @@
(chat-actions/fetch-messages chat-id))
(action-invite-people)
(action-qr-code)
(action-share chat-id)]]]
(action-share)]]]
:else nil)))
@@ -1,9 +1,6 @@
(ns status-im.contexts.communities.events
(:require [clojure.set :as set]
[clojure.walk :as walk]
[legacy.status-im.data-store.chats :as data-store.chats]
[react-native.platform :as platform]
[react-native.share :as share]
[status-im.constants :as constants]
status-im.contexts.communities.actions.community-options.events
status-im.contexts.communities.actions.leave.events
@@ -222,29 +219,3 @@
{:db (assoc db
:communities/selected-permission-addresses
(get-in db [:communities/previous-permission-addresses]))}))
(rf/reg-event-fx :communities/share-community-channel-url-with-data
(fn [_ [chat-id]]
(let [{:keys [community-id channel-id]} (data-store.chats/decode-chat-id chat-id)
title (i18n/label :t/channel-on-status)]
{:json-rpc/call
[{:method "wakuext_shareCommunityChannelURLWithData"
:params [{:CommunityID community-id :ChannelID channel-id}]
:on-success (fn [url]
(share/open
(if platform/ios?
{:activityItemSources [{:placeholderItem {:type "text"
:content title}
:item {:default {:type "url"
:content url}}
:linkMetadata {:title title}}]}
{:title title
:subject title
:message url
:url url
:isNewTask true})))
:on-error (fn [err]
(log/error "failed to retrieve community channel url with data"
{:error err
:chat-id chat-id
:event "share-community-channel-url-with-data"}))}]})))
@@ -27,11 +27,11 @@
(defn background-image
[content-width]
[rn/image
{:resize-mode :stretch
:resize-method :scale
:style {:margin-top 32
:width content-width}
:source (resources/get-image :onboarding-illustration)}])
{:style {:resize-mode :stretch
:resize-method :scale
:margin-top 32
:width content-width}
:source (resources/get-image :onboarding-illustration)}])
(defonce progress (atom nil))
(defonce paused? (atom nil))
@@ -12,8 +12,12 @@
:flex-wrap :wrap})
(def plain-text
{:color colors/white-opa-70})
{:size :paragraph-2
:weight :regular
:color colors/white-opa-70})
(def highlighted-text
{:flex 1
:color colors/white})
{:flex 1
:size :paragraph-2
:weight :regular
:color colors/white})
@@ -34,20 +34,17 @@
:heading (i18n/label :t/new-to-status)
:accessibility-label :new-to-status-button}}
[quo/text
{:size :paragraph-2
:weight :regular
:style style/plain-text}
{:style style/plain-text}
(i18n/label :t/you-already-use-status)]
[quo/text {:style style/text-container}
[quo/text
{:style style/text-container}
[quo/text
{:size :paragraph-2
:weight :regular
:style style/plain-text}
{:style style/plain-text}
(i18n/label :t/by-continuing-you-accept)]
[quo/text
{:on-press #(debounce/dispatch-and-chill [:open-modal :privacy-policy] 1000)
:size :paragraph-2
:weight :regular
{:on-press #(debounce/dispatch-and-chill
[:open-modal :privacy-policy]
1000)
:style style/highlighted-text}
(i18n/label :t/terms-of-service)]]]
[overlay/view]])
@@ -55,7 +55,9 @@
(defn view
[]
(let [state (reagent/atom (assoc (data :token) :type :token))]
(let [state (reagent/atom
(merge {:type :token}
(data :token)))]
(fn []
[preview/preview-container
{:state state
@@ -1,75 +0,0 @@
(ns status-im.contexts.shell.share.profile.view
(:require
[clojure.string :as string]
[legacy.status-im.ui.components.list-selection :as list-selection]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[status-im.common.qr-codes.view :as qr-codes]
[status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.shell.share.style :as style]
[utils.address :as address]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn profile-tab
[]
(let [{:keys [emoji-hash
customization-color
universal-profile-url]
:as profile} (rf/sub [:profile/profile])
abbreviated-url (address/get-abbreviated-profile-url
universal-profile-url)
emoji-hash-string (string/join emoji-hash)]
[:<>
[rn/view {:style style/qr-code-container}
[qr-codes/share-qr-code
{:type :profile
:unblur-on-android? true
:qr-data universal-profile-url
:qr-data-label-shown abbreviated-url
:on-share-press #(list-selection/open-share {:message universal-profile-url})
:on-text-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy universal-profile-url
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
:on-text-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy universal-profile-url
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
:profile-picture (:uri (profile.utils/photo profile))
:full-name (profile.utils/displayed-name profile)
:customization-color customization-color}]]
[rn/view {:style style/emoji-hash-container}
[rn/view {:style style/emoji-address-container}
[rn/view {:style style/emoji-address-column}
[quo/text
{:size :paragraph-2
:weight :medium
:style style/emoji-hash-label}
(i18n/label :t/emoji-hash)]
[rn/touchable-highlight
{:active-opacity 1
:underlay-color colors/neutral-80-opa-1-blur
:background-color :transparent
:on-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])
:on-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])}
[rn/text {:style style/emoji-hash-content} emoji-hash-string]]]]
[rn/view {:style style/emoji-share-button-container}
[quo/button
{:icon-only? true
:type :grey
:background :blur
:size 32
:accessibility-label :link-to-profile
:container-style {:margin-right 12}
:on-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])
:on-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])}
:i/copy]]]]))
+74 -4
View File
@@ -1,14 +1,18 @@
(ns status-im.contexts.shell.share.view
(:require
[clojure.string :as string]
[legacy.status-im.ui.components.list-selection :as list-selection]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.blur :as blur]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.contexts.shell.share.profile.view :as profile-view]
[status-im.common.qr-codes.view :as qr-codes]
[status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.shell.share.style :as style]
[status-im.contexts.shell.share.wallet.view :as wallet-view]
[utils.address :as address]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -39,6 +43,72 @@
:style style/header-heading}
(i18n/label :t/share)]])
(defn profile-tab
[]
(let [{:keys [emoji-hash
customization-color
universal-profile-url]
:as profile} (rf/sub [:profile/profile])
abbreviated-url (address/get-abbreviated-profile-url
universal-profile-url)
emoji-hash-string (string/join emoji-hash)]
[:<>
[rn/view {:style style/qr-code-container}
[qr-codes/share-qr-code
{:type :profile
:unblur-on-android? true
:qr-data universal-profile-url
:qr-data-label-shown abbreviated-url
:on-share-press #(list-selection/open-share {:message universal-profile-url})
:on-text-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy universal-profile-url
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
:on-text-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy universal-profile-url
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
:profile-picture (:uri (profile.utils/photo profile))
:full-name (profile.utils/displayed-name profile)
:customization-color customization-color}]]
[rn/view {:style style/emoji-hash-container}
[rn/view {:style style/emoji-address-container}
[rn/view {:style style/emoji-address-column}
[quo/text
{:size :paragraph-2
:weight :medium
:style style/emoji-hash-label}
(i18n/label :t/emoji-hash)]
[rn/touchable-highlight
{:active-opacity 1
:underlay-color colors/neutral-80-opa-1-blur
:background-color :transparent
:on-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])
:on-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])}
[rn/text {:style style/emoji-hash-content} emoji-hash-string]]]]
[rn/view {:style style/emoji-share-button-container}
[quo/button
{:icon-only? true
:type :grey
:background :blur
:size 32
:accessibility-label :link-to-profile
:container-style {:margin-right 12}
:on-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])
:on-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])}
:i/copy]]]]))
(defn wallet-tab
[]
[rn/text {:style style/wip-style} "not implemented"])
(defn tab-content
[]
(let [selected-tab (reagent/atom :profile)]
@@ -56,8 +126,8 @@
{:id :wallet
:label (i18n/label :t/wallet)}]}]]
(if (= @selected-tab :profile)
[profile-view/profile-tab]
[wallet-view/wallet-tab])])))
[profile-tab]
[wallet-tab])])))
(defn view
[]
@@ -1,44 +0,0 @@
(ns status-im.contexts.shell.share.wallet.component-spec
(:require
[status-im.contexts.shell.share.wallet.view :as wallet-view]
status-im.contexts.wallet.events
[test-helpers.component :as h]))
(defn render-wallet-view
[]
(let [component-rendered (h/render [wallet-view/wallet-tab])
rerender-fn (h/get-rerender-fn component-rendered)
share-qr-code (h/get-by-label-text :share-qr-code)]
;; Fires on-layout since it's needed to render the content
(h/fire-event :layout share-qr-code #js {:nativeEvent #js {:layout #js {:width 500}}})
(rerender-fn [wallet-view/wallet-tab])))
(h/describe "share wallet addresses"
(h/setup-restorable-re-frame)
(h/before-each
(fn []
(h/setup-subs {:dimensions/window-width 500
:mediaserver/port 200
:wallet/accounts [{:address "0x707f635951193ddafbb40971a0fcaab8a6415160"
:name "Wallet One"
:emoji "😆"
:color :blue}]})))
(h/test "should display the the wallet tab"
(render-wallet-view)
(h/wait-for #(h/is-truthy (h/get-by-text "Wallet One"))))
(h/test "should display the the legacy account"
(render-wallet-view)
(-> (h/wait-for #(h/get-by-label-text :share-qr-code-legacy-tab))
(.then (fn []
(h/fire-event :press (h/get-by-label-text :share-qr-code-legacy-tab))
(-> (h/wait-for #(h/is-falsy (h/query-by-text "eth:"))))))))
(h/test "should display the the multichain account"
(render-wallet-view)
(-> (h/wait-for #(h/get-by-label-text :share-qr-code-multichain-tab))
(.then (fn []
(h/fire-event :press (h/get-by-label-text :share-qr-code-multichain-tab))
(-> (h/wait-for #(h/is-truthy (h/query-by-text "eth:")))))))))
@@ -1,91 +0,0 @@
(ns status-im.contexts.shell.share.wallet.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.share :as share]
[reagent.core :as reagent]
[status-im.contexts.shell.share.style :as style]
[status-im.contexts.wallet.common.sheets.network-preferences.view :as network-preferences]
[status-im.contexts.wallet.common.utils :as utils]
[utils.i18n :as i18n]
[utils.image-server :as image-server]
[utils.re-frame :as rf]))
(def qr-size 500)
(defn- share-action
[address share-title]
(share/open
(if platform/ios?
{:activityItemSources [{:placeholderItem {:type "text"
:content address}
:item {:default {:type "text"
:content
address}}
:linkMetadata {:title share-title}}]}
{:title share-title
:subject share-title
:message address
:isNewTask true})))
(defn- open-preferences
[selected-networks]
(rf/dispatch [:show-bottom-sheet
{:theme :dark
:shell? true
:content
(fn []
[network-preferences/view
{:blur? true
:selected-networks (set selected-networks)
:on-save (fn [chain-ids]
(rf/dispatch [:hide-bottom-sheet])
(reset! selected-networks (map #(get utils/id->network %)
chain-ids)))}])}]))
(defn wallet-qr-code-item
[account width index]
(let [selected-networks (reagent/atom [:ethereum :optimism :arbitrum])
wallet-type (reagent/atom :wallet-legacy)]
(fn []
(let [share-title (str (:name account) " " (i18n/label :t/address))
qr-url (utils/get-wallet-qr {:wallet-type @wallet-type
:selected-networks @selected-networks
:address (:address account)})
qr-media-server-uri (image-server/get-qr-image-uri-for-any-url
{:url qr-url
:port (rf/sub [:mediaserver/port])
:qr-size qr-size
:error-level :highest})]
[rn/view {:style {:width width :margin-left (if (zero? index) 0 -30)}}
[rn/view {:style style/qr-code-container}
[quo/share-qr-code
{:type @wallet-type
:qr-image-uri qr-media-server-uri
:qr-data qr-url
:networks @selected-networks
:on-share-press #(share-action qr-url share-title)
:profile-picture nil
:unblur-on-android? true
:full-name (:name account)
:customization-color (:color account)
:emoji (:emoji account)
:on-multichain-press #(reset! wallet-type :wallet-multichain)
:on-legacy-press #(reset! wallet-type :wallet-legacy)
:on-settings-press #(open-preferences @selected-networks)}]]]))))
(defn wallet-tab
[]
(let [accounts (rf/sub [:wallet/accounts])
width (rf/sub [:dimensions/window-width])]
[rn/flat-list
{:horizontal true
:deceleration-rate 0.9
:snap-to-alignment "start"
:snap-to-interval (- width 30)
:disable-interval-momentum true
:scroll-event-throttle 64
:data accounts
:directional-lock-enabled true
:render-fn (fn [account index]
(wallet-qr-code-item account width index))}]))
@@ -7,24 +7,18 @@
[status-im.contexts.wallet.common.activity-tab.view :as activity]
[status-im.contexts.wallet.common.collectibles-tab.view :as collectibles]
[status-im.contexts.wallet.common.empty-tab.view :as empty-tab]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[utils.i18n :as i18n]))
(defn view
[{:keys [selected-tab]}]
(let [collectible-list (rf/sub [:wallet/current-viewing-account-collectibles])]
[rn/view {:style {:flex 1}}
(case selected-tab
:assets [assets/view]
:collectibles [collectibles/view
{:collectibles collectible-list
:on-collectible-press (fn [id]
(rf/dispatch [:wallet/get-collectible-details id])
(rf/dispatch [:navigate-to :wallet-collectible]))}]
:activity [activity/view]
:permissions [empty-tab/view
{:title (i18n/label :t/no-permissions)
:description (i18n/label :t/no-collectibles-description)
:placeholder? true}]
:dapps [dapps/view]
[about/view])]))
[rn/view {:style {:flex 1}}
(case selected-tab
:assets [assets/view]
:collectibles [collectibles/view]
:activity [activity/view]
:permissions [empty-tab/view
{:title (i18n/label :t/no-permissions)
:description (i18n/label :t/no-collectibles-description)
:placeholder? true}]
:dapps [dapps/view]
[about/view])])
@@ -5,34 +5,32 @@
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.contexts.wallet.common.empty-tab.view :as empty-tab]
[utils.i18n :as i18n]))
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- view-internal
[{:keys [theme collectibles filtered? on-collectible-press]}]
(let [no-results-match-query? (and filtered? (empty? collectibles))]
(cond
no-results-match-query?
[rn/view {:style {:flex 1 :justify-content :center}}
[quo/empty-state
{:title (i18n/label :t/nothing-found)
:description (i18n/label :t/try-to-search-something-else)
:image (resources/get-themed-image :no-collectibles theme)}]]
(empty? collectibles)
[{:keys [theme]}]
(let [specific-address (rf/sub [:wallet/current-viewing-account-address])
collectible-list (if specific-address
(rf/sub [:wallet/collectibles-per-account specific-address])
(rf/sub [:wallet/all-collectibles]))]
(if (empty? collectible-list)
[empty-tab/view
{:title (i18n/label :t/no-collectibles)
:description (i18n/label :t/no-collectibles-description)
:image (resources/get-themed-image :no-collectibles theme)}]
:else
[rn/flat-list
{:data collectibles
{:data collectible-list
:style {:flex 1}
:content-container-style {:align-items :center}
:num-columns 2
:render-fn (fn [{:keys [preview-url id]}]
[quo/collectible
{:images [preview-url]
:on-press #(on-collectible-press id)}])}])))
:on-press (fn []
(rf/dispatch [:wallet/get-collectible-details id])
(rf/dispatch
[:navigate-to
:wallet-collectible]))}])}])))
(def view (quo.theme/with-theme view-internal))
@@ -4,39 +4,30 @@
[utils.re-frame :as rf]))
(defn token-value-drawer
[token]
(let [token-data (first (rf/sub [:wallet/tokens-filtered (:token token)]))]
[:<>
[quo/action-drawer
[[{:icon :i/buy
:accessibility-label :buy
:label (i18n/label :t/buy)
:on-press #(js/alert "to be implemented")
:right-icon :i/external}
{:icon :i/send
:accessibility-label :send
:label (i18n/label :t/send)
:on-press (fn []
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:wallet/send-select-token-drawer {:token token-data}])
(rf/dispatch [:open-modal :wallet-select-address]))}
{:icon :i/receive
:accessibility-label :receive
:label (i18n/label :t/receive)
:on-press #(js/alert "to be implemented")}
{:icon :i/bridge
:accessibility-label :bridge
:label (i18n/label :t/bridge)
:on-press #(js/alert "to be implemented")}
{:icon :i/settings
:accessibility-label :settings
:label (i18n/label :t/manage-tokens)
:on-press #(js/alert "to be implemented")
:add-divider? true}
{:icon :i/hide
:accessibility-label :hide
:label (i18n/label :t/hide)
:on-press #(js/alert "to be implemented")}]]]]))
[]
[:<>
[quo/action-drawer
[[{:icon :i/buy
:accessibility-label :buy
:label (i18n/label :t/buy)
:on-press #(js/alert "to be implemented")
:right-icon :i/external}
{:icon :i/send
:accessibility-label :send
:label (i18n/label :t/send)}
{:icon :i/receive
:accessibility-label :receive
:label (i18n/label :t/receive)}
{:icon :i/bridge
:accessibility-label :bridge
:label (i18n/label :t/bridge)}
{:icon :i/settings
:accessibility-label :settings
:label (i18n/label :t/manage-tokens)
:add-divider? true}
{:icon :i/hide
:accessibility-label :hide
:label (i18n/label :t/hide)}]]]])
(defn view
[item]
@@ -45,5 +36,5 @@
{:on-long-press
#(rf/dispatch
[:show-bottom-sheet
{:content (fn [] [token-value-drawer item])
{:content token-value-drawer
:selected-item (fn [] [quo/token-value item])}])})])
@@ -173,13 +173,6 @@
constants/optimism-chain-id :optimism
constants/arbitrum-chain-id :arbitrum})
(defn get-standard-fiat-format
[crypto-value currency-symbol fiat-value]
(if (string/includes? crypto-value "<")
"<$0.01"
(prettify-balance currency-symbol fiat-value)))
(defn calculate-token-value
"This function returns token values in the props of token-value (quo) component"
[{:keys [token color currency currency-symbol]}]
@@ -191,7 +184,9 @@
constants/profile-default-currency]))
{:keys [change-pct-24hour]} market-values
crypto-value (get-standard-crypto-format token token-units)
fiat-value (get-standard-fiat-format crypto-value currency-symbol fiat-value)]
fiat-value (if (string/includes? crypto-value "<")
"<$0.01"
(prettify-balance currency-symbol fiat-value))]
{:token (:symbol token)
:token-name (:name token)
:state :default
@@ -4,18 +4,12 @@
[status-im.contexts.wallet.common.activity-tab.view :as activity]
[status-im.contexts.wallet.common.collectibles-tab.view :as collectibles]
[status-im.contexts.wallet.home.tabs.assets.view :as assets]
[status-im.contexts.wallet.home.tabs.style :as style]
[utils.re-frame :as rf]))
[status-im.contexts.wallet.home.tabs.style :as style]))
(defn view
[{:keys [selected-tab]}]
(let [collectible-list (rf/sub [:wallet/all-collectibles])]
[rn/view {:style style/container}
(case selected-tab
:assets [assets/view]
:collectibles [collectibles/view
{:collectibles collectible-list
:on-collectible-press (fn [id]
(rf/dispatch [:wallet/get-collectible-details id])
(rf/dispatch [:navigate-to :wallet-collectible]))}]
[activity/view])]))
[rn/view {:style style/container}
(case selected-tab
:assets [assets/view]
:collectibles [collectibles/view]
[activity/view])])
@@ -19,16 +19,15 @@
[address share-title]
(share/open
(if platform/ios?
{:activityItemSources [{:placeholderItem {:type "text"
:content address}
:item {:default {:type "text"
:content
address}}
:linkMetadata {:title share-title}}]}
{:title share-title
:subject share-title
:message address
:isNewTask true})))
{:activity-item-sources [{:placeholder-item {:type "text"
:content address}
:item {:default {:type "text"
:content
address}}
:link-metadata {:title share-title}}]}
{:title share-title
:subject share-title
:message address})))
(defn- open-preferences
[selected-networks]
+5 -13
View File
@@ -40,7 +40,6 @@
(update-in [:wallet :ui :send] dissoc :route)
(update-in [:wallet :ui :send] dissoc :loading-suggested-routes?))}))
(rf/reg-event-fx :wallet/select-send-account-address
(fn [{:keys [db]} [{:keys [address stack-id]}]]
{:db (-> db
@@ -49,24 +48,17 @@
:fx [[:navigate-to-within-stack [:wallet-select-asset stack-id]]]}))
(rf/reg-event-fx :wallet/select-send-address
(fn [{:keys [db]} [{:keys [address token stack-id]}]]
{:db (assoc-in db [:wallet :ui :send :to-address] address)
:fx [[:navigate-to-within-stack
(if token [:wallet-send-input-amount stack-id] [:wallet-select-asset stack-id])]]}))
(fn [{:keys [db]} [{:keys [address stack-id]}]]
{:db (-> db
(assoc-in [:wallet :ui :send :to-address] address)
(update-in [:wallet :ui :send] dissoc :send-account-address))
:fx [[:navigate-to-within-stack [:wallet-select-asset stack-id]]]}))
(rf/reg-event-fx :wallet/send-select-token
(fn [{:keys [db]} [{:keys [token stack-id]}]]
{:db (assoc-in db [:wallet :ui :send :token] token)
:fx [[:navigate-to-within-stack [:wallet-send-input-amount stack-id]]]}))
(rf/reg-event-fx :wallet/send-select-token-drawer
(fn [{:keys [db]} [{:keys [token]}]]
{:db (assoc-in db [:wallet :ui :send :token] token)}))
(rf/reg-event-fx :wallet/clean-selected-token
(fn [{:keys [db]}]
{:db (assoc-in db [:wallet :ui :send :token] nil)}))
(rf/reg-event-fx :wallet/send-select-amount
(fn [{:keys [db]} [{:keys [amount stack-id]}]]
{:db (assoc-in db [:wallet :ui :send :amount] amount)
@@ -118,7 +118,6 @@
(rf/dispatch [:wallet/clean-scanned-address])
(rf/dispatch [:wallet/clean-local-suggestions])
(rf/dispatch [:wallet/clean-account-selection])
(rf/dispatch [:wallet/clean-selected-token])
(rf/dispatch [:wallet/select-address-tab nil])
(rf/dispatch [:navigate-back]))
on-change-tab #(rf/dispatch [:wallet/select-address-tab %])
@@ -126,7 +125,6 @@
input-focused? (reagent/atom false)]
(fn []
(let [selected-tab (or (rf/sub [:wallet/send-tab]) (:id (first tabs-data)))
token (rf/sub [:wallet/wallet-send-token])
valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?]))]
(rn/use-effect (fn []
(fn []
@@ -145,7 +143,6 @@
:disabled? (not valid-ens-or-address?)
:on-press #(rf/dispatch [:wallet/select-send-address
{:address @input-value
:token token
:stack-id :wallet-select-address}])}
(i18n/label :t/continue)])}
[quo/text-combinations
@@ -1,13 +1,11 @@
(ns status-im.contexts.wallet.send.select-asset.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im.contexts.wallet.common.collectibles-tab.view :as collectibles-tab]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.select-asset.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -18,31 +16,27 @@
(defn- asset-component
[]
(fn [token _ _ {:keys [currency currency-symbol]}]
(let [on-press #(rf/dispatch [:wallet/send-select-token
{:token token
:stack-id :wallet-select-asset}])
token-units (utils/total-token-units-in-all-chains token)
crypto-formatted (utils/get-standard-crypto-format token token-units)
fiat-value (utils/total-token-fiat-value currency token)
fiat-formatted (utils/get-standard-fiat-format crypto-formatted currency-symbol fiat-value)]
(fn [token _ _ _]
(let [on-press
#(rf/dispatch [:wallet/send-select-token
{:token token
:stack-id :wallet-select-asset}])
total-balance-formatted (.toFixed (:total-balance token) 2)
balance-fiat-formatted (.toFixed (:total-balance-fiat token) 2)
currency-symbol (rf/sub [:profile/currency-symbol])]
[quo/token-network
{:token (:symbol token)
:label (:name token)
:token-value (str crypto-formatted " " (:symbol token))
:fiat-value fiat-formatted
:token-value (str total-balance-formatted " " (:symbol token))
:fiat-value (str currency-symbol balance-fiat-formatted)
:networks (:networks token)
:on-press on-press}])))
(defn- asset-list
[search-text]
(let [filtered-tokens (rf/sub [:wallet/tokens-filtered search-text])
currency (rf/sub [:profile/currency])
currency-symbol (rf/sub [:profile/currency-symbol])]
(let [filtered-tokens (rf/sub [:wallet/tokens-filtered search-text])]
[rn/flat-list
{:data filtered-tokens
:render-data {:currency currency
:currency-symbol currency-symbol}
:style {:flex 1}
:content-container-style {:padding-horizontal 8}
:keyboard-should-persist-taps :handled
@@ -50,49 +44,34 @@
:on-scroll-to-index-failed identity
:render-fn asset-component}]))
(defn- search-input
[search-text on-change-text]
[rn/view {:style style/search-input-container}
[quo/input
{:small? true
:placeholder (i18n/label :t/search-assets)
:icon-name :i/search
:value search-text
:on-change-text on-change-text}]])
(defn collectibles-grid
[search-text]
(let [collectibles (rf/sub [:wallet/current-viewing-account-collectibles-filtered search-text])
search-performed? (not (string/blank? search-text))]
[collectibles-tab/view
{:collectibles collectibles
:filtered? search-performed?
:on-collectible-press (fn [collectible-id]
(js/alert (str "Collectible to send: \n"
collectible-id
"\nNavigation not implemented yet")))}]))
(defn- tab-view
[search-text selected-tab on-change-text]
(let [unfiltered-collectibles (rf/sub [:wallet/current-viewing-account-collectibles])
show-search-input? (or (= selected-tab :tab/assets)
(and (= selected-tab :tab/collectibles)
(seq unfiltered-collectibles)))]
[:<>
(when show-search-input?
[search-input search-text on-change-text])
(case selected-tab
:tab/assets [asset-list search-text]
:tab/collectibles [collectibles-grid search-text])]))
[search-text selected-tab]
(case selected-tab
:tab/assets [asset-list search-text]
:tab/collectibles [quo/empty-state
{:title (i18n/label :t/no-collectibles)
:description (i18n/label :t/no-collectibles-description)
:placeholder? true
:container-style (style/empty-container-style (safe-area/get-top))}]))
(defn- search-input
[search-text]
(let [on-change-text #(reset! search-text %)]
(fn []
[rn/view {:style style/search-input-container}
[quo/input
{:small? true
:placeholder (i18n/label :t/search-assets)
:icon-name :i/search
:value @search-text
:on-change-text on-change-text}]])))
(defn- f-view-internal
[]
(let [selected-tab (reagent/atom (:id (first tabs-data)))
search-text (reagent/atom "")
on-change-text #(reset! search-text %)
on-change-tab #(reset! selected-tab %)
on-close #(rf/dispatch [:navigate-back-within-stack :wallet-select-asset])]
(let [selected-tab (reagent/atom (:id (first tabs-data)))
search-text (reagent/atom "")
on-close #(rf/dispatch [:navigate-back-within-stack
:wallet-select-asset])]
(fn []
[rn/safe-area-view {:style style/container}
[rn/scroll-view
@@ -115,8 +94,9 @@
:container-style {:margin-horizontal 20
:margin-vertical 8}
:data tabs-data
:on-change on-change-tab}]
[tab-view @search-text @selected-tab on-change-text]]])))
:on-change #(reset! selected-tab %)}]
[search-input search-text]
[tab-view @search-text @selected-tab]]])))
(defn- view-internal
[]
-1
View File
@@ -3,7 +3,6 @@
[status-im.common.floating-button-page.component-spec]
[status-im.contexts.chat.messenger.messages.content.audio.component-spec]
[status-im.contexts.communities.actions.community-options.component-spec]
[status-im.contexts.shell.share.wallet.component-spec]
[status-im.contexts.wallet.add-address-to-watch.component-spec]
[status-im.contexts.wallet.add-address-to-watch.confirm-address.component-spec]
[status-im.contexts.wallet.create-account.edit-derivation-path.component-spec]
+32 -4
View File
@@ -12,7 +12,7 @@
(def memo-chats-stack-items (atom nil))
(re-frame/reg-sub
:chats/chats-stack-items
:chats-stack-items
:<- [:chats/home-list-chats]
:<- [:view-id]
:<- [:home-items-show-number]
@@ -102,18 +102,46 @@
active-chats)))
(re-frame/reg-sub
:chats/chat-by-id
:chat-by-id
:<- [:chats/chats]
(fn [chats [_ chat-id]]
(get chats chat-id)))
(re-frame/reg-sub
:chats/synced-from
(fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id]))
(fn [{:keys [synced-from]}]
synced-from))
(re-frame/reg-sub
:chats/muted
(fn [[_ chat-id] _]
(re-frame/subscribe [:chats/chat-by-id chat-id]))
(re-frame/subscribe [:chat-by-id chat-id]))
(fn [{:keys [muted]}]
muted))
(re-frame/reg-sub
:chats/chat-type
(fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id]))
(fn [{:keys [chat-type]}]
chat-type))
(re-frame/reg-sub
:chats/joined
(fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id]))
(fn [{:keys [joined]}]
joined))
(re-frame/reg-sub
:chats/synced-to-and-from
(fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id]))
(fn [chat]
(select-keys chat [:synced-to :synced-from])))
(re-frame/reg-sub
:chats/current-raw-chat
:<- [:chats/chats]
@@ -367,7 +395,7 @@
(re-frame/reg-sub
:group-chat/inviter-info
(fn [[_ chat-id] _]
[(re-frame/subscribe [:chats/chat-by-id chat-id])
[(re-frame/subscribe [:chat-by-id chat-id])
(re-frame/subscribe [:multiaccount/public-key])])
(fn [[chat my-public-key]]
{:member? (group-chats.db/member? my-public-key chat)
+6 -8
View File
@@ -270,12 +270,11 @@
(re-frame/reg-sub
:contacts/contacts-by-chat
(fn [[_ chat-id]]
(fn [[_ _ chat-id] _]
[(re-frame/subscribe [:chats/chat chat-id])
(re-frame/subscribe [:contacts/contacts])
(re-frame/subscribe [:profile/profile])])
(fn [[{:keys [contacts admins]} all-contacts current-multiaccount]]
(contact.db/get-all-contacts-in-group-chat contacts admins all-contacts current-multiaccount)))
(re-frame/subscribe [:contacts/contacts])])
(fn [[chat all-contacts] [_ query-fn]]
(contact.db/query-chat-contacts chat all-contacts query-fn)))
(re-frame/reg-sub
:contacts/contact-by-address
@@ -317,9 +316,8 @@
(re-frame/reg-sub
:contacts/group-members-sections
(fn [[_ chat-id]]
[(re-frame/subscribe [:contacts/contacts-by-chat chat-id])])
(fn [[members]]
:<- [:contacts/current-chat-contacts]
(fn [members]
(let [admins (filter :admin? members)
online (filter #(and (not (:admin? %)) (:online? %)) members)
offline (filter #(and (not (:admin? %)) (not (:online? %))) members)]
+4 -1
View File
@@ -216,7 +216,10 @@
[(re-frame/subscribe [:chats/message-list chat-id])
(re-frame/subscribe [:chats/chat-messages chat-id])
(re-frame/subscribe [:chats/pinned chat-id])
(re-frame/subscribe [:chats/loading-messages? chat-id])])
(re-frame/subscribe [:chats/loading-messages? chat-id])
(re-frame/subscribe [:chats/synced-from chat-id])
(re-frame/subscribe [:chats/chat-type chat-id])
(re-frame/subscribe [:chats/joined chat-id])])
(fn [[message-list messages pin-messages loading-messages?] _]
;;TODO (perf)
(let [message-list-seq (models.message-list/->seq message-list)]
+10 -22
View File
@@ -10,17 +10,15 @@
animation-url
image-url))
(defn add-collectibles-preview-url
[collectibles]
(map (fn [{:keys [collectible-data] :as collectible}]
(assoc collectible :preview-url (preview-url collectible-data)))
collectibles))
(re-frame/reg-sub
:wallet/current-viewing-account-collectibles
:<- [:wallet/current-viewing-account]
(fn [current-account]
(-> current-account :collectibles add-collectibles-preview-url)))
:wallet/collectibles-per-account
:<- [:wallet]
(fn [wallet [_ address]]
(as-> wallet $
(get-in $ [:accounts address :collectibles])
(map (fn [{:keys [collectible-data] :as collectible}]
(assoc collectible :preview-url (preview-url collectible-data)))
$))))
(re-frame/reg-sub
:wallet/all-collectibles
@@ -29,18 +27,8 @@
(->> wallet
:accounts
(mapcat (comp :collectibles val))
(add-collectibles-preview-url))))
(re-frame/reg-sub
:wallet/current-viewing-account-collectibles-filtered
:<- [:wallet/current-viewing-account-collectibles]
(fn [current-account-collectibles [_ search-text]]
(let [search-text-lower-case (string/lower-case search-text)]
(filter (fn [{{collection-name :name} :collection-data
{collectible-name :name} :collectible-data}]
(or (string/includes? (string/lower-case collection-name) search-text-lower-case)
(string/includes? (string/lower-case collectible-name) search-text-lower-case)))
current-account-collectibles))))
(map (fn [{:keys [collectible-data] :as collectible}]
(assoc collectible :preview-url (preview-url collectible-data)))))))
(re-frame/reg-sub
:wallet/last-collectible-details
+4 -4
View File
@@ -124,10 +124,10 @@
:<- [:wallet/balances]
:<- [:profile/currency-symbol]
(fn [[accounts current-viewing-account-address balances currency-symbol]]
(let [balance (get balances current-viewing-account-address)
formatted-balance (utils/prettify-balance currency-symbol balance)]
(-> accounts
(utils/get-account-by-address current-viewing-account-address)
(let [current-viewing-account (utils/get-account-by-address accounts current-viewing-account-address)
balance (get balances current-viewing-account-address)
formatted-balance (utils/prettify-balance currency-symbol balance)]
(-> current-viewing-account
(assoc :balance balance
:formatted-balance formatted-balance)))))
-4
View File
@@ -11,10 +11,6 @@ jest.mock('react-native-fs', () => ({
default: {},
}));
jest.mock('react-native-share', () => ({
default: {},
}));
jest.mock('react-native-navigation', () => ({
getNavigationConstants: () => ({ constants: [] }),
Navigation: {
-3
View File
@@ -147,7 +147,6 @@
"change-pairing-description": "Changing the pairing code does not affect the current pairings. However, any new pairing will require the new code.",
"changed-amount-warning": "Amount was changed from {{old}} to {{new}}",
"changed-asset-warning": "Asset was changed from {{old}} to {{new}}",
"channel-on-status": "Channel on Status",
"chaos-mode": "Chaos mode",
"chaos-unicorn-day": "Chaos Unicorn Day",
"chaos-unicorn-day-details": "🦄🦄🦄🦄🦄🦄🦄🚀!",
@@ -1794,8 +1793,6 @@
"community-info-not-found": "Community information not found",
"community-info": "Community info",
"not-found": "Not found",
"nothing-found": "Nothing found",
"try-to-search-something-else": "Try to search something else",
"activity": "Activity",
"reject-and-delete": "Reject and delete",
"accept-and-add": "Accept and add",
+134 -131
View File
@@ -3173,9 +3173,9 @@
"@types/yargs-parser" "*"
"@types/yargs@^16.0.0":
version "16.0.9"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.9.tgz#ba506215e45f7707e6cbcaf386981155b7ab956e"
integrity sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==
version "16.0.5"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.5.tgz#12cc86393985735a283e387936398c2f9e5f88e3"
integrity sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==
dependencies:
"@types/yargs-parser" "*"
@@ -3418,6 +3418,11 @@ async@^2.6.3:
dependencies:
lodash "^4.17.14"
async@^3.2.2:
version "3.2.4"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -4125,6 +4130,11 @@ commander@^9.4.1:
resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
commander@~2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -4702,9 +4712,9 @@ entities@^4.2.0:
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
envinfo@^7.7.2:
version "7.11.0"
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.0.tgz#c3793f44284a55ff8c82faf1ffd91bc6478ea01f"
integrity sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==
version "7.8.1"
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
error-ex@^1.3.1:
version "1.3.2"
@@ -5321,11 +5331,6 @@ hermes-estree@0.12.0:
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.12.0.tgz#8a289f9aee854854422345e6995a48613bac2ca8"
integrity sha512-+e8xR6SCen0wyAKrMT3UD0ZCCLymKhRgjEB5sS28rKiFir/fXgLoeRilRUssFCILmGHb+OvHDUlhxs0+IEyvQw==
hermes-estree@0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.15.0.tgz#e32f6210ab18c7b705bdcb375f7700f2db15d6ba"
integrity sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==
hermes-parser@0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.12.0.tgz#114dc26697cfb41a6302c215b859b74224383773"
@@ -5333,13 +5338,6 @@ hermes-parser@0.12.0:
dependencies:
hermes-estree "0.12.0"
hermes-parser@0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.15.0.tgz#f611a297c2a2dbbfbce8af8543242254f604c382"
integrity sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==
dependencies:
hermes-estree "0.15.0"
hermes-profile-transformer@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b"
@@ -6210,6 +6208,11 @@ jest-regex-util@^25.2.6:
resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-25.2.6.tgz#d847d38ba15d2118d3b06390056028d0f2fd3964"
integrity sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw==
jest-regex-util@^27.0.6:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95"
integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==
jest-regex-util@^29.6.3:
version "29.6.3"
resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52"
@@ -6398,7 +6401,19 @@ jest-util@^29.7.0:
graceful-fs "^4.2.9"
picomatch "^2.2.3"
jest-validate@^29.6.3, jest-validate@^29.7.0:
jest-validate@^29.2.1:
version "29.6.3"
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.3.tgz#a75fca774cfb1c5758c70d035d30a1f9c2784b4d"
integrity sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==
dependencies:
"@jest/types" "^29.6.3"
camelcase "^6.2.0"
chalk "^4.0.0"
jest-get-type "^29.6.3"
leven "^3.1.0"
pretty-format "^29.6.3"
jest-validate@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c"
integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==
@@ -6823,59 +6838,60 @@ merge-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
metro-babel-transformer@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.79.1.tgz#bb2392227d3db49ffc39b98d8aebe5f7cef46302"
integrity sha512-WvE/At9r0LoNoxGgGhULV4H5ieuLs8AHfVUtTpHaOpgE326BwHNiUYaWuCpaM/BTTlajQltK/U1t+MqbbvFG9A==
metro-babel-transformer@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.76.8.tgz#5efd1027353b36b73706164ef09c290dceac096a"
integrity sha512-Hh6PW34Ug/nShlBGxkwQJSgPGAzSJ9FwQXhUImkzdsDgVu6zj5bx258J8cJVSandjNoQ8nbaHK6CaHlnbZKbyA==
dependencies:
"@babel/core" "^7.20.0"
hermes-parser "0.15.0"
hermes-parser "0.12.0"
nullthrows "^1.1.1"
metro-cache-key@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.79.1.tgz#80e6f2cd45a3ae04abb6874c75684e91f8c3668e"
integrity sha512-/u48AuINgakqYEymRrD6MzKCSYU/JEXrqGX4x6gVHVa99TKPeg5SBi3MIjpZz/tWGpcQHCKItfjLD48YhEJr3Q==
metro-cache-key@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.76.8.tgz#8a0a5e991c06f56fcc584acadacb313c312bdc16"
integrity sha512-buKQ5xentPig9G6T37Ww/R/bC+/V1MA5xU/D8zjnhlelsrPG6w6LtHUS61ID3zZcMZqYaELWk5UIadIdDsaaLw==
metro-cache@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.79.1.tgz#197286fb0d3ee6827d91893b50237070c063c157"
integrity sha512-uRlo1cYewW9t6KuRED0G/iCnlqPc5Hq+I2VELBiJr4lBYwCz8P1KwcdzgSUpAzcZBcarq6rI9JqVPvV4t6P3YQ==
metro-cache@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.76.8.tgz#296c1c189db2053b89735a8f33dbe82575f53661"
integrity sha512-QBJSJIVNH7Hc/Yo6br/U/qQDUpiUdRgZ2ZBJmvAbmAKp2XDzsapnMwK/3BGj8JNWJF7OLrqrYHsRsukSbUBpvQ==
dependencies:
metro-core "0.79.1"
metro-core "0.76.8"
rimraf "^3.0.2"
metro-config@0.76.8, metro-config@0.79.1, metro-config@^0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.79.1.tgz#34609c582202bc7a2b6712c77352758ffe6a6eed"
integrity sha512-gleXbytiPTsO88DDUuaprKQLfaOVfoj6L7yw1u6MRXmQdebK3TmWUajqnLdWDQ/D0+JBWfrkFhLjnWXHsA8Cgw==
metro-config@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.76.8.tgz#20bd5397fcc6096f98d2a813a7cecb38b8af062d"
integrity sha512-SL1lfKB0qGHALcAk2zBqVgQZpazDYvYFGwCK1ikz0S6Y/CM2i2/HwuZN31kpX6z3mqjv/6KvlzaKoTb1otuSAA==
dependencies:
connect "^3.6.5"
cosmiconfig "^5.0.5"
jest-validate "^29.6.3"
metro "0.79.1"
metro-cache "0.79.1"
metro-core "0.79.1"
metro-runtime "0.79.1"
jest-validate "^29.2.1"
metro "0.76.8"
metro-cache "0.76.8"
metro-core "0.76.8"
metro-runtime "0.76.8"
metro-core@0.76.8, metro-core@0.79.1, metro-core@^0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.79.1.tgz#1beed31d6358291d95e42ddb048ed41674f7dea9"
integrity sha512-tPlpLLOKT5D5HSFQBrvgU2gupecCA0YcnQQVOByuLjY5JMXUBU7HISHv5gpbJTUt9KlPQ8OhZV/x6ivyXaVSQg==
metro-core@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.76.8.tgz#917c8157c63406cb223522835abb8e7c6291dcad"
integrity sha512-sl2QLFI3d1b1XUUGxwzw/KbaXXU/bvFYrSKz6Sg19AdYGWFyzsgZ1VISRIDf+HWm4R/TJXluhWMEkEtZuqi3qA==
dependencies:
lodash.throttle "^4.1.1"
metro-resolver "0.79.1"
metro-resolver "0.76.8"
metro-file-map@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.79.1.tgz#c8aa95d1eac0e3fd7a2e54e4d55c6b9a300cfd95"
integrity sha512-PpPhfkj1Bj448f+5vZaaImJWFSsf6XveYGdRsfwvskcYlMsFBl4OX1WyGTJCCCzrtIOH5y1V3OADI/HS563sCA==
metro-file-map@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.76.8.tgz#a1db1185b6c316904ba6b53d628e5d1323991d79"
integrity sha512-A/xP1YNEVwO1SUV9/YYo6/Y1MmzhL4ZnVgcJC3VmHp/BYVOXVStzgVbWv2wILe56IIMkfXU+jpXrGKKYhFyHVw==
dependencies:
anymatch "^3.0.3"
debug "^2.2.0"
fb-watchman "^2.0.0"
graceful-fs "^4.2.4"
invariant "^2.2.4"
jest-regex-util "^27.0.6"
jest-util "^27.2.0"
jest-worker "^27.2.0"
micromatch "^4.0.4"
@@ -6885,13 +6901,31 @@ metro-file-map@0.79.1:
optionalDependencies:
fsevents "^2.3.2"
metro-minify-terser@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.79.1.tgz#006479abd5eea43525937a3d211af2f4b0c3133f"
integrity sha512-69zOvPazJFKE6tHlOF8PQcvXUfoXgeHreVaggjuqnCREMWBjEkTH9jOn8M3oB0JgKmEUBb4bzFr7Oz1kC7Jc3g==
metro-inspector-proxy@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.76.8.tgz#6b8678a7461b0b42f913a7881cc9319b4d3cddff"
integrity sha512-Us5o5UEd4Smgn1+TfHX4LvVPoWVo9VsVMn4Ldbk0g5CQx3Gu0ygc/ei2AKPGTwsOZmKxJeACj7yMH2kgxQP/iw==
dependencies:
connect "^3.6.5"
debug "^2.2.0"
node-fetch "^2.2.0"
ws "^7.5.1"
yargs "^17.6.2"
metro-minify-terser@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.76.8.tgz#915ab4d1419257fc6a0b9fa15827b83fe69814bf"
integrity sha512-Orbvg18qXHCrSj1KbaeSDVYRy/gkro2PC7Fy2tDSH1c9RB4aH8tuMOIXnKJE+1SXxBtjWmQ5Yirwkth2DyyEZA==
dependencies:
terser "^5.15.0"
metro-minify-uglify@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.76.8.tgz#74745045ea2dd29f8783db483b2fce58385ba695"
integrity sha512-6l8/bEvtVaTSuhG1FqS0+Mc8lZ3Bl4RI8SeRIifVLC21eeSDp4CEBUWSGjpFyUDfi6R5dXzYaFnSgMNyfxADiQ==
dependencies:
uglify-es "^3.1.9"
metro-react-native-babel-preset@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.76.8.tgz#7476efae14363cbdfeeec403b4f01d7348e6c048"
@@ -6953,11 +6987,6 @@ metro-resolver@0.76.8:
resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.76.8.tgz#0862755b9b84e26853978322464fb37c6fdad76d"
integrity sha512-KccOqc10vrzS7ZhG2NSnL2dh3uVydarB7nOhjreQ7C4zyWuiW9XpLC4h47KtGQv3Rnv/NDLJYeDqaJ4/+140HQ==
metro-resolver@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.79.1.tgz#80e6e27305eb446188009f54374b642f28f49b65"
integrity sha512-hiea5co7c5rhrdD5xYohBq2Sw20Ytzie71raIW9SsXKBKzsS0zAbrwNFW5z71lDUnp719vhobnDXJ+yE7Kq9Gg==
metro-runtime@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.76.8.tgz#74b2d301a2be5f3bbde91b8f1312106f8ffe50c3"
@@ -6966,14 +6995,6 @@ metro-runtime@0.76.8:
"@babel/runtime" "^7.0.0"
react-refresh "^0.4.0"
metro-runtime@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.79.1.tgz#5598062de56a265b88cdfa735834809552829cf3"
integrity sha512-RRBFPjaex8/Q6M+4V0oOYrd4mDG0iNkRMSdT5iojUe9pF24pRmqwG2gm3NBBgh4UAzYPI0NsJ6AB8JTmchfCAg==
dependencies:
"@babel/runtime" "^7.0.0"
react-refresh "^0.4.0"
metro-source-map@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.76.8.tgz#f085800152a6ba0b41ca26833874d31ec36c5a53"
@@ -6988,20 +7009,6 @@ metro-source-map@0.76.8:
source-map "^0.5.6"
vlq "^1.0.0"
metro-source-map@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.79.1.tgz#6698910de296957207190f6376ef0d54f3b9b4cd"
integrity sha512-Rlgld4cfWUFs5NdAErSzWfX9C4eYLPXTBBmhTHaiQEgRb0ydrfhOcofT0gYTHzp6t9lW30IO5wxlzl6gU/nOjA==
dependencies:
"@babel/traverse" "^7.20.0"
"@babel/types" "^7.20.0"
invariant "^2.2.4"
metro-symbolicate "0.79.1"
nullthrows "^1.1.1"
ob1 "0.79.1"
source-map "^0.5.6"
vlq "^1.0.0"
metro-symbolicate@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.76.8.tgz#f102ac1a306d51597ecc8fdf961c0a88bddbca03"
@@ -7014,22 +7021,10 @@ metro-symbolicate@0.76.8:
through2 "^2.0.1"
vlq "^1.0.0"
metro-symbolicate@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.79.1.tgz#29b8f59ac32e2381ec6e44023931b1118b04e4b4"
integrity sha512-cB7Yxh5SKs24EsTaONpaEPoFC6H1ya0BeAR1Ety1qeeV/gFmC8YvkwFj9S8sy6whwIf4dM9xLF2iv7Ug78C4JA==
dependencies:
invariant "^2.2.4"
metro-source-map "0.79.1"
nullthrows "^1.1.1"
source-map "^0.5.6"
through2 "^2.0.1"
vlq "^1.0.0"
metro-transform-plugins@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.79.1.tgz#103c6b5562954b6dab6b9c0b73b13742d17fcb87"
integrity sha512-kGDpBJGpijC/OVrpngCiyvzrT6sfSPqFOiyEzU02j+8UCmxKCofbdv62nT97dzseR+iWkzFPcCbq8Nc7/CFwwA==
metro-transform-plugins@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.76.8.tgz#d77c28a6547a8e3b72250f740fcfbd7f5408f8ba"
integrity sha512-PlkGTQNqS51Bx4vuufSQCdSn2R2rt7korzngo+b5GCkeX5pjinPjnO2kNhQ8l+5bO0iUD/WZ9nsM2PGGKIkWFA==
dependencies:
"@babel/core" "^7.20.0"
"@babel/generator" "^7.20.0"
@@ -7037,27 +7032,28 @@ metro-transform-plugins@0.79.1:
"@babel/traverse" "^7.20.0"
nullthrows "^1.1.1"
metro-transform-worker@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.79.1.tgz#1e48f68b532fbae15d6d82270519b9fc6e311598"
integrity sha512-WA15xo7EvJgutlhRKldgPTtwOWur4xDO5uQc5e/vZuhGtahcV0b4v2lXp+t3z5gs9DBqajsczce1A+3pY9wcQQ==
metro-transform-worker@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.76.8.tgz#b9012a196cee205170d0c899b8b175b9305acdea"
integrity sha512-mE1fxVAnJKmwwJyDtThildxxos9+DGs9+vTrx2ktSFMEVTtXS/bIv2W6hux1pqivqAfyJpTeACXHk5u2DgGvIQ==
dependencies:
"@babel/core" "^7.20.0"
"@babel/generator" "^7.20.0"
"@babel/parser" "^7.20.0"
"@babel/types" "^7.20.0"
metro "0.79.1"
metro-babel-transformer "0.79.1"
metro-cache "0.79.1"
metro-cache-key "0.79.1"
metro-source-map "0.79.1"
metro-transform-plugins "0.79.1"
babel-preset-fbjs "^3.4.0"
metro "0.76.8"
metro-babel-transformer "0.76.8"
metro-cache "0.76.8"
metro-cache-key "0.76.8"
metro-source-map "0.76.8"
metro-transform-plugins "0.76.8"
nullthrows "^1.1.1"
metro@0.76.8, metro@0.79.1, metro@^0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/metro/-/metro-0.79.1.tgz#e6e2db1d2aca30d88e419d97835572660aba2064"
integrity sha512-PDzLQn4fpV4cs6brPi3zSu3zOA3kG+x6algazYGz1FzrOIsIT+L0Hd294+V4xN73EjLrSD5vD5hNsWlBxRk/PA==
metro@0.76.8:
version "0.76.8"
resolved "https://registry.yarnpkg.com/metro/-/metro-0.76.8.tgz#ba526808b99977ca3f9ac5a7432fd02a340d13a6"
integrity sha512-oQA3gLzrrYv3qKtuWArMgHPbHu8odZOD9AoavrqSFllkPgOtmkBvNNDLCELqv5SjBfqjISNffypg+5UGG3y0pg==
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/core" "^7.20.0"
@@ -7067,6 +7063,7 @@ metro@0.76.8, metro@0.79.1, metro@^0.79.1:
"@babel/traverse" "^7.20.0"
"@babel/types" "^7.20.0"
accepts "^1.3.7"
async "^3.2.2"
chalk "^4.0.0"
ci-info "^2.0.0"
connect "^3.6.5"
@@ -7074,25 +7071,28 @@ metro@0.76.8, metro@0.79.1, metro@^0.79.1:
denodeify "^1.2.1"
error-stack-parser "^2.0.6"
graceful-fs "^4.2.4"
hermes-parser "0.15.0"
hermes-parser "0.12.0"
image-size "^1.0.2"
invariant "^2.2.4"
jest-worker "^27.2.0"
jsc-safe-url "^0.2.2"
lodash.throttle "^4.1.1"
metro-babel-transformer "0.79.1"
metro-cache "0.79.1"
metro-cache-key "0.79.1"
metro-config "0.79.1"
metro-core "0.79.1"
metro-file-map "0.79.1"
metro-minify-terser "0.79.1"
metro-resolver "0.79.1"
metro-runtime "0.79.1"
metro-source-map "0.79.1"
metro-symbolicate "0.79.1"
metro-transform-plugins "0.79.1"
metro-transform-worker "0.79.1"
metro-babel-transformer "0.76.8"
metro-cache "0.76.8"
metro-cache-key "0.76.8"
metro-config "0.76.8"
metro-core "0.76.8"
metro-file-map "0.76.8"
metro-inspector-proxy "0.76.8"
metro-minify-terser "0.76.8"
metro-minify-uglify "0.76.8"
metro-react-native-babel-preset "0.76.8"
metro-resolver "0.76.8"
metro-runtime "0.76.8"
metro-source-map "0.76.8"
metro-symbolicate "0.76.8"
metro-transform-plugins "0.76.8"
metro-transform-worker "0.76.8"
mime-types "^2.1.27"
node-fetch "^2.2.0"
nullthrows "^1.1.1"
@@ -7495,11 +7495,6 @@ ob1@0.76.8:
resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.76.8.tgz#ac4c459465b1c0e2c29aaa527e09fc463d3ffec8"
integrity sha512-dlBkJJV5M/msj9KYA9upc+nUWVwuOFFTbu28X6kZeGwcuW+JxaHSBZ70SYQnk5M+j5JbNLR6yKHmgW4M5E7X5g==
ob1@0.79.1:
version "0.79.1"
resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.79.1.tgz#11d43712ff2c089d576b13b05b0caeed28389c6b"
integrity sha512-Z05NdP9uwS6UWoqNQDqx/VuVBD7rhMBqCB52js9HRct5IsU/lcSC/9Rv4J977wcOrSmaYTXQa2HRkUg4QAIS3g==
object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -9567,6 +9562,14 @@ ua-parser-js@^0.7.18:
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31"
integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==
uglify-es@^3.1.9:
version "3.3.9"
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==
dependencies:
commander "~2.13.0"
source-map "~0.6.1"
undefsafe@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"