From 68069e0137d72d0d62eb3a9cc58f22803714d4d8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 26 Jun 2023 09:22:21 +0800 Subject: [PATCH 1/8] Updated on 2026-08-14 --- plugins/configuration/detekt.yml | 836 ------------------ .../configurations/DetektConfigurations.kt | 2 +- tangem-android-tools | 1 + 3 files changed, 2 insertions(+), 837 deletions(-) delete mode 100644 plugins/configuration/detekt.yml create mode 160000 tangem-android-tools diff --git a/plugins/configuration/detekt.yml b/plugins/configuration/detekt.yml deleted file mode 100644 index 51dbfc0927..0000000000 --- a/plugins/configuration/detekt.yml +++ /dev/null @@ -1,836 +0,0 @@ -build: - maxIssues: 0 - -config: - validation: true - warningsAsErrors: false - -processors: - active: true - -console-reports: - active: true - exclude: - - 'ProjectStatisticsReport' - - 'ComplexityReport' - - 'NotificationReport' - - 'FindingsReport' - - 'FileBasedFindingsReport' -# - 'LiteFindingsReport' - -output-reports: - active: true - exclude: - - 'HtmlOutputReport' - # - 'TxtOutputReport' - - 'XmlOutputReport' - - 'SarifOutputReport' - - 'MdOutputReport' - -comments: - active: false - AbsentOrWrongFileLicense: - active: false - licenseTemplateFile: 'license.template' - licenseTemplateIsRegex: false - CommentOverPrivateFunction: - active: false - CommentOverPrivateProperty: - active: false - DeprecatedBlockTag: - active: false - EndOfSentenceFormat: - active: false - endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' - KDocReferencesNonPublicProperty: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - OutdatedDocumentation: - active: false - matchTypeParameters: true - matchDeclarationsOrder: true - allowParamOnConstructorProperties: false - UndocumentedPublicClass: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - searchInNestedClass: true - searchInInnerClass: true - searchInInnerObject: true - searchInInnerInterface: true - UndocumentedPublicFunction: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - UndocumentedPublicProperty: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - -complexity: - active: true - CyclomaticComplexMethod: - active: true - ComplexCondition: - active: true - threshold: 4 - ComplexInterface: - active: false - threshold: 10 - includeStaticDeclarations: false - includePrivateDeclarations: false - LabeledExpression: - active: false - ignoredLabels: [ ] - LargeClass: - active: true - threshold: 300 - LongMethod: - active: true - threshold: 70 - LongParameterList: - active: true - functionThreshold: 6 - constructorThreshold: 7 - ignoreDefaultParameters: true - ignoreDataClasses: true - ignoreAnnotated: [ 'Provides' ] - MethodOverloading: - active: true - threshold: 6 - NamedArguments: - active: true - threshold: 3 - ignoreArgumentsMatchingNames: false - NestedBlockDepth: - active: true - threshold: 5 - NestedScopeFunctions: - active: false - threshold: 1 - functions: - - 'kotlin.apply' - - 'kotlin.run' - - 'kotlin.with' - - 'kotlin.let' - - 'kotlin.also' - ReplaceSafeCallChainWithRun: - active: true - StringLiteralDuplication: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - threshold: 3 - ignoreAnnotation: true - excludeStringsWithLessThan5Characters: true - ignoreStringsRegex: '$^' - TooManyFunctions: - active: true - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - thresholdInFiles: 20 - thresholdInClasses: 20 - thresholdInInterfaces: 20 - thresholdInObjects: 20 - thresholdInEnums: 20 - ignoreDeprecated: false - ignorePrivate: true - ignoreOverridden: false - -coroutines: - active: true - GlobalCoroutineUsage: - active: true - InjectDispatcher: - active: false #TODO - dispatcherNames: - - 'IO' - - 'Default' - - 'Unconfined' - RedundantSuspendModifier: - active: true - SleepInsteadOfDelay: - active: true - SuspendFunWithCoroutineScopeReceiver: - active: false - SuspendFunWithFlowReturnType: - active: true - -empty-blocks: - active: true - EmptyCatchBlock: - active: true - allowedExceptionNameRegex: '_|(ignore|expected).*' - EmptyClassBlock: - active: true - EmptyDefaultConstructor: - active: true - EmptyDoWhileBlock: - active: true - EmptyElseBlock: - active: true - EmptyFinallyBlock: - active: true - EmptyForBlock: - active: true - EmptyFunctionBlock: - active: true - ignoreOverridden: true - EmptyIfBlock: - active: true - EmptyInitBlock: - active: true - EmptyKtFile: - active: true - EmptySecondaryConstructor: - active: true - EmptyTryBlock: - active: true - EmptyWhenBlock: - active: true - EmptyWhileBlock: - active: true - -exceptions: - active: true - ExceptionRaisedInUnexpectedLocation: - active: true - methodNames: - - 'equals' - - 'finalize' - - 'hashCode' - - 'toString' - InstanceOfCheckForException: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - NotImplementedDeclaration: - active: false - ObjectExtendsThrowable: - active: true - PrintStackTrace: - active: true - RethrowCaughtException: - active: true - ReturnFromFinally: - active: true - ignoreLabeled: false - SwallowedException: - active: false - ignoredExceptionTypes: - - 'InterruptedException' - - 'MalformedURLException' - - 'NumberFormatException' - - 'ParseException' - allowedExceptionNameRegex: '_|(ignore|expected).*' - ThrowingExceptionFromFinally: - active: true - ThrowingExceptionInMain: - active: false - ThrowingExceptionsWithoutMessageOrCause: - active: true - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - exceptions: - - 'ArrayIndexOutOfBoundsException' - - 'Exception' - - 'IllegalArgumentException' - - 'IllegalMonitorStateException' - - 'IllegalStateException' - - 'IndexOutOfBoundsException' - - 'NullPointerException' - - 'RuntimeException' - - 'Throwable' - ThrowingNewInstanceOfSameException: - active: true - TooGenericExceptionCaught: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - exceptionNames: - - 'ArrayIndexOutOfBoundsException' - - 'Error' - - 'Exception' - - 'IllegalMonitorStateException' - - 'IndexOutOfBoundsException' - - 'NullPointerException' - - 'RuntimeException' - - 'Throwable' - allowedExceptionNameRegex: '_|(ignore|expected).*' - TooGenericExceptionThrown: - active: true - exceptionNames: - - 'Error' - - 'Exception' - - 'RuntimeException' - - 'Throwable' - -naming: - active: true - BooleanPropertyNaming: - active: true - allowedPattern: '^(is|has|are)' - ignoreOverridden: true - ClassNaming: - active: true - classPattern: '[A-Z][a-zA-Z0-9]*' - ConstructorParameterNaming: - active: true - parameterPattern: '[a-z][A-Za-z0-9]*' - privateParameterPattern: '[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true - EnumNaming: - active: true - enumEntryPattern: '[A-Z][_a-zA-Z0-9]*' - ForbiddenClassName: - active: false - forbiddenName: [ ] - FunctionMaxLength: - active: false - maximumFunctionNameLength: 30 - FunctionMinLength: - active: false - minimumFunctionNameLength: 3 - FunctionNaming: - active: true - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - functionPattern: '[a-z][a-zA-Z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true - ignoreAnnotated: [ 'Composable' ] - FunctionParameterNaming: - active: true - parameterPattern: '[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true - InvalidPackageDeclaration: - active: true - rootPackage: '' - requireRootInDeclaration: false - LambdaParameterNaming: - active: false - parameterPattern: '[a-z][A-Za-z0-9]*|_' - MatchingDeclarationName: # Same as FileName - active: false - mustBeFirst: true - MemberNameEqualsClassName: - active: false - ignoreOverridden: true - NoNameShadowing: - active: true - NonBooleanPropertyPrefixedWithIs: - active: true - ObjectPropertyNaming: - active: true - constantPattern: '[A-Za-z][_A-Za-z0-9]*' - propertyPattern: '[A-Za-z][_A-Za-z0-9]*' - privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' - PackageNaming: - active: true - packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*' - TopLevelPropertyNaming: - active: true - constantPattern: '[A-Z][_A-Z0-9]*' - propertyPattern: '[A-Za-z][_A-Za-z0-9]*' - privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*' - VariableMaxLength: - active: false - maximumVariableNameLength: 50 - VariableMinLength: - active: false - minimumVariableNameLength: 3 - VariableNaming: - active: true - variablePattern: '[a-z][A-Za-z0-9]*' - privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true - -performance: - active: true - ArrayPrimitive: - active: true - CouldBeSequence: - active: false - threshold: 3 - ForEachOnRange: - active: true - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - SpreadOperator: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - UnnecessaryTemporaryInstantiation: - active: true - -potential-bugs: - active: true - AvoidReferentialEquality: - active: true - forbiddenTypePatterns: - - 'kotlin.String' - CastToNullableType: - active: true - Deprecation: - active: false - DontDowncastCollectionTypes: - active: true - DoubleMutabilityForCollection: - active: true - mutableTypes: - - 'kotlin.collections.MutableList' - - 'kotlin.collections.MutableMap' - - 'kotlin.collections.MutableSet' - - 'java.util.ArrayList' - - 'java.util.LinkedHashSet' - - 'java.util.HashSet' - - 'java.util.LinkedHashMap' - - 'java.util.HashMap' - ElseCaseInsteadOfExhaustiveWhen: - active: false - EqualsAlwaysReturnsTrueOrFalse: - active: true - EqualsWithHashCodeExist: - active: true - ExitOutsideMain: - active: false - ExplicitGarbageCollectionCall: - active: true - HasPlatformType: - active: true - IgnoredReturnValue: - active: true - returnValueAnnotations: - - '*.CheckResult' - - '*.CheckReturnValue' - ignoreReturnValueAnnotations: - - '*.CanIgnoreReturnValue' - ignoreFunctionCall: [ ] - ImplicitDefaultLocale: - active: true - ImplicitUnitReturnType: - active: false - allowExplicitReturnType: true - InvalidRange: - active: true - IteratorHasNextCallsNextMethod: - active: true - IteratorNotThrowingNoSuchElementException: - active: true - LateinitUsage: - active: false - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - ignoreAnnotated: [ 'Inject' ] - ignoreOnClassesPattern: '' - MapGetWithNotNullAssertionOperator: - active: true - MissingPackageDeclaration: - active: true - excludes: [ '**/*.kts' ] - NullCheckOnMutableProperty: - active: true - NullableToStringCall: - active: true - UnconditionalJumpStatementInLoop: - active: true - UnnecessaryNotNullOperator: - active: true - UnnecessarySafeCall: - active: true - UnreachableCatchBlock: - active: true - UnreachableCode: - active: true - UnsafeCallOnNullableType: - active: true - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**' ] - UnsafeCast: - active: true - UnusedUnaryOperator: - active: true - UselessPostfixExpression: - active: true - WrongEqualsTypeParameter: - active: true - -style: - active: true - CanBeNonNullable: - active: false - CascadingCallWrapping: - active: false - includeElvis: true - ClassOrdering: - active: true - CollapsibleIfStatements: - active: true - DataClassContainsFunctions: - active: false - conversionFunctionPrefix: - - 'to' - DataClassShouldBeImmutable: - active: false - DestructuringDeclarationWithTooManyEntries: - active: true - maxDestructuringEntries: 3 - EqualsNullCall: - active: false - EqualsOnSignatureLine: - active: true - ExplicitCollectionElementAccessMethod: - active: true - ExplicitItLambdaParameter: - active: true - ExpressionBodySyntax: - active: false - includeLineWrapping: true - ForbiddenComment: - active: false - values: - - 'FIXME:' - - 'STOPSHIP:' - - 'TODO:' - allowedPatterns: '' - customMessage: '' - ForbiddenImport: - active: false - imports: [ ] - forbiddenPatterns: '' - ForbiddenMethodCall: - active: false - methods: - - reason: 'print does not allow you to configure the output stream. Use a logger instead.' - value: 'kotlin.io.print' - - reason: 'println does not allow you to configure the output stream. Use a logger instead.' - value: 'kotlin.io.println' - ForbiddenSuppress: - active: false - rules: [ ] - ForbiddenVoid: - active: false - ignoreOverridden: false - ignoreUsageInGenerics: false - FunctionOnlyReturningConstant: - active: true - ignoreOverridableFunction: true - ignoreActualFunction: true - LoopWithTooManyJumpStatements: - active: true - maxJumpCount: 2 - MagicNumber: - active: true - excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/*.kts' ] - ignoreNumbers: - - '-1' - - '0' - - '1' - - '2' - ignoreHashCodeFunction: true - ignorePropertyDeclaration: true - ignoreLocalVariableDeclaration: false - ignoreConstantDeclaration: true - ignoreCompanionObjectPropertyDeclaration: true - ignoreAnnotation: false - ignoreNamedArgument: true - ignoreEnums: false - ignoreRanges: false - ignoreExtensionFunctions: true - ignoreAnnotated: [ 'Preview' ] - MandatoryBracesIfStatements: - active: true - MandatoryBracesLoops: - active: true - MaxChainedCallsOnSameLine: - active: true - maxChainedCalls: 5 - MaxLineLength: - active: false # Same as MaximumLineLength - maxLineLength: 120 - excludePackageStatements: true - excludeImportStatements: true - excludeCommentStatements: false - MayBeConst: - active: true - ModifierOrder: - active: false # Same as ModifierOrdering - MultilineLambdaItParameter: - active: true - NestedClassesVisibility: - active: true - NewLineAtEndOfFile: - active: false # Same as FinalNewline - NoTabs: - active: true - NullableBooleanCheck: - active: true - ObjectLiteralToLambda: - active: true - OptionalAbstractKeyword: - active: true - OptionalUnit: - active: true - OptionalWhenBraces: - active: false - PreferToOverPairSyntax: - active: false - ProtectedMemberInFinalClass: - active: true - RedundantExplicitType: - active: false - RedundantHigherOrderMapUsage: - active: true - RedundantVisibilityModifierRule: - active: true - ReturnCount: - active: false - max: 2 - excludedFunctions: - - 'equals' - excludeLabeled: false - excludeReturnFromLambda: true - excludeGuardClauses: false - SafeCast: - active: true - SerialVersionUIDInSerializableClass: - active: true - SpacingBetweenPackageAndImports: - active: true - ThrowsCount: - active: false - max: 2 - excludeGuardClauses: false - TrailingWhitespace: - active: false - UnderscoresInNumericLiterals: - active: false - acceptableLength: 4 - allowNonStandardGrouping: false - UnnecessaryAbstractClass: - active: true - UnnecessaryAnnotationUseSiteTarget: - active: false - UnnecessaryApply: - active: true - UnnecessaryBackticks: - active: true - UnnecessaryFilter: - active: true - UnnecessaryInheritance: - active: true - UnnecessaryInnerClass: - active: false - UnnecessaryLet: - active: true - UnnecessaryParentheses: - active: true - UntilInsteadOfRangeTo: - active: true - UnusedImports: - active: true - UnusedPrivateClass: - active: true - ignoreAnnotated: [ 'UnusedRequiredComponent' ] - UnusedPrivateMember: - active: true - allowedNames: '(_|ignored|expected|serialVersionUID)' - ignoreAnnotated: [ 'Preview', 'UnusedRequiredComponent' ] - UseAnyOrNoneInsteadOfFind: - active: true - UseArrayLiteralsInAnnotations: - active: true - UseCheckNotNull: - active: true - UseCheckOrError: - active: true - UseDataClass: - active: false - allowVars: false - UseEmptyCounterpart: - active: true - UseIfEmptyOrIfBlank: - active: true - UseIfInsteadOfWhen: - active: false - UseIsNullOrEmpty: - active: true - UseOrEmpty: - active: true - UseRequire: - active: true - UseRequireNotNull: - active: true - UselessCallOnNotNull: - active: true - UtilityClassWithPublicConstructor: - active: true - VarCouldBeVal: - active: true - ignoreLateinitVar: false - WildcardImport: - active: false - excludeImports: - - 'java.util.*' - -formatting: - active: true - android: true - AnnotationOnSeparateLine: - active: false - AnnotationSpacing: - active: true - ArgumentListWrapping: - active: true - indentSize: 4 - maxLineLength: 120 - BlockCommentInitialStarAlignment: - active: true - ChainWrapping: - active: true - CommentSpacing: - active: true - CommentWrapping: - active: false - indentSize: 4 - DiscouragedCommentLocation: - active: true - EnumEntryNameCase: - active: true - Filename: - active: true # This rules overlaps with naming>MatchingDeclarationName from the standard rules - mustBeFirst: true - FinalNewline: # This rules overlaps with style>NewLineAtEndOfFile from the standard rules - active: true - insertFinalNewLine: true - FunKeywordSpacing: - active: true - FunctionReturnTypeSpacing: - active: true - FunctionSignature: - active: true - forceMultilineWhenParameterCountGreaterOrEqualThan: 2147483647 - functionBodyExpressionWrapping: 'default' - maxLineLength: 120 - indentSize: 4 - FunctionStartOfBodySpacing: - active: true - FunctionTypeReferenceSpacing: - active: true - ImportOrdering: - active: false - layout: 'java.**,javax.**,kotlin.**,kotlinx.**,android.**,androidx.**,*,^' - Indentation: - active: true - indentSize: 4 - KdocWrapping: - active: true - indentSize: 4 - MaximumLineLength: - excludes: [ "**/assets/**" ] - active: true # This rules overlaps with style>MaxLineLength from the standard rules - maxLineLength: 120 - excludePackageStatements: true - excludeImportStatements: true - excludeCommentStatements: false - ModifierListSpacing: - active: true - ModifierOrdering: - active: true # This rules overlaps with style>ModifierOrder from the standard rules - MultiLineIfElse: - active: true - NoBlankLineBeforeRbrace: - active: true - NoBlankLinesInChainedMethodCalls: - active: true - NoConsecutiveBlankLines: - active: true - NoEmptyClassBody: - active: true - NoEmptyFirstLineInMethodBlock: - active: true - NoLineBreakAfterElse: - active: true - NoLineBreakBeforeAssignment: - active: true - NoMultipleSpaces: - active: true - NoSemicolons: - active: true - NoTrailingSpaces: - active: true - NoUnitReturn: - active: true - NoUnusedImports: - active: true - NoWildcardImports: - active: false - packagesToUseImportOnDemandProperty: 'java.util.*,kotlinx.android.synthetic.**' - NullableTypeSpacing: - active: true - PackageName: - active: true - ParameterListSpacing: - active: true - ParameterListWrapping: - active: true - maxLineLength: 120 - SpacingAroundAngleBrackets: - active: true - SpacingAroundColon: - active: true - SpacingAroundComma: - active: true - SpacingAroundCurly: - active: true - SpacingAroundDot: - active: true - SpacingAroundDoubleColon: - active: true - SpacingAroundKeyword: - active: true - SpacingAroundOperators: - active: true - SpacingAroundParens: - active: true - SpacingAroundRangeOperator: - active: true - SpacingAroundUnaryOperator: - active: true - SpacingBetweenDeclarationsWithAnnotations: - active: true - SpacingBetweenDeclarationsWithComments: - active: false - SpacingBetweenFunctionNameAndOpeningParenthesis: - active: true - StringTemplate: - active: true - TrailingCommaOnCallSite: - active: true - useTrailingCommaOnCallSite: true - TrailingCommaOnDeclarationSite: - active: true - useTrailingCommaOnDeclarationSite: true - TypeArgumentListSpacing: - active: true - TypeParameterListSpacing: - active: true - UnnecessaryParenthesesBeforeTrailingLambda: - active: true - Wrapping: - active: true - indentSize: 4 - -compose: - ReusedModifierInstance: - active: true - UnnecessaryEventHandlerParameter: - active: true - ComposableEventParameterNaming: - active: true - ComposableParametersOrdering: - active: true - ModifierDefaultValue: - active: true - MissingModifierDefaultValue: - active: true - ModifierHeightWithText: - active: true - ModifierParameterPosition: - active: true - PublicComposablePreview: - active: true - TopLevelComposableFunctions: - active: true - ComposeFunctionName: - active: true diff --git a/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/DetektConfigurations.kt b/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/DetektConfigurations.kt index 1bcf190ab5..7f3919e6d8 100644 --- a/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/DetektConfigurations.kt +++ b/plugins/configuration/src/main/kotlin/com/tangem/plugin/configuration/configurations/DetektConfigurations.kt @@ -22,7 +22,7 @@ private fun DetektExtension.configure(project: Project) { ignoreFailures = false autoCorrect = true buildUponDefaultConfig = true - config.setFrom(project.rootProject.files("plugins/configuration/detekt.yml")) + config.setFrom(project.rootProject.files("tangem-android-tools/detekt-config.yml")) } private fun Project.configureDetektPlugins() { diff --git a/tangem-android-tools b/tangem-android-tools new file mode 160000 index 0000000000..03186c35c1 --- /dev/null +++ b/tangem-android-tools @@ -0,0 +1 @@ +Subproject commit 03186c35c13d8693d9a4c7dcb6e760fa58984e67 From aff54c3547fb5278330a47d4a5640402a8d0be34 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 25 Jun 2023 00:06:37 +0800 Subject: [PATCH 2/8] Updated on 2026-08-14 --- .../java/com/tangem/tap/common/extensions/Blockchain.kt | 1 - app/src/main/java/com/tangem/tap/domain/PayIdManager.kt | 1 - .../com/tangem/domain/common/extensions/Blockchain.kt | 8 +------- gradle/dependencies.toml | 2 +- 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt b/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt index 5b0135f4a7..7ca3e575d4 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt @@ -10,7 +10,6 @@ import com.tangem.wallet.R fun Blockchain.getGreyedOutIconRes(): Int { return when (this) { Blockchain.Arbitrum, Blockchain.ArbitrumTestnet -> R.drawable.ic_arbitrum_no_color -// Blockchain.Ducatus -> R.drawable.ic_ducatus Blockchain.Bitcoin, Blockchain.BitcoinTestnet -> R.drawable.ic_bitcoin_no_color Blockchain.BitcoinCash -> R.drawable.ic_bitcoin_cash_no_color Blockchain.Litecoin -> R.drawable.ic_litecoin_no_color diff --git a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt b/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt index 16565ff5a6..11d5300454 100644 --- a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt @@ -41,7 +41,6 @@ class PayIdManager { Blockchain.Stellar, Blockchain.Cardano, Blockchain.CardanoShelley, - Blockchain.Ducatus, Blockchain.BitcoinCash, Blockchain.Binance, Blockchain.RSK, diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt index c891e19e44..de6329b343 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt @@ -29,7 +29,6 @@ fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? { "bitcoin-cash/test" -> Blockchain.BitcoinCashTestnet "cardano" -> Blockchain.CardanoShelley "dogecoin" -> Blockchain.Dogecoin - "ducatus" -> Blockchain.Ducatus "litecoin" -> Blockchain.Litecoin "rootstock" -> Blockchain.RSK "stellar" -> Blockchain.Stellar @@ -83,7 +82,6 @@ fun Blockchain.toNetworkId(): String { Blockchain.Cardano -> "cardano" Blockchain.CardanoShelley -> "cardano" Blockchain.Dogecoin -> "dogecoin" - Blockchain.Ducatus -> "ducatus" Blockchain.Ethereum -> "ethereum" Blockchain.EthereumTestnet -> "ethereum/test" Blockchain.EthereumClassic -> "ethereum-classic" @@ -144,7 +142,6 @@ fun Blockchain.toCoinId(): String { Blockchain.Fantom, Blockchain.FantomTestnet -> "fantom" Blockchain.Tron, Blockchain.TronTestnet -> "tron" Blockchain.Polkadot, Blockchain.PolkadotTestnet -> "polkadot" - Blockchain.Ducatus -> "ducatus" Blockchain.Litecoin -> "litecoin" Blockchain.RSK -> "rootstock" Blockchain.Tezos -> "tezos" @@ -172,7 +169,4 @@ fun Blockchain.isSupportedInApp(): Boolean { return !excludedBlockchains.contains(this) } -private val excludedBlockchains = listOf( - Blockchain.Ducatus, - Blockchain.Unknown, -) \ No newline at end of file +private val excludedBlockchains = listOf(Blockchain.Unknown) \ No newline at end of file diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 269eb8f262..177713a612 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -77,7 +77,7 @@ walletConnectWeb3 = "1.8.0" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "develop-247" +tangemBlockchainSdk = "develop-250" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-266" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds From bced8fd66cea367df168feefd56190bed33dafd5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 25 Jun 2023 11:32:34 +0800 Subject: [PATCH 3/8] Updated on 2026-08-14 --- app/src/main/assets/features_dev.json | 2 - app/src/main/assets/features_prod.json | 2 - .../tap/common/redux/global/GlobalState.kt | 2 - .../com/tangem/tap/domain/PayIdManager.kt | 56 --- .../com/tangem/tap/domain/TapWalletManager.kt | 18 +- .../features/send/redux/SendScreenAction.kt | 38 +- ...ayIdMiddleware.kt => AddressMiddleware.kt} | 141 ++----- .../redux/middlewares/RequestFeeMiddleware.kt | 2 +- .../send/redux/middlewares/SendMiddleware.kt | 13 +- .../redux/reducers/AddressPayIdReducer.kt | 72 ---- .../send/redux/reducers/AddressReducer.kt | 52 +++ .../send/redux/reducers/SendScreenReducer.kt | 4 +- .../{AddressPayIdState.kt => AddressState.kt} | 15 +- .../features/send/redux/states/SendState.kt | 16 +- .../tap/features/send/ui/SendFragment.kt | 28 +- .../stateSubscribers/SendStateSubscriber.kt | 46 +-- .../tap/network/payid/PayIdVerifyApi.kt | 40 -- .../tap/network/payid/PayIdVerifyService.kt | 24 -- app/src/main/res/layout/fragment_send.xml | 4 +- app/src/main/res/layout/layout_address.xml | 57 --- ...ress_payid.xml => layout_send_address.xml} | 42 +-- .../main/res/layout/layout_send_amount.xml | 2 +- .../tangemAccess/java/com/tangem/Test2.java | 4 - .../tangem/ui/ConfirmTransactionFragment.kt | 305 ---------------- .../tangem/ui/PrepareTransactionFragment.kt | 182 ---------- .../com/tangem/ui/SignTransactionFragment.kt | 312 ---------------- .../layout/fragment_confirm_transaction.xml | 343 ------------------ .../layout/fragment_prepare_transaction.xml | 266 -------------- .../res/layout/fragment_sign_transaction.xml | 61 ---- app/src/tangemAccess/res/values/strings.xml | 6 - .../tangem/datasource/config/ConfigManager.kt | 1 - .../datasource/config/ConfigManagerImpl.kt | 26 +- .../tangem/datasource/config/models/Config.kt | 1 - .../datasource/config/models/JsonModels.kt | 1 - core/res/src/main/res/values-de/strings.xml | 5 - core/res/src/main/res/values-fr/strings.xml | 5 - core/res/src/main/res/values-it/strings.xml | 5 - core/res/src/main/res/values-ru/strings.xml | 5 - .../src/main/res/values-zh-rTW/strings.xml | 5 - core/res/src/main/res/values/strings.xml | 5 - 40 files changed, 166 insertions(+), 2048 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/domain/PayIdManager.kt rename app/src/main/java/com/tangem/tap/features/send/redux/middlewares/{AddressPayIdMiddleware.kt => AddressMiddleware.kt} (50%) delete mode 100644 app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressPayIdReducer.kt create mode 100644 app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressReducer.kt rename app/src/main/java/com/tangem/tap/features/send/redux/states/{AddressPayIdState.kt => AddressState.kt} (90%) delete mode 100644 app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyApi.kt delete mode 100644 app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyService.kt rename app/src/main/res/layout/{layout_send_address_payid.xml => layout_send_address.xml} (84%) delete mode 100644 app/src/tangemAccess/java/com/tangem/Test2.java delete mode 100644 app/src/tangemAccess/java/com/tangem/ui/ConfirmTransactionFragment.kt delete mode 100644 app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt delete mode 100644 app/src/tangemAccess/java/com/tangem/ui/SignTransactionFragment.kt delete mode 100644 app/src/tangemAccess/res/layout/fragment_confirm_transaction.xml delete mode 100644 app/src/tangemAccess/res/layout/fragment_prepare_transaction.xml delete mode 100644 app/src/tangemAccess/res/layout/fragment_sign_transaction.xml delete mode 100644 app/src/tangemAccess/res/values/strings.xml diff --git a/app/src/main/assets/features_dev.json b/app/src/main/assets/features_dev.json index 82e46b21bf..b24d083053 100644 --- a/app/src/main/assets/features_dev.json +++ b/app/src/main/assets/features_dev.json @@ -1,6 +1,4 @@ { - "isWalletPayIdEnabled": true, - "isSendingToPayIdEnabled": true, "isTopUpEnabled": true, "isCreatingTwinCardsAllowed": true } \ No newline at end of file diff --git a/app/src/main/assets/features_prod.json b/app/src/main/assets/features_prod.json index d3b1375fae..b24d083053 100644 --- a/app/src/main/assets/features_prod.json +++ b/app/src/main/assets/features_prod.json @@ -1,6 +1,4 @@ { - "isWalletPayIdEnabled": false, - "isSendingToPayIdEnabled": true, "isTopUpEnabled": true, "isCreatingTwinCardsAllowed": true } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt index c4becfb45b..91c1ae14b7 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt @@ -6,7 +6,6 @@ import com.tangem.tap.common.analytics.topup.TopUpController import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.feedback.FeedbackManager import com.tangem.tap.common.redux.StateDialog -import com.tangem.tap.domain.PayIdManager import com.tangem.tap.domain.TapWalletManager import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager import com.tangem.tap.domain.userWalletList.UserWalletsListManager @@ -20,7 +19,6 @@ data class GlobalState( val onboardingState: OnboardingState = OnboardingState(), val cardVerifiedOnline: Boolean = false, val tapWalletManager: TapWalletManager = TapWalletManager(), - val payIdManager: PayIdManager = PayIdManager(), val configManager: ConfigManager? = null, val warningManager: WarningMessagesManager? = null, val feedbackManager: FeedbackManager? = null, diff --git a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt b/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt deleted file mode 100644 index 11d5300454..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.tangem.tap.domain - -import com.tangem.blockchain.common.Blockchain -import com.tangem.common.services.Result -import com.tangem.tap.network.payid.PayIdVerifyService -import com.tangem.tap.network.payid.VerifyPayIdResponse -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.util.* - -class PayIdManager { - - @Suppress("MagicNumber") - suspend fun verifyPayId(payId: String, blockchain: Blockchain): Result = - withContext(Dispatchers.IO) { - val splitPayId = payId.split("\$") - val user = splitPayId[0] - val baseUrl = "https://${splitPayId[1]}/" - return@withContext PayIdVerifyService(baseUrl).verifyAddress(user, blockchain.getPayIdNetwork()) - } - - private fun Blockchain.getPayIdNetwork(): String { - return when (this) { - Blockchain.XRP -> "XRPL" - Blockchain.RSK -> "RSK" - else -> this.currency - }.lowercase(Locale.getDefault()) - } - - companion object { - private val payIdRegExp = ( - "^[a-z0-9!#@%&*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#@%&*+/=?^_`{|}~-]+)*\\\$(?:(?:[a-z0-9]" + - "(?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z-]*[a-z0-9])?|(?:[0-9]{1,3}\\.){3}[0-9]{1,3})\$" - ).toRegex() - - val payIdSupported: EnumSet = EnumSet.of( - Blockchain.XRP, - Blockchain.Ethereum, - Blockchain.Bitcoin, - Blockchain.Litecoin, - Blockchain.Stellar, - Blockchain.Cardano, - Blockchain.CardanoShelley, - Blockchain.BitcoinCash, - Blockchain.Binance, - Blockchain.RSK, - Blockchain.Tezos, - ) - - fun isPayId(value: String?): Boolean = value?.contains(payIdRegExp) ?: false - } -} - -fun Blockchain.isPayIdSupported(): Boolean { - return PayIdManager.payIdSupported.contains(this) -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index f9be91dcce..4e39b73bbe 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -1,6 +1,9 @@ package com.tangem.tap.domain -import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.BlockchainSdkConfig +import com.tangem.blockchain.common.Token +import com.tangem.blockchain.common.Wallet +import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess import com.tangem.core.analytics.Analytics @@ -134,22 +137,13 @@ class TapWalletManager( fun updateConfigManager(data: ScanResponse) { val configManager = store.state.globalState.configManager - val blockchain = data.cardTypesResolver.getBlockchain() + if (data.cardTypesResolver.isStart2Coin()) { - configManager?.turnOff(ConfigManager.IS_SENDING_TO_PAY_ID_ENABLED) configManager?.turnOff(ConfigManager.IS_TOP_UP_ENABLED) - } else if (blockchain == Blockchain.Bitcoin || - data.walletData?.blockchain == Blockchain.Bitcoin.id - ) { - configManager?.resetToDefault(ConfigManager.IS_SENDING_TO_PAY_ID_ENABLED) - configManager?.resetToDefault(ConfigManager.IS_TOP_UP_ENABLED) } else { - configManager?.resetToDefault(ConfigManager.IS_SENDING_TO_PAY_ID_ENABLED) configManager?.resetToDefault(ConfigManager.IS_TOP_UP_ENABLED) } } } -fun Wallet.getFirstToken(): Token? { - return getTokens().toList().getOrNull(0) -} \ No newline at end of file +fun Wallet.getFirstToken(): Token? = getTokens().toList().getOrNull(index = 0) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt index 20c206b37d..5f92c3c10b 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt @@ -6,7 +6,6 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.WalletManager import com.tangem.common.core.TangemSdkError import com.tangem.tap.common.analytics.events.Token.Send.AddressEntered -import com.tangem.tap.common.redux.ErrorAction import com.tangem.tap.common.redux.StateDialog import com.tangem.tap.common.redux.ToastNotificationAction import com.tangem.tap.domain.TapError @@ -34,15 +33,14 @@ data class PrepareSendScreen( val tokenRate: BigDecimal? = null, ) : SendScreenAction -// Address or PayId -sealed class AddressPayIdActionUi : SendScreenActionUi { - data class HandleUserInput(val data: String) : AddressPayIdActionUi() - data class PasteAddressPayId(val data: String, val sourceType: AddressEntered.SourceType) : AddressPayIdActionUi() - data class CheckClipboard(val data: String?) : AddressPayIdActionUi() - data class CheckAddressPayId(val sourceType: AddressEntered.SourceType?) : AddressPayIdActionUi() - data class SetTruncateHandler(val handler: (String) -> String) : AddressPayIdActionUi() - data class TruncateOrRestore(val truncate: Boolean) : AddressPayIdActionUi() - data class ChangePayIdState(val sendingToPayIdEnabled: Boolean) : AddressPayIdActionUi() +// Address +sealed class AddressActionUi : SendScreenActionUi { + data class HandleUserInput(val data: String) : AddressActionUi() + data class PasteAddress(val data: String, val sourceType: AddressEntered.SourceType) : AddressActionUi() + data class CheckClipboard(val data: String?) : AddressActionUi() + data class CheckAddress(val sourceType: AddressEntered.SourceType?) : AddressActionUi() + data class SetTruncateHandler(val handler: (String) -> String) : AddressActionUi() + data class TruncateOrRestore(val truncate: Boolean) : AddressActionUi() } sealed class TransactionExtrasAction : SendScreenActionUi { @@ -76,27 +74,15 @@ sealed class TransactionExtrasAction : SendScreenActionUi { } } -sealed class AddressPayIdVerifyAction : SendScreenAction { +sealed class AddressVerifyAction : SendScreenAction { enum class Error { - PAY_ID_UNSUPPORTED_BY_BLOCKCHAIN, - PAY_ID_NOT_REGISTERED, - PAY_ID_REQUEST_FAILED, ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN, ADDRESS_SAME_AS_WALLET, } - data class ChangePasteBtnEnableState(val isEnabled: Boolean) : AddressPayIdVerifyAction() + data class ChangePasteBtnEnableState(val isEnabled: Boolean) : AddressVerifyAction() - sealed class PayIdVerification : AddressPayIdVerifyAction() { - data class SetPayIdError(val error: Error?) : PayIdVerification() - data class SetPayIdWalletAddress( - val payId: String, - val payIdWalletAddress: String, - val isUserInput: Boolean, - ) : PayIdVerification() - } - - sealed class AddressVerification : AddressPayIdVerifyAction() { + sealed class AddressVerification : AddressVerifyAction() { data class SetAddressError(val error: Error?) : AddressVerification() data class SetWalletAddress(val address: String, val isUserInput: Boolean) : AddressVerification() } @@ -155,8 +141,6 @@ sealed class SendAction : SendScreenAction { override val messageResource: Int = R.string.send_transaction_success } - data class SendError(override val error: TapError) : SendAction(), ErrorAction - sealed class Dialog : SendAction(), StateDialog { data class TezosWarningDialog( val reduceCallback: () -> Unit, diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressPayIdMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressMiddleware.kt similarity index 50% rename from app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressPayIdMiddleware.kt rename to app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressMiddleware.kt index 406eacd087..576497222e 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressPayIdMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AddressMiddleware.kt @@ -2,49 +2,39 @@ package com.tangem.tap.features.send.redux.middlewares import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Wallet -import com.tangem.common.services.Result import com.tangem.core.analytics.Analytics import com.tangem.tap.common.analytics.events.Token.Send.AddressEntered import com.tangem.tap.common.redux.AppState -import com.tangem.tap.domain.PayIdManager -import com.tangem.tap.domain.isPayIdSupported import com.tangem.tap.features.send.redux.* -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.AddressVerification.SetAddressError -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.AddressVerification.SetWalletAddress -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification.SetPayIdError -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification.SetPayIdWalletAddress -import com.tangem.tap.scope -import com.tangem.tap.store -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import com.tangem.tap.features.send.redux.AddressVerifyAction.AddressVerification.SetAddressError +import com.tangem.tap.features.send.redux.AddressVerifyAction.AddressVerification.SetWalletAddress +import com.tangem.tap.features.send.redux.AddressVerifyAction.Error import org.rekotlin.Action import org.rekotlin.DispatchFunction /** [REDACTED_AUTHOR] */ -internal class AddressPayIdMiddleware { +internal class AddressMiddleware { - fun handle(action: AddressPayIdActionUi, appState: AppState?, dispatch: (Action) -> Unit) { + fun handle(action: AddressActionUi, appState: AppState?, dispatch: (Action) -> Unit) { when (action) { - is AddressPayIdActionUi.HandleUserInput -> handleUserInput(action.data, appState, dispatch) - is AddressPayIdActionUi.PasteAddressPayId -> pasteAddressPayId(action.data, action.sourceType, dispatch) - is AddressPayIdActionUi.CheckClipboard -> verifyClipboard(action.data, appState, dispatch) - is AddressPayIdActionUi.CheckAddressPayId -> verifyAddressPayId(action.sourceType, appState, dispatch) + is AddressActionUi.HandleUserInput -> handleUserInput(action.data, appState, dispatch) + is AddressActionUi.PasteAddress -> pasteAddress(action.data, action.sourceType, dispatch) + is AddressActionUi.CheckClipboard -> verifyClipboard(action.data, appState, dispatch) + is AddressActionUi.CheckAddress -> verifyAddress(action.sourceType, appState, dispatch) else -> return } } private fun handleUserInput(input: String, appState: AppState?, dispatch: DispatchFunction) { val sendState = appState?.sendState ?: return - if (input == sendState.addressPayIdState.viewFieldValue.value) return + if (input == sendState.addressState.viewFieldValue.value) return setAddressAndCheck(data = input, sourceType = null, isUserInput = true, dispatch = dispatch) } - private fun pasteAddressPayId(data: String, sourceType: AddressEntered.SourceType, dispatch: (Action) -> Unit) { + private fun pasteAddress(data: String, sourceType: AddressEntered.SourceType, dispatch: (Action) -> Unit) { setAddressAndCheck(data = data, sourceType = sourceType, isUserInput = false, dispatch = dispatch) } @@ -54,74 +44,27 @@ internal class AddressPayIdMiddleware { isUserInput: Boolean, dispatch: (Action) -> Unit, ) { - val potentialPayId = data.lowercase() - if (isPayIdEnabled() && PayIdManager.isPayId(potentialPayId)) { - dispatch(SetPayIdWalletAddress(potentialPayId, "", isUserInput)) - } else { - dispatch(SetWalletAddress(data, isUserInput)) - } - dispatch(AddressPayIdActionUi.CheckAddressPayId(sourceType)) + dispatch(SetWalletAddress(data, isUserInput)) + dispatch(AddressActionUi.CheckAddress(sourceType)) } - private fun verifyAddressPayId( + private fun verifyAddress( sourceType: AddressEntered.SourceType?, appState: AppState?, dispatch: (Action) -> Unit, ) { val sendState = appState?.sendState ?: return val wallet = sendState.walletManager?.wallet ?: return - val addressPayId = sendState.addressPayIdState.normalFieldValue ?: return - val isUserInput = sendState.addressPayIdState.viewFieldValue.isFromUserInput + val address = sendState.addressState.normalFieldValue ?: return + val isUserInput = sendState.addressState.viewFieldValue.isFromUserInput - if (isPayIdEnabled() && PayIdManager.isPayId(addressPayId)) { - verifyPayId(addressPayId, wallet, isUserInput, dispatch) - } else { - verifyAddress( - address = addressPayId, - wallet = wallet, - isUserInput = isUserInput, - dispatch = dispatch, - sourceType = sourceType, - ) - } - } - - private fun verifyPayId(payId: String, wallet: Wallet, isUserInput: Boolean, dispatch: DispatchFunction) { - val blockchain = wallet.blockchain - if (!blockchain.isPayIdSupported()) { - dispatch(SetPayIdError(Error.PAY_ID_UNSUPPORTED_BY_BLOCKCHAIN)) - return - } - - scope.launch { - val result = PayIdManager().verifyPayId(payId, blockchain) - withContext(Dispatchers.Main) { - when (result) { - is Result.Success -> { - val addressDetails = result.data.getAddressDetails() - if (addressDetails == null) { - dispatch(SetPayIdError(Error.PAY_ID_NOT_REGISTERED)) - return@withContext - } - - val address = addressDetails.address - val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(wallet, address) - if (failReason == null) { - dispatch(SetPayIdWalletAddress(payId, address, isUserInput)) - dispatch(TransactionExtrasAction.Prepare(wallet.blockchain, address, addressDetails.tag)) - dispatch(FeeAction.RequestFee) - } else { - dispatch(SetAddressError(failReason)) - dispatch(TransactionExtrasAction.Release) - } - } - is Result.Failure -> { - dispatch(SetPayIdError(Error.PAY_ID_REQUEST_FAILED)) - dispatch(TransactionExtrasAction.Release) - } - } - } - } + verifyAddress( + address = address, + wallet = wallet, + isUserInput = isUserInput, + dispatch = dispatch, + sourceType = sourceType, + ) } private fun verifyAddress( @@ -219,41 +162,33 @@ internal class AddressPayIdMiddleware { } private fun verifyClipboard(input: String?, appState: AppState?, dispatch: DispatchFunction) { - val addressPayId = input ?: return + val address = input ?: return val wallet = appState?.sendState?.walletManager?.wallet ?: return val internalDispatcher: (Action) -> Unit = { when (it) { - is SetWalletAddress, is SetPayIdWalletAddress -> { - dispatch(AddressPayIdVerifyAction.ChangePasteBtnEnableState(true)) + is SetWalletAddress -> { + dispatch(AddressVerifyAction.ChangePasteBtnEnableState(true)) } - is SetAddressError, is SetPayIdError -> { - dispatch(AddressPayIdVerifyAction.ChangePasteBtnEnableState(false)) + is SetAddressError -> { + dispatch(AddressVerifyAction.ChangePasteBtnEnableState(false)) } } } - if (PayIdManager.isPayId(addressPayId) && isPayIdEnabled()) { - verifyPayId(addressPayId, wallet, false, internalDispatcher) - } else { - verifyAddress( - address = addressPayId, - wallet = wallet, - sourceType = null, - isUserInput = false, - dispatch = internalDispatcher, - ) - } - } - - private fun isPayIdEnabled(): Boolean { - return store.state.globalState.configManager?.config?.isSendingToPayIdEnabled ?: false + verifyAddress( + address = address, + wallet = wallet, + sourceType = null, + isUserInput = false, + dispatch = internalDispatcher, + ) } } fun String.splitToMap(firstDelimiter: String, secondDelimiter: String): Map { - return this.split(firstDelimiter) + return this + .split(firstDelimiter) .map { it.split(secondDelimiter) } - .map { it.first() to it.last().toString() } - .toMap() + .associate { it.first() to it.last() } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/RequestFeeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/RequestFeeMiddleware.kt index 8a0b096c4c..3cbd54e044 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/RequestFeeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/RequestFeeMiddleware.kt @@ -38,7 +38,7 @@ class RequestFeeMiddleware { } val typedAmount = sendState.amountState.amountToExtract ?: return - val destinationAddress = sendState.addressPayIdState.destinationWalletAddress!! + val destinationAddress = sendState.addressState.destinationWalletAddress!! val destinationAmount = Amount(typedAmount, sendState.amountState.amountToSendCrypto) val txSender = if (scanResponse.isDemoCard()) { DemoTransactionSender(walletManager) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index d54adda3d5..5f8d039210 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -55,18 +55,17 @@ class SendMiddleware { { nextDispatch -> { action -> when (action) { - is AddressPayIdActionUi -> AddressPayIdMiddleware().handle(action, appState(), dispatch) + is AddressActionUi -> AddressMiddleware().handle(action, appState(), dispatch) is AmountActionUi -> AmountMiddleware().handle(action, appState(), dispatch) is RequestFee -> RequestFeeMiddleware().handle(appState(), dispatch) is SendActionUi.SendAmountToRecipient -> verifyAndSendTransaction(action, appState(), dispatch) - is PrepareSendScreen -> setIfSendingToPayIdEnabled(appState(), dispatch) is SendAction.Warnings.Update -> updateWarnings(dispatch) is SendActionUi.CheckIfTransactionDataWasProvided -> { val transactionData = appState()?.sendState?.externalTransactionData if (transactionData != null) { store.dispatchOnMain( - AddressPayIdVerifyAction.AddressVerification.SetWalletAddress( + AddressVerifyAction.AddressVerification.SetWalletAddress( address = transactionData.destinationAddress, isUserInput = false, ), @@ -96,7 +95,7 @@ private fun verifyAndSendTransaction( val sendState = appState?.sendState ?: return val walletManager = sendState.walletManager ?: return val card = appState.globalState.scanResponse?.card ?: return - val destinationAddress = sendState.addressPayIdState.destinationWalletAddress ?: return + val destinationAddress = sendState.addressState.destinationWalletAddress ?: return val typedAmount = sendState.amountState.amountToExtract ?: return val feeAmount = sendState.feeState.currentFee ?: return @@ -391,12 +390,6 @@ fun createValidateTransactionError( return TapError.ValidateTransactionErrors(tapErrors) { it.joinToString("\r\n") } } -private fun setIfSendingToPayIdEnabled(appState: AppState?, dispatch: (Action) -> Unit) { - val isSendingToPayIdEnabled = - appState?.globalState?.configManager?.config?.isSendingToPayIdEnabled ?: false - dispatch(AddressPayIdActionUi.ChangePayIdState(isSendingToPayIdEnabled)) -} - private fun updateWarnings(dispatch: (Action) -> Unit) { val warningsManager = store.state.globalState.warningManager ?: return val blockchain = store.state.sendState.walletManager?.wallet?.blockchain ?: return diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressPayIdReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressPayIdReducer.kt deleted file mode 100644 index ddacac0df8..0000000000 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressPayIdReducer.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.tangem.tap.features.send.redux.reducers - -import com.tangem.tap.features.send.redux.AddressPayIdActionUi -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.AddressVerification -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.PayIdVerification -import com.tangem.tap.features.send.redux.SendScreenAction -import com.tangem.tap.features.send.redux.states.AddressPayIdState -import com.tangem.tap.features.send.redux.states.InputViewValue -import com.tangem.tap.features.send.redux.states.SendState - -/** -[REDACTED_AUTHOR] - */ -class AddressPayIdReducer : SendInternalReducer { - override fun handle(action: SendScreenAction, sendState: SendState): SendState = when (action) { - is AddressPayIdActionUi -> handleUiAction(action, sendState, sendState.addressPayIdState) - is AddressPayIdVerifyAction -> handleAction(action, sendState, sendState.addressPayIdState) - else -> sendState - } - - private fun handleUiAction( - action: AddressPayIdActionUi, - sendState: SendState, - state: AddressPayIdState, - ): SendState { - val result = when (action) { - is AddressPayIdActionUi.HandleUserInput -> state - is AddressPayIdActionUi.SetTruncateHandler -> state.copy(truncateHandler = action.handler) - is AddressPayIdActionUi.TruncateOrRestore -> { - val value = if (action.truncate) state.truncatedFieldValue ?: "" else state.normalFieldValue ?: "" - state.copy(viewFieldValue = state.viewFieldValue.copy(value = value)) - } - is AddressPayIdActionUi.PasteAddressPayId -> return sendState - is AddressPayIdActionUi.CheckClipboard -> return sendState - is AddressPayIdActionUi.CheckAddressPayId -> return sendState - is AddressPayIdActionUi.ChangePayIdState -> state.copy(sendingToPayIdEnabled = action.sendingToPayIdEnabled) - } - return updateLastState(sendState.copy(addressPayIdState = result), result) - } - - private fun handleAction( - action: AddressPayIdVerifyAction, - sendState: SendState, - state: AddressPayIdState, - ): SendState { - val result = when (action) { - is PayIdVerification.SetPayIdWalletAddress -> { - state.copy( - viewFieldValue = InputViewValue(action.payId, action.isUserInput), - normalFieldValue = action.payId, - truncatedFieldValue = state.truncate(action.payId), - destinationWalletAddress = action.payIdWalletAddress, - error = null, - ) - } - is AddressVerification.SetWalletAddress -> { - state.copy( - viewFieldValue = InputViewValue(action.address, action.isUserInput), - normalFieldValue = action.address, - truncatedFieldValue = state.truncate(action.address), - destinationWalletAddress = action.address, - error = null, - ) - } - is AddressPayIdVerifyAction.ChangePasteBtnEnableState -> state.copy(pasteIsEnabled = action.isEnabled) - is AddressVerification.SetAddressError -> state.copy(error = action.error, destinationWalletAddress = null) - is PayIdVerification.SetPayIdError -> state.copy(error = action.error, destinationWalletAddress = null) - } - return updateLastState(sendState.copy(addressPayIdState = result), result) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressReducer.kt new file mode 100644 index 0000000000..a5b44bff0f --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/AddressReducer.kt @@ -0,0 +1,52 @@ +package com.tangem.tap.features.send.redux.reducers + +import com.tangem.tap.features.send.redux.AddressActionUi +import com.tangem.tap.features.send.redux.AddressVerifyAction +import com.tangem.tap.features.send.redux.AddressVerifyAction.AddressVerification +import com.tangem.tap.features.send.redux.SendScreenAction +import com.tangem.tap.features.send.redux.states.AddressState +import com.tangem.tap.features.send.redux.states.InputViewValue +import com.tangem.tap.features.send.redux.states.SendState + +/** +[REDACTED_AUTHOR] + */ +class AddressReducer : SendInternalReducer { + override fun handle(action: SendScreenAction, sendState: SendState): SendState = when (action) { + is AddressActionUi -> handleUiAction(action, sendState, sendState.addressState) + is AddressVerifyAction -> handleAction(action, sendState, sendState.addressState) + else -> sendState + } + + private fun handleUiAction(action: AddressActionUi, sendState: SendState, state: AddressState): SendState { + val result = when (action) { + is AddressActionUi.HandleUserInput -> state + is AddressActionUi.SetTruncateHandler -> state.copy(truncateHandler = action.handler) + is AddressActionUi.TruncateOrRestore -> { + val value = if (action.truncate) state.truncatedFieldValue ?: "" else state.normalFieldValue ?: "" + state.copy(viewFieldValue = state.viewFieldValue.copy(value = value)) + } + is AddressActionUi.PasteAddress -> return sendState + is AddressActionUi.CheckClipboard -> return sendState + is AddressActionUi.CheckAddress -> return sendState + } + return updateLastState(sendState.copy(addressState = result), result) + } + + private fun handleAction(action: AddressVerifyAction, sendState: SendState, state: AddressState): SendState { + val result = when (action) { + is AddressVerification.SetWalletAddress -> { + state.copy( + viewFieldValue = InputViewValue(action.address, action.isUserInput), + normalFieldValue = action.address, + truncatedFieldValue = state.truncate(action.address), + destinationWalletAddress = action.address, + error = null, + ) + } + is AddressVerifyAction.ChangePasteBtnEnableState -> state.copy(pasteIsEnabled = action.isEnabled) + is AddressVerification.SetAddressError -> state.copy(error = action.error, destinationWalletAddress = null) + } + return updateLastState(sendState.copy(addressState = result), result) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt index 4134e8c148..463b0dcaea 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt @@ -25,7 +25,7 @@ object SendScreenReducer { val reducer: SendInternalReducer = when (action) { is PrepareSendScreen -> PrepareSendScreenStatesReducer() - is AddressPayIdActionUi, is AddressPayIdVerifyAction -> AddressPayIdReducer() + is AddressActionUi, is AddressVerifyAction -> AddressReducer() is TransactionExtrasAction -> TransactionExtrasReducer() is AmountActionUi, is AmountAction -> AmountReducer() is FeeActionUi, is FeeAction -> FeeReducer() @@ -71,7 +71,7 @@ private class SendReducer : SendInternalReducer { amountState = state.amountState.copy( inputIsEnabled = false, ), - addressPayIdState = state.addressPayIdState.copy( + addressState = state.addressState.copy( inputIsEnabled = false, ), ) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressState.kt similarity index 90% rename from app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt rename to app/src/main/java/com/tangem/tap/features/send/redux/states/AddressState.kt index 9f0851e06d..b6b65a595f 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressState.kt @@ -2,17 +2,16 @@ package com.tangem.tap.features.send.redux.states import androidx.core.text.isDigitsOnly import com.tangem.blockchain.blockchains.stellar.StellarMemo -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction +import com.tangem.tap.features.send.redux.AddressVerifyAction import java.math.BigInteger -data class AddressPayIdState( +data class AddressState( val viewFieldValue: InputViewValue = InputViewValue(""), val normalFieldValue: String? = null, val truncatedFieldValue: String? = null, val destinationWalletAddress: String? = null, - val error: AddressPayIdVerifyAction.Error? = null, + val error: AddressVerifyAction.Error? = null, val truncateHandler: ((String) -> String)? = null, - val sendingToPayIdEnabled: Boolean = false, val pasteIsEnabled: Boolean = false, val inputIsEnabled: Boolean = true, ) : SendScreenState { @@ -22,8 +21,6 @@ data class AddressPayIdState( fun truncate(value: String): String = truncateHandler?.invoke(value) ?: value fun isReady(): Boolean = error == null && destinationWalletAddress?.isNotEmpty() ?: false - - fun isPayIdState(): Boolean = destinationWalletAddress != null && destinationWalletAddress != normalFieldValue } data class TransactionExtrasState( @@ -98,11 +95,7 @@ data class BinanceMemoState( val viewFieldValue: InputViewValue = InputViewValue(""), val memo: BigInteger? = null, val error: TransactionExtraError? = null, -) { - companion object { - val MAX_NUMBER: BigInteger = BigInteger("FFFFFFFFFFFFFFFF", 16) - } -} +) // tag must contains only digits data class XrpDestinationTagState( diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt index 6a47e2d342..8400f07c87 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt @@ -34,7 +34,7 @@ data class SendState( val coinConverter: CurrencyConverter? = null, val tokenConverter: CurrencyConverter? = null, val lastChangedStates: LinkedHashSet = linkedSetOf(), - val addressPayIdState: AddressPayIdState = AddressPayIdState(), + val addressState: AddressState = AddressState(), val transactionExtrasState: TransactionExtrasState = TransactionExtrasState(), val amountState: AmountState = AmountState(), val feeState: FeeState = FeeState(), @@ -52,7 +52,7 @@ data class SendState( MainCurrencyType.CRYPTO -> amountState.amountToExtract?.decimals ?: 0 } - fun convertFiatToCoin(value: BigDecimal): BigDecimal { + private fun convertFiatToCoin(value: BigDecimal): BigDecimal { return if (!this.coinIsConvertible()) value else coinConverter!!.toCrypto(value) } @@ -60,14 +60,14 @@ data class SendState( return if (!this.tokenIsConvertible()) value else tokenConverter!!.toCrypto(value) } - fun convertCoinToFiat(value: BigDecimal, scaleWithPrecision: Boolean = false): BigDecimal { + private fun convertCoinToFiat(value: BigDecimal, scaleWithPrecision: Boolean = false): BigDecimal { if (!this.coinIsConvertible()) return value val converter = coinConverter!! return if (!scaleWithPrecision) converter.toFiat(value) else converter.toFiatWithPrecision(value) } - fun convertTokenToFiat(value: BigDecimal, scaleWithPrecision: Boolean = false): BigDecimal { + private fun convertTokenToFiat(value: BigDecimal, scaleWithPrecision: Boolean = false): BigDecimal { if (!this.tokenIsConvertible()) return value val converter = tokenConverter!! @@ -107,13 +107,13 @@ data class SendState( } companion object { - fun addressPayIdIsReady(): Boolean = store.state.sendState.addressPayIdState.isReady() + private fun addressIsReady(): Boolean = store.state.sendState.addressState.isReady() - fun amountIsReady(): Boolean = store.state.sendState.amountState.isReady() + private fun amountIsReady(): Boolean = store.state.sendState.amountState.isReady() - fun isReadyToRequestFee(): Boolean = addressPayIdIsReady() && amountIsReady() + fun isReadyToRequestFee(): Boolean = addressIsReady() && amountIsReady() - fun isReadyToSend(): Boolean = addressPayIdIsReady() && amountIsReady() && + fun isReadyToSend(): Boolean = addressIsReady() && amountIsReady() && store.state.sendState.feeState.isReady() } } diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt index 64c4fc53a7..fec34d9996 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt @@ -33,7 +33,7 @@ import com.tangem.tap.common.toggleWidget.ViewStateWidget import com.tangem.tap.features.BaseStoreFragment import com.tangem.tap.features.addBackPressHandler import com.tangem.tap.features.send.redux.* -import com.tangem.tap.features.send.redux.AddressPayIdActionUi.* +import com.tangem.tap.features.send.redux.AddressActionUi.* import com.tangem.tap.features.send.redux.AmountActionUi.* import com.tangem.tap.features.send.redux.FeeActionUi.* import com.tangem.tap.features.send.redux.states.FeeType @@ -80,7 +80,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) { etAmountToSend = view.findViewById(R.id.etAmountToSend) initSendButtonStates() - setupAddressOrPayIdLayout() + setupAddressLayout() setupTransactionExtrasLayout() setupAmountLayout() setupFeeLayout() @@ -99,14 +99,14 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) { sendBtn = IndeterminateProgressButtonWidget(btnSend, progress) } - private fun setupAddressOrPayIdLayout() = with(binding.lSendAddressPayid) { - store.dispatch(SetTruncateHandler { etAddressOrPayId.truncateMiddleWith(it, "...") }) + private fun setupAddressLayout() = with(binding.lSendAddress) { + store.dispatch(SetTruncateHandler { etAddress.truncateMiddleWith(it, "...") }) store.dispatch(CheckClipboard(requireContext().getFromClipboard()?.toString())) - etAddressOrPayId.apply { + etAddress.apply { setOnSystemPasteButtonClickListener { store.dispatch( - PasteAddressPayId( + PasteAddress( data = requireContext().getFromClipboard()?.toString() ?: "", sourceType = Token.Send.AddressEntered.SourceType.PastePopup, ), @@ -119,9 +119,9 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) { inputtedTextAsFlow() .debounce(EDIT_TEXT_INPUT_DEBOUNCE) - .filter { store.state.sendState.addressPayIdState.viewFieldValue.value != it } + .filter { store.state.sendState.addressState.viewFieldValue.value != it } .onEach { - store.dispatch(AddressPayIdActionUi.HandleUserInput(it)) + store.dispatch(AddressActionUi.HandleUserInput(it)) } .launchIn(mainScope) } @@ -129,12 +129,12 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) { imvPaste.setOnClickListener { Analytics.send(Token.Send.ButtonPaste()) store.dispatch( - PasteAddressPayId( + PasteAddress( data = requireContext().getFromClipboard()?.toString() ?: "", sourceType = Token.Send.AddressEntered.SourceType.PasteButton, ), ) - store.dispatch(TruncateOrRestore(!etAddressOrPayId.isFocused)) + store.dispatch(TruncateOrRestore(!etAddress.isFocused)) } imvQrCode.setOnClickListener { Analytics.send(Token.Send.ButtonQRCode()) @@ -145,7 +145,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) { } } - private fun setupTransactionExtrasLayout() = with(binding.lSendAddressPayid) { + private fun setupTransactionExtrasLayout() = with(binding.lSendAddress) { // TODO: [REDACTED_TASK_KEY] etXlmMemo.inputtedTextAsFlow() .debounce(EDIT_TEXT_INPUT_DEBOUNCE) @@ -202,15 +202,15 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) { // Delayed launch is needed in order for the UI to be drawn and to process the sent events. // If do not use the delay, then etAmount error field is not displayed when // inserting an incorrect amount by shareUri - binding.lSendAddressPayid.imvQrCode.postDelayed( + binding.lSendAddress.imvQrCode.postDelayed( { store.dispatch( - PasteAddressPayId( + PasteAddress( data = scannedCode, sourceType = Token.Send.AddressEntered.SourceType.QRCode, ), ) - store.dispatch(TruncateOrRestore(!binding.lSendAddressPayid.etAddressOrPayId.isFocused)) + store.dispatch(TruncateOrRestore(!binding.lSendAddress.etAddress.isFocused)) }, 200, ) diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 12f16a0274..7c12e82496 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -7,30 +7,15 @@ import android.view.View import android.view.ViewGroup import androidx.core.text.bold import com.tangem.common.extensions.remove -import com.tangem.tap.common.extensions.beginDelayedTransition -import com.tangem.tap.common.extensions.enableError -import com.tangem.tap.common.extensions.getColor -import com.tangem.tap.common.extensions.getString -import com.tangem.tap.common.extensions.hide -import com.tangem.tap.common.extensions.show -import com.tangem.tap.common.extensions.update +import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.getMessageString import com.tangem.tap.common.text.DecimalDigitsInputFilter import com.tangem.tap.domain.MultiMessageError import com.tangem.tap.domain.assembleErrors import com.tangem.tap.features.BaseStoreFragment -import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error +import com.tangem.tap.features.send.redux.AddressVerifyAction.Error import com.tangem.tap.features.send.redux.SendAction -import com.tangem.tap.features.send.redux.states.AddressPayIdState -import com.tangem.tap.features.send.redux.states.AmountState -import com.tangem.tap.features.send.redux.states.FeeState -import com.tangem.tap.features.send.redux.states.MainCurrencyType -import com.tangem.tap.features.send.redux.states.ReceiptLayoutType -import com.tangem.tap.features.send.redux.states.ReceiptState -import com.tangem.tap.features.send.redux.states.SendState -import com.tangem.tap.features.send.redux.states.StateId -import com.tangem.tap.features.send.redux.states.TransactionExtraError -import com.tangem.tap.features.send.redux.states.TransactionExtrasState +import com.tangem.tap.features.send.redux.states.* import com.tangem.tap.features.send.ui.FeeUiHelper import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.send.ui.dialogs.KaspaWarningDialog @@ -61,7 +46,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber lastChangedStates.forEach { when (it) { StateId.SEND_SCREEN -> handleSendScreen(fg, state) - StateId.ADDRESS_PAY_ID -> handleAddressPayIdState(fg, state.addressPayIdState) + StateId.ADDRESS_PAY_ID -> handleAddressState(fg, state.addressState) StateId.TRANSACTION_EXTRAS -> handleTransactionExtrasState(fg, state.transactionExtrasState) StateId.AMOUNT -> handleAmountState(fg, state.amountState) StateId.FEE -> handleFeeState(fg, state.feeState) @@ -72,7 +57,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber @Suppress("ComplexMethod") private fun handleTransactionExtrasState(fg: SendFragment, infoState: TransactionExtrasState) = - with(fg.binding.lSendAddressPayid) { + with(fg.binding.lSendAddress) { fun showView(view: View, info: Any?) { view.show(info != null) } @@ -192,13 +177,10 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber ) } - private fun handleAddressPayIdState(fg: SendFragment, state: AddressPayIdState) = - with(fg.binding.lSendAddressPayid) { + private fun handleAddressState(fg: SendFragment, state: AddressState) { + with(fg.binding.lSendAddress) { fun parseError(context: Context, error: Error?): String? { val resId = when (error) { - Error.PAY_ID_UNSUPPORTED_BY_BLOCKCHAIN -> R.string.send_error_payid_unsupported_by_blockchain - Error.PAY_ID_NOT_REGISTERED -> R.string.send_error_payid_not_registered - Error.PAY_ID_REQUEST_FAILED -> R.string.send_error_payid_request_failed Error.ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN -> R.string.send_validation_invalid_address Error.ADDRESS_SAME_AS_WALLET -> R.string.send_error_address_same_as_wallet else -> null @@ -208,8 +190,8 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber imvPaste.isEnabled = state.pasteIsEnabled - val et = etAddressOrPayId - val til = tilAddressOrPayId + val et = etAddress + val til = tilAddress val parsedError = parseError(til.context, state.error) til.isEnabled = state.inputIsEnabled @@ -218,19 +200,15 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber flPaste.show(state.inputIsEnabled) flQrCode.show(state.inputIsEnabled) - val hintResId = if (state.sendingToPayIdEnabled) { - R.string.send_destination_hint_address_payid - } else { - R.string.send_destination_hint_address - } - til.hint = til.getString(hintResId) + til.hint = til.getString(R.string.send_destination_hint_address) til.error = parsedError til.isErrorEnabled = parsedError != null til.helperText = state.destinationWalletAddress - til.isHelperTextEnabled = state.isPayIdState() && parsedError == null + til.isHelperTextEnabled = parsedError == null if (!state.viewFieldValue.isFromUserInput) et.update(state.viewFieldValue.value) } + } private fun handleAmountState(fg: SendFragment, state: AmountState) = with(fg.binding.lSendAmount) { if (state.error != null) { diff --git a/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyApi.kt b/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyApi.kt deleted file mode 100644 index d9d00a663b..0000000000 --- a/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyApi.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.tangem.tap.network.payid - -import com.squareup.moshi.JsonClass -import retrofit2.http.GET -import retrofit2.http.Header -import retrofit2.http.Path - -/** -[REDACTED_AUTHOR] - */ -interface PayIdVerifyApi { - @GET("{user}") - suspend fun verifyAddress( - @Path("user") user: String, - @Header("Accept") acceptNetworkHeader: String, - @Header("PayID-Version") payIdVersion: String = "1.0", - ): VerifyPayIdResponse -} - -@JsonClass(generateAdapter = true) -data class VerifyPayIdResponse( - val addresses: List = mutableListOf(), - val payId: String? = null, -) { - fun getAddressDetails(): PayIdAddressDetails? = if (addresses.isNotEmpty()) addresses[0].addressDetails else null -} - -@JsonClass(generateAdapter = true) -data class PayIdAddress( - var paymentNetwork: String, - var environment: String, - var addressDetailsType: String, - var addressDetails: PayIdAddressDetails, -) - -@JsonClass(generateAdapter = true) -data class PayIdAddressDetails( - var address: String, - var tag: String? = null, -) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyService.kt b/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyService.kt deleted file mode 100644 index 05d16f8724..0000000000 --- a/app/src/main/java/com/tangem/tap/network/payid/PayIdVerifyService.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.tangem.tap.network.payid - -import com.tangem.common.services.Result -import com.tangem.common.services.performRequest -import com.tangem.datasource.api.common.createRetrofitInstance - -/** -[REDACTED_AUTHOR] - */ -class PayIdVerifyService( - private val baseUrl: String, -) { - - private val api = createRetrofitInstance( - baseUrl = baseUrl, - logEnabled = false, - ).create(PayIdVerifyApi::class.java) - - suspend fun verifyAddress(user: String, network: String): Result { - return performRequest { api.verifyAddress(user, createNetworkHeader(network)) } - } - - private fun createNetworkHeader(network: String): String = "application/$network-mainnet+json" -} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_send.xml b/app/src/main/res/layout/fragment_send.xml index fe0eebf2a3..8ec3dfb594 100644 --- a/app/src/main/res/layout/fragment_send.xml +++ b/app/src/main/res/layout/fragment_send.xml @@ -39,8 +39,8 @@ android:orientation="vertical"> diff --git a/app/src/main/res/layout/layout_address.xml b/app/src/main/res/layout/layout_address.xml index 22853700ed..713c384939 100644 --- a/app/src/main/res/layout/layout_address.xml +++ b/app/src/main/res/layout/layout_address.xml @@ -150,63 +150,6 @@ app:layout_constraintTop_toBottomOf="@id/tv_explore" tools:text="Send only Ethereum (ETH) from Ethereum network to this address. Using other tokens and networks may result in loss of funds." /> - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_send_address_payid.xml b/app/src/main/res/layout/layout_send_address.xml similarity index 84% rename from app/src/main/res/layout/layout_send_address_payid.xml rename to app/src/main/res/layout/layout_send_address.xml index 1bf69a649f..c6dd2873c8 100644 --- a/app/src/main/res/layout/layout_send_address_payid.xml +++ b/app/src/main/res/layout/layout_send_address.xml @@ -18,10 +18,9 @@ app:layout_constraintTop_toTopOf="parent"> + app:layout_constraintTop_toTopOf="@+id/tilAddress"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + app:layout_constraintTop_toBottomOf="@+id/tilAddress"> = Build.VERSION_CODES.N) - Html.fromHtml(engine!!.balanceHTML, Html.FROM_HTML_MODE_LEGACY) - else - Html.fromHtml(engine!!.balanceHTML) - tvBalance.text = html - - isIncludeFee = arguments?.getBoolean(Constant.EXTRA_FEE_INCLUDED, true) ?: true - - if (isIncludeFee) - tvIncFee.setText(R.string.confirm_transaction_including_fee) - else - tvIncFee.setText(R.string.confirm_transaction_not_including_fee) - - amount = CoinEngine.Amount(arguments?.getString(Constant.EXTRA_AMOUNT) ?: "0", - arguments?.getString(Constant.EXTRA_AMOUNT_CURRENCY) ?: "") - - if (engine.allowSelectFeeInclusion()) - tvIncFee.visibility = View.VISIBLE - else - tvIncFee.visibility = View.INVISIBLE - - if (ctx.card.blockchainID == Blockchain.Token.id) { - // for Blockchain.Token limit decimals - etAmount.setText(amount.toValueString(ctx.card.tokensDecimal)) - } else { - // for others - etAmount.setText(amount.toValueString()) - } - - tvCurrency.text = engine.balanceCurrency - tvCurrency2.text = engine.feeCurrency - tvCardID.text = ctx.card.cidDescription - etWallet.setText(arguments?.getString(Constant.EXTRA_TARGET_ADDRESS)) - - btnSend.visibility = View.INVISIBLE - - if (!engine.allowSelectFeeLevel()) { - rgFee.visibility = View.INVISIBLE - } - - etFee.isEnabled = sp.getBoolean(getString(R.string.pref_manual_editing_fee), false) - - // set listeners - rgFee.setOnCheckedChangeListener { _, checkedId -> doSetFee(checkedId) } - etFee.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { - - } - - override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { - try { - val eqFee = engine.evaluateFeeEquivalent(etFee!!.text.toString()) - tvFeeEquivalent.text = eqFee - - if (!ctx.coinData!!.amountEquivalentDescriptionAvailable) { - tvFeeEquivalent.error = getString(R.string.confirm_transaction_error_service_unavailable) - tvCurrency2.visibility = View.GONE - tvFeeEquivalent.visibility = View.GONE - } else - tvFeeEquivalent.error = null - - if (sp.getBoolean(getString(R.string.pref_manual_editing_fee), false)) - (activity as MainActivity).toastHelper - .showSingleToast(context, getString(R.string.confirm_transaction_warning_risk_delaying)) - - } catch (e: Exception) { - e.printStackTrace() - tvFeeEquivalent.text = "" - } - } - - override fun afterTextChanged(s: Editable) { - - } - }) - btnSend.setOnClickListener { - if (UtilHelper.isOnline(requireContext())) { - val calendar = Calendar.getInstance() - calendar.add(Calendar.MINUTE, -1) - - if (dtVerified == null || dtVerified!!.before(calendar.time)) { - finishWithError(Activity.RESULT_CANCELED, getString(R.string.confirm_transaction_error_data_is_outdated)) - return@setOnClickListener - } - - val engineCoin = CoinEngineFactory.create(ctx) - - if (engineCoin!!.isNeedCheckNode && !nodeCheck) { - Toast.makeText(context, getString(R.string.confirm_transaction_error_cannot_reach_node), Toast.LENGTH_LONG).show() - return@setOnClickListener - } - - val txFee = engineCoin.convertToAmount(etFee.text.toString(), tvCurrency2.text.toString()) - val txAmount = engineCoin.convertToAmount(etAmount.text.toString(), tvCurrency.text.toString()) - - if (!engineCoin.hasBalanceInfo()) { - finishWithError(Activity.RESULT_CANCELED, getString(R.string.confirm_transaction_error_cannot_check_balance)) - return@setOnClickListener - - } else if (!engineCoin.isBalanceNotZero) { - finishWithError(Activity.RESULT_CANCELED, getString(R.string.general_wallet_empty)) - return@setOnClickListener - - } else if (!engineCoin.isExtractPossible) { - finishWithError(Activity.RESULT_CANCELED, getString(R.string.confirm_transaction_error_incoming_transaction_unconfirmed)) - return@setOnClickListener - } - - if (!engineCoin.checkNewTransactionAmountAndFee(txAmount, txFee, isIncludeFee)) { - finishWithError(Activity.RESULT_CANCELED, getString(R.string.prepare_transaction_error_not_enough_funds)) - return@setOnClickListener - } - - requestPIN2Count = 0 - val data = Bundle() - data.putString(Constant.EXTRA_MODE, PinRequestFragment.Mode.RequestPIN2.toString()) - ctx.saveToBundle(data) - data.putBoolean(Constant.EXTRA_FEE_INCLUDED, isIncludeFee) - navigateForResult(Constant.REQUEST_CODE_REQUEST_PIN2_, R.id.action_confirmTransactionFragment_to_pinRequestFragment, data) - } else - Toast.makeText(context, getString(R.string.general_error_no_connection), Toast.LENGTH_SHORT).show() - } - - progressBar.visibility = View.VISIBLE - - if (!navigatedBack) requestFee() - } - - private fun requestFee() { - val coinEngine = CoinEngineFactory.create(ctx) - coinEngine!!.requestFee( - object : CoinEngine.BlockchainRequestsCallbacks { - override fun onComplete(success: Boolean) { - if (success) { - progressBar?.visibility = View.INVISIBLE - dtVerified = Date() - doSetFee(rgFee?.checkedRadioButtonId ?: R.id.rbNormalFee) - } else { - finishWithError(Activity.RESULT_CANCELED, ctx.error) - } - } - - override fun onProgress() { - } - - override fun allowAdvance(): Boolean { - return UtilHelper.isOnline(requireContext()) - } - }, - etWallet.text.toString(), - amount) - } - - override fun onNavigationResult(requestCode: String, resultCode: Int, data: Bundle?) { - Log.d("LIFECYCLE", "NavigationResult assessed ${this::class.java.simpleName}") - if (requestCode == Constant.REQUEST_CODE_SIGN_TRANSACTION) { - if (data != null) { - if (data.containsKey(EXTRA_TANGEM_CARD_UID) && data.containsKey(EXTRA_TANGEM_CARD)) { - val updatedCard = TangemCard(data.getString(EXTRA_TANGEM_CARD_UID)) - updatedCard.loadFromBundle(data.getBundle(EXTRA_TANGEM_CARD)) - ctx.card = updatedCard - } - } - if (resultCode == Constant.RESULT_INVALID_PIN_ && requestPIN2Count < 2) { - requestPIN2Count++ - val bundle = Bundle() - bundle.putString(Constant.EXTRA_MODE, PinRequestFragment.Mode.RequestPIN2.toString()) - ctx.saveToBundle(bundle) - bundle.putBoolean(Constant.EXTRA_FEE_INCLUDED, isIncludeFee) - navigateForResult(Constant.REQUEST_CODE_REQUEST_PIN2_, - R.id.action_confirmTransactionFragment_to_pinRequestFragment, - bundle) - return - } - navigateBackWithResult(resultCode, data) - } else if (requestCode == Constant.REQUEST_CODE_REQUEST_PIN2_) { - if (resultCode == Activity.RESULT_OK) { - val bundle = Bundle() - ctx.saveToBundle(bundle) - bundle.putString(Constant.EXTRA_TARGET_ADDRESS, etWallet!!.text.toString()) - bundle.putString(Constant.EXTRA_AMOUNT, etAmount.text.toString()) - bundle.putString(Constant.EXTRA_AMOUNT_CURRENCY, tvCurrency.text.toString()) - bundle.putString(Constant.EXTRA_FEE, etFee.text.toString()) - bundle.putString(Constant.EXTRA_FEE_CURRENCY, tvCurrency2.text.toString()) - bundle.putBoolean(Constant.EXTRA_FEE_INCLUDED, isIncludeFee) - navigateForResult(Constant.REQUEST_CODE_SIGN_TRANSACTION, - R.id.action_confirmTransactionFragment_to_signTransactionFragment, - bundle) - } else - Toast.makeText(context, R.string.confirm_transaction_error_pin_2_is_required, Toast.LENGTH_LONG).show() - } - } - - override fun onTagDiscovered(tag: Tag) { - try { - (activity as MainActivity).nfcManager.ignoreTag(tag) - } catch (e: IOException) { - e.printStackTrace() - } - } - - private fun doSetFee(checkedRadioButtonId: Int) { - var txtFee = "" - when (checkedRadioButtonId) { - R.id.rbMinimalFee -> - if (ctx.coinData.minFee != null) { - txtFee = ctx.coinData.minFee!!.toValueString() - btnSend?.visibility = View.VISIBLE - } else - btnSend?.visibility = View.INVISIBLE - - R.id.rbNormalFee -> - if (ctx.coinData.normalFee != null) { - txtFee = ctx.coinData.normalFee!!.toValueString() - btnSend?.visibility = View.VISIBLE - } else - btnSend?.visibility = View.INVISIBLE - - R.id.rbMaximumFee -> - if (ctx.coinData.maxFee != null) { - txtFee = ctx.coinData.maxFee!!.toValueString() - btnSend?.visibility = View.VISIBLE - } else - btnSend?.visibility = View.INVISIBLE - } - etFee?.setText(txtFee.replace(',', '.')) - } - - private fun finishWithError(errorCode: Int, message: String) { - navigateBackWithResult( - errorCode, - bundleOf(Constant.EXTRA_MESSAGE to message), - R.id.loadedWalletFragment) - } -} \ No newline at end of file diff --git a/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt b/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt deleted file mode 100644 index 387f992bb6..0000000000 --- a/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt +++ /dev/null @@ -1,182 +0,0 @@ -package com.tangem.ui - -import android.app.Activity -import android.content.Context -import android.nfc.NfcAdapter -import android.nfc.Tag -import android.os.Build -import android.os.Bundle -import android.text.Html -import android.view.View -import android.view.inputmethod.EditorInfo -import android.view.inputmethod.InputMethodManager -import android.widget.Toast -import com.tangem.Constant -import com.tangem.data.isPayIdSupported -import com.tangem.ui.activity.MainActivity -import com.tangem.ui.fragment.BaseFragment -import com.tangem.ui.fragment.qr.CameraPermissionManager -import com.tangem.ui.navigation.NavigationResultListener -import com.tangem.util.UtilHelper -import com.tangem.util.extensions.isStart2CoinCard -import com.tangem.wallet.CoinEngineFactory -import com.tangem.wallet.R -import com.tangem.wallet.TangemContext -import kotlinx.android.synthetic.tangemAccess.fragment_prepare_transaction.* -import java.io.IOException - -class PrepareTransactionFragment : BaseFragment(), NavigationResultListener, NfcAdapter.ReaderCallback { - companion object { - val TAG: String = PrepareTransactionFragment::class.java.simpleName - } - - override val layoutId = R.layout.fragment_prepare_transaction - - private val ctx: TangemContext by lazy { TangemContext.loadFromBundle(context, arguments) } - private val cameraPermissionManager: CameraPermissionManager by lazy { CameraPermissionManager(this) } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - tvCardID.text = ctx.card?.cidDescription - val engine = CoinEngineFactory.create(ctx) - - @Suppress("DEPRECATION") val html = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - Html.fromHtml(engine!!.balanceHTML, Html.FROM_HTML_MODE_LEGACY) - else - Html.fromHtml(engine!!.balanceHTML) - tvBalance.text = html - - if (ctx.blockchain.isPayIdSupported() && !ctx.card.isStart2CoinCard()) { - etWallet.hint = getString(R.string.prepare_transaction_hint_address_or_pay_id) - } - - if (!engine.allowSelectFeeInclusion()) { - rgIncFee.visibility = View.INVISIBLE - } else { - rgIncFee.visibility = View.VISIBLE - } - - if (ctx.card!!.remainingSignatures < 2) { - etAmount.isEnabled = false - } - - if (ctx.card.remainingSignatures == 1) { - androidx.appcompat.app.AlertDialog.Builder(requireContext()) - .setTitle(R.string.prepare_transaction_warning_last_signature) - .setMessage(R.string.prepare_transaction_warning_send_full_amount) - .setPositiveButton(R.string.general_ok) { _, _ -> } - .create() - .show() - } - - tvCurrency.text = engine.balance.currency - etAmount.setText(engine.balance.toValueString()) - - // limit number of symbols after comma - etAmount.filters = engine.amountInputFilters - - // set listeners - etAmount.setOnEditorActionListener { lv, actionId, _ -> - if (actionId == EditorInfo.IME_ACTION_DONE) { - val imm = lv.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.hideSoftInputFromWindow(lv.windowToken, 0) - lv.clearFocus() - true - } else { - false - } - } - - btnVerify.setOnClickListener { - if (!UtilHelper.isOnline(requireContext())) { - Toast.makeText(context, R.string.general_error_no_connection, Toast.LENGTH_LONG).show() - return@setOnClickListener - } - - val engine1 = CoinEngineFactory.create(ctx) - val strAmount: String = etAmount.text.toString().replace(",", ".") - val amount = engine1!!.convertToAmount(etAmount.text.toString(), tvCurrency.text.toString()) - - try { - if (!engine.checkNewTransactionAmount(amount)) - etAmount.error = getString(R.string.prepare_transaction_error_not_enough_funds) - else - etAmount.error = null - } catch (e: Exception) { - etAmount.error = getString(R.string.prepare_transaction_error_unknown_amount_format) - } - - // check wallet address - if (!engine1.validateAddress(etWallet.text.toString())) { - etWallet.error = getString(R.string.prepare_transaction_error_incorrect_destination) - return@setOnClickListener - } else - etWallet.error = null - - if (etWallet.text.toString() == ctx.coinData!!.wallet) { - etWallet.error = getString(R.string.prepare_transaction_error_same_address) - return@setOnClickListener - } - - if (!etAmount.error.isNullOrEmpty() || !etWallet.error.isNullOrEmpty()) { - return@setOnClickListener - } - - val data = Bundle() - ctx.saveToBundle(data) - data.putString(Constant.EXTRA_TARGET_ADDRESS, etWallet!!.text.toString()) - data.putBoolean(Constant.EXTRA_FEE_INCLUDED, (rgIncFee!!.checkedRadioButtonId == R.id.rbFeeIn)) - data.putString(Constant.EXTRA_AMOUNT, strAmount) - data.putString(Constant.EXTRA_AMOUNT_CURRENCY, tvCurrency.text.toString()) - navigateForResult( - Constant.REQUEST_CODE_SEND_TRANSACTION__, - R.id.action_prepareTransactionFragment_to_confirmTransactionFragment, - data) - } - - ivCamera.setOnClickListener { - if (cameraPermissionManager.isPermissionGranted()) { - navigateForResult(Constant.REQUEST_CODE_SCAN_QR, R.id.action_prepareTransactionFragment_to_qrScanFragment) - } else { - cameraPermissionManager.requirePermission() - } - } - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - cameraPermissionManager.handleRequestPermissionResult(requestCode, grantResults) { - navigateForResult(Constant.REQUEST_CODE_SCAN_QR, R.id.action_prepareTransactionFragment_to_qrScanFragment) - } - } - - override fun onNavigationResult(requestCode: String, resultCode: Int, data: Bundle?) { - if (requestCode == Constant.REQUEST_CODE_SCAN_QR && resultCode == Activity.RESULT_OK && data != null && data.containsKey("QRCode")) { - val code = data.getString("QRCode") - val schemeSplit = code!!.split(":") - when (schemeSplit.size) { - 2 -> { - if (schemeSplit[0] == ctx.blockchain.uriScheme) { - etWallet?.setText(schemeSplit[1]) - } else { - etWallet?.setText(code) - } - } - else -> { - etWallet?.setText(code) - } - } - } else if (requestCode == Constant.REQUEST_CODE_SEND_TRANSACTION__) { - navigateBackWithResult(resultCode, data) - } - } - - override fun onTagDiscovered(tag: Tag) { - try { - (activity as MainActivity).nfcManager.ignoreTag(tag) - } catch (e: IOException) { - e.printStackTrace() - } - } -} \ No newline at end of file diff --git a/app/src/tangemAccess/java/com/tangem/ui/SignTransactionFragment.kt b/app/src/tangemAccess/java/com/tangem/ui/SignTransactionFragment.kt deleted file mode 100644 index fdcdc64a72..0000000000 --- a/app/src/tangemAccess/java/com/tangem/ui/SignTransactionFragment.kt +++ /dev/null @@ -1,312 +0,0 @@ -package com.tangem.ui - -import android.app.Activity -import android.content.res.ColorStateList -import android.graphics.Color -import android.media.MediaPlayer -import android.nfc.NfcAdapter -import android.nfc.Tag -import android.nfc.tech.IsoDep -import android.os.Bundle -import android.view.View -import androidx.activity.OnBackPressedCallback -import com.google.firebase.analytics.FirebaseAnalytics -import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.tangem.App -import com.tangem.Constant -import com.tangem.tangem_card.reader.CardProtocol -import com.tangem.tangem_card.tasks.SignTask -import com.tangem.tangem_card.util.Util -import com.tangem.tangem_sdk.android.nfc.NfcDeviceAntennaLocation -import com.tangem.tangem_sdk.android.reader.NfcReader -import com.tangem.tangem_sdk.data.EXTRA_TANGEM_CARD -import com.tangem.tangem_sdk.data.EXTRA_TANGEM_CARD_UID -import com.tangem.tangem_sdk.data.asBundle -import com.tangem.ui.activity.MainActivity -import com.tangem.ui.dialog.NoExtendedLengthSupportDialog -import com.tangem.ui.dialog.WaitSecurityDelayDialog -import com.tangem.ui.fragment.BaseFragment -import com.tangem.ui.navigation.NavigationResultListener -import com.tangem.util.Analytics -import com.tangem.util.AnalyticsEvent -import com.tangem.util.LOG -import com.tangem.wallet.CoinEngine -import com.tangem.wallet.CoinEngineFactory -import com.tangem.wallet.R -import com.tangem.wallet.TangemContext -import kotlinx.android.synthetic.main.layout_progress_horizontal.* -import kotlinx.android.synthetic.main.layout_touch_card.* -import kotlinx.android.synthetic.tangemAccess.fragment_sign_transaction.* - - -class SignTransactionFragment : BaseFragment(), NavigationResultListener, - NfcAdapter.ReaderCallback, CardProtocol.Notifications { - - companion object { - val TAG: String = SignTransactionFragment::class.java.simpleName - } - - override val layoutId = R.layout.fragment_sign_transaction - - private lateinit var ctx: TangemContext - private lateinit var mpFinishSignSound: MediaPlayer - - private lateinit var nfcDeviceAntenna: NfcDeviceAntennaLocation - - private var signTransactionTask: SignTask? = null - - private lateinit var amount: CoinEngine.Amount - private lateinit var fee: CoinEngine.Amount - private var isIncludeFee = true - private var outAddressStr: String? = null - private var lastReadSuccess = true - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - ctx = TangemContext.loadFromBundle(context, arguments) - - val callback = object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - navigateBackWithResult(Activity.RESULT_CANCELED) - } - } - requireActivity().onBackPressedDispatcher.addCallback(this, callback) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - mpFinishSignSound = MediaPlayer.create(context, R.raw.scan_card_sound) - - // init NFC Antenna - nfcDeviceAntenna = NfcDeviceAntennaLocation(requireContext(), ivHandCardHorizontal, ivHandCardVertical, llHand, llNfc) - nfcDeviceAntenna.init() - - amount = CoinEngine.Amount(arguments?.getString(Constant.EXTRA_AMOUNT), arguments?.getString(Constant.EXTRA_AMOUNT_CURRENCY)) - fee = CoinEngine.Amount(arguments?.getString(Constant.EXTRA_FEE), arguments?.getString(Constant.EXTRA_FEE_CURRENCY)) - isIncludeFee = arguments?.getBoolean(Constant.EXTRA_FEE_INCLUDED, true) ?: true - outAddressStr = arguments?.getString(Constant.EXTRA_TARGET_ADDRESS) - - tvCardID.text = ctx.card!!.cidDescription - progressBar.progressTintList = ColorStateList.valueOf(Color.DKGRAY) - progressBar.visibility = View.INVISIBLE - - FirebaseAnalytics.getInstance(requireActivity()) - .logEvent(AnalyticsEvent.READY_TO_SIGN.event, Analytics.setCardData(ctx)) - } - - override fun onPause() { - signTransactionTask?.cancel(true) - super.onPause() - } - - override fun onStop() { - signTransactionTask?.cancel(true) - super.onStop() - } - - override fun onNavigationResult(requestCode: String, resultCode: Int, data: Bundle?) { - if (requestCode == Constant.REQUEST_CODE_SEND_TRANSACTION_) { - navigateBackWithResult(resultCode, data) - } - } - - override fun onTagDiscovered(tag: Tag) { - try { - // get IsoDep handle and run cardReader thread - val isoDep = IsoDep.get(tag) - val uid = tag.id - val sUID = Util.byteArrayToHexString(uid) - - if (sUID == ctx.card.uid) { - if (lastReadSuccess) - isoDep.timeout = ctx.card.pauseBeforePIN2 + 5000 - else - isoDep.timeout = ctx.card.pauseBeforePIN2 + 65000 - - val coinEngine = CoinEngineFactory.create(ctx) - coinEngine?.setOnNeedSendTransaction { tx -> - if (tx != null) { - val data = Bundle() - ctx.saveToBundle(data) - data.putByteArray(Constant.EXTRA_TX, tx) - navigateForResult( - Constant.REQUEST_CODE_SEND_TRANSACTION_, - R.id.action_signTransactionFragment_to_sendTransactionFragment, - data) - } - } - val transactionToSign = coinEngine?.constructTransaction(amount, fee, isIncludeFee, outAddressStr) - - signTransactionTask = SignTask(ctx.card, NfcReader((activity as MainActivity).nfcManager, isoDep), - App.localStorage, App.pinStorage, this, transactionToSign) - signTransactionTask?.start() - } else - (activity as MainActivity).nfcManager.ignoreTag(isoDep.tag) - - } catch (e: CardProtocol.TangemException_WrongAmount) { - try { - val data = Bundle() - data.putString(Constant.EXTRA_MESSAGE, getString(R.string.send_transaction_error_wrong_amount)) - data.putString(EXTRA_TANGEM_CARD_UID, ctx.card.uid) - data.putBundle(EXTRA_TANGEM_CARD, ctx.card.asBundle) - navigateBackWithResult(Activity.RESULT_CANCELED, data) - } catch (e: Exception) { - e.printStackTrace() - } - } catch(e: IllegalArgumentException) { - val data = Bundle() - data.putString(Constant.EXTRA_MESSAGE, e.message) - navigateBackWithResult(Activity.RESULT_CANCELED, data, R.id.loadedWalletFragment) - } catch (e: Exception) { - e.printStackTrace() - } - } - - override fun onReadStart(cardProtocol: CardProtocol) { - rlProgressBar?.post { rlProgressBar.visibility = View.VISIBLE } - - progressBar?.post { - progressBar?.visibility = View.VISIBLE - progressBar?.progress = 5 - } - } - - override fun onReadProgress(protocol: CardProtocol, progress: Int) { - progressBar?.post { progressBar?.progress = progress } - } - - override fun onReadFinish(cardProtocol: CardProtocol?) { - signTransactionTask = null - if (cardProtocol != null) { - if (cardProtocol.error == null) { - - FirebaseAnalytics.getInstance(requireActivity()) - .logEvent(AnalyticsEvent.SIGNED.event, Analytics.setCardData(ctx)) - - rlProgressBar?.post { rlProgressBar?.visibility = View.GONE } - - progressBar?.post { - progressBar?.progress = 100 - progressBar?.progressTintList = ColorStateList.valueOf(Color.GREEN) - } - - mpFinishSignSound.start() - } else { - lastReadSuccess = false - FirebaseCrashlytics.getInstance().recordException(cardProtocol.error) - if (cardProtocol.error.javaClass == CardProtocol.TangemException_InvalidPIN::class.java) { - progressBar?.post { - progressBar?.progress = 100 - progressBar?.progressTintList = ColorStateList.valueOf(Color.RED) - } - progressBar?.postDelayed({ - try { - progressBar?.progress = 0 - progressBar?.progressTintList = ColorStateList.valueOf(Color.DKGRAY) - progressBar?.visibility = View.INVISIBLE - val data = Bundle() - data.putString(Constant.EXTRA_MESSAGE, getString(R.string.send_transaction_error_cannot_sign)) - data.putString(EXTRA_TANGEM_CARD_UID, cardProtocol.card.uid) - data.putBundle(EXTRA_TANGEM_CARD, cardProtocol.card.asBundle) - navigateBackWithResult(Constant.RESULT_INVALID_PIN_, data) - } catch (e: Exception) { - e.printStackTrace() - } - }, 500) - } else { - if (cardProtocol.error is CardProtocol.TangemException_WrongAmount) { - try { - val data = Bundle() - data.putString(Constant.EXTRA_MESSAGE, getString(R.string.send_transaction_error_wrong_amount)) - data.putString(EXTRA_TANGEM_CARD_UID, cardProtocol.card.uid) - data.putBundle(EXTRA_TANGEM_CARD, cardProtocol.card.asBundle) - navigateBackWithResult(Activity.RESULT_CANCELED, data) - } catch (e: Exception) { - e.printStackTrace() - } - } - progressBar?.post { - if (cardProtocol.error is CardProtocol.TangemException_ExtendedLengthNotSupported) { - if (!NoExtendedLengthSupportDialog.allReadyShowed) { - NoExtendedLengthSupportDialog.message = getText(R.string.dialog_the_nfc_adapter_length_apdu).toString() + "\n" + getText(R.string.dialog_the_nfc_adapter_length_apdu_advice).toString() - NoExtendedLengthSupportDialog().show(requireFragmentManager(), NoExtendedLengthSupportDialog.TAG) - } - } else { - (activity as? MainActivity)?.toastHelper?.showSingleToast( - context, getString(R.string.general_notification_scan_again) - ) - } - progressBar?.progress = 100 - progressBar?.progressTintList = ColorStateList.valueOf(Color.RED) - } - } - } - } - - rlProgressBar?.postDelayed({ - try { - rlProgressBar?.visibility = View.GONE - } catch (e: Exception) { - e.printStackTrace() - } - }, 500) - - progressBar?.postDelayed({ - try { - progressBar?.progress = 0 - progressBar?.progressTintList = ColorStateList.valueOf(Color.DKGRAY) - progressBar?.visibility = View.INVISIBLE - } catch (e: Exception) { - e.printStackTrace() - } - }, 500) - } - - override fun onReadCancel() { - signTransactionTask = null - - progressBar?.postDelayed({ - try { - progressBar?.progress = 0 - progressBar?.progressTintList = ColorStateList.valueOf(Color.DKGRAY) - progressBar?.visibility = View.INVISIBLE - } catch (e: Exception) { - e.printStackTrace() - } - }, 500) - } - -// private val waitSecurityDelayDialogNew = WaitSecurityDelayDialogNew() - - override fun onReadBeforeRequest(timeout: Int) { - LOG.i(TAG, "onReadBeforeRequest timeout $timeout") - activity?.let { WaitSecurityDelayDialog.onReadBeforeRequest(it, timeout) } - -// if (!waitSecurityDelayDialogNew.isAdded) -// waitSecurityDelayDialogNew.show(supportFragmentManager, WaitSecurityDelayDialogNew.TAG) - - -// val readBeforeRequest = ReadBeforeRequest() -// readBeforeRequest.timeout = timeout -// EventBus.getDefault().post(readBeforeRequest) - } - - override fun onReadAfterRequest() { - LOG.i(TAG, "onReadAfterRequest") - activity?.let { WaitSecurityDelayDialog.onReadAfterRequest(it) } - -// val readAfterRequest = ReadAfterRequest() -// EventBus.getDefault().post(readAfterRequest) - } - - override fun onReadWait(msec: Int) { - LOG.i(TAG, "onReadWait msec $msec") - activity?.let { WaitSecurityDelayDialog.onReadWait(it, msec) } - -// val readWait = ReadWait() -// readWait.msec = msec -// EventBus.getDefault().post(readWait) - } - -} \ No newline at end of file diff --git a/app/src/tangemAccess/res/layout/fragment_confirm_transaction.xml b/app/src/tangemAccess/res/layout/fragment_confirm_transaction.xml deleted file mode 100644 index 6bb5f43dda..0000000000 --- a/app/src/tangemAccess/res/layout/fragment_confirm_transaction.xml +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -