Compare commits

...
Author SHA1 Message Date
Cristian Lungu f3fd33d63a fix: tx confirmation title network color 2024-11-05 14:06:13 +02:00
Cristian Lungu 08fea7fe5f fix: input amount fee rebase leftover 2024-11-05 13:46:43 +02:00
Cristian Lungu 792caf5259 fix: tx confirmation summary-info address initials 2024-11-05 13:34:37 +02:00
Cristian Lungu c02d97d380 fix: hide "Amount received" on collectible confirmation 2024-11-05 13:33:46 +02:00
Cristian Lungu 3001fa91e9 ref: extracted transaction title component 2024-11-05 13:33:20 +02:00
Cristian Lungu 2714c7b9e5 fix: network-values reagent warning 2024-11-05 11:52:45 +02:00
Cristian Lungu 307155a4ca ref: split tx confirmation subs into components 2024-11-04 20:23:41 +02:00
Cristian Lungu a5ef314d6a ref: account summary from tx confirmation 2024-11-04 20:21:07 +02:00
Cristian Lungu 2ba16e6762 fix: refactored send confirmation title 2024-11-04 20:21:07 +02:00
Cristian Lungu 6acda08ebb fix: network-values amount should be fixed 2024-11-04 20:16:12 +02:00
Cristian Lungu 90166ad45a fix: sending BonderFee as string 2024-11-04 20:16:11 +02:00
Cristian Lungu ef8490961a fix: addressed review comments 2024-11-04 20:16:11 +02:00
Cristian Lungu e4ae78bb25 test: added subscription tests 2024-11-04 20:16:11 +02:00
Cristian Lungu ea07780e9c fix: lint 2024-11-04 20:16:11 +02:00
Cristian Lungu ff569f328a fix: wallet input component tests 2024-11-04 20:16:11 +02:00
Cristian Lungu e4b42fc0ca fix: tests for estimated-received 2024-11-04 20:16:10 +02:00
Cristian Lungu 9397dd46e8 feat: added bridge bonder-fee info sheet 2024-11-04 20:16:10 +02:00
Cristian Lungu 34d6b3c1d5 feat: moved send estimated-fees in separate ns 2024-11-04 20:16:10 +02:00
Cristian Lungu 3c7d299ef7 feat: title-icon prop for quo/data-item 2024-11-04 20:16:10 +02:00
Cristian Lungu 43a8be9d52 fix: route out value not using token decimals 2024-11-04 20:16:10 +02:00
Cristian Lungu adff7a5120 ref: moved estimated received from event to sub 2024-11-04 20:16:09 +02:00
Cristian Lungu 4db4b5c84b test: added test cases for out amount and received 2024-11-04 20:16:09 +02:00
Cristian Lungu 23d84a54fc fix: show correct bridge values for to/received/fees 2024-11-04 20:16:09 +02:00
Cristian Lungu 5d51ae55b5 test: estimated-received-by-chain-test tests 2024-11-04 20:16:09 +02:00
Cristian Lungu d51d88fc0b ref: added token precision constant 2024-11-04 20:16:09 +02:00
Cristian Lungu bf8fa45e52 fix: using estimated received value for transactions 2024-11-04 20:16:08 +02:00
Lungu Cristian 077b885617 Fix wallet action buttons alignment (#21514)
* fix: wallet-ctas dynamic spacing

* fix: updated bridge icon according to designs
2024-11-04 20:01:54 +02:00
Tetiana Churikova 2e42da5996 gh: added Type (#21472) 2024-11-04 16:53:18 +01:00
Tetiana Churikova f6dc9d1ad3 e2e: skipping waku tests and fixes (#21471) 2024-11-04 16:33:03 +01:00
Mohamed Javid 9f1eb60e21 chore_: Remove Goerli code (#21508)
This commit removes the goerli-related code from the mobile repo.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-11-04 18:10:36 +05:30
Mohamed Javid 8e7d5233df fix(wallet)_: Bridging tx improvements (#21523)
This commit fixes two issues faced in L1 to L2 tx:

- fail with 'L1_ETH_BRG: Value does not match amount' error
- reverted tx due to out of gas error

Status go changes: https://github.com/status-im/status-go/pull/6012

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-11-04 15:04:36 +05:30
Mohamed Javid 4f40fda6a3 fix(wallet)_: Chain prefix for ENS resolved address (#21504)
This commit removes chain prefixes being added to ENS resolved address in send flow

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-11-01 21:09:59 +05:30
flexsurfer f0079961f4 [#21316] Keycard - Allow user to migrate existing Profile to the new … (#21467) 2024-11-01 12:48:07 +01:00
Lungu Cristian 9862abb7eb Fix "Failed to get dApps" error when a session expired (#21531)
* fix: pass the topic instead of entire session

* chore: added logs for future debugging
2024-10-30 15:51:26 +02:00
Brian Sztamfater 6d7697870d feat(swap): add metrics for swaps (#21485)
Signed-off-by: Brian Sztamfater <brian@status.im>
2024-10-29 12:01:47 -03:00
Parvesh Monu 4f53a2b11e fix No tabs are available in the app on Graphene OS (#21520) 2024-10-29 20:14:26 +05:30
Siddarth Kumar fd9e8273e1 chore(deps)_: use gradle plugin to get deps (#21502)
related issue : https://github.com/status-im/status-mobile/issues/15447

This commit makes use of https://github.com/gradle/github-dependency-graph-gradle-plugin to generate deps so that we may get rid of the AWK script that parses `gradle` output to figure out `gradle` dependencies.

credits to Vedran for doing initial research on this dependency generator plugin.

We still miss a few dependencies and are not completely able to get rid of the hack list step just yet.

I also moved `react-native-share` out of  `pluginManagement ` block in `android/settings.gradle` because it does not belong there.
2024-10-29 11:39:50 +05:30
Parvesh Monu 6afaba23b5 fix Error when creating an account on e2e build (#21496) 2024-10-29 00:54:07 +05:30
126 changed files with 2545 additions and 1847 deletions
-1
View File
@@ -1,6 +1,5 @@
CACHED_WEBVIEWS_ENABLED=1
DEBUG_WEBVIEW=1
DEFAULT_NETWORK=mainnet_rpc
DEV_BUILD=1
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
+2 -3
View File
@@ -1,5 +1,4 @@
DEBUG_WEBVIEW=1
DEFAULT_NETWORK=goerli_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.staging
@@ -22,8 +21,8 @@ KEYCARD_TEST_MENU=1
QR_READ_TEST_MENU=1
ENABLE_ROOT_ALERT=0
APN_TOPIC=im.status.ethereum.pr
VERIFY_TRANSACTION_CHAIN_ID=5
VERIFY_ENS_CHAIN_ID=5
VERIFY_TRANSACTION_CHAIN_ID=11155111
VERIFY_ENS_CHAIN_ID=11155111
TEST_STATEOFUS=1
DATABASE_MANAGEMENT_ENABLED=1
COMMUNITIES_ENABLED=1
+2 -3
View File
@@ -1,6 +1,5 @@
CACHED_WEBVIEWS_ENABLED=1
DEBUG_WEBVIEW=1
DEFAULT_NETWORK=goerli_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
GROUP_CHATS_ENABLED=1
@@ -21,8 +20,8 @@ KEYCARD_TEST_MENU=0
ENABLE_ROOT_ALERT=1
DISABLE_WALLET_ON_MOBILE_NETWORK=1
APN_TOPIC=im.status.ethereum.pr
VERIFY_TRANSACTION_CHAIN_ID=5
VERIFY_ENS_CHAIN_ID=5
VERIFY_TRANSACTION_CHAIN_ID=11155111
VERIFY_ENS_CHAIN_ID=11155111
TEST_STATEOFUS=1
BLANK_PREVIEW=0
DATABASE_MANAGEMENT_ENABLED=1
-1
View File
@@ -1,5 +1,4 @@
DEBUG_WEBVIEW=1
DEFAULT_NETWORK=mainnet_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
GROUP_CHATS_ENABLED=1
-1
View File
@@ -1,5 +1,4 @@
DEBUG_WEBVIEW=0
DEFAULT_NETWORK=mainnet_rpc
ETHEREUM_DEV_CLUSTER=0
EXTENSIONS=0
GROUP_CHATS_ENABLED=1
+1 -1
View File
@@ -2,7 +2,7 @@
name: Bug Report
about: Bug Report
title: ''
labels: ['bug', ':1234: low prio']
type: 'Bug'
assignees: ''
---
+9
View File
@@ -0,0 +1,9 @@
initscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath "org.gradle:github-dependency-graph-gradle-plugin:+"
}
}
apply plugin: org.gradle.dependencygraph.simple.SimpleDependencyGraphPlugin
+3 -3
View File
@@ -1,12 +1,12 @@
pluginManagement {
include ':react-native-share'
project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android')
includeBuild('../node_modules/@react-native/gradle-plugin')
repositories {
mavenLocal() // Let's prioritize local Maven repos so that Nix can provide them offline
gradlePluginPortal()
}
}
include ':react-native-share'
project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android')
rootProject.name = 'StatusIm'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':react-native-nfc-manager'
+1 -1
View File
@@ -92,7 +92,7 @@ For particular example it was failed on `Recover access(password:qwerty, keycard
Not all features of the app could be covered by e2e at the moment:
- Colours or place of an element on UI.
- Real ETH/token transactions. Thats the main reason we have separate .apk build for automation needs - it defaults to Goerli network. Also it has enabled keycard test menu, ENS names and chat commands are also on Goerli network (the same in PR builds, but not in nightlies / release)
- Real ETH/token transactions. Thats the main reason we have separate .apk build for automation needs - it defaults to Sepolia network. Also it has enabled keycard test menu, ENS names and chat commands are also on Sepolia network (the same in PR builds, but not in nightlies / release)
- Autologin/Biometric related actions (autologin available when device meets certain conditions like the it has set unlock password and device is not rooted: all emulators are rooted in SauceLabs)
## Brief flow for test to be automated
@@ -14,9 +14,8 @@ RCT_EXPORT_MODULE();
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");
NSLog(@"SendLogs() method called");
#endif
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
@@ -34,25 +33,6 @@ RCT_EXPORT_METHOD(sendLogs:(NSString *)dbJson
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"];
@@ -62,10 +42,6 @@ RCT_EXPORT_METHOD(sendLogs:(NSString *)dbJson
[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];
if ([fileManager fileExistsAtPath:requestsLogFile.path]) {
+453 -541
View File
File diff suppressed because it is too large Load Diff
+55 -13
View File
@@ -315,6 +315,7 @@ com.android.tools.build:gradle:7.0.4
com.android.tools.build:gradle:7.2.1
com.android.tools.build:gradle:7.3.1
com.android.tools.build:gradle:7.4.2
com.android.tools.build:gradle:8.1.1
com.android.tools.build:manifest-merger:24.3.1
com.android.tools.build:manifest-merger:24.5.0
com.android.tools.build:manifest-merger:26.0.1
@@ -339,6 +340,7 @@ com.android.tools.ddms:ddmlib:30.2.1
com.android.tools.ddms:ddmlib:30.3.1
com.android.tools.ddms:ddmlib:30.4.2
com.android.tools.ddms:ddmlib:31.1.1
com.android.tools.emulator:proto:31.1.1
com.android.tools.external.com-intellij:intellij-core:26.0.1
com.android.tools.external.lombok:lombok-ast:0.2.3
com.android.tools.external.org-jetbrains:uast:26.0.1
@@ -381,32 +383,43 @@ com.android.tools.utp:android-device-provider-ddmlib-proto:30.2.1
com.android.tools.utp:android-device-provider-ddmlib-proto:30.3.1
com.android.tools.utp:android-device-provider-ddmlib-proto:30.4.2
com.android.tools.utp:android-device-provider-ddmlib-proto:31.1.1
com.android.tools.utp:android-device-provider-ddmlib:31.1.1
com.android.tools.utp:android-device-provider-gradle-proto:30.0.4
com.android.tools.utp:android-device-provider-gradle-proto:30.2.1
com.android.tools.utp:android-device-provider-gradle-proto:30.3.1
com.android.tools.utp:android-device-provider-gradle-proto:30.4.2
com.android.tools.utp:android-device-provider-gradle-proto:31.1.1
com.android.tools.utp:android-device-provider-gradle:31.1.1
com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:30.2.1
com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:30.3.1
com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:30.4.2
com.android.tools.utp:android-test-plugin-host-additional-test-output-proto:31.1.1
com.android.tools.utp:android-test-plugin-host-additional-test-output:31.1.1
com.android.tools.utp:android-test-plugin-host-apk-installer-proto:31.1.1
com.android.tools.utp:android-test-plugin-host-apk-installer:31.1.1
com.android.tools.utp:android-test-plugin-host-coverage-proto:30.2.1
com.android.tools.utp:android-test-plugin-host-coverage-proto:30.3.1
com.android.tools.utp:android-test-plugin-host-coverage-proto:30.4.2
com.android.tools.utp:android-test-plugin-host-coverage-proto:31.1.1
com.android.tools.utp:android-test-plugin-host-coverage:31.1.1
com.android.tools.utp:android-test-plugin-host-device-info-proto:31.1.1
com.android.tools.utp:android-test-plugin-host-device-info:31.1.1
com.android.tools.utp:android-test-plugin-host-emulator-control-proto:31.1.1
com.android.tools.utp:android-test-plugin-host-emulator-control:31.1.1
com.android.tools.utp:android-test-plugin-host-logcat-proto:31.1.1
com.android.tools.utp:android-test-plugin-host-logcat:31.1.1
com.android.tools.utp:android-test-plugin-host-retention-proto:30.0.4
com.android.tools.utp:android-test-plugin-host-retention-proto:30.2.1
com.android.tools.utp:android-test-plugin-host-retention-proto:30.3.1
com.android.tools.utp:android-test-plugin-host-retention-proto:30.4.2
com.android.tools.utp:android-test-plugin-host-retention-proto:31.1.1
com.android.tools.utp:android-test-plugin-host-retention:31.1.1
com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:30.0.4
com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:30.2.1
com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:30.3.1
com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:30.4.2
com.android.tools.utp:android-test-plugin-result-listener-gradle-proto:31.1.1
com.android.tools.utp:android-test-plugin-result-listener-gradle:31.1.1
com.android.tools:annotations:24.3.1
com.android.tools:annotations:24.5.0
com.android.tools:annotations:26.0.1
@@ -574,6 +587,7 @@ com.google.code.gson:gson:2.8.0
com.google.code.gson:gson:2.8.5
com.google.code.gson:gson:2.8.6
com.google.code.gson:gson:2.8.9
com.google.code.gson:gson:2.9.1
com.google.crypto.tink:tink:1.3.0-rc2
com.google.crypto.tink:tink:1.7.0
com.google.dagger:dagger:2.28.3
@@ -583,6 +597,7 @@ com.google.errorprone:error_prone_annotations:2.3.1
com.google.errorprone:error_prone_annotations:2.3.2
com.google.errorprone:error_prone_annotations:2.3.4
com.google.errorprone:error_prone_annotations:2.4.0
com.google.errorprone:error_prone_annotations:2.7.1
com.google.errorprone:error_prone_annotations:2.9.0
com.google.errorprone:error_prone_annotations:2.11.0
com.google.flatbuffers:flatbuffers-java:1.12.0
@@ -594,6 +609,7 @@ com.google.guava:guava:27.0.1-jre
com.google.guava:guava:28.1-jre
com.google.guava:guava:29.0-jre
com.google.guava:guava:30.1-jre
com.google.guava:guava:31.0.1-jre
com.google.guava:guava:31.1-jre
com.google.guava:listenablefuture:1.0
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
@@ -610,9 +626,14 @@ com.google.protobuf:protobuf-java:3.4.0
com.google.protobuf:protobuf-java:3.10.0
com.google.protobuf:protobuf-java:3.17.2
com.google.protobuf:protobuf-java:3.19.3
com.google.testing.platform:android-device-provider-local:0.0.8-alpha08
com.google.testing.platform:android-driver-instrumentation:0.0.8-alpha08
com.google.testing.platform:android-test-plugin:0.0.8-alpha08
com.google.testing.platform:core-proto:0.0.8-alpha04
com.google.testing.platform:core-proto:0.0.8-alpha07
com.google.testing.platform:core-proto:0.0.8-alpha08
com.google.testing.platform:core:0.0.8-alpha08
com.google.testing.platform:launcher:0.0.8-alpha08
com.google.test.platform:core-proto:0.0.2-dev
com.google.zxing:core:3.4.1
com.ibm.icu:icu4j:53.1
@@ -785,6 +806,8 @@ org.glassfish.jaxb:jaxb-runtime:2.3.2
org.glassfish.jaxb:txw2:2.2.11
org.glassfish.jaxb:txw2:2.3.1
org.glassfish.jaxb:txw2:2.3.2
org.gradle.toolchains:foojay-resolver:0.5.0
org.gradle:github-dependency-graph-gradle-plugin:1.3.1
org.hamcrest:hamcrest-core:1.3
org.hamcrest:hamcrest:2.2
org.jacoco:org.jacoco.core:0.7.4.201502262128
@@ -798,45 +821,64 @@ org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.1
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.3
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.1
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.3
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3
org.jetbrains.kotlin:kotlin-android-extensions:1.6.20
org.jetbrains.kotlin:kotlin-android-extensions:1.8.0
org.jetbrains.kotlin:kotlin-android-extensions:1.9.0
org.jetbrains.kotlin:kotlin-annotations-jvm:1.3.72
org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.6.20
org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.8.0
org.jetbrains.kotlin:kotlin-build-common:1.6.20
org.jetbrains.kotlin:kotlin-build-common:1.8.0
org.jetbrains.kotlin:kotlin-build-tools-api:1.9.0
org.jetbrains.kotlin:kotlin-build-tools-impl:1.9.0
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.6.20
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.0
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.0
org.jetbrains.kotlin:kotlin-compiler-runner:1.6.20
org.jetbrains.kotlin:kotlin-compiler-runner:1.8.0
org.jetbrains.kotlin:kotlin-compiler-runner:1.9.0
org.jetbrains.kotlin:kotlin-daemon-client:1.6.20
org.jetbrains.kotlin:kotlin-daemon-client:1.8.0
org.jetbrains.kotlin:kotlin-daemon-client:1.9.0
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.6.20
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.8.0
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.9.0
org.jetbrains.kotlin:kotlin-gradle-plugins-bom:1.9.0
org.jetbrains.kotlin:kotlin-gradle-plugin-annotations:1.9.0
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.6.20
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.0
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.9.0
org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.8.0
org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.9.0
org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.8.0
org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.9.0
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.6.20
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.8.0
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.9.0
org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20
org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0
org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0
org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.6.20
org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.8.0
org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.9.0
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.8.0
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.9.0
org.jetbrains.kotlin:kotlin-native-utils:1.6.20
org.jetbrains.kotlin:kotlin-native-utils:1.8.0
org.jetbrains.kotlin:kotlin-native-utils:1.9.0
org.jetbrains.kotlin:kotlin-project-model:1.6.20
org.jetbrains.kotlin:kotlin-project-model:1.8.0
org.jetbrains.kotlin:kotlin-project-model:1.9.0
org.jetbrains.kotlin:kotlin-reflect:1.1.3-2
org.jetbrains.kotlin:kotlin-reflect:1.2.0
@@ -848,13 +890,18 @@ org.jetbrains.kotlin:kotlin-reflect:1.6.10
org.jetbrains.kotlin:kotlin-reflect:1.7.10
org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC2
org.jetbrains.kotlin:kotlin-scripting-common:1.6.20
org.jetbrains.kotlin:kotlin-scripting-common:1.8.0
org.jetbrains.kotlin:kotlin-scripting-common:1.9.0
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.6.20
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.8.0
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.9.0
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.6.20
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.8.0
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.9.0
org.jetbrains.kotlin:kotlin-scripting-jvm:1.6.20
org.jetbrains.kotlin:kotlin-scripting-jvm:1.8.0
org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.0
org.jetbrains.kotlin:kotlin-script-runtime:1.8.0
org.jetbrains.kotlin:kotlin-script-runtime:1.9.0
org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50
@@ -863,6 +910,7 @@ org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32
org.jetbrains.kotlin:kotlin-stdlib-common:1.5.31
org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10
org.jetbrains.kotlin:kotlin-stdlib-common:1.8.0
org.jetbrains.kotlin:kotlin-stdlib-common:1.8.20-RC2
org.jetbrains.kotlin:kotlin-stdlib-common:1.8.21
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0
@@ -874,6 +922,7 @@ org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.20
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.20-RC2
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0
@@ -883,6 +932,7 @@ org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.31
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20-RC2
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0
@@ -894,15 +944,19 @@ org.jetbrains.kotlin:kotlin-stdlib:1.4.32
org.jetbrains.kotlin:kotlin-stdlib:1.5.31
org.jetbrains.kotlin:kotlin-stdlib:1.6.20
org.jetbrains.kotlin:kotlin-stdlib:1.7.10
org.jetbrains.kotlin:kotlin-stdlib:1.8.0
org.jetbrains.kotlin:kotlin-stdlib:1.8.20-RC2
org.jetbrains.kotlin:kotlin-stdlib:1.8.21
org.jetbrains.kotlin:kotlin-stdlib:1.9.0
org.jetbrains.kotlin:kotlin-stdlib:1.9.22
org.jetbrains.kotlin:kotlin-tooling-core:1.8.0
org.jetbrains.kotlin:kotlin-tooling-core:1.9.0
org.jetbrains.kotlin:kotlin-tooling-metadata:1.6.20
org.jetbrains.kotlin:kotlin-util-io:1.6.20
org.jetbrains.kotlin:kotlin-util-io:1.8.0
org.jetbrains.kotlin:kotlin-util-io:1.9.0
org.jetbrains.kotlin:kotlin-util-klib:1.6.20
org.jetbrains.kotlin:kotlin-util-klib:1.8.0
org.jetbrains.kotlin:kotlin-util-klib:1.9.0
org.jetbrains.trove4j:trove4j:20160824
org.jetbrains:annotations:13.0
@@ -964,20 +1018,8 @@ org.tensorflow:tensorflow-lite-metadata:0.1.0-rc1
org.tensorflow:tensorflow-lite-metadata:0.1.0-rc2
xerces:xercesImpl:2.12.0
xml-apis:xml-apis:1.4.01
com.android.tools.build:gradle:1.3.1
com.squareup.okio:okio:1.13.0
com.squareup.okio:okio:1.15.0
com.squareup.okhttp3:okhttp:3.12.1
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.22
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.9.0
org.gradle.toolchains.foojay-resolver-convention:org.gradle.toolchains.foojay-resolver-convention.gradle.plugin:0.5.0
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.0
com.android.tools.build:gradle:8.1.1
com.google.errorprone:error_prone_annotations:2.7.1
com.android.tools.lint:lint-gradle:31.1.1
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0
com.android.tools.build:gradle:3.5.4
androidx.annotation:annotation:1.6.0
androidx.annotation:annotation-jvm:1.6.0
com.android.tools.lint:lint-gradle:31.1.1
com.facebook.react:hermes-android:0.73.5
+30 -38
View File
@@ -416,6 +416,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/30.2.1/dvlib-30.
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/30.3.1/dvlib-30.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/30.4.2/dvlib-30.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/31.1.1/dvlib-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/emulator/proto/31.1.1/proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/external/com-intellij/intellij-core/26.0.1/intellij-core-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/external/com-intellij/intellij-core/31.1.1/intellij-core-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/external/com-intellij/kotlin-compiler/31.1.1/kotlin-compiler-31.1.1.pom
@@ -487,32 +488,43 @@ https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-pro
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-ddmlib-proto/30.3.1/android-device-provider-ddmlib-proto-30.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-ddmlib-proto/30.4.2/android-device-provider-ddmlib-proto-30.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-ddmlib-proto/31.1.1/android-device-provider-ddmlib-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-ddmlib/31.1.1/android-device-provider-ddmlib-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-gradle-proto/30.0.4/android-device-provider-gradle-proto-30.0.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-gradle-proto/30.2.1/android-device-provider-gradle-proto-30.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-gradle-proto/30.3.1/android-device-provider-gradle-proto-30.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-gradle-proto/30.4.2/android-device-provider-gradle-proto-30.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-gradle-proto/31.1.1/android-device-provider-gradle-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-device-provider-gradle/31.1.1/android-device-provider-gradle-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-additional-test-output-proto/30.2.1/android-test-plugin-host-additional-test-output-proto-30.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-additional-test-output-proto/30.3.1/android-test-plugin-host-additional-test-output-proto-30.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-additional-test-output-proto/30.4.2/android-test-plugin-host-additional-test-output-proto-30.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-additional-test-output-proto/31.1.1/android-test-plugin-host-additional-test-output-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-additional-test-output/31.1.1/android-test-plugin-host-additional-test-output-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-apk-installer-proto/31.1.1/android-test-plugin-host-apk-installer-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-apk-installer/31.1.1/android-test-plugin-host-apk-installer-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-coverage-proto/30.2.1/android-test-plugin-host-coverage-proto-30.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-coverage-proto/30.3.1/android-test-plugin-host-coverage-proto-30.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-coverage-proto/30.4.2/android-test-plugin-host-coverage-proto-30.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-coverage-proto/31.1.1/android-test-plugin-host-coverage-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-coverage/31.1.1/android-test-plugin-host-coverage-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-device-info-proto/31.1.1/android-test-plugin-host-device-info-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-device-info/31.1.1/android-test-plugin-host-device-info-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-emulator-control-proto/31.1.1/android-test-plugin-host-emulator-control-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-emulator-control/31.1.1/android-test-plugin-host-emulator-control-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-logcat-proto/31.1.1/android-test-plugin-host-logcat-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-logcat/31.1.1/android-test-plugin-host-logcat-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-retention-proto/30.0.4/android-test-plugin-host-retention-proto-30.0.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-retention-proto/30.2.1/android-test-plugin-host-retention-proto-30.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-retention-proto/30.3.1/android-test-plugin-host-retention-proto-30.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-retention-proto/30.4.2/android-test-plugin-host-retention-proto-30.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-retention-proto/31.1.1/android-test-plugin-host-retention-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-host-retention/31.1.1/android-test-plugin-host-retention-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-result-listener-gradle-proto/30.0.4/android-test-plugin-result-listener-gradle-proto-30.0.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-result-listener-gradle-proto/30.2.1/android-test-plugin-result-listener-gradle-proto-30.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-result-listener-gradle-proto/30.3.1/android-test-plugin-result-listener-gradle-proto-30.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-result-listener-gradle-proto/30.4.2/android-test-plugin-result-listener-gradle-proto-30.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-result-listener-gradle-proto/31.1.1/android-test-plugin-result-listener-gradle-proto-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/utp/android-test-plugin-result-listener-gradle/31.1.1/android-test-plugin-result-listener-gradle-31.1.1.pom
https://dl.google.com/dl/android/maven2/com/android/zipflinger/4.1.0/zipflinger-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/zipflinger/7.0.4/zipflinger-7.0.4.pom
https://dl.google.com/dl/android/maven2/com/android/zipflinger/7.2.1/zipflinger-7.2.1.pom
@@ -522,9 +534,14 @@ https://dl.google.com/dl/android/maven2/com/android/zipflinger/8.1.1/zipflinger-
https://dl.google.com/dl/android/maven2/com/google/android/material/material/1.0.0/material-1.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/material/material/1.2.0-alpha03/material-1.2.0-alpha03.pom
https://dl.google.com/dl/android/maven2/com/google/prefab/cli/2.0.0/cli-2.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/testing/platform/android-device-provider-local/0.0.8-alpha08/android-device-provider-local-0.0.8-alpha08.pom
https://dl.google.com/dl/android/maven2/com/google/testing/platform/android-driver-instrumentation/0.0.8-alpha08/android-driver-instrumentation-0.0.8-alpha08.pom
https://dl.google.com/dl/android/maven2/com/google/testing/platform/android-test-plugin/0.0.8-alpha08/android-test-plugin-0.0.8-alpha08.pom
https://dl.google.com/dl/android/maven2/com/google/testing/platform/core-proto/0.0.8-alpha04/core-proto-0.0.8-alpha04.pom
https://dl.google.com/dl/android/maven2/com/google/testing/platform/core-proto/0.0.8-alpha07/core-proto-0.0.8-alpha07.pom
https://dl.google.com/dl/android/maven2/com/google/testing/platform/core-proto/0.0.8-alpha08/core-proto-0.0.8-alpha08.pom
https://dl.google.com/dl/android/maven2/com/google/testing/platform/core/0.0.8-alpha08/core-0.0.8-alpha08.pom
https://dl.google.com/dl/android/maven2/com/google/testing/platform/launcher/0.0.8-alpha08/launcher-0.0.8-alpha08.pom
https://dl.google.com/dl/android/maven2/com/google/test/platform/core-proto/0.0.2-dev/core-proto-0.0.2-dev.pom
https://jitpack.io/com/github/Dimezis/BlurView/version-2.0.4/BlurView-version-2.0.4.pom
https://jitpack.io/com/github/status-im/function/0.0.1/function-0.0.1.pom
@@ -535,6 +552,7 @@ https://jitpack.io/com/github/wix-playground/reflow-animator/1.0.6/reflow-animat
https://jitpack.io/com/github/yalantis/ucrop/2.2.6-native/ucrop-2.2.6-native.pom
https://jitpack.io/com/github/zacharee/AndroidPdfViewer/4.0.1/AndroidPdfViewer-4.0.1.pom
https://plugins.gradle.org/m2/com/adarshr/gradle-test-logger-plugin/2.0.0/gradle-test-logger-plugin-2.0.0.pom
https://plugins.gradle.org/m2/org/gradle/github-dependency-graph-gradle-plugin/1.3.1/github-dependency-graph-gradle-plugin-1.3.1.pom
https://plugins.gradle.org/m2/org/gradle/toolchains/foojay-resolver-convention/org.gradle.toolchains.foojay-resolver-convention.gradle.plugin/0.5.0/org.gradle.toolchains.foojay-resolver-convention.gradle.plugin-0.5.0.pom
https://plugins.gradle.org/m2/org/gradle/toolchains/foojay-resolver/0.5.0/foojay-resolver-0.5.0.pom
https://repo.maven.apache.org/maven2/antlr/antlr/2.7.1/antlr-2.7.1.pom
@@ -733,7 +751,7 @@ https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotatio
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.10.0/error_prone_annotations-2.10.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.11.0/error_prone_annotations-2.11.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.27.0/error_prone_annotations-2.27.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.33.0/error_prone_annotations-2.33.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.35.1/error_prone_annotations-2.35.1.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.0.18/error_prone_parent-2.0.18.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.2.0/error_prone_parent-2.2.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.3.1/error_prone_parent-2.3.1.pom
@@ -746,7 +764,7 @@ https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.10.0/error_prone_parent-2.10.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.11.0/error_prone_parent-2.11.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.27.0/error_prone_parent-2.27.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.33.0/error_prone_parent-2.33.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.35.1/error_prone_parent-2.35.1.pom
https://repo.maven.apache.org/maven2/com/google/flatbuffers/flatbuffers-java/1.12.0/flatbuffers-java-1.12.0.pom
https://repo.maven.apache.org/maven2/com/google/google/1/google-1.pom
https://repo.maven.apache.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.pom
@@ -791,7 +809,7 @@ https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/3.13.0/pro
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/3.17.2/protobuf-bom-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/3.19.2/protobuf-bom-3.19.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/3.19.3/protobuf-bom-3.19.3.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/4.29.0-RC1/protobuf-bom-4.29.0-RC1.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/4.29.0-RC2/protobuf-bom-4.29.0-RC2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-javalite/3.17.2/protobuf-javalite-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-javalite/3.19.2/protobuf-javalite-3.19.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java-util/3.4.0/protobuf-java-util-3.4.0.pom
@@ -808,7 +826,7 @@ https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.13.0/pr
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.17.2/protobuf-java-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.19.2/protobuf-java-3.19.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.19.3/protobuf-java-3.19.3.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/4.29.0-RC1/protobuf-java-4.29.0-RC1.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/4.29.0-RC2/protobuf-java-4.29.0-RC2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-lite/3.0.1/protobuf-lite-3.0.1.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.0.0/protobuf-parent-3.0.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.4.0/protobuf-parent-3.4.0.pom
@@ -819,7 +837,7 @@ https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.13.0/
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.17.2/protobuf-parent-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.19.2/protobuf-parent-3.19.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.19.3/protobuf-parent-3.19.3.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/4.29.0-RC1/protobuf-parent-4.29.0-RC1.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/4.29.0-RC2/protobuf-parent-4.29.0-RC2.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth-parent/1.4.4/truth-parent-1.4.4.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth/1.4.4/truth-1.4.4.pom
https://repo.maven.apache.org/maven2/com/google/zxing/core/3.4.1/core-3.4.1.pom
@@ -841,11 +859,7 @@ https://repo.maven.apache.org/maven2/com/squareup/okhttp3/parent/3.9.1/parent-3.
https://repo.maven.apache.org/maven2/com/squareup/okhttp3/parent/3.12.1/parent-3.12.1.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.2.0/okio-jvm-3.2.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.9.1/okio-jvm-3.9.1.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-parent/1.13.0/okio-parent-1.13.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-parent/1.15.0/okio-parent-1.15.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-parent/1.17.4/okio-parent-1.17.4.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.13.0/okio-1.13.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.15.0/okio-1.15.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.17.4/okio-1.17.4.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.8.0/okio-2.8.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.9.0/okio-2.9.0.pom
@@ -1197,81 +1211,68 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-an
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-android/1.6.1/kotlinx-coroutines-android-1.6.1.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-android/1.7.3/kotlinx-coroutines-android-1.7.3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-bom/1.6.1/kotlinx-coroutines-bom-1.6.1.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-bom/1.6.3/kotlinx-coroutines-bom-1.6.3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-bom/1.7.3/kotlinx-coroutines-bom-1.7.3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.4.1/kotlinx-coroutines-core-jvm-1.4.1.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.0/kotlinx-coroutines-core-jvm-1.5.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.2/kotlinx-coroutines-core-jvm-1.5.2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.6.1/kotlinx-coroutines-core-jvm-1.6.1.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.6.3/kotlinx-coroutines-core-jvm-1.6.3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.7.3/kotlinx-coroutines-core-jvm-1.7.3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.4.1/kotlinx-coroutines-core-1.4.1.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.5.2/kotlinx-coroutines-core-1.5.2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.6.1/kotlinx-coroutines-core-1.6.1.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.6.3/kotlinx-coroutines-core-1.6.3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.7.3/kotlinx-coroutines-core-1.7.3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-metadata-jvm/0.1.0/kotlinx-metadata-jvm-0.1.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.22/org.jetbrains.kotlin.jvm.gradle.plugin-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.8.0/org.jetbrains.kotlin.jvm.gradle.plugin-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.9.0/org.jetbrains.kotlin.jvm.gradle.plugin-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-android-extensions/1.6.20/kotlin-android-extensions-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-android-extensions/1.7.22/kotlin-android-extensions-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-android-extensions/1.8.0/kotlin-android-extensions-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-android-extensions/1.9.0/kotlin-android-extensions-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-annotations-jvm/1.3.72/kotlin-annotations-jvm-1.3.72.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.6.20/kotlin-annotation-processing-gradle-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.22/kotlin-annotation-processing-gradle-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.8.0/kotlin-annotation-processing-gradle-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-common/1.6.20/kotlin-build-common-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-common/1.7.22/kotlin-build-common-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-common/1.8.0/kotlin-build-common-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-common/1.9.0/kotlin-build-common-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-tools-api/1.9.0/kotlin-build-tools-api-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-build-tools-impl/1.9.0/kotlin-build-tools-impl-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.6.20/kotlin-compiler-embeddable-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.22/kotlin-compiler-embeddable-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.8.0/kotlin-compiler-embeddable-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.9.0/kotlin-compiler-embeddable-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-runner/1.6.20/kotlin-compiler-runner-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.22/kotlin-compiler-runner-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-runner/1.8.0/kotlin-compiler-runner-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-compiler-runner/1.9.0/kotlin-compiler-runner-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-client/1.6.20/kotlin-daemon-client-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-client/1.7.22/kotlin-daemon-client-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-client/1.8.0/kotlin-daemon-client-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-client/1.9.0/kotlin-daemon-client-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.6.20/kotlin-daemon-embeddable-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.22/kotlin-daemon-embeddable-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.8.0/kotlin-daemon-embeddable-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.9.0/kotlin-daemon-embeddable-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.9.0/kotlin-gradle-plugins-bom-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.9.0/kotlin-gradle-plugin-annotations-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.6.20/kotlin-gradle-plugin-api-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.22/kotlin-gradle-plugin-api-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.8.0/kotlin-gradle-plugin-api-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.9.0/kotlin-gradle-plugin-api-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.7.22/kotlin-gradle-plugin-idea-proto-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.8.0/kotlin-gradle-plugin-idea-proto-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.9.0/kotlin-gradle-plugin-idea-proto-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.22/kotlin-gradle-plugin-idea-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.8.0/kotlin-gradle-plugin-idea-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.9.0/kotlin-gradle-plugin-idea-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.6.20/kotlin-gradle-plugin-model-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.22/kotlin-gradle-plugin-model-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.8.0/kotlin-gradle-plugin-model-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.9.0/kotlin-gradle-plugin-model-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.6.20/kotlin-gradle-plugin-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.22/kotlin-gradle-plugin-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.8.0/kotlin-gradle-plugin-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-gradle-plugin/1.9.0/kotlin-gradle-plugin-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.6.20/kotlin-klib-commonizer-api-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.22/kotlin-klib-commonizer-api-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.8.0/kotlin-klib-commonizer-api-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.9.0/kotlin-klib-commonizer-api-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.8.0/kotlin-klib-commonizer-embeddable-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-klib-commonizer-embeddable/1.9.0/kotlin-klib-commonizer-embeddable-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-native-utils/1.6.20/kotlin-native-utils-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-native-utils/1.7.22/kotlin-native-utils-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-native-utils/1.8.0/kotlin-native-utils-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-native-utils/1.9.0/kotlin-native-utils-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-project-model/1.6.20/kotlin-project-model-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-project-model/1.7.22/kotlin-project-model-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-project-model/1.8.0/kotlin-project-model-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-project-model/1.9.0/kotlin-project-model-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.1.3-2/kotlin-reflect-1.1.3-2.pom
@@ -1283,27 +1284,21 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.5.31/
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.20/kotlin-reflect-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.10/kotlin-reflect-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.22/kotlin-reflect-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.8.20-RC2/kotlin-reflect-1.8.20-RC2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/2.1.0-Beta2/kotlin-reflect-2.1.0-Beta2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.20/kotlin-scripting-common-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.22/kotlin-scripting-common-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.8.0/kotlin-scripting-common-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.9.0/kotlin-scripting-common-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.6.20/kotlin-scripting-compiler-embeddable-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.22/kotlin-scripting-compiler-embeddable-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.8.0/kotlin-scripting-compiler-embeddable-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.9.0/kotlin-scripting-compiler-embeddable-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.6.20/kotlin-scripting-compiler-impl-embeddable-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.22/kotlin-scripting-compiler-impl-embeddable-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.8.0/kotlin-scripting-compiler-impl-embeddable-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.9.0/kotlin-scripting-compiler-impl-embeddable-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.6.20/kotlin-scripting-jvm-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.22/kotlin-scripting-jvm-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.8.0/kotlin-scripting-jvm-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-jvm/1.9.0/kotlin-scripting-jvm-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.6.20/kotlin-script-runtime-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.7.22/kotlin-script-runtime-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.8.0/kotlin-script-runtime-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.9.0/kotlin-script-runtime-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.71/kotlin-stdlib-common-1.2.71.pom
@@ -1326,7 +1321,6 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.20/kotlin-stdlib-common-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.21/kotlin-stdlib-common-1.6.21.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10/kotlin-stdlib-common-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.22/kotlin-stdlib-common-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.0/kotlin-stdlib-common-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.20-RC2/kotlin-stdlib-common-1.8.20-RC2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.20/kotlin-stdlib-common-1.8.20.pom
@@ -1345,6 +1339,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.5
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.0/kotlin-stdlib-jdk7-1.6.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.10/kotlin-stdlib-jdk7-1.6.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.20/kotlin-stdlib-jdk7-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.21/kotlin-stdlib-jdk7-1.6.21.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10/kotlin-stdlib-jdk7-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.0/kotlin-stdlib-jdk7-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.20-RC2/kotlin-stdlib-jdk7-1.8.20-RC2.pom
@@ -1362,6 +1357,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.5
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.0/kotlin-stdlib-jdk8-1.6.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.10/kotlin-stdlib-jdk8-1.6.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.20/kotlin-stdlib-jdk8-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.21/kotlin-stdlib-jdk8-1.6.21.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10/kotlin-stdlib-jdk8-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.0/kotlin-stdlib-jdk8-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.20-RC2/kotlin-stdlib-jdk8-1.8.20-RC2.pom
@@ -1391,7 +1387,6 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.10/k
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.20/kotlin-stdlib-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.21/kotlin-stdlib-1.6.21.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.10/kotlin-stdlib-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.22/kotlin-stdlib-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.8.0/kotlin-stdlib-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.8.20-RC2/kotlin-stdlib-1.8.20-RC2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.8.20/kotlin-stdlib-1.8.20.pom
@@ -1401,16 +1396,13 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.0/ko
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.22/kotlin-stdlib-1.9.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.25/kotlin-stdlib-1.9.25.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/2.1.0-Beta2/kotlin-stdlib-2.1.0-Beta2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-core/1.7.22/kotlin-tooling-core-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-core/1.8.0/kotlin-tooling-core-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-core/1.9.0/kotlin-tooling-core-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-metadata/1.6.20/kotlin-tooling-metadata-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-io/1.6.20/kotlin-util-io-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-io/1.7.22/kotlin-util-io-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-io/1.8.0/kotlin-util-io-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-io/1.9.0/kotlin-util-io-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-klib/1.6.20/kotlin-util-klib-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-klib/1.7.22/kotlin-util-klib-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-klib/1.8.0/kotlin-util-klib-1.8.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-klib/1.9.0/kotlin-util-klib-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/markdown-jvm/0.2.1/markdown-jvm-0.2.1.pom
@@ -1420,7 +1412,7 @@ https://repo.maven.apache.org/maven2/org/json/json/20180813/json-20180813.pom
https://repo.maven.apache.org/maven2/org/json/json/20240303/json-20240303.pom
https://repo.maven.apache.org/maven2/org/jsoup/jsoup/1.13.1/jsoup-1.13.1.pom
https://repo.maven.apache.org/maven2/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.11.2/junit-bom-5.11.2.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.11.3/junit-bom-5.11.3.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.7.7/stax-ex-1.7.7.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.8.1/stax-ex-1.8.1.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.8/stax-ex-1.8.pom
+2 -14
View File
@@ -42,22 +42,10 @@ function gen_deps_list() {
# https://github.com/status-im/status-mobile/issues/15447
function add_deps_hack() {
echo -n \
'com.android.tools.build:gradle:1.3.1
com.squareup.okio:okio:1.13.0
com.squareup.okio:okio:1.15.0
com.squareup.okhttp3:okhttp:3.12.1
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.22
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.9.0
org.gradle.toolchains.foojay-resolver-convention:org.gradle.toolchains.foojay-resolver-convention.gradle.plugin:0.5.0
'org.gradle.toolchains.foojay-resolver-convention:org.gradle.toolchains.foojay-resolver-convention.gradle.plugin:0.5.0
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.0
com.android.tools.build:gradle:8.1.1
com.google.errorprone:error_prone_annotations:2.7.1
com.android.tools.lint:lint-gradle:31.1.1
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0
com.android.tools.build:gradle:3.5.4
androidx.annotation:annotation:1.6.0
androidx.annotation:annotation-jvm:1.6.0
com.android.tools.lint:lint-gradle:31.1.1
com.facebook.react:hermes-android:0.73.5' \
>> "${DEPS_LIST}"
}
+8 -19
View File
@@ -7,6 +7,7 @@
set -Eeuo pipefail
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
GRADLE_REPORTS_DIR="${GIT_ROOT}/android/build/reports/dependency-graph-snapshots"
# Gradle needs to be run in 'android' subfolder.
cd "${GIT_ROOT}/android"
@@ -15,23 +16,11 @@ GRADLE_LOG_FILE='/tmp/gradle.log'
function show_gradle_log() { cat "${GRADLE_LOG_FILE}" >&2; }
trap show_gradle_log ERR
# Run the gradle command for a project:
# - ':buildEnvironment' to get build tools
# - ':dependencies' to get direct deps limited those by
# implementation config to avoid test dependencies
DEPS=("${@}")
declare -a BUILD_DEPS
declare -a NORMAL_DEPS
for i in "${!DEPS[@]}"; do
BUILD_DEPS[${i}]="${DEPS[${i}]}:buildEnvironment"
NORMAL_DEPS[${i}]="${DEPS[${i}]}:dependencies"
done
./gradlew -I init.gradle \
--dependency-verification=off \
--no-configuration-cache --no-configure-on-demand \
:ForceDependencyResolutionPlugin_resolveAllDependencies > "${GRADLE_LOG_FILE}" 2>&1
# And clean up the output using AWK script.
AWK_SCRIPT="${GIT_ROOT}/nix/deps/gradle/gradle_parser.awk"
./gradlew --no-daemon --console plain \
"${BUILD_DEPS[@]}" \
"${NORMAL_DEPS[@]}" \
| tee "${GRADLE_LOG_FILE}" \
| awk -f "${AWK_SCRIPT}"
# skip org.webkit:android-jsc, its provided by react-native
# remove when new architecture is enabled
jq -r '.[].dependency | select(startswith("org.webkit:android-jsc") | not)' "${GRADLE_REPORTS_DIR}/dependency-resolution.json"
-55
View File
@@ -1,55 +0,0 @@
# This script parses the AWFUL Gradle output of :dependencies calls
# and outputs just the names of the packages in the Maven format:
# <groupId>:<artifactId>:<version>
function findPackage(line, regex) {
rval = match(line, regex, matches)
if (rval != 0) {
dep = sprintf("%s:%s:%s", matches[1], matches[2], matches[3])
if (deps[dep] == nil) {
deps[dep] = 1
}
return 1
}
return 0
}
# Gradle outputs dependencies in groups defined by configurations.
# Those configurations are words followed by a dash and a description.
# There's also a special 'classpath' configuration we want.
/^(classpath|[a-zA-Z0-9]+)( - .*)?$/ {
# Ignore configurations starting with 'test'
if (tolower($1) ~ /^test/) {
next
}
# Lines after configuration name list packages
for (getline line; line != ""; getline line) {
# JavaScript Core (JSC) is provided by node_modules
if (line ~ "org.webkit:android-jsc") { continue }
# Example: +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.50
if (findPackage(line, "--- ([^ :]+):([^ :]+):([^ :]+)$")) {
continue
}
# Example: +--- androidx.lifecycle:lifecycle-common:{strictly 2.0.0} -> 2.0.0 (c)
if (findPackage(line, "--- ([^ :]+):([^ :]+):[^:]+ -> ([^ :]+) ?(\\([*c]\\))?$")) {
continue
}
# Example: +--- com.android.support:appcompat-v7:28.0.0 -> androidx.appcompat:appcompat:1.0.2
if (findPackage(line, "--- [^ :]+:[^ :]+:[^ ]+ -> ([^ :]+):([^ :]+):([^ :]+)$")) {
continue
}
}
}
END{
# It's nicer to sort it
asorti(deps, sorted)
for (i in sorted) {
print sorted[i]
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1001 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

-3
View File
@@ -32,12 +32,9 @@ trap "rm -vf ${SECRETS_FILE_PATH}" EXIT ERR INT QUIT
# Names of variables containing secrets to save in env file.
SECRETS_ENV_VARS=(
'ALCHEMY_ETHEREUM_MAINNET_TOKEN'
'ALCHEMY_ETHEREUM_GOERLI_TOKEN'
'ALCHEMY_ETHEREUM_SEPOLIA_TOKEN'
'ALCHEMY_ARBITRUM_GOERLI_TOKEN'
'ALCHEMY_ARBITRUM_MAINNET_TOKEN'
'ALCHEMY_ARBITRUM_SEPOLIA_TOKEN'
'ALCHEMY_OPTIMISM_GOERLI_TOKEN'
'ALCHEMY_OPTIMISM_MAINNET_TOKEN'
'ALCHEMY_OPTIMISM_SEPOLIA_TOKEN'
'RARIBLE_MAINNET_API_KEY'
-9
View File
@@ -75,13 +75,10 @@
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
:compiler-options {:output-feature-set :es5
;; We disable `:fn-deprecated` warnings because we
@@ -114,13 +111,10 @@
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
:compiler-options {:output-feature-set :es6
;;disable for android build as there
@@ -158,13 +152,10 @@
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"
status-im.config/WALLET_CONNECT_PROJECT_ID #shadow/env "WALLET_CONNECT_PROJECT_ID"}
:compiler-options
+10 -12
View File
@@ -3,8 +3,7 @@
["react-native" :as rn]
["react-native-status-keycard" :default status-keycard]
[react-native.platform :as platform]
[taoensso.timbre :as log]
[utils.address :as address]))
[taoensso.timbre :as log]))
(defonce event-emitter
(if platform/ios?
@@ -94,22 +93,14 @@
[{:keys [on-success on-failure]}]
(.. status-keycard
(getApplicationInfo)
(then (fn [response]
(let [info (-> response
(js->clj :keywordize-keys true)
(update :key-uid address/normalized-hex))]
(on-success info))))
(then on-success)
(catch on-failure)))
(defn factory-reset
[{:keys [on-success on-failure]}]
(.. status-keycard
(factoryReset)
(then (fn [response]
(let [info (-> response
(js->clj :keywordize-keys true)
(update :key-uid address/normalized-hex))]
(on-success info))))
(then on-success)
(catch on-failure)))
(defn install-applet
@@ -155,6 +146,13 @@
(then on-success)
(catch on-failure)))
(defn save-mnemonic
[{:keys [mnemonic pin on-success on-failure]}]
(.. status-keycard
(saveMnemonic mnemonic pin)
(then on-success)
(catch on-failure)))
(defn unblock-pin
[{:keys [puk new-pin on-success on-failure]}]
(when (and new-pin puk)
+2 -2
View File
@@ -20,9 +20,9 @@
{:mainnet {:name "Ether"
:symbol :ETH
:decimals 18}
:goerli {:name "Goerli Ether"
:sepolia {:name "Sepolia Ether"
:symbol :ETH
:symbol-display :ETHgo
:symbol-display :ETH
:decimals 18}
:xdai {:name "xDAI"
:symbol :ETH
@@ -15,12 +15,12 @@
(def etherscan-supported?
#{(chain/chain-keyword->chain-id :mainnet)
(chain/chain-keyword->chain-id :goerli)})
(chain/chain-keyword->chain-id :sepolia)})
(def binance-mainnet-chain-id (chain/chain-keyword->chain-id :bsc))
(def binance-testnet-chain-id (chain/chain-keyword->chain-id :bsc-testnet))
(def network->subdomain {5 "goerli"})
(def network->subdomain {11155111 "sepolia"})
(defn get-transaction-details-url
[chain-id tx-hash]
+6 -7
View File
@@ -508,17 +508,16 @@
new-password-hashed
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")
(defn convert-to-keycard-profile
[{:keys [key-uid] :as profile} settings password new-password callback]
(.convertToKeycardAccount ^js (encryption)
key-uid
(types/clj->json multiaccount-data)
(types/clj->json profile)
(types/clj->json settings)
""
current-password#
(:keycard-instance-uid settings)
password
new-password
callback))
#(when callback (callback (types/json->clj %)))))
(defn backup-disabled-data-dir
[]
@@ -3,12 +3,12 @@
(def inner-container
{:flex-direction :row
:justify-content :center
:justify-content :space-between
:flex 1})
(def button-container
{:padding-vertical 8
:width 77.75
:flex 1
:justify-content :center
:align-items :center})
+1 -1
View File
@@ -16,7 +16,7 @@
"
[{:keys [holder-name locked?]}]
(let [theme (quo.theme/use-theme)
label (if (boolean holder-name)
label (if holder-name
(i18n/label :t/user-keycard {:name holder-name})
(i18n/label :t/empty-keycard))]
[rn/view {:style (style/card-container locked? theme)}
+4 -2
View File
@@ -3,8 +3,10 @@
(defn container
[container-style]
(merge container-style
{:flex-direction :row
:align-items :flex-start}))
{:padding-vertical 7
:padding-horizontal 20
:flex-direction :row
:align-items :flex-start}))
(def index
{:margin-left 5})
+1 -1
View File
@@ -45,7 +45,7 @@
:or {type :bullet}}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (style/container container-style)}
[rn/view {:style style/index}
[rn/view
(case type
:step
[step/view
@@ -55,26 +55,36 @@
theme))}])]))
(defn- left-title
[{:keys [title blur?]}]
[{:keys [title blur? title-icon]}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style style/title-container}
[text/text
{:weight :regular
:size :paragraph-2
:style (style/title blur? theme)}
title]]))
title]
(when title-icon
[icons/icon title-icon
{:accessibility-label :title-icon
:size 12
:color (if blur?
colors/neutral-40
(colors/theme-colors colors/neutral-50
colors/neutral-40
theme))}])]))
(defn- left-side
"The description can either be given as a string `subtitle-type` or a component `custom-subtitle`"
[{:keys [title status size blur? custom-subtitle icon subtitle subtitle-type subtitle-color icon-color
customization-color network-image emoji]
customization-color network-image emoji title-icon]
:as props}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style style/left-side}
[left-title
{:title title
:blur? blur?
:theme theme}]
[rn/view
[left-title
{:title title
:title-icon title-icon
:blur? blur?}]]
(if (= status :loading)
[left-loading
{:size size
@@ -132,6 +142,7 @@
[:subtitle {:optional true} [:maybe [:or :string :double]]]
[:custom-subtitle {:optional true} [:maybe fn?]]
[:icon {:optional true} [:maybe :keyword]]
[:title-icon {:optional true} [:maybe :keyword]]
[:emoji {:optional true} [:maybe :string]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:network-image {:optional true} [:maybe :schema.common/image-source]]
@@ -59,12 +59,15 @@
- :image-source - resource - image to display on :network, :collectible and :user
- :theme - :light / :dark"
[{:keys [label customization-color type container-style]
:as props
:or {customization-color colors/neutral-80-opa-5}}]
(let [theme (quo.theme/use-theme)]
:as props}]
(let [theme (quo.theme/use-theme)
default-color (if (= theme :light)
colors/neutral-80-opa-5
colors/white-opa-5)
color (or customization-color default-color)]
[rn/view
{:accessibility-label :container
:style (merge (style/main (assoc props :customization-color customization-color)
:style (merge (style/main (assoc props :customization-color color)
theme)
container-style)}
[left-view props]
@@ -8,8 +8,7 @@
(def header
{:flex-direction :row
:justify-content :space-between
:height 32})
:justify-content :space-between})
(def header-title
{:flex 1
@@ -59,7 +59,6 @@
[rn/view {:style (merge style/container container-style)}
[text/text
{:size :heading-1
:number-of-lines 1
:weight :semi-bold
:style style/text
:accessibility-label accessibility-label}
@@ -7,8 +7,7 @@
:margin-bottom 8})
(def item-text
{:margin-top 10
:margin-left -4})
{:margin-left -24})
(def info-text
{:margin-top -5})
+5
View File
@@ -22,6 +22,11 @@
:qr-code (js/require "../resources/images/ui2/qr-code.png")
:keycard-logo (js/require "../resources/images/ui2/keycard-logo.png")
:keycard-watermark (js/require "../resources/images/ui2/keycard-watermark.png")
:keycard-buy (js/require "../resources/images/ui2/keycard-buy.png")
:keycard-migration (js/require "../resources/images/ui2/keycard-migration.png")
:keycard-migration-failed (js/require "../resources/images/ui2/keycard-migration-failed.png")
:keycard-migration-succeeded (js/require "../resources/images/ui2/keycard-migration-succeeded.png")
:not-keycard (js/require "../resources/images/ui2/not-keycard.png")
:discover (js/require "../resources/images/ui2/discover.png")
:invite-friends (js/require "../resources/images/ui2/invite-friends.png")
:transaction-progress (js/require "../resources/images/ui2/transaction-progress.png")
@@ -1,9 +1,10 @@
(ns status-im.common.standard-authentication.enter-password.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.standard-authentication.core :as standard-authentication]
[status-im.common.standard-authentication.enter-password.style :as style]
[status-im.common.standard-authentication.password-input.view :as password-input]
[status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -31,11 +32,12 @@
:full-name (profile.utils/displayed-name profile)
:customization-color customization-color
:size 24}]]
[password-input/view
[standard-authentication/password-input
{:on-press-biometrics on-press-biometrics
:blur? true
:processing processing
:error error
:error {:error? (not (string/blank? error))
:error-message error}
:default-password password
:sign-in-enabled? sign-in-enabled?}]
[quo/button
@@ -1,6 +1,5 @@
(ns status-im.common.standard-authentication.password-input.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
@@ -12,14 +11,6 @@
[utils.re-frame :as rf]
[utils.security.core :as security]))
(defn- get-error-message
[error]
(if (and (some? error)
(or (= error "file is not a database")
(string/starts-with? (string/lower-case error) "failed")))
(i18n/label :t/oops-wrong-password)
error))
(defn- error-info
[error-message processing shell?]
(let [theme (quo.theme/use-theme)
@@ -49,21 +40,21 @@
(i18n/label :t/forgot-password)]]]))
(defn view
[{:keys [shell? on-press-biometrics blur?]}]
(let [{:keys [error processing]} (rf/sub [:profile/login])
error-message (rn/use-memo #(get-error-message error) [error])
error? (boolean (seq error-message))
default-value (rn/use-ref-atom "") ;;bug on Android
;;https://github.com/status-im/status-mobile/issues/19004
theme (quo.theme/use-theme)
on-change-password (rn/use-callback
(fn [entered-password]
(reset! default-value entered-password)
(debounce/debounce-and-dispatch [:profile/on-password-input-changed
{:password (security/mask-data
entered-password)
:error ""}]
100)))]
[{:keys [shell? on-press-biometrics blur? processing error]}]
(let [{:keys [error?
error-message]} error
default-value (rn/use-ref-atom "") ;;bug on Android
;;https://github.com/status-im/status-mobile/issues/19004
theme (quo.theme/use-theme)
on-change-password (rn/use-callback
(fn [entered-password]
(reset! default-value entered-password)
(debounce/debounce-and-dispatch
[:profile/on-password-input-changed
{:password (security/mask-data
entered-password)
:error ""}]
100)))]
[:<>
[rn/view {:style {:flex-direction :row}}
[quo/input
+3 -9
View File
@@ -18,28 +18,23 @@
(goog-define RARIBLE_MAINNET_API_KEY "")
(goog-define RARIBLE_TESTNET_API_KEY "")
(goog-define ALCHEMY_ETHEREUM_MAINNET_TOKEN "")
(goog-define ALCHEMY_ETHEREUM_GOERLI_TOKEN "")
(goog-define ALCHEMY_ETHEREUM_SEPOLIA_TOKEN "")
(goog-define ALCHEMY_ARBITRUM_MAINNET_TOKEN "")
(goog-define ALCHEMY_ARBITRUM_GOERLI_TOKEN "")
(goog-define ALCHEMY_ARBITRUM_SEPOLIA_TOKEN "")
(goog-define ALCHEMY_OPTIMISM_MAINNET_TOKEN "")
(goog-define ALCHEMY_OPTIMISM_GOERLI_TOKEN "")
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
(goog-define WALLET_CONNECT_PROJECT_ID "87815d72a81d739d2a7ce15c2cfdefb3")
(goog-define MIXPANEL_APP_ID "3350627")
(goog-define MIXPANEL_TOKEN "5c73bda2d36a9f688a5ee45641fb6775")
(def mainnet-rpc-url (str "https://eth-archival.rpc.grove.city/v1/" POKT_TOKEN))
(def goerli-rpc-url (str "https://goerli-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
(def sepolia-rpc-url (str "https://sepolia-archival.rpc.grove.city/v1/" POKT_TOKEN))
(def mainnet-chain-explorer-link "https://etherscan.io/address/")
(def optimism-mainnet-chain-explorer-link "https://optimistic.etherscan.io/address/")
(def arbitrum-mainnet-chain-explorer-link "https://arbiscan.io/address/")
(def sepolia-chain-explorer-link "https://sepolia.etherscan.io/address/")
(def optimism-sepolia-chain-explorer-link "https://sepolia-optimistic.etherscan.io/address/")
(def arbitrum-sepolia-chain-explorer-link "https://sepolia.arbiscan.io/address/")
(def goerli-chain-explorer-link "https://goerli.etherscan.io/address/")
(def optimism-goerli-chain-explorer-link "https://goerli-optimistic.etherscan.io/address/")
(def opensea-link "https://opensea.io")
(def opensea-tesnet-link "https://testnets.opensea.io")
@@ -79,7 +74,6 @@
(def log-request-go (enabled? (get-config :LOG_REQUEST_GO "0")))
(def fleet (get-config :FLEET ""))
(def apn-topic (get-config :APN_TOPIC "im.status.ethereum"))
(def default-network (get-config :DEFAULT_NETWORK "goerli_rpc"))
(def max-installations 2)
; currently not supported in status-go
(def enable-remove-profile-picture? false)
@@ -100,13 +94,13 @@
(def verify-transaction-url
(if (= :mainnet (chain/chain-id->chain-keyword verify-transaction-chain-id))
mainnet-rpc-url
goerli-rpc-url))
sepolia-rpc-url))
(def verify-ens-chain-id (js/parseInt (get-config :VERIFY_ENS_CHAIN_ID "1")))
(def verify-ens-url
(if (= :mainnet (chain/chain-id->chain-keyword verify-ens-chain-id))
mainnet-rpc-url
goerli-rpc-url))
sepolia-rpc-url))
(def verify-ens-contract-address
(get-config :VERIFY_ENS_CONTRACT_ADDRESS
((chain/chain-id->chain-keyword verify-ens-chain-id) utils.ens/ens-registries)))
+5 -11
View File
@@ -295,6 +295,8 @@
(def ^:const token-sort-priority {"SNT" 1 "STT" 1 "ETH" 2 "DAI" 3})
(def ^:const token-display-precision 6)
(def ^:const dapp-permission-contact-code "contact-code")
(def ^:const dapp-permission-web3 "web3")
(def ^:const dapp-permission-qr-code "qr-code")
@@ -473,30 +475,22 @@
;; wallet
(def ^:const ethereum-mainnet-chain-id 1)
(def ^:const ethereum-goerli-chain-id 5)
(def ^:const ethereum-sepolia-chain-id 11155111)
(def ^:const arbitrum-mainnet-chain-id 42161)
(def ^:const arbitrum-goerli-chain-id 421613)
(def ^:const arbitrum-sepolia-chain-id 421614)
(def ^:const optimism-mainnet-chain-id 10)
(def ^:const optimism-goerli-chain-id 420)
(def ^:const optimism-sepolia-chain-id 11155420)
(def opensea-url-names
{:ethereum "ethereum"
:sepolia "sepolia"
:goerli "goerli"})
:sepolia "sepolia"})
(def ^:const ethereum "ethereum")
(def ^:const sepolia "sepolia")
(def ^:const goerli "goerli")
(def ^:const mainnet-chain-ids
#{ethereum-mainnet-chain-id arbitrum-mainnet-chain-id optimism-mainnet-chain-id})
(def ^:const goerli-chain-ids
#{ethereum-goerli-chain-id arbitrum-goerli-chain-id optimism-goerli-chain-id})
(def ^:const sepolia-chain-ids
#{ethereum-sepolia-chain-id arbitrum-sepolia-chain-id optimism-sepolia-chain-id})
@@ -516,7 +510,6 @@
(def ^:const arbitrum-full-name "Arbitrum")
(def ^:const sepolia-full-name "Sepolia")
(def ^:const goerli-full-name "Goerli")
(def ^:const mainnet-network-name :mainnet)
(def ^:const ethereum-network-name :ethereum)
@@ -580,13 +573,14 @@
(def ^:const sheet-screen-handle-height 20)
(def ^:const status-hostname "status.app")
(def ^:const get-keycard-url "https://get.keycard.tech/")
(def ^:const community-joined-notification-type "communityJoined")
(def ^:const default-telemetry-server-url "https://telemetry.status.im")
(def ^:const contact-item-height 56)
(def ^:const page-nav-height 56)
(def ^:const currency-item-height 64)
(def ^:const slippages [0.1 0.5 1])
@@ -4,20 +4,18 @@
[status-im.common.events-helper :as events-helper]
[status-im.common.standard-authentication.core :as standard-auth]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
[utils.re-frame :as rf]))
(defn view
[]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])
{:keys [on-success]} (rf/sub [:get-screen-params])]
[:<>
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/close
:on-press events-helper/navigate-back}]
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/authorise-with-password)
:description :context-tag
@@ -31,5 +29,5 @@
:container-style {}
:customization-color customization-color
:track-text (i18n/label :t/slide-to-authorise)
:on-auth-success #(println "TBD" (security/safe-unmask-data %))
:on-auth-success #(when on-success (on-success %))
:auth-button-label (i18n/label :t/confirm)}]]]))
+8 -15
View File
@@ -10,10 +10,8 @@
[]
[:<>
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/arrow-left
:on-press events-helper/navigate-back}]
{:icon-name :i/arrow-left
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/check-keycard)
:description :text
@@ -23,14 +21,9 @@
{:resize-mode :contain
:source (resources/get-image :check-your-keycard)}]]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[rn/view {:style {:padding-horizontal 10}}
[quo/markdown-list
{:container-style {:padding-vertical 10}
:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list
{:container-style {:padding-bottom 25}
:description (i18n/label :t/keep-card-steady)}]]
[quo/button
{:on-press #(rf/dispatch [:keycard/connect])
:container-style {:margin-horizontal 20}}
(i18n/label :t/ready-to-scan)]])
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/ready-to-scan)
:button-one-props {:on-press #(rf/dispatch [:keycard/migration.check-empty-card])}}]])
+42 -103
View File
@@ -3,10 +3,10 @@
[native-module.core :as native-module]
[react-native.async-storage :as async-storage]
[react-native.platform :as platform]
status-im.contexts.keycard.nfc.effects
[status-im.contexts.keycard.utils :as keycard.utils]
[status-im.contexts.profile.config :as profile.config]
[taoensso.timbre :as log]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
[utils.re-frame :as rf]))
(defonce ^:private active-listeners (atom []))
@@ -32,106 +32,45 @@
(rf/reg-fx :effects.keycard/register-card-events register-card-events)
(rf/reg-fx :effects.keycard/unregister-card-events unregister-card-events)
(defn check-nfc-enabled
[]
(log/debug "[keycard] check-nfc-enabled")
(keycard/check-nfc-enabled
{:on-success
(fn [response]
(log/debug "[keycard response] check-nfc-enabled")
(rf/dispatch [:keycard/on-check-nfc-enabled-success response]))}))
(rf/reg-fx :effects.keycard/check-nfc-enabled check-nfc-enabled)
(rf/reg-fx :effects.keycard/get-application-info
(fn [args]
(keycard/get-application-info (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/get-keys
(fn [args]
(keycard/get-keys (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/sign
(fn [args]
(keycard/sign (keycard.utils/wrap-handlers args))))
(rf/reg-fx :keycard/init-card
(fn [args]
(keycard/init-card (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/generate-and-load-key
(fn [args]
(keycard/generate-and-load-key (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/login-with-keycard
(fn [{:keys [key-uid password whisper-private-key]}]
(native-module/login-account
(assoc (profile.config/login)
:keyUid key-uid
:password password
:keycardWhisperPrivateKey whisper-private-key))))
(rf/reg-fx :effects.keycard/set-pairing-to-keycard
(fn [pairings]
(keycard/set-pairings pairings)))
(rf/reg-fx
:effects.keycard.ios/start-nfc
(fn [args]
(log/debug "fx start-nfc")
(keycard/start-nfc args)))
:keycard/persist-pairings
(fn [pairings]
(async-storage/set-item! "status-keycard-pairings" pairings)))
(rf/reg-fx
:effects.keycard.ios/stop-nfc
(fn [args]
(log/debug "fx stop-nfc")
(keycard/stop-nfc args)))
(defn- error-object->map
[^js object]
{:code (.-code object)
:error (.-message object)})
(defn get-application-info
[{:keys [on-success on-failure] :as args}]
(log/debug "[keycard] get-application-info")
(keycard/get-application-info
(assoc
args
:on-success
(fn [response]
(log/debug "[keycard response succ] get-application-info")
(when on-success
(on-success response)))
:on-failure
(fn [response]
(log/error "[keycard response fail] get-application-info")
(when on-failure
(on-failure (error-object->map response)))))))
(rf/reg-fx :effects.keycard/get-application-info get-application-info)
(defn get-keys
[{:keys [on-success on-failure] :as args}]
(log/debug "[keycard] get-keys")
(keycard/get-keys
(assoc
args
:on-success
(fn [response]
(log/debug "[keycard response succ] get-keys")
(when on-success
(on-success (transforms/js->clj response))))
:on-failure
(fn [response]
(log/warn "[keycard response fail] get-keys"
(error-object->map response))
(when on-failure
(on-failure (error-object->map response)))))))
(rf/reg-fx :effects.keycard/get-keys get-keys)
(defn login
[{:keys [key-uid password whisper-private-key]}]
(native-module/login-account
(assoc (profile.config/login)
:keyUid key-uid
:password password
:keycardWhisperPrivateKey whisper-private-key)))
(rf/reg-fx :effects.keycard/login-with-keycard login)
(defn retrieve-pairings
[]
(async-storage/get-item
"status-keycard-pairings"
#(rf/dispatch [:keycard/on-retrieve-pairings-success %])))
(rf/reg-fx :effects.keycard/retrieve-pairings retrieve-pairings)
(defn set-pairing-to-keycard
[pairings]
(keycard/set-pairings pairings))
(rf/reg-fx :effects.keycard/set-pairing-to-keycard set-pairing-to-keycard)
(defn sign
[{:keys [on-success on-failure] :as args}]
(log/debug "[keycard] sign")
(keycard/sign
(assoc
args
:on-success
(fn [response]
(log/debug "[keycard response succ] sign")
(when on-success
(on-success (transforms/js->clj response))))
:on-failure
(fn [response]
(log/warn "[keycard response fail] sign"
(error-object->map response))
(when on-failure
(on-failure (error-object->map response)))))))
(rf/reg-fx :effects.keycard/sign sign)
(rf/reg-fx :effects.keycard/retrieve-pairings
(fn []
(async-storage/get-item
"status-keycard-pairings"
#(rf/dispatch [:keycard/on-retrieve-pairings-success %]))))
+12 -9
View File
@@ -3,7 +3,7 @@
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.resources :as resources]
[status-im.contexts.keycard.sheets.migrate.view :as sheets.migrate]
[status-im.contexts.keycard.migrate.sheets.view :as sheets.migrate]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -11,10 +11,8 @@
[]
[:<>
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/arrow-left
:on-press events-helper/navigate-back}]
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-empty)
:description :text
@@ -26,10 +24,15 @@
:subtitle (i18n/label :t/use-keycard-login-sign)
:button-label (i18n/label :t/import-profile-key-pair)
:accessibility-label :get-keycard
:image (resources/get-image :generate-keys)
:on-press #(rf/dispatch [:show-bottom-sheet
{:theme :dark
:content (fn [] [sheets.migrate/view])}])}]]
:image (resources/get-image :keycard-buy)
:on-press (fn []
(rf/dispatch
[:show-bottom-sheet
{:theme :dark
:content (fn []
[sheets.migrate/view
{:on-continue #(rf/dispatch
[:keycard/migration.get-phrase])}])}]))}]]
[quo/information-box
{:type :default
:style {:margin-top 32 :margin-horizontal 28}}
+21 -26
View File
@@ -1,42 +1,37 @@
(ns status-im.contexts.keycard.error.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.events-helper :as events-helper]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def titles
{:keycard/error.keycard-wrong {:title "Keycard is not empty"
:description "You cant use it to store new keys right now"}
:keycard/error.keycard-unpaired {:title "Keycard is full"
:description "All pairing slots are occupied"}
:keycard/error.keycard-frozen {:title "Keycard is locked"
:description "You cant use it right now"}
:keycard/error.keycard-locked {:title "Keycard is locked"
:description "You cant use it right now"}})
{:keycard/error.keycard-blank {:title (i18n/label :t/keycard-empty)
:description (i18n/label :t/no-key-pair-keycard)}
:keycard/error.keycard-wrong-profile {:title (i18n/label :t/keycard-not-empty)
:description (i18n/label :t/cant-store-new-keys)}
:keycard/error.keycard-unpaired {:title (i18n/label :t/keycard-full)
:description (i18n/label :t/pairing-slots-occupied)}
:keycard/error.keycard-frozen {:title (i18n/label :t/keycard-locked)
:description (i18n/label :t/cant-use-right-now)}
:keycard/error.keycard-locked {:title (i18n/label :t/keycard-locked)
:description (i18n/label :t/cant-use-right-now)}})
(defn view
[]
(let [{:keys [top bottom]} (safe-area/get-insets)
error (rf/sub [:keycard/application-info-error])
(let [error (rf/sub [:keycard/application-info-error])
{:keys [title description]} (get titles error)]
[quo/overlay
{:type :shell
:container-style {:padding-top top
:padding-bottom bottom}}
[:<>
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/arrow-left
:on-press events-helper/navigate-back}]
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title title
:description :text
:description-text description}]
[rn/view {:height 226}]
[rn/view {:padding-horizontal 20}
[quo/info-message
{:container-style {:padding-top 15}
:icon :i/info
:size :default}
"To unlock or factory reset the Keycard, please use the Status desktop app. If you'd like this features on mobile, feel free to upvote them and discuss in the Status community."]]]))
[rn/view {:style {:margin-horizontal 20}}
[quo/keycard {:holder-name ""}]
[quo/information-box
{:type :default
:style {:margin-top 20}}
(i18n/label :t/unlock-reset-instructions)]]]))
+70 -69
View File
@@ -1,116 +1,117 @@
(ns status-im.contexts.keycard.events
(:require [re-frame.core :as rf]
status-im.contexts.keycard.login.events
status-im.contexts.keycard.nfc-sheet.events
status-im.contexts.keycard.migrate.events
status-im.contexts.keycard.migrate.re-encrypting.events
status-im.contexts.keycard.nfc.events
status-im.contexts.keycard.nfc.sheets.events
status-im.contexts.keycard.pin.events
status-im.contexts.keycard.sign.events
[status-im.contexts.keycard.utils :as keycard.utils]
[taoensso.timbre :as log]))
(rf/reg-event-fx :keycard/on-check-nfc-enabled-success
(fn [{:keys [db]} [nfc-enabled?]]
{:db (assoc-in db [:keycard :nfc-enabled?] nfc-enabled?)}))
(rf/reg-event-fx :keycard.ios/on-nfc-user-cancelled
(fn [{:keys [db]}]
(log/debug "[keycard] nfc user cancelled")
{:db (-> db
(assoc-in [:keycard :pin :status] nil)
(assoc-in [:keycard :on-nfc-cancelled-event-vector] nil))
:fx [(when-let [on-nfc-cancelled-event-vector (get-in db [:keycard :on-nfc-cancelled-event-vector])]
[:dispatch on-nfc-cancelled-event-vector])]}))
utils.datetime))
(rf/reg-event-fx :keycard/on-card-connected
(fn [{:keys [db]} _]
(log/debug "[keycard] card globally connected")
{:db (assoc-in db [:keycard :card-connected?] true)
:fx [(when-let [event (get-in db [:keycard :on-card-connected-event-vector])]
[:dispatch event])]}))
(rf/reg-event-fx :keycard/on-card-disconnected
(fn [{:keys [db]} _]
(log/debug "[keycard] card disconnected")
{:db (assoc-in db [:keycard :card-connected?] false)
:fx [(when-let [event (get-in db [:keycard :on-card-disconnected-event-vector])]
[:dispatch event])]}))
(rf/reg-event-fx :keycard.ios/start-nfc
(fn [_]
{:effects.keycard.ios/start-nfc nil}))
(rf/reg-event-fx :keycard.ios/on-nfc-timeout
(fn [{:keys [db]} _]
(log/debug "[keycard] nfc timeout")
{:db (assoc-in db [:keycard :card-connected?] false)
:fx [[:dispatch-later [{:ms 500 :dispatch [:keycard.ios/start-nfc]}]]]}))
(rf/reg-event-fx :keycard/on-retrieve-pairings-success
(fn [{:keys [db]} [pairings]]
{:db (assoc-in db [:keycard :pairings] pairings)
:fx [[:effects.keycard/set-pairing-to-keycard pairings]]}))
(rf/reg-event-fx :keycard.ios/on-start-nfc-success
(fn [{:keys [db]} [{:keys [on-cancel-event-vector]}]]
(log/debug "[keycard] nfc started success")
{:db (assoc-in db [:keycard :on-nfc-cancelled-event-vector] on-cancel-event-vector)}))
(rf/reg-event-fx :keycard/update-pairings
(fn [{:keys [db]} [instance-uid pairing]]
(let [pairings (get-in db [:keycard :pairings])
new-pairings (assoc pairings
instance-uid
{:pairing pairing
:paired-on (utils.datetime/timestamp)})]
{:db (assoc-in db [:keycard :pairings] new-pairings)
:keycard/persist-pairings new-pairings})))
(rf/reg-event-fx :keycard/on-action-with-pin-error
(fn [{:keys [db]} [error]]
(log/debug "[keycard] on-action-with-pin-error: " error)
(let [tag-was-lost? (keycard.utils/tag-lost? (:error error))
pin-retries-count (keycard.utils/pin-retries (:error error))]
(if tag-was-lost?
(if (or tag-was-lost? (nil? pin-retries-count))
{:db (assoc-in db [:keycard :pin :status] nil)}
(if (nil? pin-retries-count)
{:effects.utils/show-popup {:title "wrong-keycard"}}
{:db (-> db
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
(assoc-in [:keycard :pin :status] :error))
:fx [[:dispatch [:keycard/disconnect]]
(when (zero? pin-retries-count)
[:effects.utils/show-popup {:title "frozen-keycard"}])]})))))
(rf/reg-event-fx :keycard/on-get-application-info-success
(fn [{:keys [db]} [application-info {:keys [key-uid on-success-fx]}]]
(if-let [error (keycard.utils/validate-application-info key-uid application-info)]
(case error
:keycard/error.not-keycard
{:fx [[:dispatch [:keycard/disconnect]]
[:dispatch [:open-modal :screen/keycard.not-keycard]]]}
:keycard/error.keycard-blank
{:fx [[:dispatch [:keycard/disconnect]]
[:dispatch [:open-modal :screen/keycard.empty]]]}
{:db (assoc-in db [:keycard :application-info-error] error)
{:db (-> db
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
(assoc-in [:keycard :pin :status] :error))
:fx [[:dispatch [:keycard/disconnect]]
[:dispatch [:open-modal :screen/keycard.error]]]})
{:db (-> db
(assoc-in [:keycard :application-info] application-info)
(assoc-in [:keycard :pin :status] :verifying))
:fx on-success-fx})))
(when (zero? pin-retries-count)
[:dispatch
[:keycard/on-application-info-error
:keycard/error.keycard-locked]])]}))))
(rf/reg-event-fx :keycard/get-application-info
(fn [_ [{:keys [on-success on-failure]}]]
{:effects.keycard/get-application-info {:on-success on-success :on-failure on-failure}}))
(rf/reg-event-fx :keycard/get-keys
(fn [_ [data]]
{:effects.keycard/get-keys data}))
(rf/reg-event-fx :keycard/cancel-connection
(fn [{:keys [db]}]
{:db (-> db
(assoc-in [:keycard :on-card-connected-event-vector] nil)
(assoc-in [:keycard :on-nfc-cancelled-event-vector] nil))}))
{:db (update db :keycard dissoc :on-card-connected-event-vector :on-nfc-cancelled-event-vector)}))
(rf/reg-event-fx :keycard/disconnect
(fn [_ _]
{:fx [[:dispatch [:keycard/cancel-connection]]
[:dispatch [:keycard/hide-connection-sheet]]]}))
(rf/reg-event-fx :keycard/on-application-info-error
(fn [{:keys [db]} [error]]
{:db (assoc-in db [:keycard :application-info-error] error)
:fx [[:dispatch [:keycard/disconnect]]
[:dispatch
[:open-modal
(if (= :keycard/error.not-keycard error)
:screen/keycard.not-keycard
:screen/keycard.error)]]]}))
(rf/reg-event-fx :keycard/update-application-info
(fn [{:keys [db]} [app-info]]
{:db (update db
:keycard
#(-> %
(assoc :application-info app-info)
(dissoc :application-info-error)))}))
(rf/reg-event-fx :keycard/get-application-info
(fn [_ [{:keys [key-uid on-success on-error]}]]
{:effects.keycard/get-application-info
{:on-success (fn [{:keys [instance-uid new-pairing] :as app-info}]
(rf/dispatch [:keycard/update-application-info app-info])
(when (and instance-uid new-pairing)
(rf/dispatch [:keycard/update-pairings instance-uid new-pairing]))
(if-let [error (keycard.utils/validate-application-info key-uid app-info)]
(if on-error
(on-error error)
(rf/dispatch [:keycard/on-application-info-error error]))
(when on-success (on-success app-info))))
:on-error (fn []
(if on-error
(on-error :keycard/error.not-keycard)
(rf/dispatch [:keycard/on-application-info-error
:keycard/error.not-keycard])))}}))
(rf/reg-event-fx :keycard/connect
(fn [{:keys [db]} [args]]
(let [connected? (get-in db [:keycard :card-connected?])
event-vector [:keycard/get-application-info
{:on-success #(rf/dispatch [:keycard/on-get-application-info-success % args])}]]
(fn [{:keys [db]} [{:keys [key-uid on-success on-error on-connect-event-vector]}]]
(let [event-vector
(or on-connect-event-vector
[:keycard/get-application-info
{:key-uid key-uid
:on-success on-success
:on-error on-error}])]
{:db (assoc-in db [:keycard :on-card-connected-event-vector] event-vector)
:fx [[:dispatch
[:keycard/show-connection-sheet
{:on-cancel-event-vector [:keycard/cancel-connection]}]]
(when connected?
(when (get-in db [:keycard :card-connected?])
[:dispatch event-vector])]})))
@@ -5,7 +5,6 @@
(fn [{:keys [db]} [data]]
(let [{:keys [key-uid encryption-public-key
whisper-private-key]} data
key-uid (str "0x" key-uid)
profile (get-in db [:profile/profiles-overview key-uid])]
{:db
(-> db
@@ -0,0 +1,132 @@
(ns status-im.contexts.keycard.migrate.events
(:require [clojure.string :as string]
[status-im.contexts.keycard.pin.view :as keycard.pin]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :keycard/migration.check-empty-card
(fn [{:keys [db]}]
{:fx [[:dispatch
[:keycard/connect
{:key-uid (get-in db [:profile/profile :key-uid])
:on-success
(fn []
;;TODO keys already on the keycard, new flow needs to be implemented
;; https://github.com/status-im/status-mobile/issues/21446
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.authorise
{:on-success
#(rf/dispatch [:keycard/migration.authorisation-success %])}]))
:on-error
(fn [error]
(if (= error :keycard/error.keycard-blank)
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.empty]))
(rf/dispatch [:keycard/on-application-info-error error])))}]]]}))
(defn get-application-info-and-continue
[key-uid]
(rf/dispatch [:keycard/get-application-info
{:key-uid key-uid
:on-success #(rf/dispatch [:keycard/migration.continue])
:on-error
(fn [error]
(if (= error :keycard/error.keycard-blank)
(rf/dispatch [:keycard/migration.continue])
(rf/dispatch [:keycard/on-application-info-error error])))}]))
(rf/reg-event-fx :keycard/migration.continue
(fn [{:keys [db]}]
(let [key-uid (get-in db [:profile/profile :key-uid])
{:keys [initialized? has-master-key?]} (get-in db [:keycard :application-info])
{:keys [masked-phrase pin]} (get-in db [:keycard :migration])
on-failure (fn []
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:navigate-to
:screen/keycard.migrate.fail]))]
(cond
(not initialized?)
{:fx [[:keycard/init-card
{:pin pin
:on-success #(get-application-info-and-continue key-uid)
:on-failure on-failure}]]}
(not has-master-key?)
{:fx [[:effects.keycard/generate-and-load-key
{:mnemonic (security/safe-unmask-data masked-phrase)
:pin pin
:on-success #(get-application-info-and-continue key-uid)
:on-failure on-failure}]]}
:else
{:fx [[:effects.keycard/get-keys
{:pin pin
:on-success #(rf/dispatch [:keycard/migration.convert-to-keycard-profile %])
:on-failure on-failure}]]}))))
(rf/reg-event-fx :keycard/migration.start
(fn [{:keys [db]}]
{:fx [[:dispatch
[:keycard/connect
{:key-uid (get-in db [:profile/profile :key-uid])
:on-success #(rf/dispatch [:keycard/migration.continue])
:on-error
(fn [error]
(if (= error :keycard/error.keycard-blank)
(rf/dispatch [:keycard/migration.continue])
(rf/dispatch [:keycard/on-application-info-error error])))}]]]}))
(rf/reg-event-fx :keycard/migration.get-phrase
(fn [{:keys [db]}]
{:db (assoc-in db [:keycard :migration] nil)
:fx [[:dispatch [:navigate-back]]
(if (string/blank? (get-in db [:profile/profile :mnemonic]))
[:dispatch
[:open-modal :screen/use-recovery-phrase
{:on-success #(rf/dispatch [:keycard/migration.phrase-entered %])}]]
[:dispatch
[:open-modal :screen/backup-recovery-phrase
{:on-success #(rf/dispatch [:keycard/migration.phrase-backed-up %])}]])]}))
(rf/reg-event-fx :keycard/migration.phrase-entered
(fn [{:keys [db]} [{:keys [phrase]}]]
{:db (assoc-in db [:keycard :migration :masked-phrase] (security/mask-data phrase))
:fx [[:dispatch [:navigate-back]]
[:dispatch
[:open-modal :screen/keycard.authorise
{:on-success #(rf/dispatch [:keycard/migration.authorisation-success %])}]]]}))
(rf/reg-event-fx :keycard/migration.phrase-backed-up
(fn [{:keys [db]}]
{:db (assoc-in db
[:keycard :migration :masked-phrase]
(security/mask-data (get-in db [:profile/profile :mnemonic])))
:fx [[:dispatch [:profile.settings/profile-update :mnemonic nil]]
[:dispatch [:navigate-back]]
[:dispatch
[:open-modal :screen/keycard.authorise
{:on-success #(rf/dispatch [:keycard/migration.authorisation-success %])}]]]}))
(rf/reg-event-fx :keycard/migration.authorisation-success
(fn [{:keys [db]} [masked-password]]
(let [{:keys [initialized?]} (get-in db [:keycard :application-info])]
{:db (assoc-in db [:keycard :migration :masked-password] masked-password)
:fx [[:dispatch [:navigate-back]]
(if initialized?
[:dispatch
[:show-bottom-sheet
{:content (fn []
[keycard.pin/auth
{:on-complete #(rf/dispatch [:keycard/migration.pin-created %])}])}]]
[:dispatch
[:open-modal :screen/keycard.pin.create
{:on-complete (fn [new-pin]
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/migration.pin-created new-pin]))}]])]})))
(rf/reg-event-fx :keycard/migration.pin-created
(fn [{:keys [db]} [pin]]
{:db (assoc-in db [:keycard :migration :pin] pin)
:fx [[:dispatch [:open-modal :screen/keycard.migrate]]]}))
@@ -0,0 +1,32 @@
(ns status-im.contexts.keycard.migrate.fail.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])]
[:<>
[quo/page-top
{:title (i18n/label :t/failed-to-migrate-key-pair)
:description :context-tag
:context-tag {:full-name profile-name
:profile-picture profile-picture
:customization-color customization-color}
:container-style {:margin-top constants/page-nav-height}}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :keycard-migration-failed)}]]
[quo/divider-label (i18n/label :t/what-you-can-do)]
[quo/markdown-list {:description (i18n/label :t/log-out-remove-profile)}]
[quo/markdown-list {:description (i18n/label :t/recover-status-profile)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/log-out-remove)
:button-one-props {:on-press #(rf/dispatch [:logout])}}]]))
@@ -0,0 +1,31 @@
(ns status-im.contexts.keycard.migrate.re-encrypting.events
(:require [clojure.string :as string]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :keycard/migration.convert-to-keycard-profile
(fn [{:keys [db]} [{:keys [key-uid instance-uid encryption-public-key]}]]
(let [{:keys [masked-password]} (get-in db [:keycard :migration])
{:keys [pairing paired-on]} (get-in db [:keycard :pairings instance-uid])
{:keys [kdfIterations]} (:profile/profile db)]
{:fx [[:dispatch [:keycard/disconnect]]
[:dispatch [:navigate-back]]
[:dispatch [:open-modal :screen/keycard.re-encrypting]]
[:effects.profile/convert-to-keycard-profile
{:profile
{:key-uid key-uid
:keycard-pairing pairing
:kdfIterations kdfIterations}
:settings
{:keycard-instance-uid instance-uid
:keycard-paired-on paired-on
:keycard-pairing pairing}
:password
(security/safe-unmask-data masked-password)
:new-password
encryption-public-key
:callback
(fn [{:keys [error]}]
(if (string/blank? error)
(rf/dispatch [:navigate-to :screen/keycard.migrate.success])
(rf/dispatch [:navigate-to :screen/keycard.migrate.fail])))}]]})))
@@ -0,0 +1,27 @@
(ns status-im.contexts.keycard.migrate.re-encrypting.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])]
[:<>
[quo/page-top
{:title (i18n/label :t/re-encrypting-data)
:description :context-tag
:context-tag {:full-name profile-name
:profile-picture profile-picture
:customization-color customization-color}
:container-style {:margin-top constants/page-nav-height}}]
[quo/text {:style {:padding-horizontal 20}}
(i18n/label :t/do-not-quit)]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :keycard-migration)}]]]))
@@ -1,15 +1,14 @@
(ns status-im.contexts.keycard.sheets.migrate.view
(ns status-im.contexts.keycard.migrate.sheets.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])
recovery-phrase-backed-up? (rf/sub [:profile/recovery-phrase-backed-up?])]
[{:keys [on-continue]}]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])]
[:<>
[quo/drawer-top
{:type :context-tag
@@ -28,11 +27,7 @@
[quo/bottom-actions
{:actions :two-actions
:button-one-label (i18n/label :t/continue)
:button-one-props {:on-press #(if recovery-phrase-backed-up?
(rf/dispatch [:open-modal :screen/use-recovery-phrase
{:on-success (fn [])}])
(rf/dispatch [:open-modal :screen/backup-recovery-phrase
{:on-success (fn [])}]))}
:button-one-props {:on-press on-continue}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:type :grey
:on-press #(rf/dispatch [:hide-bottom-sheet])}}]]))
@@ -0,0 +1,31 @@
(ns status-im.contexts.keycard.migrate.success.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])]
[:<>
[quo/page-top
{:title (i18n/label :t/key-pair-migrated-successfully)
:description :context-tag
:context-tag {:full-name profile-name
:profile-picture profile-picture
:customization-color customization-color}
:container-style {:margin-top constants/page-nav-height}}]
[quo/text {:style {:padding-horizontal 20}}
(i18n/label :t/use-keycard-for-status)]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :keycard-migration-succeeded)}]]
[quo/button
{:on-press #(rf/dispatch [:logout])
:container-style {:margin-horizontal 20}}
(i18n/label :t/logout)]]))
@@ -0,0 +1,34 @@
(ns status-im.contexts.keycard.migrate.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.resources :as resources]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/ready-to-migrate-key-pair)
:description :context-tag
:context-tag {:full-name profile-name
:profile-picture profile-picture
:customization-color customization-color}}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :keycard-migration)}]]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/scan-keycard)
:button-one-props {:on-press #(rf/dispatch [:keycard/migration.start])}}]]))
@@ -0,0 +1,11 @@
(ns status-im.contexts.keycard.nfc.effects
(:require [keycard.keycard :as keycard]
[utils.re-frame :as rf]))
(rf/reg-fx :effects.keycard/check-nfc-enabled
(fn []
(keycard/check-nfc-enabled
{:on-success #(rf/dispatch [:keycard/on-check-nfc-enabled-success %])})))
(rf/reg-fx :effects.keycard.ios/start-nfc keycard/start-nfc)
(rf/reg-fx :effects.keycard.ios/stop-nfc keycard/stop-nfc)
@@ -0,0 +1,27 @@
(ns status-im.contexts.keycard.nfc.events
(:require [utils.re-frame :as rf]))
(rf/reg-event-fx :keycard.ios/start-nfc
(fn [_]
{:fx [[:effects.keycard.ios/start-nfc]]}))
(rf/reg-event-fx :keycard.ios/on-start-nfc-success
(fn [{:keys [db]} [{:keys [on-cancel-event-vector]}]]
{:db (assoc-in db [:keycard :on-nfc-cancelled-event-vector] on-cancel-event-vector)}))
(rf/reg-event-fx :keycard.ios/on-nfc-timeout
(fn [{:keys [db]} _]
{:db (assoc-in db [:keycard :card-connected?] false)
:fx [[:dispatch-later [{:ms 500 :dispatch [:keycard.ios/start-nfc]}]]]}))
(rf/reg-event-fx :keycard/on-check-nfc-enabled-success
(fn [{:keys [db]} [nfc-enabled?]]
{:db (assoc-in db [:keycard :nfc-enabled?] nfc-enabled?)}))
(rf/reg-event-fx :keycard.ios/on-nfc-user-cancelled
(fn [{:keys [db]}]
{:db (-> db
(assoc-in [:keycard :pin :status] nil)
(assoc-in [:keycard :on-nfc-cancelled-event-vector] nil))
:fx [(when-let [on-nfc-cancelled-event-vector (get-in db [:keycard :on-nfc-cancelled-event-vector])]
[:dispatch on-nfc-cancelled-event-vector])]}))
@@ -1,4 +1,4 @@
(ns status-im.contexts.keycard.nfc-sheet.events
(ns status-im.contexts.keycard.nfc.sheets.events
(:require [re-frame.core :as rf]
[react-native.platform :as platform]
[taoensso.timbre :as log]))
@@ -1,4 +1,4 @@
(ns status-im.contexts.keycard.nfc-sheet.view
(ns status-im.contexts.keycard.nfc.sheets.view
(:require [quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]
@@ -1,28 +1,24 @@
(ns status-im.contexts.keycard.not-keycard.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.events-helper :as events-helper]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[status-im.common.resources :as resources]
[utils.i18n :as i18n]))
(defn view
[]
(let [{:keys [top bottom]} (safe-area/get-insets)]
[quo/overlay
{:type :shell
:container-style {:padding-top top
:padding-bottom bottom}}
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/arrow-left
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/oops-not-keycard)
:description :text
:description-text (i18n/label :t/make-sure-keycard)}]
[rn/view {:flex 1}]
[rn/view {:padding-horizontal 20}
[quo/button {:on-press #(rf/dispatch [:keycard/connect])}
(i18n/label :t/try-again)]]]))
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/oops-not-keycard)
:description :text
:description-text (i18n/label :t/make-sure-keycard)}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :not-keycard)}]]
[rn/view {:padding-horizontal 20}
[quo/button {:on-press events-helper/navigate-back}
(i18n/label :t/try-again)]]])
@@ -2,12 +2,15 @@
(:require [clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.constants :as constants]
[utils.i18n :as i18n]))
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[{:keys [on-complete]}]
(let [[pin set-pin] (rn/use-state "")
[]
(let [{:keys [on-complete]} (rf/sub [:get-screen-params])
[pin set-pin] (rn/use-state "")
[first-pin set-first-pin] (rn/use-state "")
[error? set-error] (rn/use-state false)
[stage set-stage] (rn/use-state :create)
@@ -38,10 +41,15 @@
(set-stage :repeat)))))))
[pin stage first-pin])]
[rn/view {:style {:padding-bottom 12 :flex 1}}
[quo/drawer-top
{:title (if (= :create stage)
(i18n/label :t/create-keycard-pin)
(i18n/label :t/repeat-keycard-pin))}]
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (if (= :create stage)
(i18n/label :t/create-keycard-pin)
(i18n/label :t/repeat-keycard-pin))
:description :text
:description-text "Youll need this PIN to login and sign transactions"}]
[rn/view {:style {:flex 1 :justify-content :center :align-items :center :padding-vertical 34}}
[quo/pin-input
{:blur? false
@@ -23,3 +23,7 @@
(assoc-in [:keycard :pin :status] nil))
:fx [(when (and on-complete (= (dec max-numbers) (count pin)))
[:effects.keycard.pin/dispatch-on-complete [on-complete new-pin]])]}))))
(rf/reg-event-fx :keycard.pin/clear
(fn [{:keys [db]}]
{:db (assoc-in db [:keycard :pin] nil)}))
+9 -5
View File
@@ -6,10 +6,12 @@
[utils.re-frame :as rf]))
(defn auth
[{:keys [on-complete]}]
(let [{:keys [text status]} (rf/sub [:keycard/pin])
pin-retry-counter (rf/sub [:keycard/pin-retry-counter])
error? (= status :error)]
[{:keys [on-complete error]}]
(let [{:keys [error? error-message]} error
{:keys [text status]} (rf/sub [:keycard/pin])
pin-retry-counter (rf/sub [:keycard/pin-retry-counter])
error? (or error? (= status :error))]
(rn/use-unmount #(rf/dispatch [:keycard.pin/clear]))
[rn/view {:padding-bottom 12 :flex 1}
[rn/view {:flex 1 :justify-content :center :align-items :center :padding 34}
[quo/pin-input
@@ -18,7 +20,9 @@
:number-of-filled-pins (count text)
:error? error?
:info (when error?
(i18n/label :t/pin-retries-left {:number pin-retry-counter}))}]]
(if error-message
error-message
(i18n/label :t/pin-retries-left {:number pin-retry-counter})))}]]
[quo/numbered-keyboard
{:delete-key? true
:on-delete #(rf/dispatch [:keycard.pin/delete-pressed])
+17 -13
View File
@@ -8,6 +8,10 @@
:s (subs signature 64 128)
:v (str (js/parseInt (subs signature 128 130) 16))}})
(rf/reg-event-fx :keycard/sign
(fn [_ [data]]
{:effects.keycard/sign data}))
(rf/reg-event-fx :keycard/sign-hash
(fn [{:keys [db]} [pin-text tx-hash]]
(let [current-address (get-in db [:wallet :current-viewing-account-address])
@@ -15,16 +19,16 @@
key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:dispatch
[:keycard/connect
{:key-uid key-uid
:on-success-fx [[:effects.keycard/sign
{:pin pin-text
:path path
:hash (utils.address/naked-address tx-hash)
:on-success
#(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch
[:wallet/proceed-with-transactions-signatures
(get-signature-map tx-hash %)]))
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error
%])}]]}]]]})))
{:key-uid key-uid
:on-success
(fn []
(rf/dispatch
[:keycard/sign
{:pin pin-text
:path path
:hash (utils.address/naked-address tx-hash)
:on-success (fn [signature]
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:wallet/proceed-with-transactions-signatures
(get-signature-map tx-hash signature)]))
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]))}]]]})))
+49 -25
View File
@@ -1,5 +1,7 @@
(ns status-im.contexts.keycard.utils
(:require [taoensso.timbre :as log]))
(:require [clojure.string :as string]
[utils.address :as address]
[utils.transforms :as transforms]))
(def pin-mismatch-error #"Unexpected error SW, 0x63C(\d+)|wrongPIN\(retryCounter: (\d+)\)")
@@ -16,33 +18,55 @@
(re-matches #".*NFCError:100.*" error)))
(defn validate-application-info
[profile-key-uid {:keys [key-uid paired? pin-retry-counter puk-retry-counter] :as application-info}]
(let [profile-mismatch? (or (nil? profile-key-uid) (not= profile-key-uid key-uid))]
(log/debug "[keycard]" "login-with-keycard"
"empty application info" (empty? application-info)
"no key-uid" (empty? key-uid)
"profile-mismatch?" profile-mismatch?
"no pairing" paired?)
(cond
(empty? application-info)
:keycard/error.not-keycard
[profile-key-uid
{:keys [key-uid has-master-key? paired? pin-retry-counter puk-retry-counter] :as application-info}]
(empty? (:key-uid application-info))
:keycard/error.keycard-blank
(cond
(empty? application-info)
:keycard/error.not-keycard
profile-mismatch?
:keycard/error.keycard-wrong
(not has-master-key?)
:keycard/error.keycard-blank
(not paired?)
:keycard/error.keycard-unpaired
(not= profile-key-uid key-uid)
:keycard/error.keycard-wrong-profile
(and (zero? pin-retry-counter)
(or (nil? puk-retry-counter)
(pos? puk-retry-counter)))
:keycard/error.keycard-frozen
(not paired?)
:keycard/error.keycard-unpaired
(zero? puk-retry-counter)
:keycard/error.keycard-locked
(and (zero? pin-retry-counter)
(or (nil? puk-retry-counter)
(pos? puk-retry-counter)))
:keycard/error.keycard-frozen
:else
nil)))
(zero? puk-retry-counter)
:keycard/error.keycard-locked
:else
nil))
(defn- error-object->map
[^js object]
{:code (.-code object)
:error (.-message object)})
(defn normalize-key-uid
[{:keys [key-uid] :as data}]
(if (string/blank? key-uid)
data
(update data :key-uid address/normalized-hex)))
(defn get-on-success
[{:keys [on-success]}]
#(when on-success (on-success (normalize-key-uid (transforms/js->clj %)))))
(defn get-on-failure
[{:keys [on-failure]}]
#(when on-failure (on-failure (error-object->map %))))
(defn wrap-handlers
[args]
(assoc
args
:on-success (get-on-success args)
:on-failure (get-on-failure args)))
@@ -37,24 +37,21 @@
(defonce is-dragging? (atom nil))
(defonce drag-amount (atom nil))
;; Layout height calculation
;; 1. Always prefer on-layout height over window height, as some devices include status bar height in
;; the window while others do not.
;; https://github.com/status-im/status-mobile/issues/14633#issuecomment-1366191478
;; 2. This preference is unless on-layout is triggered with a random value.
;; https://github.com/status-im/status-mobile/issues/14849
;; To ensure that on-layout height falls within the actual height range, a difference between window
;; height and the maximum possible status bar height is allowed (assumed to be 60, as the Pixel emulator
;; has a height of 52).
(defn store-screen-height
[evt]
(let [window-height (:height (rn/get-window))
height (or (oget evt "nativeEvent" "layout" "height") 0)
width (or (oget evt "nativeEvent" "layout" "width") 0)]
;; Layout height calculation
;; 1. Make sure height is more than width, and on-layout is not fired while the
;; screen is horizontal
;; 2. Initialize values with 0 in case of nil
;; 3. In the case of notch devices, the dimensions height will be smaller than
;; on-layout,
;; (without status bar height included)
;; https://github.com/status-im/status-mobile/issues/14633
;; 4. In the case of devices without a notch, both heights should be the same,
;; but actual values differ in some pixels, so arbitrary 5 pixels is allowed
(when (and (> height width)
(>= (+ height 5) (or window-height 0))
(not= height @shell.state/screen-height))
(let [window-height (or (:height (rn/get-window)) 0)
height (or (oget evt "nativeEvent" "layout" "height") 0)]
(when (and (not= height @shell.state/screen-height)
(< (Math/abs (- window-height height)) 60))
(reset! shell.state/screen-height height)
(async-storage/set-item! :screen-height height))))
+25 -3
View File
@@ -67,6 +67,28 @@
(fn [_ [error]]
{:dispatch [:biometric/show-message (ex-cause error)]}))
;; Navigate to next screen once onboarding animation and account creation both are complete
;; Note: If account creation fails, user will get stuck on loading screen
;; TODO: Show error screen in case account creation/restoration fails
(rf/reg-event-fx :onboarding/account-creation-complete
(fn [{:keys [db]} [opts]]
(let [loading-animation-complete? (or (:loading-animation-complete? opts)
(:onboarding/loading-animation-complete? db))
loading-screen (or (:loading-screen opts) (:onboarding/loading-screen db))
login-signal-received? (or (:login-signal-received? opts)
(:onboarding/login-signal-received? db))]
(if (and loading-animation-complete? login-signal-received?)
{:db (-> db
(dissoc :onboarding/loading-screen)
(dissoc :onboarding/loading-animation-complete?)
(dissoc :onboarding/login-signal-received?))
:fx [[:dispatch
[:navigate-to-within-stack [:screen/onboarding.enable-notifications loading-screen]]]]}
{:db (-> db
(assoc :onboarding/loading-screen loading-screen)
(assoc :onboarding/loading-animation-complete? loading-animation-complete?)
(assoc :onboarding/login-signal-received? login-signal-received?))}))))
(rf/defn create-account-and-login
{:events [:onboarding/create-account-and-login]}
[{:keys [db] :as cofx}]
@@ -88,9 +110,9 @@
(when-not syncing-account-recovered?
[:dispatch [:syncing/clear-syncing-installation-id]])]
:dispatch-later [{:ms constants/onboarding-generating-keys-animation-duration-ms
:dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications
loading-screen]]}]
:dispatch [:onboarding/account-creation-complete
{:loading-animation-complete? true
:loading-screen loading-screen}]}]
:db (-> db
(dissoc :profile/login)
(dissoc :auth-method)
@@ -25,6 +25,12 @@
{:key :i/copy}
{:key nil
:value "None"}]}
{:type :select
:key :title-icon
:options [{:key :i/chevron-right}
{:key :i/copy}
{:key nil
:value "None"}]}
{:type :select
:key :right-content
:options [{:key nil
@@ -22,13 +22,10 @@
:raribleMainnetAPIKey config/RARIBLE_MAINNET_API_KEY
:raribleTestnetAPIKey config/RARIBLE_TESTNET_API_KEY
:alchemyEthereumMainnetToken config/ALCHEMY_ETHEREUM_MAINNET_TOKEN
:alchemyEthereumGoerliToken config/ALCHEMY_ETHEREUM_GOERLI_TOKEN
:alchemyEthereumSepoliaToken config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN
:alchemyOptimismMainnetToken config/ALCHEMY_OPTIMISM_MAINNET_TOKEN
:alchemyOptimismGoerliToken config/ALCHEMY_OPTIMISM_GOERLI_TOKEN
:alchemyOptimismSepoliaToken config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN
:alchemyArbitrumMainnetToken config/ALCHEMY_ARBITRUM_MAINNET_TOKEN
:alchemyArbitrumGoerliToken config/ALCHEMY_ARBITRUM_GOERLI_TOKEN
:alchemyArbitrumSepoliaToken config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN})
(defn create
@@ -13,3 +13,7 @@
(rf/reg-fx :effects.profile/enable-local-notifications
(fn []
(native-module/start-local-notifications)))
(rf/reg-fx :effects.profile/convert-to-keycard-profile
(fn [{:keys [profile settings password new-password callback]}]
(native-module/convert-to-keycard-profile profile settings password new-password callback)))
@@ -83,7 +83,8 @@
[[:dispatch [:update-theme-and-init-root :screen/onboarding.syncing-results]]]
(get db :onboarding/new-account?)
[[:dispatch [:onboarding/finalize-setup]]]
[[:dispatch [:onboarding/finalize-setup]]
[:dispatch [:onboarding/account-creation-complete {:login-signal-received? true}]]]
:else
[[:dispatch [:update-theme-and-init-root :shell-stack]]
@@ -1,5 +1,6 @@
(ns status-im.contexts.profile.profiles.view
(:require
[clojure.string :as string]
[native-module.core :as native-module]
[quo.core :as quo]
[react-native.core :as rn]
@@ -182,7 +183,7 @@
:render-fn profile-card}]]))
(defn password-input
[]
[processing error]
(let [auth-method (rf/sub [:auth-method])
on-press-biometrics (fn []
(rf/dispatch [:biometric/authenticate
@@ -193,18 +194,31 @@
%])}]))]
[standard-authentication/password-input
{:shell? true
{:processing processing
:error error
:shell? true
:blur? true
:on-press-biometrics (when (= auth-method constants/auth-method-biometric) on-press-biometrics)}]))
(defn- get-error-message
[error]
(if (and (some? error)
(or (= error "file is not a database")
(string/starts-with? (string/lower-case error) "failed")))
(i18n/label :t/oops-wrong-password)
error))
(defn login-section
[{:keys [show-profiles]}]
(let [processing (rf/sub [:profile/login-processing])
{:keys [key-uid name keycard-pairing
(let [{:keys [key-uid name keycard-pairing
customization-color]} (rf/sub [:profile/login-profile])
sign-in-enabled? (rf/sub [:sign-in-enabled?])
profile-picture (rf/sub [:profile/login-profiles-picture key-uid])
login-multiaccount (rn/use-callback #(rf/dispatch [:profile.login/login]))]
{:keys [error processing]} (rf/sub [:profile/login])
error-message (rn/use-memo #(get-error-message error) [error])
error {:error? (boolean (seq error-message))
:error-message error-message}
login-profile (rn/use-callback #(rf/dispatch [:profile.login/login]))]
[rn/keyboard-avoiding-view
{:style style/login-container
:keyboard-vertical-offset (- (safe-area/get-bottom))}
@@ -239,17 +253,20 @@
:card-style style/login-profile-card}]
(if keycard-pairing
[keycard.pin/auth
{:on-complete
(fn [pin-text]
{:error error
:on-complete
(fn [pin]
(rf/dispatch
[:keycard/connect
{:key-uid key-uid
:on-success-fx [[:effects.keycard/get-keys
{:pin pin-text
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error
%])}]]}]))}]
[password-input])]
{:key-uid key-uid
:on-success
(fn []
(rf/dispatch
[:keycard/get-keys
{:pin pin
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]))}]))}]
[password-input processing error])]
(when-not keycard-pairing
[quo/button
{:size 40
@@ -258,7 +275,7 @@
:accessibility-label :login-button
:icon-left :i/unlocked
:disabled? (or (not sign-in-enabled?) processing)
:on-press login-multiaccount
:on-press login-profile
:container-style {:margin-bottom (+ (safe-area/get-bottom) 12)}}
(i18n/label :t/log-in)])]))
@@ -50,17 +50,6 @@
{:on-success on-success}])
:on-cancel nil}]]})))
(rf/reg-event-fx :profile.settings/toggle-goerli-test-network
(fn [{:keys [db]}]
(let [value (get-in db [:profile/profile :is-goerli-enabled?])
on-success #(rf/dispatch [:logout])]
{:fx [[:ui/show-confirmation
{:content (i18n/label :t/goerli-testnet-toggle-confirmation)
:on-accept #(rf/dispatch [:profile.settings/profile-update :is-goerli-enabled?
(not value)
{:on-success on-success}])
:on-cancel nil}]]})))
(rf/reg-event-fx :profile.settings/change-preview-privacy
(fn [_ [private?]]
(let [private?' (boolean private?)]
@@ -4,6 +4,7 @@
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.resources :as resources]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -27,11 +28,11 @@
:subtitle (i18n/label :t/secure-wallet-card)
:button-label (i18n/label :t/buy-keycard)
:accessibility-label :get-keycard
:image (resources/get-image :generate-keys)
:on-press #()}]
:image (resources/get-image :keycard-buy)
:on-press #(rf/dispatch [:browser.ui/open-url constants/get-keycard-url])}]
[rn/view {:style {:margin-top 24}}
[quo/text
{:style {:margin-bottom 12
{:style {:margin-bottom 1
:color colors/white-opa-70}
:size :paragraph-2
:weight :medium}
@@ -41,10 +41,9 @@
(for [label points]
^{:key label}
[quo/markdown-list
{:description (i18n/label label)
:blur? true
:type (when lock? :lock)
:container-style {:padding-top 8}}])]})
{:description (i18n/label label)
:blur? true
:type (when lock? :lock)}])]})
(defn- on-privacy-policy-press
[]
@@ -357,8 +357,7 @@
{:chain-id chain-id
:token-id token-id
:contract-address contract-address
:test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
:is-goerli-enabled? (get-in db [:profile/profile :is-goerli-enabled?])})]
:test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])})]
{:fx [[:dispatch
[:hide-bottom-sheet]]
[:dispatch-later
@@ -377,5 +376,4 @@
{:chain-id chain-id
:token-id token-id
:contract-address contract-address
:test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
:is-goerli-enabled? (get-in db [:profile/profile :is-goerli-enabled?])})]]]}))
:test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])})]]]}))
@@ -33,17 +33,11 @@
(when (> total 1) (str "x" total)))
(defn- get-opensea-network-name
[chain-id test-networks-enabled? is-goerli-enabled?]
[chain-id test-networks-enabled?]
(let [network-kw (network-utils/id->network chain-id)
network-name (name network-kw)
mainnet? (= :mainnet network-kw)]
(cond (and test-networks-enabled? is-goerli-enabled? mainnet?)
(:goerli constants/opensea-url-names)
(and test-networks-enabled? is-goerli-enabled?)
(str network-name "-" (:goerli constants/opensea-url-names))
(and test-networks-enabled? mainnet?)
(cond (and test-networks-enabled? mainnet?)
(:sepolia constants/opensea-url-names)
test-networks-enabled?
@@ -63,11 +57,10 @@
(defn get-opensea-collectible-url
[{:keys [chain-id token-id contract-address
test-networks-enabled? is-goerli-enabled?]}]
test-networks-enabled?]}]
(let [base-link (get-opensea-base-url test-networks-enabled?)
opensea-network-name (get-opensea-network-name chain-id
test-networks-enabled?
is-goerli-enabled?)]
test-networks-enabled?)]
(str base-link "/assets/" opensea-network-name "/" contract-address "/" token-id)))
(defn get-collectible-unique-id
@@ -43,26 +43,4 @@
:contract-address contract-address
:token-id token-id
:test-networks-enabled? true})
"https://testnets.opensea.io/assets/optimism-sepolia/0xC/0xT")))
(testing "get-opensea-collectible-url goerli"
(is (= (utils/get-opensea-collectible-url {:chain-id constants/ethereum-goerli-chain-id
:contract-address contract-address
:token-id token-id
:test-networks-enabled? true
:is-goerli-enabled? true})
"https://testnets.opensea.io/assets/goerli/0xC/0xT")))
(testing "get-opensea-collectible-url goerli arbitrum"
(is (= (utils/get-opensea-collectible-url {:chain-id constants/arbitrum-goerli-chain-id
:contract-address contract-address
:token-id token-id
:test-networks-enabled? true
:is-goerli-enabled? true})
"https://testnets.opensea.io/assets/arbitrum-goerli/0xC/0xT")))
(testing "get-opensea-collectible-url goerli optimism"
(is (= (utils/get-opensea-collectible-url {:chain-id constants/optimism-goerli-chain-id
:contract-address contract-address
:token-id token-id
:test-networks-enabled? true
:is-goerli-enabled? true})
"https://testnets.opensea.io/assets/optimism-goerli/0xC/0xT"))))
"https://testnets.opensea.io/assets/optimism-sepolia/0xC/0xT"))))
@@ -445,7 +445,7 @@
(defn transaction-path
[{:keys [from-address to-address token-id-from token-address token-id-to route data
slippage-percentage eth-transfer?]}]
(let [{:keys [bridge-name amount-in bonder-fees from
(let [{:keys [bridge-name amount-in from
to]} route
tx-data (transaction-data {:from-address from-address
:to-address to-address
@@ -453,6 +453,7 @@
:route route
:data data
:eth-transfer? eth-transfer?})
bonder-fees (-> route :bounder-fees money/to-string)
to-chain-id (:chain-id to)
from-chain-id (:chain-id from)]
(cond-> {:BridgeName bridge-name
@@ -14,12 +14,6 @@
(= chain-id constants/optimism-mainnet-chain-id)
config/optimism-mainnet-chain-explorer-link
(= chain-id constants/ethereum-goerli-chain-id)
config/goerli-chain-explorer-link
(= chain-id constants/optimism-goerli-chain-id)
config/optimism-goerli-chain-explorer-link
(= chain-id constants/ethereum-sepolia-chain-id)
config/sepolia-chain-explorer-link
@@ -10,58 +10,42 @@
(def id->network
{constants/ethereum-mainnet-chain-id constants/mainnet-network-name
constants/ethereum-goerli-chain-id constants/mainnet-network-name
constants/ethereum-sepolia-chain-id constants/mainnet-network-name
constants/optimism-mainnet-chain-id constants/optimism-network-name
constants/optimism-goerli-chain-id constants/optimism-network-name
constants/optimism-sepolia-chain-id constants/optimism-network-name
constants/arbitrum-mainnet-chain-id constants/arbitrum-network-name
constants/arbitrum-goerli-chain-id constants/arbitrum-network-name
constants/arbitrum-sepolia-chain-id constants/arbitrum-network-name})
(defn- get-chain-id
[{:keys [mainnet-chain-id sepolia-chain-id goerli-chain-id testnet-enabled? goerli-enabled?]}]
(cond
(and testnet-enabled? goerli-enabled?)
goerli-chain-id
testnet-enabled?
[{:keys [mainnet-chain-id sepolia-chain-id testnet-enabled?]}]
(if testnet-enabled?
sepolia-chain-id
:else
mainnet-chain-id))
(defn network->chain-id
([db network]
(let [{:keys [test-networks-enabled? is-goerli-enabled?]} (:profile/profile db)]
(let [{:keys [test-networks-enabled?]} (:profile/profile db)]
(network->chain-id {:network network
:testnet-enabled? test-networks-enabled?
:goerli-enabled? is-goerli-enabled?})))
([{:keys [network testnet-enabled? goerli-enabled?]}]
:testnet-enabled? test-networks-enabled?})))
([{:keys [network testnet-enabled?]}]
(condp contains? (keyword network)
#{constants/mainnet-network-name (keyword constants/mainnet-short-name)}
(get-chain-id
{:mainnet-chain-id constants/ethereum-mainnet-chain-id
:sepolia-chain-id constants/ethereum-sepolia-chain-id
:goerli-chain-id constants/ethereum-goerli-chain-id
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?})
:testnet-enabled? testnet-enabled?})
#{constants/optimism-network-name (keyword constants/optimism-short-name)}
(get-chain-id
{:mainnet-chain-id constants/optimism-mainnet-chain-id
:sepolia-chain-id constants/optimism-sepolia-chain-id
:goerli-chain-id constants/optimism-goerli-chain-id
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?})
:testnet-enabled? testnet-enabled?})
#{constants/arbitrum-network-name (keyword constants/arbitrum-short-name)}
(get-chain-id
{:mainnet-chain-id constants/arbitrum-mainnet-chain-id
:sepolia-chain-id constants/arbitrum-sepolia-chain-id
:goerli-chain-id constants/arbitrum-goerli-chain-id
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?}))))
:testnet-enabled? testnet-enabled?}))))
(defn network-list
[{:keys [balances-per-chain]} networks]
@@ -82,19 +66,13 @@
(network-list $ networks)))
(defn get-default-chain-ids-by-mode
[{:keys [test-networks-enabled? is-goerli-enabled?]}]
(cond
(and test-networks-enabled? is-goerli-enabled?)
constants/goerli-chain-ids
test-networks-enabled?
[{:keys [test-networks-enabled?]}]
(if test-networks-enabled?
constants/sepolia-chain-ids
:else
constants/mainnet-chain-ids))
(defn resolve-receiver-networks
[{:keys [prefix testnet-enabled? goerli-enabled?]}]
[{:keys [prefix testnet-enabled?]}]
(let [prefix (if (string/blank? prefix)
constants/default-multichain-address-prefix
prefix)
@@ -104,8 +82,7 @@
(mapv
#(network->chain-id
{:network %
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?})))))
:testnet-enabled? testnet-enabled?})))))
(def network->short-name
{constants/mainnet-network-name constants/mainnet-short-name
@@ -185,16 +162,13 @@
[chain-id]
(as-> chain-id $
(condp contains? $
#{constants/ethereum-mainnet-chain-id constants/ethereum-goerli-chain-id
constants/ethereum-sepolia-chain-id}
#{constants/ethereum-mainnet-chain-id constants/ethereum-sepolia-chain-id}
mainnet-network-details
#{constants/arbitrum-mainnet-chain-id constants/arbitrum-goerli-chain-id
constants/arbitrum-sepolia-chain-id}
#{constants/arbitrum-mainnet-chain-id constants/arbitrum-sepolia-chain-id}
arbitrum-network-details
#{constants/optimism-mainnet-chain-id constants/optimism-goerli-chain-id
constants/optimism-sepolia-chain-id}
#{constants/optimism-mainnet-chain-id constants/optimism-sepolia-chain-id}
optimism-network-details
nil)
@@ -6,19 +6,17 @@
(deftest network->chain-id-test
(testing "network->chain-id function"
(is (= (utils/network->chain-id {:network :mainnet :testnet-enabled? false :goerli-enabled? false})
(is (= (utils/network->chain-id {:network :mainnet :testnet-enabled? false})
constants/ethereum-mainnet-chain-id))
(is (= (utils/network->chain-id {:network :eth :testnet-enabled? true :goerli-enabled? false})
(is (= (utils/network->chain-id {:network :eth :testnet-enabled? true})
constants/ethereum-sepolia-chain-id))
(is (= (utils/network->chain-id {:network "optimism" :testnet-enabled? true :goerli-enabled? false})
(is (= (utils/network->chain-id {:network "optimism" :testnet-enabled? true})
constants/optimism-sepolia-chain-id))
(is (= (utils/network->chain-id {:network "oeth" :testnet-enabled? false :goerli-enabled? true})
(is (= (utils/network->chain-id {:network "oeth" :testnet-enabled? false})
constants/optimism-mainnet-chain-id))
(is (= (utils/network->chain-id {:network :oeth :testnet-enabled? true :goerli-enabled? true})
constants/optimism-goerli-chain-id))
(is (= (utils/network->chain-id {:network :arb1 :testnet-enabled? false :goerli-enabled? false})
(is (= (utils/network->chain-id {:network :arb1 :testnet-enabled? false})
constants/arbitrum-mainnet-chain-id))
(is (= (utils/network->chain-id {:network :arbitrum :testnet-enabled? true :goerli-enabled? false})
(is (= (utils/network->chain-id {:network :arbitrum :testnet-enabled? true})
constants/arbitrum-sepolia-chain-id))))
(deftest short-names->network-preference-prefix-test
@@ -233,13 +233,12 @@
(defn new->old-route-path
[new-path]
(let [bonder-fees (:tx-bonder-fees new-path)
token-fees (+ (money/wei->ether bonder-fees)
(money/wei->ether (:tx-token-fees new-path)))]
(let [bonder-fees (-> new-path :tx-bonder-fees money/bignumber)
token-fees (-> new-path :tx-token-fees money/bignumber)]
{:from (:from-chain new-path)
:amount-in-locked (:amount-in-locked new-path)
:amount-in (:amount-in new-path)
:max-amount-in "0x0"
:max-amount-in (:max-amount-in new-path)
:gas-fees {:gas-price "0"
:base-fee (send-utils/convert-to-gwei (:tx-base-fee
new-path)
+4 -16
View File
@@ -387,23 +387,14 @@
(rf/dispatch [:wallet/set-ens-address nil ens])
(on-error-fn))))}]]]})))
(defn- resolved-address->prefixed-address
[address networks]
(let [prefixes (->> networks
(map network-utils/network->short-name)
network-utils/short-names->network-preference-prefix)]
(str prefixes (eip55/address->checksum address))))
(rf/reg-event-fx
:wallet/set-ens-address
(fn [{:keys [db]} [result ens]]
(let [networks [constants/ethereum-network-name constants/optimism-network-name]
suggestion (if result
(let [suggestion (if result
[{:type item-types/address
:ens ens
:address (eip55/address->checksum result)
:networks networks
:full-address (resolved-address->prefixed-address result networks)}]
:full-address (eip55/address->checksum result)}]
[])]
{:db (-> db
(assoc-in [:wallet :ui :search-address :local-suggestions] suggestion)
@@ -511,10 +502,8 @@
(for [[k v] chains :when (= v "down")] k))
keys)
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
is-goerli-enabled? (get-in db [:profile/profile :is-goerli-enabled?])
chain-ids-by-mode (network-utils/get-default-chain-ids-by-mode
{:test-networks-enabled? test-networks-enabled?
:is-goerli-enabled? is-goerli-enabled?})
{:test-networks-enabled? test-networks-enabled?})
chains-filtered-by-mode (remove #(not (contains? chain-ids-by-mode %)) down-chain-ids)
chains-down? (and (network.data-store/online? db) (seq chains-filtered-by-mode))
chain-names (when chains-down?
@@ -527,8 +516,7 @@
(when (seq down-chain-ids)
(log/info "[wallet] Chain(s) down: " down-chain-ids)
(log/info "[wallet] Chain name(s) down: " chain-names)
(log/info "[wallet] Test network enabled: " (boolean test-networks-enabled?))
(log/info "[wallet] Goerli network enabled: " (boolean is-goerli-enabled?)))
(log/info "[wallet] Test network enabled: " (boolean test-networks-enabled?)))
;; NOTE <shivekkhurana>: We used to show an error toast, but disabled it because the down
;; signal is sent randomly. Needs to be investigated and enabled again !
@@ -152,11 +152,9 @@
(fn [{:keys [db]} [{:keys [address recipient stack-id start-flow?]}]]
(let [[prefix to-address] (utils/split-prefix-and-address address)
testnet-enabled? (get-in db [:profile/profile :test-networks-enabled?])
goerli-enabled? (get-in db [:profile/profile :is-goerli-enabled?])
receiver-networks (network-utils/resolve-receiver-networks
{:prefix prefix
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?})
:testnet-enabled? testnet-enabled?})
collectible-tx? (send-utils/tx-type-collectible?
(-> db :wallet :ui :send :tx-type))
collectible (when collectible-tx?
@@ -561,7 +559,7 @@
:error error-message}))
{:fx [[:dispatch
(cond
(and failure? swap?) [:wallet/swap-proposal-error error-message]
(and failure? swap?) [:wallet/swap-proposal-error error]
failure? [:wallet/suggested-routes-error error-message]
swap? [:wallet/swap-proposal-success (fix-routes data)]
:else [:wallet/suggested-routes-success (fix-routes data)
@@ -357,11 +357,9 @@
(testing "testing when collectible balance is more than 1"
(let [collectible (collectible-with-balance 2)
testnet-enabled? false
goerli-enabled? false
receiver-networks (network-utils/resolve-receiver-networks
{:prefix prefix
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?})
:testnet-enabled? testnet-enabled?})
expected-result {:db {:wallet {:ui {:send {:other-props :value
:recipient recipient
:to-address to-address
@@ -371,8 +369,7 @@
:receiver-networks receiver-networks
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? false
:is-goerli-enabled? false}}
:profile/profile {:test-networks-enabled? false}}
:fx [nil
[:dispatch
[:wallet/wizard-navigate-forward
@@ -383,8 +380,7 @@
{:wallet {:ui {:send {:other-props :value
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? testnet-enabled?
:is-goerli-enabled? goerli-enabled?}})
:profile/profile {:test-networks-enabled? testnet-enabled?}})
(is (match? expected-result
(dispatch [event-id
{:address address
@@ -394,11 +390,9 @@
(testing "testing when collectible balance is 1"
(let [collectible (collectible-with-balance 1)
testnet-enabled? false
goerli-enabled? false
receiver-networks (network-utils/resolve-receiver-networks
{:prefix prefix
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?})
:testnet-enabled? testnet-enabled?})
expected-result {:db {:wallet {:ui {:send {:other-props :value
:recipient recipient
:to-address to-address
@@ -408,8 +402,7 @@
:receiver-networks receiver-networks
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? false
:is-goerli-enabled? false}}
:profile/profile {:test-networks-enabled? false}}
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]]
[:dispatch
[:wallet/wizard-navigate-forward
@@ -420,8 +413,7 @@
{:wallet {:ui {:send {:other-props :value
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? testnet-enabled?
:is-goerli-enabled? goerli-enabled?}})
:profile/profile {:test-networks-enabled? testnet-enabled?}})
(is (match? expected-result
(dispatch [event-id
{:address address
@@ -104,16 +104,19 @@
:wallet/wallet-send-tx-type :tx/send
:wallet/wallet-send-fee-fiat-formatted "$5,00"
:wallet/sending-collectible? false
:wallet/total-amount (money/bignumber "250")})
:wallet/send-total-amount-formatted "250 ETH"
:wallet/total-amount (money/bignumber "250")
:wallet/bridge-to-network-details nil
:wallet/send-amount-fixed ""
:wallet/send-display-token-decimals 5})
(h/describe "Send > input amount screen"
(h/setup-restorable-re-frame)
(h/test "Default render"
(h/setup-subs sub-mocks)
(h/setup-subs (assoc sub-mocks :wallet/send-display-token-decimals 2))
(h/render-with-theme-provider [input-amount/view
{:crypto-decimals 2
:limit-crypto (money/bignumber 250)
{:limit-crypto (money/bignumber 250)
:initial-crypto-currency? false}])
(h/is-truthy (h/get-by-text "0"))
(h/is-truthy (h/get-by-text "USD"))
@@ -122,12 +125,11 @@
(h/is-disabled (h/get-by-label-text :button-one)))
(h/test "Fill token input and confirm"
(h/setup-subs sub-mocks)
(h/setup-subs (assoc sub-mocks :wallet/send-display-token-decimals 10))
(let [on-confirm (h/mock-fn)]
(h/render-with-theme-provider [input-amount/view
{:crypto-decimals 10
:limit-crypto (money/bignumber 1000)
{:limit-crypto (money/bignumber 1000)
:on-confirm on-confirm
:initial-crypto-currency? true}])
@@ -147,10 +149,9 @@
(h/was-called on-confirm)))))))
(h/test "Try to fill more than limit"
(h/setup-subs sub-mocks)
(h/setup-subs (assoc sub-mocks :wallet/send-display-token-decimals 1))
(h/render-with-theme-provider [input-amount/view
{:crypto-decimals 1
:limit-crypto (money/bignumber 1)}])
{:limit-crypto (money/bignumber 1)}])
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
@@ -159,11 +160,10 @@
(h/is-truthy (h/get-by-label-text :container-error)))
(h/test "Switch from crypto to fiat and check limit"
(h/setup-subs sub-mocks)
(h/setup-subs (assoc sub-mocks :wallet/send-display-token-decimals 1))
(h/render-with-theme-provider [input-amount/view
{:crypto-decimals 1
:limit-crypto (money/bignumber 10)
:on-confirm #()}])
{:limit-crypto (money/bignumber 10)
:on-confirm #()}])
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
@@ -0,0 +1,67 @@
(ns status-im.contexts.wallet.send.input-amount.estimated-fees
(:require
[quo.core :as quo]
[quo.theme]
[react-native.core :as rn]
[status-im.common.not-implemented :as not-implemented]
[status-im.contexts.wallet.send.input-amount.style :as style]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- bonder-fee-info-sheet
[]
[:<>
[quo/drawer-top
{:title (i18n/label :t/understanding-bonder-fees-title)}]
[rn/view {:style {:padding-horizontal 20}}
[quo/text
{:weight :regular
:size :paragraph-2}
(i18n/label :t/understanding-bonder-fees-description)]]])
(defn- show-bonder-fee-info
[]
(rf/dispatch
[:show-bottom-sheet {:content bonder-fee-info-sheet}]))
(defn- received-amount
[{:keys [loading-routes?]}]
(let [amount (rf/sub [:wallet/send-total-amount-formatted])
tx-type (rf/sub [:wallet/wallet-send-tx-type])
{:keys [full-name]} (rf/sub [:wallet/bridge-to-network-details])]
[quo/data-item
(cond-> {:container-style style/amount-data-item
:status (if loading-routes? :loading :default)
:size :small
:title (i18n/label :t/recipient-gets)
:subtitle amount}
(= tx-type :tx/bridge)
(assoc
:title-icon :i/info
:title (i18n/label :t/bridged-to
{:network full-name})
:on-press show-bonder-fee-info))]))
(defn view
[{:keys [loading-routes? fees]}]
[rn/view {:style style/estimated-fees-container}
(when (ff/enabled? ::ff/wallet.advanced-sending)
[rn/view {:style style/estimated-fees-content-container}
[quo/button
{:icon-only? true
:type :outline
:size 32
:inner-style {:opacity 1}
:accessibility-label :advanced-button
:disabled? loading-routes?
:on-press not-implemented/alert}
:i/advanced]])
[quo/data-item
{:container-style style/fees-data-item
:status (if loading-routes? :loading :default)
:size :small
:title (i18n/label :t/fees)
:subtitle fees}]
[received-amount {:loading-routes? loading-routes?}]])
@@ -11,45 +11,17 @@
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im.contexts.wallet.common.asset-list.view :as asset-list]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.input-amount.estimated-fees :as estimated-fees]
[status-im.contexts.wallet.send.input-amount.style :as style]
[status-im.contexts.wallet.send.routes.view :as routes]
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
[status-im.contexts.wallet.sheets.unpreferred-networks-alert.view :as unpreferred-networks-alert]
[status-im.feature-flags :as ff]
[status-im.setup.hot-reload :as hot-reload]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.number :as number]
[utils.re-frame :as rf]))
(defn- estimated-fees
[{:keys [loading-routes? fees amount]}]
[rn/view {:style style/estimated-fees-container}
(when (ff/enabled? ::ff/wallet.advanced-sending)
[rn/view {:style style/estimated-fees-content-container}
[quo/button
{:icon-only? true
:type :outline
:size 32
:inner-style {:opacity 1}
:accessibility-label :advanced-button
:disabled? loading-routes?
:on-press #(js/alert "Not implemented yet")}
:i/advanced]])
[quo/data-item
{:container-style style/fees-data-item
:status (if loading-routes? :loading :default)
:size :small
:title (i18n/label :t/fees)
:subtitle fees}]
[quo/data-item
{:container-style style/amount-data-item
:status (if loading-routes? :loading :default)
:size :small
:title (i18n/label :t/recipient-gets)
:subtitle amount}]])
(defn- every-network-value-is-zero?
[sender-network-values]
(every? (fn [{:keys [total-amount]}]
@@ -165,7 +137,6 @@
;; for component tests only
[{default-on-confirm :on-confirm
default-limit-crypto :limit-crypto
default-crypto-decimals :crypto-decimals
on-navigate-back :on-navigate-back
button-one-label :button-one-label
button-one-props :button-one-props
@@ -199,17 +170,13 @@
:market-values-per-currency
currency
:price)
token-decimals (-> token
utils/token-usd-price
utils/one-cent-value
utils/calc-max-crypto-decimals)
token-decimals (rf/sub [:wallet/send-display-token-decimals])
[input-state set-input-state] (rn/use-state controlled-input/init-state)
clear-input! #(set-input-state controlled-input/delete-all)
currency-symbol (rf/sub [:profile/currency-symbol])
loading-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
route (rf/sub [:wallet/wallet-send-route])
on-confirm (or default-on-confirm handle-on-confirm)
crypto-decimals (or token-decimals default-crypto-decimals)
max-limit (if crypto-currency?
(utils/cut-crypto-decimals-to-fit-usd-cents
token-balance
@@ -221,15 +188,8 @@
(controlled-input/input-error input-state)))
amount-in-crypto (if crypto-currency?
input-value
(number/remove-trailing-zeroes
(.toFixed (/ input-value conversion-rate)
crypto-decimals)))
total-amount-receiver (rf/sub [:wallet/total-amount true])
amount-text (str (number/remove-trailing-zeroes
(.toFixed total-amount-receiver
(min token-decimals 6)))
" "
token-symbol)
(rf/sub [:wallet/send-amount-fixed
(/ input-value conversion-rate)]))
show-select-asset-sheet #(rf/dispatch
[:show-bottom-sheet
{:content (fn []
@@ -382,10 +342,9 @@
[not-enough-asset])
(when (or (and (not no-routes-found?) (or loading-routes? route))
not-enough-asset?)
[estimated-fees
[estimated-fees/view
{:loading-routes? loading-routes?
:fees fee-formatted
:amount amount-text}])
:fees fee-formatted}])
(when show-no-routes?
[no-routes-found])
[quo/bottom-actions
@@ -417,7 +376,7 @@
:delete-key? true
:on-press (fn [c]
(let [new-text (str input-value c)
max-decimals (if crypto-currency? crypto-decimals 2)
max-decimals (if crypto-currency? token-decimals 2)
regex-pattern (str "^\\d*\\.?\\d{0," max-decimals "}$")
regex (re-pattern regex-pattern)]
(when (re-matches regex new-text)
@@ -243,37 +243,40 @@
[{:keys [network-values token-symbol on-press on-long-press receiver? loading-routes?
token-not-supported-in-receiver-networks?]}]
[rn/view
(map-indexed (fn [index
{chain-id :chain-id
network-value-type :type
total-amount :total-amount}]
(let [status (cond (and (= network-value-type :not-available)
loading-routes?
token-not-supported-in-receiver-networks?)
:loading
(= network-value-type :not-available)
:disabled
:else network-value-type)]
[rn/view
{:key (str (if receiver? "to" "from") "-" chain-id)
:style {:margin-top (if (pos? index) 11 7.5)}}
[quo/network-bridge
{:amount (if (= network-value-type :not-available)
(i18n/label :t/not-available)
(str total-amount " " token-symbol))
:network (network-utils/id->network chain-id)
:status status
:on-press #(when (not loading-routes?)
(cond
(= network-value-type :edit)
(open-preferences)
on-press (on-press chain-id total-amount)))
:on-long-press #(when (and (not loading-routes?) (not= status :disabled))
(cond
(= network-value-type :add)
(open-preferences)
on-long-press (on-long-press chain-id total-amount)))}]]))
network-values)])
(doall
(map-indexed (fn [index
{chain-id :chain-id
network-value-type :type
total-amount :total-amount}]
(let [status (cond (and (= network-value-type :not-available)
loading-routes?
token-not-supported-in-receiver-networks?)
:loading
(= network-value-type :not-available)
:disabled
:else network-value-type)
amount-formatted (-> (rf/sub [:wallet/send-amount-fixed total-amount])
(str " " token-symbol))]
^{:key (str (if receiver? "to" "from") "-" chain-id)}
[rn/view
{:style {:margin-top (if (pos? index) 11 7.5)}}
[quo/network-bridge
{:amount (if (= network-value-type :not-available)
(i18n/label :t/not-available)
amount-formatted)
:network (network-utils/id->network chain-id)
:status status
:on-press #(when (not loading-routes?)
(cond
(= network-value-type :edit)
(open-preferences)
on-press (on-press chain-id total-amount)))
:on-long-press #(when (and (not loading-routes?) (not= status :disabled))
(cond
(= network-value-type :add)
(open-preferences)
on-long-press (on-long-press chain-id total-amount)))}]]))
network-values))])
(defn render-network-links
[{:keys [network-links sender-network-values]}]
@@ -0,0 +1,81 @@
(ns status-im.contexts.wallet.send.transaction-confirmation.account-summary
(:require
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.transaction-confirmation.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- account-summary-header
[{:keys [label accessibility-label]}]
(let [theme (quo.theme/use-theme)]
[quo/text
{:size :paragraph-2
:weight :medium
:style (style/section-label theme)
:accessibility-label accessibility-label}
label]))
(defn- current-user-account-summary
[{:keys [network-values]}]
(let [{:keys [color emoji name address]} (rf/sub [:wallet/current-viewing-account])]
[quo/summary-info
{:type :status-account
:networks? true
:values network-values
:account-props {:customization-color color
:size 32
:emoji emoji
:type :default
:name name
:address (utils/get-shortened-address address)}}]))
(defn- recipient-account-summary
[{:keys [network-values]}]
(let [{:keys [label emoji customization-color recipient-type]} (rf/sub [:wallet/send-recipient])
address (rf/sub [:wallet/send-to-address])
shortened-address (utils/get-shortened-address address)
summary-type (condp = recipient-type
:saved-address :saved-account
:account :status-account
:address :account
:account)]
[quo/summary-info
{:type summary-type
:networks? true
:values network-values
:account-props (cond-> {:customization-color customization-color
:size 32
:emoji emoji
:type :default
:name (or label address)
:full-name label
:address shortened-address}
(= recipient-type :address)
(assoc :full-name "0 x"
:monospace? true
:lowercase? true))}]))
(defn from-summary
[]
(let [network-values (rf/sub [:wallet/network-values false])]
[rn/view {:style style/summary-container}
[account-summary-header
{:label (i18n/label :t/from-capitalized)
:accessibility-label :summary-from-label}]
[current-user-account-summary {:network-values network-values}]]))
(defn to-summary
[]
(let [network-values (rf/sub [:wallet/network-values true])
tx-type (rf/sub [:wallet/send-tx-type])]
[rn/view {:style style/summary-container}
[account-summary-header
{:label (i18n/label :t/to-capitalized)
:accessibility-label :summary-to-label}]
(if (= tx-type :tx/bridge)
[current-user-account-summary {:network-values network-values}]
[recipient-account-summary {:network-values network-values}])]))
@@ -1,13 +1,17 @@
(ns status-im.contexts.wallet.send.transaction-confirmation.style
(:require [quo.foundations.colors :as colors]))
(def summary-container
{:padding-horizontal 20
:padding-bottom 16})
(def detail-item
{:flex 1
:height 36
:background-color :transparent})
(def content-container
{:padding-top 12
{:padding-top 8
:padding-horizontal 20
:padding-bottom 32})
@@ -0,0 +1,131 @@
(ns status-im.contexts.wallet.send.transaction-confirmation.transaction-title
(:require [quo.core :as quo]
[react-native.core :as rn]
[react-native.utils :as rn.utils]
[status-im.contexts.wallet.send.transaction-confirmation.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- title-container
[& argv]
(let [[_ children] (rn.utils/get-props-and-children argv)]
(into [rn/view {:style style/content-container}]
children)))
(defn- title-row
[& argv]
(let [[_ children] (rn.utils/get-props-and-children argv)]
(into [rn/view
{:style {:flex-direction :row
:margin-top 4}}]
children)))
(defn- title-text
[text]
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :send-label}
text])
(defn- title-token
[]
(let [amount (rf/sub [:wallet/send-amount])
token-display-name (rf/sub [:wallet/wallet-send-token-symbol])]
[quo/summary-tag
{:token token-display-name
:label (str amount " " token-display-name)
:type :token}]))
(defn- title-collectible
[]
(let [{:keys [collectible-data preview-url]} (rf/sub [:wallet/send-collectible])]
[quo/summary-tag
{:label (:name collectible-data)
:image-source (:uri preview-url)
:type :collectible}]))
(defn- title-network
[{:keys [chain-id]}]
(let [{:keys [full-name source network-name]} (rf/sub [:wallet/network-details-by-chain-id chain-id])]
[quo/summary-tag
{:label full-name
:type :network
:image-source source
:customization-color network-name}]))
(defn- from-bridge-networks
[]
(let [chain-ids (rf/sub [:wallet/send-from-chain-ids])]
[:<>
(doall (map-indexed (fn [idx chain-id]
^{:key (str "transaction-title" idx)}
[title-row
[title-text
(if (zero? idx)
(i18n/label :t/from)
(str (i18n/label :t/and) " "))]
[title-network {:chain-id chain-id}]])
chain-ids))]))
(defn- to-bridge-network
[]
(let [chain-id (rf/sub [:wallet/send-bridge-to-chain-id])]
[title-network {:chain-id chain-id}]))
(defn- title-account
[]
(let [{:keys [name emoji color]} (rf/sub [:wallet/current-viewing-account])]
[quo/summary-tag
{:label name
:type :account
:emoji emoji
:customization-color color}]))
(defn- title-recipient
[]
(let [{:keys [recipient-type emoji label customization-color]} (rf/sub [:wallet/send-recipient])]
[quo/summary-tag
{:type recipient-type
:emoji emoji
:label label
:customization-color customization-color}]))
(defn- bridge-title
[]
[title-container
[title-row
[title-text (i18n/label :t/bridge)]
[title-token]]
[from-bridge-networks]
[title-row
[title-text (i18n/label :t/to)]
[to-bridge-network]]
[title-row
[title-text (i18n/label :t/in)]
[title-account]]])
(defn- send-title
[]
(let [sending-collectible? (rf/sub [:wallet/sending-collectible?])]
[title-container
[title-row
[title-text (i18n/label :t/send)]
(if sending-collectible?
[title-collectible]
[title-token])]
[title-row
[title-text (i18n/label :t/from)]
[title-account]]
[title-row
[title-text (i18n/label :t/to)]
[title-recipient]]]))
(defn view
[]
(let [tx-type (rf/sub [:wallet/send-tx-type])]
(condp = tx-type
:tx/bridge [bridge-title]
:tx/send [send-title]
[send-title])))
@@ -1,158 +1,17 @@
(ns status-im.contexts.wallet.send.transaction-confirmation.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]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.standard-authentication.core :as standard-auth]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.transaction-confirmation.account-summary :as account-summary]
[status-im.contexts.wallet.send.transaction-confirmation.style :as style]
[status-im.contexts.wallet.send.utils :as send-utils]
[status-im.contexts.wallet.send.transaction-confirmation.transaction-title :as transaction-title]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(defn- transaction-title
[{:keys [token-display-name amount account route to-network image-url transaction-type
collectible? recipient]}]
(let [to-network-name (:network-name to-network)
to-network-color (if (= to-network-name :mainnet) :ethereum to-network-name)]
[rn/view {:style style/content-container}
[rn/view {:style {:flex-direction :row}}
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :send-label}
(if (= transaction-type :tx/bridge)
(i18n/label :t/bridge)
(i18n/label :t/send))]
[quo/summary-tag
(cond-> {:token (if collectible? "" token-display-name)
:label (str amount " " token-display-name)
:type (if collectible? :collectible :token)}
collectible? (assoc :image-source image-url))]]
(if (= transaction-type :tx/bridge)
(doall
(map-indexed
(fn [idx path]
(let [from-network (:from path)
chain-id (:chain-id from-network)
network (rf/sub [:wallet/network-details-by-chain-id
chain-id])
network-name (:network-name network)
network-name-text (name network-name)
network-name-capitalized (when (seq network-name-text)
(string/capitalize network-name-text))
network-color (if (= network-name :mainnet) :ethereum network-name)]
(with-meta
[rn/view
{:style {:flex-direction :row
:margin-top 4}}
(if (zero? idx)
[:<>
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :send-label}
(i18n/label :t/from)]
[quo/summary-tag
{:label network-name-capitalized
:type :network
:image-source (:source network)
:customization-color network-color}]]
[:<>
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :send-label}
(str (i18n/label :t/and) " ")]
[quo/summary-tag
{:label network-name-capitalized
:type :network
:image-source (:source network)
:customization-color network-color}]])]
{:key (str "transaction-title" idx)})))
route))
[rn/view
{:style {:flex-direction :row
:margin-top 4}}
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :send-label}
(i18n/label :t/from)]
[quo/summary-tag
{:label (:name account)
:type :account
:emoji (:emoji account)
:customization-color (:color account)}]])
[rn/view
{:style {:flex-direction :row
:margin-top 4}}
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :send-label}
(i18n/label :t/to)]
(if (= transaction-type :tx/bridge)
[quo/summary-tag
{:type :network
:image-source (:source to-network)
:label (string/capitalize (name (:network-name to-network)))
:customization-color to-network-color}]
[quo/summary-tag (assoc recipient :type (:recipient-type recipient))])]
(when (= transaction-type :tx/bridge)
[rn/view
{:style {:flex-direction :row
:margin-top 4}}
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :send-label}
(i18n/label :t/in)]
[quo/summary-tag
{:label (:name account)
:type :account
:emoji (:emoji account)
:customization-color (:color account)}]])]))
(defn- user-summary
[{:keys [account-props theme label accessibility-label summary-type recipient bridge-tx? account-to?]}]
(let [network-values (rf/sub [:wallet/network-values account-to?])
summary-info-type (case (:recipient-type recipient)
:saved-address :saved-account
:account :status-account
summary-type)]
[rn/view
{:style {:padding-horizontal 20
:padding-bottom 16}}
[quo/text
{:size :paragraph-2
:weight :medium
:style (style/section-label theme)
:accessibility-label accessibility-label}
label]
[quo/summary-info
{:type summary-info-type
:networks? true
:values (send-utils/network-values-for-ui network-values)
:account-props (cond-> account-props
(and account-to? (not bridge-tx?))
(assoc
:size 32
:name (:label recipient)
:full-name (:label recipient)
:emoji (:emoji recipient)
:customization-color (:customization-color recipient)))}]]))
(defn- data-item
[{:keys [title subtitle]}]
[quo/data-item
@@ -164,11 +23,53 @@
:title title
:subtitle subtitle}])
(defn- estimated-time-view
[]
(let [estimated-time (rf/sub [:wallet/send-estimated-time])]
[data-item
{:title (i18n/label :t/est-time)
:subtitle (i18n/label :t/time-in-mins
{:minutes (str estimated-time)})}]))
(defn- max-fees-view
[]
(let [native-currency-symbol (-> (rf/sub [:wallet/send-route])
first
(get-in [:from :native-currency-symbol]))
max-fees (rf/sub [:wallet/wallet-send-fee-fiat-formatted
native-currency-symbol])]
[data-item
{:title (i18n/label :t/max-fees)
:subtitle max-fees}]))
(defn- bridge-received-amount
[]
(let [to-network (rf/sub [:wallet/bridge-to-network-details])
amount (rf/sub [:wallet/send-total-amount-formatted])]
[data-item
{:title (i18n/label :t/bridged-to
{:network (:abbreviated-name to-network)})
:subtitle amount}]))
(defn- send-received-amount
[]
(let [amount (rf/sub [:wallet/send-total-amount-formatted])]
[data-item
{:title (i18n/label :t/recipient-gets)
:subtitle amount}]))
(defn- received-amount-view
[]
(let [tx-type (rf/sub [:wallet/send-tx-type])]
(if (= tx-type :tx/bridge)
[bridge-received-amount]
[send-received-amount])))
(defn- transaction-details
[{:keys [estimated-time-min max-fees token-display-name amount to-network route
transaction-type]}]
(let [route-loaded? (and route (seq route))
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])]
[]
(let [route-loaded? (seq (rf/sub [:wallet/send-route]))
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
sending-collectible? (rf/sub [:wallet/sending-collectible?])]
[rn/view
{:style (style/details-container
{:loading-suggested-routes? loading-suggested-routes?
@@ -176,127 +77,60 @@
(cond
loading-suggested-routes?
[rn/activity-indicator {:style {:flex 1}}]
route-loaded?
[:<>
[data-item
{:title (i18n/label :t/est-time)
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time-min)})}]
[data-item
{:title (i18n/label :t/max-fees)
:subtitle max-fees}]
[data-item
{:title (if (= transaction-type :tx/bridge)
(i18n/label :t/bridged-to
{:network (:abbreviated-name to-network)})
(i18n/label :t/recipient-gets))
:subtitle (str amount " " token-display-name)}]]
[estimated-time-view]
[max-fees-view]
(when-not sending-collectible?
[received-amount-view])]
:else
[quo/text {:style {:align-self :center}}
(i18n/label :t/no-routes-found-confirmation)])]))
(defn- slide-to-confirm
[]
(let [route-loaded? (seq (rf/sub [:wallet/send-route]))
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
tx-type (rf/sub [:wallet/send-tx-type])
customization-color (rf/sub [:wallet/current-viewing-account-color])]
(when (and (not loading-suggested-routes?) route-loaded?)
[standard-auth/slide-button
{:keycard-supported? true
:size :size-48
:track-text (if (= tx-type :tx/bridge)
(i18n/label :t/slide-to-bridge)
(i18n/label :t/slide-to-send))
:container-style {:z-index 2}
:customization-color customization-color
:on-auth-success #(rf/dispatch
[:wallet/send-transaction
(security/safe-unmask-data %)])
:auth-button-label (i18n/label :t/confirm)}])))
(defn- on-close
[]
(rf/dispatch [:wallet/transaction-confirmation-navigate-back]))
(defn view
[_]
(let [on-close #(rf/dispatch [:wallet/transaction-confirmation-navigate-back])]
(fn []
(let [theme (quo.theme/use-theme)
send-transaction-data (rf/sub [:wallet/wallet-send])
{:keys [token-display-name collectible amount
route
to-address bridge-to-chain-id type
recipient]} send-transaction-data
collectible? (some? collectible)
image-url (when collectible
(get-in collectible [:preview-url :uri]))
transaction-type (:tx-type send-transaction-data)
estimated-time-min (reduce + (map :estimated-time route))
token-symbol (or token-display-name
(-> send-transaction-data :token :symbol))
first-route (first route)
native-currency-symbol (get-in first-route
[:from :native-currency-symbol])
fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted
native-currency-symbol])
account (rf/sub [:wallet/current-viewing-account])
account-color (:color account)
bridge-to-network (when bridge-to-chain-id
(rf/sub [:wallet/network-details-by-chain-id
bridge-to-chain-id]))
loading-suggested-routes? (rf/sub
[:wallet/wallet-send-loading-suggested-routes?])
total-amount-receiver (rf/sub [:wallet/total-amount true])
from-account-props {:customization-color account-color
:size 32
:emoji (:emoji account)
:type :default
:name (:name account)
:address (utils/get-shortened-address
(:address
account))}
user-props {:full-name to-address
:address (utils/get-shortened-address
to-address)}]
[rn/view {:style {:flex 1}}
[floating-button-page/view
{:footer-container-padding 0
:header [quo/page-nav
{:icon-name :i/arrow-left
:on-press on-close
:margin-top (safe-area/get-top)
:background :blur
:accessibility-label :top-bar}]
:footer [:<>
[transaction-details
{:estimated-time-min estimated-time-min
:max-fees fee-formatted
:token-display-name token-symbol
:amount total-amount-receiver
:to-network bridge-to-network
:theme theme
:route route
:transaction-type transaction-type}]
(when (and (not loading-suggested-routes?) route (seq route))
[standard-auth/slide-button
{:keycard-supported? true
:size :size-48
:track-text (if (= transaction-type :tx/bridge)
(i18n/label :t/slide-to-bridge)
(i18n/label :t/slide-to-send))
:container-style {:z-index 2}
:customization-color account-color
:on-auth-success #(rf/dispatch
[:wallet/send-transaction
(security/safe-unmask-data %)])
:auth-button-label (i18n/label :t/confirm)}])]
:gradient-cover? true
:customization-color (:color account)}
[rn/view
[transaction-title
{:token-display-name token-symbol
:amount amount
:account account
:type type
:recipient recipient
:route route
:to-network bridge-to-network
:image-url image-url
:transaction-type transaction-type
:collectible? collectible?}]
[user-summary
{:summary-type :status-account
:accessibility-label :summary-from-label
:label (i18n/label :t/from-capitalized)
:account-props from-account-props
:theme theme}]
[user-summary
{:summary-type (if (= transaction-type :tx/bridge)
:status-account
:account)
:accessibility-label :summary-to-label
:label (i18n/label :t/to-capitalized)
:account-props (if (= transaction-type :tx/bridge)
from-account-props
user-props)
:recipient recipient
:bridge-tx? (= transaction-type :tx/bridge)
:account-to? true
:theme theme}]]]]))))
(let [customization-color (rf/sub [:wallet/current-viewing-account-color])]
[rn/view {:style {:flex 1}}
[floating-button-page/view
{:footer-container-padding 0
:header [quo/page-nav
{:icon-name :i/arrow-left
:on-press on-close
:margin-top (safe-area/get-top)
:background :blur
:accessibility-label :top-bar}]
:footer [:<>
[transaction-details]
[slide-to-confirm]]
:gradient-cover? true
:customization-color customization-color}
[rn/view
[transaction-title/view]
[account-summary/from-summary]
[account-summary/to-summary]]]]))
+57 -13
View File
@@ -1,9 +1,7 @@
(ns status-im.contexts.wallet.send.utils
(:require
[native-module.core :as native-module]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[utils.hex :as utils.hex]
[utils.money :as money]))
(defn amount-in-hex
@@ -43,21 +41,67 @@
[route]
(money/wei->ether (reduce money/add (map calculate-gas-fee route))))
(defn- path-amount-in
[path]
(-> path :amount-in money/from-hex))
(defn- path-amount-out
[path]
(if (= (:bridge-name path) constants/bridge-name-hop)
(let [{:keys [token-fees bonder-fees amount-in]} path]
(-> amount-in
money/from-hex
(money/sub token-fees)
(money/add bonder-fees)))
(-> path :amount-out money/from-hex)))
(defn- convert-wei-to-eth
[amount native-token? token-decimals]
(money/with-precision
(if native-token?
(money/wei->ether amount)
(money/token->unit amount token-decimals))
constants/token-display-precision))
(defn network-amounts-by-chain
[{:keys [route token-decimals native-token? receiver?]}]
(reduce
(fn [acc path]
(let [amount-hex (if receiver? (:amount-out path) (:amount-in path))
amount-units (native-module/hex-to-number
(utils.hex/normalize-hex amount-hex))
amount (money/with-precision
(if native-token?
(money/wei->ether amount-units)
(money/token->unit amount-units
token-decimals))
6)
chain-id (if receiver? (get-in path [:to :chain-id]) (get-in path [:from :chain-id]))]
(update acc chain-id money/add amount)))
(let [amount (if receiver?
(path-amount-out path)
(path-amount-in path))
chain-id (if receiver?
(get-in path [:to :chain-id])
(get-in path [:from :chain-id]))]
(as-> amount $
(convert-wei-to-eth $ native-token? token-decimals)
(update acc chain-id money/add $))))
{}
route))
(defn path-estimated-received
"Calculates the (`bignumber`) estimated received token amount. For
bridge transactions, the amount is the difference between the
`amount-in` and the `token-fees`."
[path]
(if (-> path :bridge-name (= constants/bridge-name-hop))
(-> path
:amount-in
money/from-hex
(money/sub (:token-fees path)))
(-> path
:amount-out
money/from-hex)))
(defn estimated-received-by-chain
[route token-decimals native-token?]
(reduce
(fn [acc path]
(let [chain-id (get-in path [:to :chain-id])
estimated-received (-> path
path-estimated-received
(convert-wei-to-eth native-token? token-decimals))]
(update acc chain-id money/add estimated-received)))
{}
route))
@@ -79,9 +79,91 @@
:receiver? receiver?})
expected {1 (money/bignumber "2")
10 (money/bignumber "2")}]
(doseq [[chain-id exp-value] expected]
(is (money/equal-to (get result chain-id) exp-value)))))
(testing "Correctly calculates network (out) amounts for bridge transaction"
(let [route [{:bridge-name "Hop"
:amount-in "0xde0b6b3a7640000"
:bonder-fees (money/bignumber "200000000000000")
:token-fees (money/bignumber "230000000000000")
:to {:chain-id 1}}
{:bridge-name "Hop"
:bonder-fees (money/bignumber "300000000000000")
:token-fees (money/bignumber "410000000000000")
:amount-in "0xde0b6b3a7640000"
:to {:chain-id 10}}]
token-decimals 6
native-token? true
receiver? true
result (utils/network-amounts-by-chain {:route route
:token-decimals token-decimals
:native-token? native-token?
:receiver? receiver?})
expected {1 (money/bignumber "0.99997")
10 (money/bignumber "0.99989")}]
(doseq [[chain-id exp-value] expected]
(is (money/equal-to (get result chain-id) exp-value))))))
(deftest estimated-received-by-chain-test
(testing "Correctly calculates the bridge estimated received amount"
(let [chain-id 1
route [{:bridge-name "Hop"
:amount-in "0xde0b6b3a7640000"
:token-fees (money/bignumber "230000000000000")
:to {:chain-id 1}}]
token-decimals 18
native-token? true
result (utils/estimated-received-by-chain route token-decimals native-token?)
expected (money/bignumber "0.99977")]
(is (money/equal-to (get result chain-id) expected))))
(testing "Correctly calculates the estimated received amount with native token"
(let [chain-id 1
route [{:amount-out "0x1bc16d674ec80000"
:to {:chain-id chain-id}}]
token-decimals 18
native-token? true
result (utils/estimated-received-by-chain route token-decimals native-token?)
expected (money/bignumber "2")]
(is (money/equal-to (get result chain-id) expected))))
(testing "Correctly calculates the estimated received amount with non-native token"
(let [chain-id 10
route [{:amount-out "0x1bc16d674ec80000"
:to {:chain-id chain-id}}]
token-decimals 18
native-token? false
result (utils/estimated-received-by-chain route token-decimals native-token?)
expected (money/bignumber "2")]
(is (money/equal-to (get result chain-id) expected))))
(testing
"Correctly calculates the estimated received amount with multiple routes on different networks"
(let [route [{:amount-out "0x1bc16d674ec80000"
:to {:chain-id 1}}
{:amount-out "0xde0b6b3a7640000"
:to {:chain-id 10}}]
token-decimals 18
native-token? false
result (utils/estimated-received-by-chain route token-decimals native-token?)
expected {10 (money/bignumber "1")
1 (money/bignumber "2")}]
(doseq [[chain-id exp-value] expected]
(is (money/equal-to (get result chain-id) exp-value)))))
(testing "Correctly calculates the estimated received amount with multiple routes on the same network"
(let [chain-id 10
route [{:amount-out "0x1bc16d674ec80000"
:to {:chain-id chain-id}}
{:amount-out "0x1bc16d674ec80000"
:to {:chain-id chain-id}}]
token-decimals 18
native-token? false
result (utils/estimated-received-by-chain route token-decimals native-token?)
expected (money/bignumber "4")]
(is (money/equal-to (get result chain-id) expected)))))
(deftest network-values-for-ui-test
(testing "Sanitizes values correctly for display"
(let [amounts {1 (money/bignumber "0")
+145 -47
View File
@@ -27,12 +27,14 @@
:test-networks-enabled? test-networks-enabled?
:token-symbol (get-in data [:asset-to-pay :symbol])}))
network' (or network
(swap-utils/select-network asset-to-pay))]
(swap-utils/select-network asset-to-pay))
start-point (if open-new-screen? :action-menu :swap-button)]
{:db (-> db
(assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay)
(assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive)
(assoc-in [:wallet :ui :swap :network] network')
(assoc-in [:wallet :ui :swap :launch-screen] view-id))
(assoc-in [:wallet :ui :swap :launch-screen] view-id)
(assoc-in [:wallet :ui :swap :start-point] start-point))
:fx (if network'
[[:dispatch [:wallet/switch-current-viewing-account (:address account)]]
[:dispatch
@@ -40,6 +42,13 @@
[:open-modal :screen/wallet.setup-swap]
[:navigate-to-within-stack
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]])]
[:dispatch
[:centralized-metrics/track :metric/swap-start
{:network (:chain-id network)
:pay_token (:symbol asset-to-pay)
:receive_token (:symbol asset-to-receive)
:start_point start-point
:launch_screen view-id}]]
[:dispatch [:wallet.swap/set-default-slippage]]]
[[:dispatch
[:show-bottom-sheet
@@ -57,22 +66,36 @@
(rf/reg-event-fx :wallet.swap/select-asset-to-pay
(fn [{:keys [db]} [{:keys [token]}]]
{:db (update-in db
[:wallet :ui :swap]
#(-> %
(assoc :asset-to-pay token)
(dissoc :amount
:amount-hex
:last-request-uuid
:swap-proposal
:error-response
:loading-swap-proposal?
:approval-transaction-id
:approved-amount)))}))
(let [previous-token (get-in db [:wallet :ui :swap :asset-to-pay])
network (get-in db [:wallet :ui :swap :network])]
{:db (update-in db
[:wallet :ui :swap]
#(-> %
(assoc :asset-to-pay token)
(dissoc :amount
:amount-hex
:last-request-uuid
:swap-proposal
:error-response
:loading-swap-proposal?
:approval-transaction-id
:approved-amount)))
:fx [[:dispatch
[:centralized-metrics/track :metric/swap-asset-to-pay-changed
{:network (:chain-id network)
:previous_token (:symbol previous-token)
:new_token (:symbol token)}]]]})))
(rf/reg-event-fx :wallet.swap/select-asset-to-receive
(fn [{:keys [db]} [{:keys [token]}]]
{:db (assoc-in db [:wallet :ui :swap :asset-to-receive] token)}))
(let [previous-token (get-in db [:wallet :ui :swap :asset-to-receive])
network (get-in db [:wallet :ui :swap :network])]
{:db (assoc-in db [:wallet :ui :swap :asset-to-receive] token)
:fx [[:dispatch
[:centralized-metrics/track :metric/swap-asset-to-receive-changed
{:network (:chain-id network)
:previous_token (:symbol previous-token)
:new_token (:symbol token)}]]]})))
(rf/reg-event-fx :wallet.swap/set-default-slippage
(fn [{:keys [db]}]
@@ -132,9 +155,15 @@
:last-request-uuid request-uuid
:amount amount
:amount-hex amount-in-hex
:loading-swap-proposal? true)
:loading-swap-proposal? true
:initial-response? true)
clean-approval-transaction?
(dissoc :approval-transaction-id :approved-amount :swap-proposal)))
:fx [[:dispatch
[:centralized-metrics/track :metric/swap-proposal-start
{:network swap-chain-id
:pay_token pay-token-id
:receive_token receive-token-id}]]]
:json-rpc/call [{:method "wallet_getSuggestedRoutesAsync"
:params params
:on-error (fn [error]
@@ -148,6 +177,10 @@
(fn [{:keys [db]} [swap-proposal]]
(let [last-request-uuid (get-in db [:wallet :ui :swap :last-request-uuid])
amount-hex (get-in db [:wallet :ui :swap :amount-hex])
asset-to-pay (get-in db [:wallet :ui :swap :asset-to-pay])
asset-to-receive (get-in db [:wallet :ui :swap :asset-to-receive])
network (get-in db [:wallet :ui :swap :network])
initial-response? (get-in db [:wallet :ui :swap :initial-response?])
view-id (:view-id db)
request-uuid (:uuid swap-proposal)
best-routes (:best swap-proposal)
@@ -163,22 +196,45 @@
:swap-proposal (when-not (empty? best-routes)
(assoc (first best-routes) :uuid request-uuid))
:error-response error-response
:loading-swap-proposal? false)}
:loading-swap-proposal? false
:initial-response? false)}
(and initial-response? (seq best-routes))
(assoc :fx
[[:dispatch
[:centralized-metrics/track :metric/swap-proposal-received
{:network (:chain-id network)
:pay_token (:symbol asset-to-pay)
:receive_token (:symbol asset-to-receive)}]]])
(and initial-response? (empty? best-routes))
(assoc :fx
[[:dispatch
[:centralized-metrics/track :metric/swap-proposal-failed
{:error (:code error-response)}]]])
;; Router is unstable and it can return a swap proposal and after auto-refetching it can
;; return an error. Ideally this shouldn't happen, but adding this behavior so if the
;; user is in swap confirmation screen or in token approval confirmation screen, we
;; navigate back to setup swap screen so proper error is displayed.
(and (empty? best-routes) (= view-id :screen/wallet.swap-set-spending-cap))
(assoc :fx [[:dismiss-modal :screen/wallet.swap-set-spending-cap]])
(assoc :fx
[[:dispatch
[:centralized-metrics/track :metric/swap-proposal-failed
{:error (:code error-response)}]]
[:dismiss-modal :screen/wallet.swap-set-spending-cap]])
(and (empty? best-routes) (= view-id :screen/wallet.swap-confirmation))
(assoc :fx [[:navigate-back]]))))))
(assoc :fx
[[:dispatch
[:centralized-metrics/track :metric/swap-proposal-failed
{:error (:code error-response)}]]
[:navigate-back]]))))))
(rf/reg-event-fx :wallet/swap-proposal-error
(fn [{:keys [db]} [error-message]]
(fn [{:keys [db]} [error-response]]
{:db (-> db
(update-in [:wallet :ui :swap] dissoc :route :swap-proposal)
(assoc-in [:wallet :ui :swap :loading-swap-proposal?] false)
(assoc-in [:wallet :ui :swap :error-response] error-message))}))
(assoc-in [:wallet :ui :swap :error-response] error-response))
:fx [[:dispatch
[:centralized-metrics/track :metric/swap-proposal-failed {:error (:code error-response)}]]]}))
(rf/reg-event-fx :wallet/stop-get-swap-proposal
(fn []
@@ -279,16 +335,25 @@
(-> amount-out
(number/hex->whole receive-token-decimals)
(money/to-fixed receive-token-decimals)))]
(rf/dispatch [:centralized-metrics/track
(if approval-required?
:metric/swap-approval-execution-start
:metric/swap-transaction-execution-start)
(cond-> {:network swap-chain-id
:pay_token token-id-from}
(not approval-required?)
(assoc :receive_token token-id-to))])
(rf/dispatch [:wallet.swap/add-authorized-transaction
(cond-> {:transaction result
:approval-transaction?
approval-required?}
(not approval-required?)
(assoc :swap-data
{:pay-token-symbol token-id-from
:pay-amount amount
{:pay-token-symbol token-id-from
:pay-amount amount
:receive-token-symbol token-id-to
:receive-amount receive-amount}))])
:receive-amount receive-amount
:swap-chain-id swap-chain-id}))])
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:dismiss-modal
(if approval-required?
@@ -308,6 +373,15 @@
:receive-amount receive-amount})}]
500)))))
:on-error (fn [error]
(rf/dispatch [:centralized-metrics/track
(if approval-required?
:metric/swap-approval-execution-failed
:metric/swap-transaction-execution-failed)
(cond-> {:network swap-chain-id
:error error
:pay_token token-id-from}
(not approval-required?)
(assoc :receive_token token-id-to))])
(log/error "failed swap transaction"
{:event :wallet/swap-transaction
:error error
@@ -342,19 +416,26 @@
(rf/reg-event-fx :wallet.swap/approve-transaction-update
(fn [{:keys [db]} [{:keys [status]}]]
(let [{:keys [amount asset-to-pay swap-proposal]} (get-in db [:wallet :ui :swap])
provider-name (:bridge-name swap-proposal)
token-symbol (:symbol asset-to-pay)
current-viewing-account-address (get-in db
[:wallet :current-viewing-account-address])
account-name (get-in db
[:wallet :accounts
current-viewing-account-address :name])
transaction-confirmed-or-failed? (#{:confirmed :failed} status)
transaction-confirmed? (= status :confirmed)]
(let [{:keys [amount asset-to-pay swap-proposal
network]} (get-in db [:wallet :ui :swap])
provider-name (:bridge-name swap-proposal)
token-symbol (:symbol asset-to-pay)
swap-chain-id (:chain-id network)
current-viewing-account-address (get-in db
[:wallet :current-viewing-account-address])
account-name (get-in db
[:wallet :accounts
current-viewing-account-address :name])
transaction-confirmed-or-failed? (#{:confirmed :failed} status)
transaction-confirmed? (= status :confirmed)]
(when transaction-confirmed-or-failed?
(cond-> {:fx
[[:dispatch
[:centralized-metrics/track :metric/swap-approval-execution-finished
{:network swap-chain-id
:pay_token token-symbol
:succeeded transaction-confirmed?}]]
[:dispatch
[:toasts/upsert
{:id :approve-transaction-update
:type (if transaction-confirmed? :positive :negative)
@@ -377,16 +458,23 @@
(rf/reg-event-fx :wallet.swap/swap-transaction-update
(fn [{:keys [db]} [{:keys [tx-hash status]}]]
(let [{:keys [pay-amount pay-token-symbol
receive-amount receive-token-symbol]} (get-in db
[:wallet :transactions tx-hash
:swap-data])
transaction-confirmed-or-failed? (#{:confirmed :failed} status)
transaction-confirmed? (= status :confirmed)]
receive-amount receive-token-symbol
swap-chain-id]} (get-in db
[:wallet :transactions tx-hash
:swap-data])
transaction-confirmed-or-failed? (#{:confirmed :failed} status)
transaction-confirmed? (= status :confirmed)]
(when transaction-confirmed-or-failed?
{:db (-> db
(update-in [:wallet :swap-transaction-ids] disj tx-hash)
(update-in [:wallet :transactions] dissoc tx-hash))
:fx [[:dispatch
[:centralized-metrics/track :metric/swap-transaction-execution-finished
{:network swap-chain-id
:pay_token pay-token-symbol
:receive_token receive-token-symbol
:succeeded transaction-confirmed?}]]
[:dispatch
[:toasts/upsert
{:id :swap-transaction-update
:type (if transaction-confirmed? :positive :negative)
@@ -401,13 +489,13 @@
(rf/reg-event-fx :wallet.swap/flip-assets
(fn [{:keys [db]}]
(let [{:keys [asset-to-pay asset-to-receive
swap-proposal amount]} (get-in db [:wallet :ui :swap])
receive-token-decimals (:decimals asset-to-receive)
amount-out (when swap-proposal (:amount-out swap-proposal))
receive-amount (when amount-out
(-> amount-out
(number/hex->whole receive-token-decimals)
(money/to-fixed receive-token-decimals)))]
swap-proposal amount network]} (get-in db [:wallet :ui :swap])
receive-token-decimals (:decimals asset-to-receive)
amount-out (when swap-proposal (:amount-out swap-proposal))
receive-amount (when amount-out
(-> amount-out
(number/hex->whole receive-token-decimals)
(money/to-fixed receive-token-decimals)))]
{:db (update-in db
[:wallet :ui :swap]
#(-> %
@@ -420,7 +508,17 @@
:loading-swap-proposal?
:last-request-uuid
:approved-amount
:approval-transaction-id)))})))
:approval-transaction-id)))
:fx [[:dispatch
[:centralized-metrics/track :metric/swap-asset-to-pay-changed
{:network (:chain-id network)
:previous_token (:symbol asset-to-pay)
:new_token (:symbol asset-to-receive)}]]
[:dispatch
[:centralized-metrics/track :metric/swap-asset-to-receive-changed
{:network (:chain-id network)
:previous_token (:symbol asset-to-receive)
:new_token (:symbol asset-to-pay)}]]]})))
(rf/reg-event-fx :wallet/end-swap-flow
(fn [{:keys [db]}]
@@ -40,6 +40,7 @@
(let [[search-text set-search-text] (rn/use-state "")
on-change-text #(set-search-text %)
on-close (fn []
(rf/dispatch [:centralized-metrics/track :metric/swap-closed])
(rf/dispatch [:wallet/clean-swap])
(rf/dispatch [:navigate-back]))]
[rn/safe-area-view {:style style/container}

Some files were not shown because too many files have changed in this diff Show More