From ec4408e7121a00f5dc3a5eb43df01aa0c4458c44 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov <80246944+fedorov-d@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:59:17 +0400 Subject: [PATCH 1/4] IOS-7349 Send input token and public key in estimate gas and enter/exit requests --- .../CommonWalletModelsFactory.swift | 20 ++- .../Mocks/Staking/YieldInfo+Mock.swift | 2 +- TangemApp.xcodeproj/project.pbxproj | 24 +++- .../Models/AdditionalAddresses.swift | 13 ++ TangemStaking/Models/StakingAction.swift | 27 ++++ .../Models/StakingActionRequestParams.swift | 34 ++++++ TangemStaking/Models/StakingBalanceInfo.swift | 4 +- TangemStaking/Models/StakingToken.swift | 31 +++++ TangemStaking/Models/StakingTokenItem.swift | 4 +- TangemStaking/Models/StakingWallet.swift | 4 +- TangemStaking/Models/YieldInfo.swift | 4 +- .../StakeKitMapper/StakeKitMapper.swift | 21 +++- .../CommonStakingAPIProvider.swift | 108 +++++++++++----- .../StakingAPIProvider.swift | 16 +-- .../DTOs/StakeKitDTO+Actions.swift | 27 ++-- .../StakingAPIService/DTOs/StakeKitDTO.swift | 40 +++++- .../StakingManager/CommonStakingManager.swift | 115 ++++++++++++------ .../StakingManager/StakingManager.swift | 18 --- 18 files changed, 375 insertions(+), 137 deletions(-) create mode 100644 TangemStaking/Models/AdditionalAddresses.swift create mode 100644 TangemStaking/Models/StakingAction.swift create mode 100644 TangemStaking/Models/StakingActionRequestParams.swift create mode 100644 TangemStaking/Models/StakingToken.swift diff --git a/Tangem/App/Factories/WalletModels/CommonWalletModelsFactory.swift b/Tangem/App/Factories/WalletModels/CommonWalletModelsFactory.swift index 0240b2965b..ffe8ea68d4 100644 --- a/Tangem/App/Factories/WalletModels/CommonWalletModelsFactory.swift +++ b/Tangem/App/Factories/WalletModels/CommonWalletModelsFactory.swift @@ -64,13 +64,17 @@ struct CommonWalletModelsFactory { ) } - func makeStakingManager(tokenItem: TokenItem, address: String) -> StakingManager? { + func makeStakingManager(publicKey: Data, tokenItem: TokenItem, address: String) -> StakingManager? { guard let integrationId = StakingFeatureProvider().yieldId(for: tokenItem), let item = tokenItem.stakingTokenItem else { return nil } - let wallet = StakingWallet(item: item, address: address) + let wallet = StakingWallet( + item: item, + address: address, + publicKey: publicKey + ) return StakingDependenciesFactory().makeStakingManager(integrationId: integrationId, wallet: wallet) } } @@ -98,7 +102,11 @@ extension CommonWalletModelsFactory: WalletModelsFactory { let shouldPerformHealthCheck = shouldPerformHealthCheck(blockchain: currentBlockchain, amountType: .coin) let mainCoinModel = WalletModel( walletManager: walletManager, - stakingManager: makeStakingManager(tokenItem: tokenItem, address: walletManager.wallet.address), + stakingManager: makeStakingManager( + publicKey: walletManager.wallet.publicKey.blockchainKey, + tokenItem: tokenItem, + address: walletManager.wallet.address + ), transactionHistoryService: transactionHistoryService, amountType: .coin, shouldPerformHealthCheck: shouldPerformHealthCheck, @@ -119,7 +127,11 @@ extension CommonWalletModelsFactory: WalletModelsFactory { let shouldPerformHealthCheck = shouldPerformHealthCheck(blockchain: currentBlockchain, amountType: amountType) let tokenModel = WalletModel( walletManager: walletManager, - stakingManager: makeStakingManager(tokenItem: tokenItem, address: walletManager.wallet.address), + stakingManager: makeStakingManager( + publicKey: walletManager.wallet.publicKey.blockchainKey, + tokenItem: tokenItem, + address: walletManager.wallet.address + ), transactionHistoryService: transactionHistoryService, amountType: amountType, shouldPerformHealthCheck: shouldPerformHealthCheck, diff --git a/Tangem/Preview Content/Mocks/Staking/YieldInfo+Mock.swift b/Tangem/Preview Content/Mocks/Staking/YieldInfo+Mock.swift index 47113cc993..d3495208d9 100644 --- a/Tangem/Preview Content/Mocks/Staking/YieldInfo+Mock.swift +++ b/Tangem/Preview Content/Mocks/Staking/YieldInfo+Mock.swift @@ -33,7 +33,7 @@ extension YieldInfo { ), ], defaultValidator: nil, - item: .init(network: .tron, contractAddress: nil), + item: .init(network: .tron, contractAddress: nil, name: "", decimals: 0, symbol: ""), unbondingPeriod: .days(14), warmupPeriod: .days(0), rewardClaimingType: .manual, diff --git a/TangemApp.xcodeproj/project.pbxproj b/TangemApp.xcodeproj/project.pbxproj index b2d96b47d0..41ac161dfb 100644 --- a/TangemApp.xcodeproj/project.pbxproj +++ b/TangemApp.xcodeproj/project.pbxproj @@ -11,6 +11,10 @@ 0A0DB7582C48FB0000003450 /* RewardRateValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A0DB7572C48FAFF00003450 /* RewardRateValues.swift */; }; 0A0E01772C64AA79009E01F2 /* StakingSendAmountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A0E01762C64AA79009E01F2 /* StakingSendAmountValidator.swift */; }; 0A1992A62B5FBDF800344312 /* CurrencyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A1992A52B5FBDF800344312 /* CurrencyTests.swift */; }; + 0A3BF9692C6CDAD900163492 /* AdditionalAddresses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3BF9682C6CDAD900163492 /* AdditionalAddresses.swift */; }; + 0A3BF96B2C6CE96B00163492 /* StakingAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3BF96A2C6CE96B00163492 /* StakingAction.swift */; }; + 0A3BF96D2C6DD9DA00163492 /* StakingTokenItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3BF96C2C6DD9DA00163492 /* StakingTokenItem.swift */; }; + 0A3BF96F2C6DDB9000163492 /* StakingActionRequestParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3BF96E2C6DDB9000163492 /* StakingActionRequestParams.swift */; }; 0A81B3732BB2D24A0008F21C /* BlockchainURLSchemesParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A81B3722BB2D24A0008F21C /* BlockchainURLSchemesParser.swift */; }; 0A81B38E2BB3018E0008F21C /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 0A81B38D2BB3018E0008F21C /* ZIPFoundation */; }; 0AB5A4732C5267CB00491764 /* SegmentedPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB5A4722C5267CB00491764 /* SegmentedPicker.swift */; }; @@ -1490,7 +1494,7 @@ EF729B722AF3E86300D80205 /* ExpressProvidersSelectorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF729B6D2AF3E86300D80205 /* ExpressProvidersSelectorViewModel.swift */; }; EF729B732AF3E86300D80205 /* ExpressProvidersSelectorRoutable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF729B6E2AF3E86300D80205 /* ExpressProvidersSelectorRoutable.swift */; }; EF729B772AF3E95F00D80205 /* ProviderRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF729B762AF3E95F00D80205 /* ProviderRowView.swift */; }; - EF72DC062C467001003DD97F /* StakingTokenItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF72DC042C467001003DD97F /* StakingTokenItem.swift */; }; + EF72DC062C467001003DD97F /* StakingToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF72DC042C467001003DD97F /* StakingToken.swift */; }; EF72DC1D2C4670D9003DD97F /* TransactionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF72DC1C2C4670D9003DD97F /* TransactionType.swift */; }; EF72DC1F2C4670E6003DD97F /* TransactionStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF72DC1E2C4670E6003DD97F /* TransactionStatus.swift */; }; EF74F50D289BF5AE001034D2 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF74F50B289BF5AE001034D2 /* Fonts.swift */; }; @@ -1886,6 +1890,10 @@ 0A0E01762C64AA79009E01F2 /* StakingSendAmountValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingSendAmountValidator.swift; sourceTree = ""; }; 0A1992A52B5FBDF800344312 /* CurrencyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurrencyTests.swift; sourceTree = ""; }; 0A35044D2E5DF9354751E2DE /* Pods-TangemStakingTests.release(alpha).xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TangemStakingTests.release(alpha).xcconfig"; path = "Target Support Files/Pods-TangemStakingTests/Pods-TangemStakingTests.release(alpha).xcconfig"; sourceTree = ""; }; + 0A3BF9682C6CDAD900163492 /* AdditionalAddresses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalAddresses.swift; sourceTree = ""; }; + 0A3BF96A2C6CE96B00163492 /* StakingAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingAction.swift; sourceTree = ""; }; + 0A3BF96C2C6DD9DA00163492 /* StakingTokenItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingTokenItem.swift; sourceTree = ""; }; + 0A3BF96E2C6DDB9000163492 /* StakingActionRequestParams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingActionRequestParams.swift; sourceTree = ""; }; 0A81B3722BB2D24A0008F21C /* BlockchainURLSchemesParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockchainURLSchemesParser.swift; sourceTree = ""; }; 0AB5A4722C5267CB00491764 /* SegmentedPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedPicker.swift; sourceTree = ""; }; 0BE949936543D22F51E09DBD /* Pods-Tangem-TangemUITests.release(alpha).xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tangem-TangemUITests.release(alpha).xcconfig"; path = "Target Support Files/Pods-Tangem-TangemUITests/Pods-Tangem-TangemUITests.release(alpha).xcconfig"; sourceTree = ""; }; @@ -3466,7 +3474,7 @@ EF729B6D2AF3E86300D80205 /* ExpressProvidersSelectorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpressProvidersSelectorViewModel.swift; sourceTree = ""; }; EF729B6E2AF3E86300D80205 /* ExpressProvidersSelectorRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpressProvidersSelectorRoutable.swift; sourceTree = ""; }; EF729B762AF3E95F00D80205 /* ProviderRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderRowView.swift; sourceTree = ""; }; - EF72DC042C467001003DD97F /* StakingTokenItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StakingTokenItem.swift; sourceTree = ""; }; + EF72DC042C467001003DD97F /* StakingToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StakingToken.swift; sourceTree = ""; }; EF72DC1C2C4670D9003DD97F /* TransactionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionType.swift; sourceTree = ""; }; EF72DC1E2C4670E6003DD97F /* TransactionStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionStatus.swift; sourceTree = ""; }; EF74D6A62BA8A8A0000550F3 /* Publisher+ThrowingAsyncMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Publisher+ThrowingAsyncMap.swift"; sourceTree = ""; }; @@ -9481,7 +9489,8 @@ EFB019442C417143009EE857 /* StakingTransactionInfo.swift */, EFB019482C4174D1009EE857 /* EnterAction.swift */, EF0FBB862C53FFAE0095A6BD /* ExitAction.swift */, - EF72DC042C467001003DD97F /* StakingTokenItem.swift */, + EF72DC042C467001003DD97F /* StakingToken.swift */, + 0A3BF96C2C6DD9DA00163492 /* StakingTokenItem.swift */, EFBC5C6E2C00A74100B662E0 /* StakingWallet.swift */, EF72DC1C2C4670D9003DD97F /* TransactionType.swift */, EF72DC1E2C4670E6003DD97F /* TransactionStatus.swift */, @@ -9489,6 +9498,9 @@ 0A0DB7572C48FAFF00003450 /* RewardRateValues.swift */, EF0FBB882C53FFC10095A6BD /* ActionTransaction.swift */, EF0FBB8A2C53FFCD0095A6BD /* ActionStatus.swift */, + 0A3BF9682C6CDAD900163492 /* AdditionalAddresses.swift */, + 0A3BF96A2C6CE96B00163492 /* StakingAction.swift */, + 0A3BF96E2C6DDB9000163492 /* StakingActionRequestParams.swift */, ); path = Models; sourceTree = ""; @@ -12364,6 +12376,7 @@ EFB019472C4172D6009EE857 /* StakeKitDTO+NetworkType.swift in Sources */, EF407E5D2C04D64B00366733 /* StakingAPIProvider.swift in Sources */, EFBC5C732C00A74100B662E0 /* YieldInfo.swift in Sources */, + 0A3BF9692C6CDAD900163492 /* AdditionalAddresses.swift in Sources */, EFBC5C752C00A74100B662E0 /* StakingAPIService.swift in Sources */, EFBC5C902C00B8B800B662E0 /* StakeKitDTO+Yield.swift in Sources */, EF407E382C04B09A00366733 /* Logger.swift in Sources */, @@ -12379,10 +12392,12 @@ DC592B8A2C419F50005AB9A7 /* StakingPendingHashesRepository.swift in Sources */, EF0FBB872C53FFAE0095A6BD /* ExitAction.swift in Sources */, EF407E662C04D75100366733 /* StakeKitDTO+Actions.swift in Sources */, - EF72DC062C467001003DD97F /* StakingTokenItem.swift in Sources */, + EF72DC062C467001003DD97F /* StakingToken.swift in Sources */, EF031A282C08E65A001535C9 /* StakingCalculator.swift in Sources */, EF8DBCDD2C060A03009072CF /* StakingManager.swift in Sources */, + 0A3BF96F2C6DDB9000163492 /* StakingActionRequestParams.swift in Sources */, EFBC5C792C00A79E00B662E0 /* StakeKitStakingAPIService.swift in Sources */, + 0A3BF96B2C6CE96B00163492 /* StakingAction.swift in Sources */, EFB019492C4174D1009EE857 /* EnterAction.swift in Sources */, EF407E5F2C04D65B00366733 /* CommonStakingAPIProvider.swift in Sources */, EFB019432C41710F009EE857 /* StakingBalanceInfo.swift in Sources */, @@ -12397,6 +12412,7 @@ 0A0DB7582C48FB0000003450 /* RewardRateValues.swift in Sources */, EF72DC1D2C4670D9003DD97F /* TransactionType.swift in Sources */, EF407E622C04D67400366733 /* StakeKitMapper.swift in Sources */, + 0A3BF96D2C6DD9DA00163492 /* StakingTokenItem.swift in Sources */, EF0FBB892C53FFC10095A6BD /* ActionTransaction.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/TangemStaking/Models/AdditionalAddresses.swift b/TangemStaking/Models/AdditionalAddresses.swift new file mode 100644 index 0000000000..8dc8bfb41b --- /dev/null +++ b/TangemStaking/Models/AdditionalAddresses.swift @@ -0,0 +1,13 @@ +// +// AdditionalAddresses.swift +// TangemStaking +// +// Created by Dmitry Fedorov on 14.08.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation + +public struct AdditionalAddresses { + let cosmosPubKey: String? +} diff --git a/TangemStaking/Models/StakingAction.swift b/TangemStaking/Models/StakingAction.swift new file mode 100644 index 0000000000..a7b5474ded --- /dev/null +++ b/TangemStaking/Models/StakingAction.swift @@ -0,0 +1,27 @@ +// +// StakingAction.swift +// TangemStaking +// +// Created by Dmitry Fedorov on 14.08.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation + +public struct StakingAction { + let amount: Decimal + let validator: String + let type: ActionType + + public init(amount: Decimal, validator: String, type: StakingAction.ActionType) { + self.amount = amount + self.validator = validator + self.type = type + } + + public enum ActionType { + case stake + case claimRewards + case unstake + } +} diff --git a/TangemStaking/Models/StakingActionRequestParams.swift b/TangemStaking/Models/StakingActionRequestParams.swift new file mode 100644 index 0000000000..6447423e9f --- /dev/null +++ b/TangemStaking/Models/StakingActionRequestParams.swift @@ -0,0 +1,34 @@ +// +// StakingActionRequestParams.swift +// TangemStaking +// +// Created by Dmitry Fedorov on 15.08.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation + +public struct StakingActionRequestParams { + let amount: Decimal + let address: String + let additionalAddresses: AdditionalAddresses? + let token: StakingToken? + let validator: String + let integrationId: String + + init( + amount: Decimal, + address: String, + additionalAddresses: AdditionalAddresses? = nil, + token: StakingToken? = nil, + validator: String, + integrationId: String + ) { + self.amount = amount + self.address = address + self.additionalAddresses = additionalAddresses + self.token = token + self.validator = validator + self.integrationId = integrationId + } +} diff --git a/TangemStaking/Models/StakingBalanceInfo.swift b/TangemStaking/Models/StakingBalanceInfo.swift index 8b1f199a0a..add1ad7ffa 100644 --- a/TangemStaking/Models/StakingBalanceInfo.swift +++ b/TangemStaking/Models/StakingBalanceInfo.swift @@ -9,7 +9,7 @@ import Foundation public struct StakingBalanceInfo: Hashable { - public let item: StakingTokenItem + public let item: StakingToken public let blocked: Decimal public let rewards: Decimal? public let balanceGroupType: BalanceGroupType @@ -17,7 +17,7 @@ public struct StakingBalanceInfo: Hashable { public let passthrough: String? public init( - item: StakingTokenItem, + item: StakingToken, blocked: Decimal, rewards: Decimal?, balanceGroupType: BalanceGroupType, diff --git a/TangemStaking/Models/StakingToken.swift b/TangemStaking/Models/StakingToken.swift new file mode 100644 index 0000000000..8a4b78cb5a --- /dev/null +++ b/TangemStaking/Models/StakingToken.swift @@ -0,0 +1,31 @@ +// +// StakingToken.swift +// TangemStaking +// +// Created by Sergey Balashov on 15.07.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation + +public struct StakingToken: Hashable { + public let network: StakeKitNetworkType + public let contractAddress: String? + public let name: String + public let decimals: Int + public let symbol: String + + public init( + network: StakeKitNetworkType, + contractAddress: String? = nil, + name: String, + decimals: Int, + symbol: String + ) { + self.network = network + self.contractAddress = contractAddress + self.name = name + self.decimals = decimals + self.symbol = symbol + } +} diff --git a/TangemStaking/Models/StakingTokenItem.swift b/TangemStaking/Models/StakingTokenItem.swift index 141f46d564..482cecbe79 100644 --- a/TangemStaking/Models/StakingTokenItem.swift +++ b/TangemStaking/Models/StakingTokenItem.swift @@ -2,7 +2,7 @@ // StakingTokenItem.swift // TangemStaking // -// Created by Sergey Balashov on 15.07.2024. +// Created by Dmitry Fedorov on 15.08.2024. // Copyright © 2024 Tangem AG. All rights reserved. // @@ -12,7 +12,7 @@ public struct StakingTokenItem: Hashable { public let network: StakeKitNetworkType public let contractAddress: String? - public init(network: StakeKitNetworkType, contractAddress: String?) { + public init(network: StakeKitNetworkType, contractAddress: String? = nil) { self.network = network self.contractAddress = contractAddress } diff --git a/TangemStaking/Models/StakingWallet.swift b/TangemStaking/Models/StakingWallet.swift index 205163f9d8..4227ced02f 100644 --- a/TangemStaking/Models/StakingWallet.swift +++ b/TangemStaking/Models/StakingWallet.swift @@ -11,9 +11,11 @@ import Foundation public struct StakingWallet: Hashable { public let item: StakingTokenItem public let address: String + public let publicKey: Data? - public init(item: StakingTokenItem, address: String) { + public init(item: StakingTokenItem, address: String, publicKey: Data? = nil) { self.item = item self.address = address + self.publicKey = publicKey } } diff --git a/TangemStaking/Models/YieldInfo.swift b/TangemStaking/Models/YieldInfo.swift index 5a110a647e..7108bb89ca 100644 --- a/TangemStaking/Models/YieldInfo.swift +++ b/TangemStaking/Models/YieldInfo.swift @@ -26,7 +26,7 @@ public struct YieldInfo: Hashable { public let defaultValidator: String? // Metadata - public let item: StakingTokenItem + public let item: StakingToken public let unbondingPeriod: Period public let warmupPeriod: Period @@ -43,7 +43,7 @@ public struct YieldInfo: Hashable { exitMinimumRequirement: Decimal, validators: [ValidatorInfo], defaultValidator: String?, - item: StakingTokenItem, + item: StakingToken, unbondingPeriod: Period, warmupPeriod: Period, rewardClaimingType: RewardClaimingType, diff --git a/TangemStaking/Services/StakeKitMapper/StakeKitMapper.swift b/TangemStaking/Services/StakeKitMapper/StakeKitMapper.swift index 6ef871e071..8b5e939f87 100644 --- a/TangemStaking/Services/StakeKitMapper/StakeKitMapper.swift +++ b/TangemStaking/Services/StakeKitMapper/StakeKitMapper.swift @@ -187,12 +187,18 @@ struct StakeKitMapper { } } - func mapToStakingTokenItem(from token: StakeKitDTO.Token) throws -> StakingTokenItem { + func mapToStakingTokenItem(from token: StakeKitDTO.Token) throws -> StakingToken { guard let network = StakeKitNetworkType(rawValue: token.network) else { throw StakeKitMapperError.noData("StakeKitNetworkType not found") } - return StakingTokenItem(network: network, contractAddress: token.address) + return StakingToken( + network: network, + contractAddress: token.address, + name: token.name, + decimals: token.decimals, + symbol: token.symbol + ) } func mapToRewardType(from rewardType: StakeKitDTO.Yield.Info.Response.RewardType) -> RewardType { @@ -252,6 +258,17 @@ struct StakeKitMapper { rewardsPendingAction(from: balance)?.passthrough } + func mapToTokenDTO(from tokenItem: StakingToken) -> StakeKitDTO.Token { + StakeKitDTO.Token( + network: tokenItem.network.rawValue, + name: tokenItem.name, + decimals: tokenItem.decimals, + address: tokenItem.contractAddress, + symbol: tokenItem.symbol, + logoURI: nil + ) + } + private func rewardsPendingAction(from balance: StakeKitDTO.Balances.Response.Balance) -> StakeKitDTO.Balances.Response.Balance.PendingAction? { guard balance.type == .rewards else { return nil diff --git a/TangemStaking/Services/StakingAPIProvider/CommonStakingAPIProvider.swift b/TangemStaking/Services/StakingAPIProvider/CommonStakingAPIProvider.swift index 3741633994..c37cac3486 100644 --- a/TangemStaking/Services/StakingAPIProvider/CommonStakingAPIProvider.swift +++ b/TangemStaking/Services/StakingAPIProvider/CommonStakingAPIProvider.swift @@ -36,16 +36,22 @@ class CommonStakingAPIProvider: StakingAPIProvider { return balancesInfo } - func estimateStakeFee( - amount: Decimal, - address: String, - validator: String, - integrationId: String - ) async throws -> Decimal { + func estimateStakeFee(params: StakingActionRequestParams) async throws -> Decimal { let request = StakeKitDTO.EstimateGas.Enter.Request( - integrationId: integrationId, - addresses: .init(address: address), - args: .init(amount: amount.description, validatorAddress: validator) + integrationId: params.integrationId, + addresses: .init( + address: params.address, + additionalAddresses: params.additionalAddresses.flatMap { + StakeKitDTO.Address.AdditionalAddresses(cosmosPubKey: $0.cosmosPubKey) + } + ), + args: .init( + amount: params.amount.description, + validatorAddress: params.validator, + inputToken: params.token.flatMap { + mapper.mapToTokenDTO(from: $0) + } + ) ) let response = try await service.estimateGasEnterAction(request: request) @@ -55,16 +61,22 @@ class CommonStakingAPIProvider: StakingAPIProvider { return result } - func estimateUnstakeFee( - amount: Decimal, - address: String, - validator: String, - integrationId: String - ) async throws -> Decimal { + func estimateUnstakeFee(params: StakingActionRequestParams) async throws -> Decimal { let request = StakeKitDTO.EstimateGas.Exit.Request( - integrationId: integrationId, - addresses: .init(address: address), - args: .init(amount: amount.description, validatorAddress: validator) + integrationId: params.integrationId, + addresses: .init( + address: params.address, + additionalAddresses: params.additionalAddresses.flatMap { + StakeKitDTO.Address.AdditionalAddresses(cosmosPubKey: $0.cosmosPubKey) + } + ), + args: .init( + amount: params.amount.description, + validatorAddress: params.validator, + inputToken: params.token.flatMap { + mapper.mapToTokenDTO(from: $0) + } + ) ) let response = try await service.estimateGasExitAction(request: request) @@ -75,18 +87,26 @@ class CommonStakingAPIProvider: StakingAPIProvider { } func estimateClaimRewardsFee( - amount: Decimal, - address: String, - validator: String, - integrationId: String, + params: StakingActionRequestParams, passthrough: String ) async throws -> Decimal { let request = StakeKitDTO.EstimateGas.Pending.Request( type: .claimRewards, - integrationId: integrationId, + integrationId: params.integrationId, passthrough: passthrough, - addresses: .init(address: address), - args: .init(amount: amount.description, validatorAddress: validator) + addresses: .init( + address: params.address, + additionalAddresses: params.additionalAddresses.flatMap { + StakeKitDTO.Address.AdditionalAddresses(cosmosPubKey: $0.cosmosPubKey) + } + ), + args: .init( + amount: params.amount.description, + validatorAddress: params.validator, + inputToken: params.token.flatMap { + mapper.mapToTokenDTO(from: $0) + } + ) ) let response = try await service.estimateGasPendingAction(request: request) @@ -96,11 +116,22 @@ class CommonStakingAPIProvider: StakingAPIProvider { return result } - func enterAction(amount: Decimal, address: String, validator: String, integrationId: String) async throws -> EnterAction { + func enterAction(params: StakingActionRequestParams) async throws -> EnterAction { let request = StakeKitDTO.Actions.Enter.Request( - integrationId: integrationId, - addresses: .init(address: address), - args: .init(amount: amount.description, validatorAddress: validator) + integrationId: params.integrationId, + addresses: .init( + address: params.address, + additionalAddresses: params.additionalAddresses.flatMap { + StakeKitDTO.Address.AdditionalAddresses(cosmosPubKey: $0.cosmosPubKey) + } + ), + args: .init( + amount: params.amount.description, + validatorAddress: params.validator, + inputToken: params.token.flatMap { + mapper.mapToTokenDTO(from: $0) + } + ) ) let response = try await service.enterAction(request: request) @@ -108,11 +139,22 @@ class CommonStakingAPIProvider: StakingAPIProvider { return enterAction } - func exitAction(amount: Decimal, address: String, validator: String, integrationId: String) async throws -> ExitAction { + func exitAction(params: StakingActionRequestParams) async throws -> ExitAction { let request = StakeKitDTO.Actions.Exit.Request( - integrationId: integrationId, - addresses: .init(address: address), - args: .init(amount: amount.description, validatorAddress: validator) + integrationId: params.integrationId, + addresses: .init( + address: params.address, + additionalAddresses: params.additionalAddresses.flatMap { + StakeKitDTO.Address.AdditionalAddresses(cosmosPubKey: $0.cosmosPubKey) + } + ), + args: .init( + amount: params.amount.description, + validatorAddress: params.validator, + inputToken: params.token.flatMap { + mapper.mapToTokenDTO(from: $0) + } + ) ) let response = try await service.exitAction(request: request) diff --git a/TangemStaking/Services/StakingAPIProvider/StakingAPIProvider.swift b/TangemStaking/Services/StakingAPIProvider/StakingAPIProvider.swift index 7b0057950e..779e80f9d6 100644 --- a/TangemStaking/Services/StakingAPIProvider/StakingAPIProvider.swift +++ b/TangemStaking/Services/StakingAPIProvider/StakingAPIProvider.swift @@ -13,18 +13,12 @@ public protocol StakingAPIProvider { func yield(integrationId: String) async throws -> YieldInfo func balances(wallet: StakingWallet) async throws -> [StakingBalanceInfo] - func estimateStakeFee(amount: Decimal, address: String, validator: String, integrationId: String) async throws -> Decimal - func estimateUnstakeFee(amount: Decimal, address: String, validator: String, integrationId: String) async throws -> Decimal - func estimateClaimRewardsFee( - amount: Decimal, - address: String, - validator: String, - integrationId: String, - passthrough: String - ) async throws -> Decimal + func estimateStakeFee(params: StakingActionRequestParams) async throws -> Decimal + func estimateUnstakeFee(params: StakingActionRequestParams) async throws -> Decimal + func estimateClaimRewardsFee(params: StakingActionRequestParams, passthrough: String) async throws -> Decimal - func enterAction(amount: Decimal, address: String, validator: String, integrationId: String) async throws -> EnterAction - func exitAction(amount: Decimal, address: String, validator: String, integrationId: String) async throws -> ExitAction + func enterAction(params: StakingActionRequestParams) async throws -> EnterAction + func exitAction(params: StakingActionRequestParams) async throws -> ExitAction func pendingAction() async throws // TODO: https://tangem.atlassian.net/browse/IOS-7482 func transaction(id: String) async throws -> StakingTransactionInfo diff --git a/TangemStaking/Services/StakingAPIService/DTOs/StakeKitDTO+Actions.swift b/TangemStaking/Services/StakingAPIService/DTOs/StakeKitDTO+Actions.swift index a23a1afdb6..d165d76ec6 100644 --- a/TangemStaking/Services/StakingAPIService/DTOs/StakeKitDTO+Actions.swift +++ b/TangemStaking/Services/StakingAPIService/DTOs/StakeKitDTO+Actions.swift @@ -85,11 +85,6 @@ extension StakeKitDTO { let integrationId: String let addresses: Address let args: Args - - struct Args: Encodable { - let amount: String - let validatorAddress: String - } } struct Response: Decodable { @@ -110,11 +105,6 @@ extension StakeKitDTO { let integrationId: String let addresses: Address let args: Args - - struct Args: Encodable { - let amount: String - let validatorAddress: String? - } } struct Response: Decodable { @@ -139,16 +129,23 @@ extension StakeKitDTO { let args: Args } - struct Args: Encodable { - let amount: String - let validatorAddress: String - } - struct Response: Decodable { let amount: String? let token: Token let gasLimit: String } } + + struct Args: Encodable { + let amount: String + let validatorAddress: String + let inputToken: Token? + + init(amount: String, validatorAddress: String, inputToken: StakeKitDTO.Token? = nil) { + self.amount = amount + self.validatorAddress = validatorAddress + self.inputToken = inputToken + } + } } } diff --git a/TangemStaking/Services/StakingAPIService/DTOs/StakeKitDTO.swift b/TangemStaking/Services/StakingAPIService/DTOs/StakeKitDTO.swift index f041b118d1..982384a559 100644 --- a/TangemStaking/Services/StakingAPIService/DTOs/StakeKitDTO.swift +++ b/TangemStaking/Services/StakingAPIService/DTOs/StakeKitDTO.swift @@ -20,10 +20,10 @@ enum StakeKitDTO { struct Token: Codable { let network: String - let name: String? - let decimals: Int? + let name: String + let decimals: Int let address: String? - let symbol: String? + let symbol: String let logoURI: String? } @@ -49,6 +49,40 @@ enum StakeKitDTO { struct Address: Codable { let address: String + let additionalAddresses: AdditionalAddresses? + + init(address: String, additionalAddresses: StakeKitDTO.Address.AdditionalAddresses? = nil) { + self.address = address + self.additionalAddresses = additionalAddresses + } + + struct AdditionalAddresses: Codable { + let cosmosPubKey: String? + let binanceBeaconAddress: String? + let stakeAccounts: [String]? + let lidoStakeAccounts: [String]? + let tezosPubKey: String? + let cAddressBech: String? + let pAddressBech: String? + + init( + cosmosPubKey: String? = nil, + binanceBeaconAddress: String? = nil, + stakeAccounts: [String]? = nil, + lidoStakeAccounts: [String]? = nil, + tezosPubKey: String? = nil, + cAddressBech: String? = nil, + pAddressBech: String? = nil + ) { + self.cosmosPubKey = cosmosPubKey + self.binanceBeaconAddress = binanceBeaconAddress + self.stakeAccounts = stakeAccounts + self.lidoStakeAccounts = lidoStakeAccounts + self.tezosPubKey = tezosPubKey + self.cAddressBech = cAddressBech + self.pAddressBech = pAddressBech + } + } } struct Required: Decodable { diff --git a/TangemStaking/Services/StakingManager/CommonStakingManager.swift b/TangemStaking/Services/StakingManager/CommonStakingManager.swift index e32a3991b4..9ece69dfa5 100644 --- a/TangemStaking/Services/StakingManager/CommonStakingManager.swift +++ b/TangemStaking/Services/StakingManager/CommonStakingManager.swift @@ -8,6 +8,7 @@ import Foundation import Combine +import TangemSdk class CommonStakingManager { private let integrationId: String @@ -60,24 +61,36 @@ extension CommonStakingManager: StakingManager { switch (state, action.type) { case (.availableToStake(let yieldInfo), .stake): return try await provider.estimateStakeFee( - amount: action.amount, - address: wallet.address, - validator: action.validator, - integrationId: yieldInfo.id + params: StakingActionRequestParams( + amount: action.amount, + address: wallet.address, + additionalAddresses: additionalAddresses(), + token: yieldInfo.item, + validator: action.validator, + integrationId: yieldInfo.id + ) ) case (.staked(let staked), .stake): return try await provider.estimateStakeFee( - amount: action.amount, - address: wallet.address, - validator: action.validator, - integrationId: staked.yieldInfo.id + params: StakingActionRequestParams( + amount: action.amount, + address: wallet.address, + additionalAddresses: additionalAddresses(), + token: staked.yieldInfo.item, + validator: action.validator, + integrationId: staked.yieldInfo.id + ) ) case (.staked(let staked), .unstake): return try await provider.estimateUnstakeFee( - amount: action.amount, - address: wallet.address, - validator: action.validator, - integrationId: staked.yieldInfo.id + params: StakingActionRequestParams( + amount: action.amount, + address: wallet.address, + additionalAddresses: additionalAddresses(), + token: staked.yieldInfo.item, + validator: action.validator, + integrationId: staked.yieldInfo.id + ) ) case (.staked(let staked), .claimRewards): guard let balance = staked.balance(validator: action.validator) else { @@ -89,10 +102,14 @@ extension CommonStakingManager: StakingManager { } return try await provider.estimateClaimRewardsFee( - amount: action.amount, - address: wallet.address, - validator: action.validator, - integrationId: staked.yieldInfo.id, + params: StakingActionRequestParams( + amount: action.amount, + address: wallet.address, + additionalAddresses: additionalAddresses(), + token: staked.yieldInfo.item, + validator: action.validator, + integrationId: staked.yieldInfo.id + ), passthrough: passthrough ) default: @@ -105,15 +122,25 @@ extension CommonStakingManager: StakingManager { switch (state, action.type) { case (.availableToStake(let yieldInfo), .stake): return try await getTransactionToStake( - amount: action.amount, - validator: action.validator, - integrationId: yieldInfo.id + params: StakingActionRequestParams( + amount: action.amount, + address: wallet.address, + additionalAddresses: additionalAddresses(), + token: yieldInfo.item, + validator: action.validator, + integrationId: yieldInfo.id + ) ) case (.staked(let staked), .stake): return try await getTransactionToStake( - amount: action.amount, - validator: action.validator, - integrationId: staked.yieldInfo.id + params: StakingActionRequestParams( + amount: action.amount, + address: wallet.address, + additionalAddresses: additionalAddresses(), + token: staked.yieldInfo.item, + validator: action.validator, + integrationId: staked.yieldInfo.id + ) ) case (.staked(let staked), .unstake): guard let balance = staked.balance(validator: action.validator) else { @@ -121,9 +148,14 @@ extension CommonStakingManager: StakingManager { } return try await getTransactionToUnstake( - amount: balance.blocked, - validator: action.validator, - integrationId: staked.yieldInfo.id + params: StakingActionRequestParams( + amount: balance.blocked, + address: wallet.address, + additionalAddresses: additionalAddresses(), + token: staked.yieldInfo.item, + validator: action.validator, + integrationId: staked.yieldInfo.id + ) ) default: throw StakingManagerError.stakingManagerStateNotSupportTransactionAction(action: action) @@ -153,13 +185,8 @@ private extension CommonStakingManager { return .staked(.init(balances: balances, yieldInfo: yield, canStakeMore: canStakeMore)) } - func getTransactionToStake(amount: Decimal, validator: String, integrationId: String) async throws -> StakingTransactionInfo { - let action = try await provider.enterAction( - amount: amount, - address: wallet.address, - validator: validator, - integrationId: integrationId - ) + func getTransactionToStake(params: StakingActionRequestParams) async throws -> StakingTransactionInfo { + let action = try await provider.enterAction(params: params) guard let transactionId = action.transactions.first(where: { $0.stepIndex == action.currentStepIndex })?.id else { throw StakingManagerError.transactionNotFound @@ -173,12 +200,8 @@ private extension CommonStakingManager { return transaction } - func getTransactionToUnstake(amount: Decimal, validator: String, integrationId: String) async throws -> StakingTransactionInfo { - let action = try await provider.exitAction( - amount: amount, address: wallet.address, - validator: validator, - integrationId: integrationId - ) + func getTransactionToUnstake(params: StakingActionRequestParams) async throws -> StakingTransactionInfo { + let action = try await provider.exitAction(params: params) guard let transactionId = action.transactions.first(where: { $0.stepIndex == action.currentStepIndex })?.id else { throw StakingManagerError.transactionNotFound @@ -196,7 +219,7 @@ private extension CommonStakingManager { // MARK: - Helping private extension CommonStakingManager { - func canStakeMore(item: StakingTokenItem) -> Bool { + func canStakeMore(item: StakingToken) -> Bool { switch item.network { case .solana: return true @@ -204,6 +227,20 @@ private extension CommonStakingManager { return false } } + + func additionalAddresses() -> AdditionalAddresses? { + switch wallet.item.network { + case .cosmos: + guard let publicKey = wallet.publicKey, + let compressedPublicKey = try? Secp256k1Key(with: publicKey).compress() else { + return nil + } + + return AdditionalAddresses(cosmosPubKey: compressedPublicKey.base64EncodedString()) + default: + return nil + } + } } // MARK: - Log diff --git a/TangemStaking/Services/StakingManager/StakingManager.swift b/TangemStaking/Services/StakingManager/StakingManager.swift index a21429cdfc..27261c3e5d 100644 --- a/TangemStaking/Services/StakingManager/StakingManager.swift +++ b/TangemStaking/Services/StakingManager/StakingManager.swift @@ -18,24 +18,6 @@ public protocol StakingManager { func transaction(action: StakingAction) async throws -> StakingTransactionInfo } -public struct StakingAction { - let amount: Decimal - let validator: String - let type: ActionType - - public init(amount: Decimal, validator: String, type: StakingAction.ActionType) { - self.amount = amount - self.validator = validator - self.type = type - } - - public enum ActionType { - case stake - case claimRewards - case unstake - } -} - public enum StakingManagerState: Hashable, CustomStringConvertible { case loading case notEnabled From a9af6d3653cd19e7097360a22c180252e3138955 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov <80246944+fedorov-d@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:26:12 +0400 Subject: [PATCH 2/4] IOS-7349 Remove optional --- TangemStaking/Models/StakingWallet.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TangemStaking/Models/StakingWallet.swift b/TangemStaking/Models/StakingWallet.swift index 4227ced02f..f2a03e4040 100644 --- a/TangemStaking/Models/StakingWallet.swift +++ b/TangemStaking/Models/StakingWallet.swift @@ -11,9 +11,9 @@ import Foundation public struct StakingWallet: Hashable { public let item: StakingTokenItem public let address: String - public let publicKey: Data? + public let publicKey: Data - public init(item: StakingTokenItem, address: String, publicKey: Data? = nil) { + public init(item: StakingTokenItem, address: String, publicKey: Data) { self.item = item self.address = address self.publicKey = publicKey From 96f0f2f29eb9e6b89fc47ec880e5545d7c7b53d5 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov <80246944+fedorov-d@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:41:28 +0400 Subject: [PATCH 3/4] IOS-7349 Fix build issue --- .../Services/StakingManager/CommonStakingManager.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TangemStaking/Services/StakingManager/CommonStakingManager.swift b/TangemStaking/Services/StakingManager/CommonStakingManager.swift index 9ece69dfa5..73c7915f16 100644 --- a/TangemStaking/Services/StakingManager/CommonStakingManager.swift +++ b/TangemStaking/Services/StakingManager/CommonStakingManager.swift @@ -231,8 +231,7 @@ private extension CommonStakingManager { func additionalAddresses() -> AdditionalAddresses? { switch wallet.item.network { case .cosmos: - guard let publicKey = wallet.publicKey, - let compressedPublicKey = try? Secp256k1Key(with: publicKey).compress() else { + guard let compressedPublicKey = try? Secp256k1Key(with: wallet.publicKey).compress() else { return nil } From df19d494fb427d63c215bff4384c7bd8f092ab58 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov <80246944+fedorov-d@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:29:31 +0400 Subject: [PATCH 4/4] IOS-7349 Use single model for staking token --- .../TokenItem+StakingTokenItem.swift | 5 ++- .../StakingFeatureProvider.swift | 6 ++-- TangemApp.xcodeproj/project.pbxproj | 12 +++---- .../Models/StakingActionRequestParams.swift | 4 +-- TangemStaking/Models/StakingBalanceInfo.swift | 4 +-- TangemStaking/Models/StakingToken.swift | 31 ------------------- TangemStaking/Models/StakingTokenItem.swift | 16 ++++++++-- TangemStaking/Models/YieldInfo.swift | 4 +-- .../StakeKitMapper/StakeKitMapper.swift | 6 ++-- .../StakingManager/CommonStakingManager.swift | 2 +- 10 files changed, 35 insertions(+), 55 deletions(-) delete mode 100644 TangemStaking/Models/StakingToken.swift diff --git a/Tangem/App/Models/TokenItem/TokenItem+StakingTokenItem.swift b/Tangem/App/Models/TokenItem/TokenItem+StakingTokenItem.swift index a76f80d54f..1d26958877 100644 --- a/Tangem/App/Models/TokenItem/TokenItem+StakingTokenItem.swift +++ b/Tangem/App/Models/TokenItem/TokenItem+StakingTokenItem.swift @@ -14,7 +14,10 @@ extension TokenItem { StakeKitNetworkType(rawValue: blockchain.coinId).map { network in StakingTokenItem( network: network, - contractAddress: contractAddress + contractAddress: contractAddress, + name: name, + decimals: decimalCount, + symbol: currencySymbol ) } } diff --git a/Tangem/App/Services/EnvironmentProvider/StakingFeatureProvider.swift b/Tangem/App/Services/EnvironmentProvider/StakingFeatureProvider.swift index f3c1727bb9..dba08c44d6 100644 --- a/Tangem/App/Services/EnvironmentProvider/StakingFeatureProvider.swift +++ b/Tangem/App/Services/EnvironmentProvider/StakingFeatureProvider.swift @@ -65,9 +65,9 @@ extension StakingFeatureProvider { var testableBlockchainIds: Set { [ - StakingTokenItem(network: .solana, contractAddress: nil), - StakingTokenItem(network: .cosmos, contractAddress: nil), - StakingTokenItem(network: .ethereum, contractAddress: "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0"), + StakingTokenItem(network: .solana, contractAddress: nil, name: "Solana", decimals: 9, symbol: "SOL"), + StakingTokenItem(network: .cosmos, contractAddress: nil, name: "Cosmos", decimals: 6, symbol: "ATOM"), + StakingTokenItem(network: .ethereum, contractAddress: "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0", name: "Ethereum", decimals: 18, symbol: "ETH"), ] } diff --git a/TangemApp.xcodeproj/project.pbxproj b/TangemApp.xcodeproj/project.pbxproj index a1e869c9a5..33162df7b2 100644 --- a/TangemApp.xcodeproj/project.pbxproj +++ b/TangemApp.xcodeproj/project.pbxproj @@ -13,7 +13,6 @@ 0A1992A62B5FBDF800344312 /* CurrencyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A1992A52B5FBDF800344312 /* CurrencyTests.swift */; }; 0A3BF9692C6CDAD900163492 /* AdditionalAddresses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3BF9682C6CDAD900163492 /* AdditionalAddresses.swift */; }; 0A3BF96B2C6CE96B00163492 /* StakingAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3BF96A2C6CE96B00163492 /* StakingAction.swift */; }; - 0A3BF96D2C6DD9DA00163492 /* StakingTokenItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3BF96C2C6DD9DA00163492 /* StakingTokenItem.swift */; }; 0A3BF96F2C6DDB9000163492 /* StakingActionRequestParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3BF96E2C6DDB9000163492 /* StakingActionRequestParams.swift */; }; 0A81B3732BB2D24A0008F21C /* BlockchainURLSchemesParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A81B3722BB2D24A0008F21C /* BlockchainURLSchemesParser.swift */; }; 0A81B38E2BB3018E0008F21C /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 0A81B38D2BB3018E0008F21C /* ZIPFoundation */; }; @@ -1495,7 +1494,7 @@ EF729B722AF3E86300D80205 /* ExpressProvidersSelectorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF729B6D2AF3E86300D80205 /* ExpressProvidersSelectorViewModel.swift */; }; EF729B732AF3E86300D80205 /* ExpressProvidersSelectorRoutable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF729B6E2AF3E86300D80205 /* ExpressProvidersSelectorRoutable.swift */; }; EF729B772AF3E95F00D80205 /* ProviderRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF729B762AF3E95F00D80205 /* ProviderRowView.swift */; }; - EF72DC062C467001003DD97F /* StakingToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF72DC042C467001003DD97F /* StakingToken.swift */; }; + EF72DC062C467001003DD97F /* StakingTokenItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF72DC042C467001003DD97F /* StakingTokenItem.swift */; }; EF72DC1D2C4670D9003DD97F /* TransactionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF72DC1C2C4670D9003DD97F /* TransactionType.swift */; }; EF72DC1F2C4670E6003DD97F /* TransactionStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF72DC1E2C4670E6003DD97F /* TransactionStatus.swift */; }; EF74F50D289BF5AE001034D2 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF74F50B289BF5AE001034D2 /* Fonts.swift */; }; @@ -1893,7 +1892,6 @@ 0A35044D2E5DF9354751E2DE /* Pods-TangemStakingTests.release(alpha).xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TangemStakingTests.release(alpha).xcconfig"; path = "Target Support Files/Pods-TangemStakingTests/Pods-TangemStakingTests.release(alpha).xcconfig"; sourceTree = ""; }; 0A3BF9682C6CDAD900163492 /* AdditionalAddresses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalAddresses.swift; sourceTree = ""; }; 0A3BF96A2C6CE96B00163492 /* StakingAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingAction.swift; sourceTree = ""; }; - 0A3BF96C2C6DD9DA00163492 /* StakingTokenItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingTokenItem.swift; sourceTree = ""; }; 0A3BF96E2C6DDB9000163492 /* StakingActionRequestParams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingActionRequestParams.swift; sourceTree = ""; }; 0A81B3722BB2D24A0008F21C /* BlockchainURLSchemesParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockchainURLSchemesParser.swift; sourceTree = ""; }; 0AB5A4722C5267CB00491764 /* SegmentedPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedPicker.swift; sourceTree = ""; }; @@ -3476,7 +3474,7 @@ EF729B6D2AF3E86300D80205 /* ExpressProvidersSelectorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpressProvidersSelectorViewModel.swift; sourceTree = ""; }; EF729B6E2AF3E86300D80205 /* ExpressProvidersSelectorRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpressProvidersSelectorRoutable.swift; sourceTree = ""; }; EF729B762AF3E95F00D80205 /* ProviderRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderRowView.swift; sourceTree = ""; }; - EF72DC042C467001003DD97F /* StakingToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StakingToken.swift; sourceTree = ""; }; + EF72DC042C467001003DD97F /* StakingTokenItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StakingTokenItem.swift; sourceTree = ""; }; EF72DC1C2C4670D9003DD97F /* TransactionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionType.swift; sourceTree = ""; }; EF72DC1E2C4670E6003DD97F /* TransactionStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionStatus.swift; sourceTree = ""; }; EF74D6A62BA8A8A0000550F3 /* Publisher+ThrowingAsyncMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Publisher+ThrowingAsyncMap.swift"; sourceTree = ""; }; @@ -9500,8 +9498,7 @@ EFB019442C417143009EE857 /* StakingTransactionInfo.swift */, EFB019482C4174D1009EE857 /* EnterAction.swift */, EF0FBB862C53FFAE0095A6BD /* ExitAction.swift */, - EF72DC042C467001003DD97F /* StakingToken.swift */, - 0A3BF96C2C6DD9DA00163492 /* StakingTokenItem.swift */, + EF72DC042C467001003DD97F /* StakingTokenItem.swift */, EFBC5C6E2C00A74100B662E0 /* StakingWallet.swift */, EF72DC1C2C4670D9003DD97F /* TransactionType.swift */, EF72DC1E2C4670E6003DD97F /* TransactionStatus.swift */, @@ -12404,7 +12401,7 @@ DC592B8A2C419F50005AB9A7 /* StakingPendingHashesRepository.swift in Sources */, EF0FBB872C53FFAE0095A6BD /* ExitAction.swift in Sources */, EF407E662C04D75100366733 /* StakeKitDTO+Actions.swift in Sources */, - EF72DC062C467001003DD97F /* StakingToken.swift in Sources */, + EF72DC062C467001003DD97F /* StakingTokenItem.swift in Sources */, EF031A282C08E65A001535C9 /* StakingCalculator.swift in Sources */, EF8DBCDD2C060A03009072CF /* StakingManager.swift in Sources */, 0A3BF96F2C6DDB9000163492 /* StakingActionRequestParams.swift in Sources */, @@ -12424,7 +12421,6 @@ 0A0DB7582C48FB0000003450 /* RewardRateValues.swift in Sources */, EF72DC1D2C4670D9003DD97F /* TransactionType.swift in Sources */, EF407E622C04D67400366733 /* StakeKitMapper.swift in Sources */, - 0A3BF96D2C6DD9DA00163492 /* StakingTokenItem.swift in Sources */, EF0FBB892C53FFC10095A6BD /* ActionTransaction.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/TangemStaking/Models/StakingActionRequestParams.swift b/TangemStaking/Models/StakingActionRequestParams.swift index 6447423e9f..a0f1a166c1 100644 --- a/TangemStaking/Models/StakingActionRequestParams.swift +++ b/TangemStaking/Models/StakingActionRequestParams.swift @@ -12,7 +12,7 @@ public struct StakingActionRequestParams { let amount: Decimal let address: String let additionalAddresses: AdditionalAddresses? - let token: StakingToken? + let token: StakingTokenItem? let validator: String let integrationId: String @@ -20,7 +20,7 @@ public struct StakingActionRequestParams { amount: Decimal, address: String, additionalAddresses: AdditionalAddresses? = nil, - token: StakingToken? = nil, + token: StakingTokenItem? = nil, validator: String, integrationId: String ) { diff --git a/TangemStaking/Models/StakingBalanceInfo.swift b/TangemStaking/Models/StakingBalanceInfo.swift index add1ad7ffa..8b1f199a0a 100644 --- a/TangemStaking/Models/StakingBalanceInfo.swift +++ b/TangemStaking/Models/StakingBalanceInfo.swift @@ -9,7 +9,7 @@ import Foundation public struct StakingBalanceInfo: Hashable { - public let item: StakingToken + public let item: StakingTokenItem public let blocked: Decimal public let rewards: Decimal? public let balanceGroupType: BalanceGroupType @@ -17,7 +17,7 @@ public struct StakingBalanceInfo: Hashable { public let passthrough: String? public init( - item: StakingToken, + item: StakingTokenItem, blocked: Decimal, rewards: Decimal?, balanceGroupType: BalanceGroupType, diff --git a/TangemStaking/Models/StakingToken.swift b/TangemStaking/Models/StakingToken.swift deleted file mode 100644 index 8a4b78cb5a..0000000000 --- a/TangemStaking/Models/StakingToken.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// StakingToken.swift -// TangemStaking -// -// Created by Sergey Balashov on 15.07.2024. -// Copyright © 2024 Tangem AG. All rights reserved. -// - -import Foundation - -public struct StakingToken: Hashable { - public let network: StakeKitNetworkType - public let contractAddress: String? - public let name: String - public let decimals: Int - public let symbol: String - - public init( - network: StakeKitNetworkType, - contractAddress: String? = nil, - name: String, - decimals: Int, - symbol: String - ) { - self.network = network - self.contractAddress = contractAddress - self.name = name - self.decimals = decimals - self.symbol = symbol - } -} diff --git a/TangemStaking/Models/StakingTokenItem.swift b/TangemStaking/Models/StakingTokenItem.swift index 482cecbe79..01c07afce7 100644 --- a/TangemStaking/Models/StakingTokenItem.swift +++ b/TangemStaking/Models/StakingTokenItem.swift @@ -2,7 +2,7 @@ // StakingTokenItem.swift // TangemStaking // -// Created by Dmitry Fedorov on 15.08.2024. +// Created by Sergey Balashov on 15.07.2024. // Copyright © 2024 Tangem AG. All rights reserved. // @@ -11,9 +11,21 @@ import Foundation public struct StakingTokenItem: Hashable { public let network: StakeKitNetworkType public let contractAddress: String? + public let name: String + public let decimals: Int + public let symbol: String - public init(network: StakeKitNetworkType, contractAddress: String? = nil) { + public init( + network: StakeKitNetworkType, + contractAddress: String? = nil, + name: String, + decimals: Int, + symbol: String + ) { self.network = network self.contractAddress = contractAddress + self.name = name + self.decimals = decimals + self.symbol = symbol } } diff --git a/TangemStaking/Models/YieldInfo.swift b/TangemStaking/Models/YieldInfo.swift index 7108bb89ca..5a110a647e 100644 --- a/TangemStaking/Models/YieldInfo.swift +++ b/TangemStaking/Models/YieldInfo.swift @@ -26,7 +26,7 @@ public struct YieldInfo: Hashable { public let defaultValidator: String? // Metadata - public let item: StakingToken + public let item: StakingTokenItem public let unbondingPeriod: Period public let warmupPeriod: Period @@ -43,7 +43,7 @@ public struct YieldInfo: Hashable { exitMinimumRequirement: Decimal, validators: [ValidatorInfo], defaultValidator: String?, - item: StakingToken, + item: StakingTokenItem, unbondingPeriod: Period, warmupPeriod: Period, rewardClaimingType: RewardClaimingType, diff --git a/TangemStaking/Services/StakeKitMapper/StakeKitMapper.swift b/TangemStaking/Services/StakeKitMapper/StakeKitMapper.swift index 8b5e939f87..7923606d76 100644 --- a/TangemStaking/Services/StakeKitMapper/StakeKitMapper.swift +++ b/TangemStaking/Services/StakeKitMapper/StakeKitMapper.swift @@ -187,12 +187,12 @@ struct StakeKitMapper { } } - func mapToStakingTokenItem(from token: StakeKitDTO.Token) throws -> StakingToken { + func mapToStakingTokenItem(from token: StakeKitDTO.Token) throws -> StakingTokenItem { guard let network = StakeKitNetworkType(rawValue: token.network) else { throw StakeKitMapperError.noData("StakeKitNetworkType not found") } - return StakingToken( + return StakingTokenItem( network: network, contractAddress: token.address, name: token.name, @@ -258,7 +258,7 @@ struct StakeKitMapper { rewardsPendingAction(from: balance)?.passthrough } - func mapToTokenDTO(from tokenItem: StakingToken) -> StakeKitDTO.Token { + func mapToTokenDTO(from tokenItem: StakingTokenItem) -> StakeKitDTO.Token { StakeKitDTO.Token( network: tokenItem.network.rawValue, name: tokenItem.name, diff --git a/TangemStaking/Services/StakingManager/CommonStakingManager.swift b/TangemStaking/Services/StakingManager/CommonStakingManager.swift index 73c7915f16..8e8c5cfe78 100644 --- a/TangemStaking/Services/StakingManager/CommonStakingManager.swift +++ b/TangemStaking/Services/StakingManager/CommonStakingManager.swift @@ -219,7 +219,7 @@ private extension CommonStakingManager { // MARK: - Helping private extension CommonStakingManager { - func canStakeMore(item: StakingToken) -> Bool { + func canStakeMore(item: StakingTokenItem) -> Bool { switch item.network { case .solana: return true