Skip to content

Commit

Permalink
Merge pull request #965 from novasamatech/develop
Browse files Browse the repository at this point in the history
v7.7.4
  • Loading branch information
ERussel committed Feb 5, 2024
2 parents 7f67964 + e69d4a0 commit 9223284
Show file tree
Hide file tree
Showing 21 changed files with 469 additions and 82 deletions.
4 changes: 4 additions & 0 deletions novawallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@
0CCA245D2AC6918800AEF23D /* XcmV3Junction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA245C2AC6918800AEF23D /* XcmV3Junction.swift */; };
0CCA245F2AC6974200AEF23D /* XcmV3Multilocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA245E2AC6974200AEF23D /* XcmV3Multilocation.swift */; };
0CCA24652AC6B51200AEF23D /* AssetHubSwapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA24642AC6B51200AEF23D /* AssetHubSwapTests.swift */; };
0CCCDF742B62AA3400473D42 /* ParaStkPreferredCollatorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCCDF732B62AA3400473D42 /* ParaStkPreferredCollatorFactory.swift */; };
0CCE25212A44306200286709 /* TransactionHistoryPhishingFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCE25202A44306200286709 /* TransactionHistoryPhishingFilter.swift */; };
0CD1F4D100ED82D137AB9834 /* ParaStkStakeSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2F1EEBF48485F02BF690A4 /* ParaStkStakeSetupViewController.swift */; };
0CD352932ACAD7A500B3E446 /* AssetHubExtrinsicService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD352922ACAD7A500B3E446 /* AssetHubExtrinsicService.swift */; };
Expand Down Expand Up @@ -4591,6 +4592,7 @@
0CCA245C2AC6918800AEF23D /* XcmV3Junction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcmV3Junction.swift; sourceTree = "<group>"; };
0CCA245E2AC6974200AEF23D /* XcmV3Multilocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcmV3Multilocation.swift; sourceTree = "<group>"; };
0CCA24642AC6B51200AEF23D /* AssetHubSwapTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetHubSwapTests.swift; sourceTree = "<group>"; };
0CCCDF732B62AA3400473D42 /* ParaStkPreferredCollatorFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParaStkPreferredCollatorFactory.swift; sourceTree = "<group>"; };
0CCE25202A44306200286709 /* TransactionHistoryPhishingFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionHistoryPhishingFilter.swift; sourceTree = "<group>"; };
0CD352922ACAD7A500B3E446 /* AssetHubExtrinsicService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetHubExtrinsicService.swift; sourceTree = "<group>"; };
0CD352942ACAF59900B3E446 /* BigRational.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigRational.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -16204,6 +16206,7 @@
841E5558282E6A7700C8438F /* ParaStkDurationOperationFactory.swift */,
84C3420628314D9600156569 /* ParaStkScheduledRequestsQueryFactory.swift */,
84C11F162840BD46007F7C05 /* ParaStkCollatorsOperationFactory.swift */,
0CCCDF732B62AA3400473D42 /* ParaStkPreferredCollatorFactory.swift */,
);
path = ParachainStaking;
sourceTree = "<group>";
Expand Down Expand Up @@ -22833,6 +22836,7 @@
8493D0E326FF571D00A28008 /* PriceProviderFactory.swift in Sources */,
8858917629A4BC7D00320896 /* VotesContentView.swift in Sources */,
F7EB8F835CFA7FC949EF4C22 /* YourValidatorListWireframe.swift in Sources */,
0CCCDF742B62AA3400473D42 /* ParaStkPreferredCollatorFactory.swift in Sources */,
AEA0C8AC267B6B5200F9666F /* SelectedValidatorListViewFactory.swift in Sources */,
84ED6BE428698D2E00B3C558 /* TransferCrossChainConfirmInteractor.swift in Sources */,
DBA436B3B1C90965FE8F9B79 /* YourValidatorListPresenter.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions novawallet/Common/Configs/ApplicationConfigs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,12 @@ extension ApplicationConfig: ApplicationConfigProtocol {

var paritySignerTroubleshoutingURL: URL {
// swiftlint:disable:next line_length
URL(string: "https://docs.novawallet.io/nova-wallet-wiki/welcome-to-nova-wallet/hardware-wallets/parity-signer/troubleshooting")!
URL(string: "https://docs.novawallet.io/nova-wallet-wiki/wallet-management/hardware-wallets/parity-signer/troubleshooting")!
}

var polkadotVaultTroubleshoutingURL: URL {
// swiftlint:disable:next line_length
URL(string: "https://docs.novawallet.io/nova-wallet-wiki/welcome-to-nova-wallet/hardware-wallets/polkadot-vault/troubleshooting")!
URL(string: "https://docs.novawallet.io/nova-wallet-wiki/wallet-management/hardware-wallets/polkadot-vault/troubleshooting")!
}

var ledgerGuideURL: URL {
Expand Down
27 changes: 27 additions & 0 deletions novawallet/Common/Helpers/CancellableCallHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,30 @@ func execute<T>(

operationQueue.addOperations([operation], waitUntilFinished: false)
}

func execute<T>(
operation: BaseOperation<T>,
inOperationQueue operationQueue: OperationQueue,
backingCallIn callStore: CancellableCallStore,
runningCallbackIn callbackQueue: DispatchQueue?,
callbackClosure: @escaping (Result<T, Error>) -> Void
) {
operation.completionBlock = {
dispatchInQueueWhenPossible(callbackQueue) {
guard callStore.clearIfMatches(call: operation) else {
return
}

do {
let value = try operation.extractNoCancellableResultData()
callbackClosure(.success(value))
} catch {
callbackClosure(.failure(error))
}
}
}

callStore.store(call: operation)

operationQueue.addOperations([operation], waitUntilFinished: false)
}
1 change: 1 addition & 0 deletions novawallet/Common/Model/KnownChainIds.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum KnowChainId {
static let rococo = "a84b46a3e602245284bb9a72c4abd58ee979aa7a5d7f8c4dfdddfaaf0665a4ae"
static let westend = "e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e"
static let westmint = "67f9723393ef76214df0118c34bbbd3dbebc8ed46a10973a8c969d48fe7598c9"
static let polimec = "7eb9354488318e7549c722669dcbdcdc526f1fef1420e7944667212f3601fdbd"

static var kiltOnEnviroment: String {
#if F_DEV
Expand Down
11 changes: 5 additions & 6 deletions novawallet/Common/Model/Xcm/XcmFeeModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ protocol XcmFeeModelProtocol {
var weightLimit: BigUInt { get }
}

extension XcmFeeModelProtocol {
var total: BigUInt {
senderPart + holdingPart
}
}

struct XcmFeeModel: XcmFeeModelProtocol {
// fee paid in native token in the origin chain
let senderPart: BigUInt

// total fee paid in sending token in reserve and destination chains
let holdingPart: BigUInt

// limit of the xcm
let weightLimit: BigUInt
}

Expand Down
3 changes: 2 additions & 1 deletion novawallet/Modules/Staking/Model/StakingConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ struct StakingConstants {
"DhK6qU2U5kDWeJKvPRtmnWRs8ETUGZ9S9QmNmQFuzrNoKm4",
"EtETk1FbrDg7FoAfkREuXT7xHxCjbEf28sBvWf6zfB5wFyV"
],
KnowChainId.alephZero: ["5DBhSX89qijHkzUt9gcqsq9RiXxDfbjxyma1z78JSCdt4SoU"]
KnowChainId.alephZero: ["5DBhSX89qijHkzUt9gcqsq9RiXxDfbjxyma1z78JSCdt4SoU"],
KnowChainId.polimec: ["5A5Qgq3wn6JeH8Qtu7rakxULpBhtyqyX8iNj1XV8WFg3U58T"]
]

static func preferredValidatorIds(for chain: ChainModel) -> [AccountId] {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import Foundation
import SubstrateSdk
import RobinHood

protocol ParaStkPreferredCollatorFactoryProtocol {
func createPreferredCollatorWrapper() -> CompoundOperationWrapper<DisplayAddress?>
}

final class ParaStkPreferredCollatorFactory {
let chain: ChainModel
let connection: JSONRPCEngine
let runtimeService: RuntimeCodingServiceProtocol
let identityOperationFactory: IdentityOperationFactoryProtocol
let collatorService: ParachainStakingCollatorServiceProtocol
let rewardService: ParaStakingRewardCalculatorServiceProtocol
let operationQueue: OperationQueue

init(
chain: ChainModel,
connection: JSONRPCEngine,
runtimeService: RuntimeCodingServiceProtocol,
collatorService: ParachainStakingCollatorServiceProtocol,
rewardService: ParaStakingRewardCalculatorServiceProtocol,
identityOperationFactory: IdentityOperationFactoryProtocol,
operationQueue: OperationQueue
) {
self.chain = chain
self.connection = connection
self.runtimeService = runtimeService
self.rewardService = rewardService
self.collatorService = collatorService
self.identityOperationFactory = identityOperationFactory
self.operationQueue = operationQueue
}

private func createResultWrapper(
dependingOn mergeOperation: BaseOperation<AccountId?>
) -> CompoundOperationWrapper<DisplayAddress?> {
OperationCombiningService<DisplayAddress?>.compoundNonOptionalWrapper(
operationManager: OperationManager(operationQueue: operationQueue)
) {
let optAccountId = try mergeOperation.extractNoCancellableResultData()

guard let accountId = optAccountId else {
return CompoundOperationWrapper.createWithResult(nil)
}

let identityWrapper = self.identityOperationFactory.createIdentityWrapper(
for: { [accountId] },
engine: self.connection,
runtimeService: self.runtimeService,
chainFormat: self.chain.chainFormat
)

let mappingOperation = ClosureOperation<DisplayAddress?> {
let identities = try identityWrapper.targetOperation.extractNoCancellableResultData()
let address = try accountId.toAddress(using: self.chain.chainFormat)
let name = identities[address]?.displayName

return DisplayAddress(address: address, username: name ?? "")
}

mappingOperation.addDependency(identityWrapper.targetOperation)

return CompoundOperationWrapper(
targetOperation: mappingOperation,
dependencies: identityWrapper.allOperations
)
}
}
}

extension ParaStkPreferredCollatorFactory: ParaStkPreferredCollatorFactoryProtocol {
func createPreferredCollatorWrapper() -> CompoundOperationWrapper<DisplayAddress?> {
let preferredCollators = StakingConstants.preferredValidatorIds(for: chain)

guard !preferredCollators.isEmpty else {
return CompoundOperationWrapper.createWithResult(nil)
}

let collatorsSet = Set(preferredCollators)

let collatorsOperation = collatorService.fetchInfoOperation()
let rewardOperation = rewardService.fetchCalculatorOperation()

let mergeOperation = ClosureOperation<AccountId?> {
let collators = try collatorsOperation.extractNoCancellableResultData().collators
let rewardsCalculator = try rewardOperation.extractNoCancellableResultData()

let optCollator = collators
.filter { collatorsSet.contains($0.accountId) }
.sorted { col1, col2 in
let optApr1 = try? rewardsCalculator.calculateAPR(for: col1.accountId)
let optApr2 = try? rewardsCalculator.calculateAPR(for: col2.accountId)

if let apr1 = optApr1, let apr2 = optApr2 {
return apr1 > apr2
} else if optApr1 != nil {
return true
} else {
return false
}
}
.first

return optCollator?.accountId
}

mergeOperation.addDependency(collatorsOperation)
mergeOperation.addDependency(rewardOperation)

let resultWrapper = createResultWrapper(dependingOn: mergeOperation)
resultWrapper.addDependency(operations: [mergeOperation])

let dependencies = [collatorsOperation, rewardOperation] + [mergeOperation] +
resultWrapper.dependencies

return CompoundOperationWrapper(targetOperation: resultWrapper.targetOperation, dependencies: dependencies)
}
}
41 changes: 31 additions & 10 deletions novawallet/Modules/Staking/Parachain/Model/CollatorsSortType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,37 @@ enum CollatorsSortType: Equatable {
}

extension Array where Element == CollatorSelectionInfo {
func sortedByType(_ type: CollatorsSortType) -> [CollatorSelectionInfo] {
switch type {
case .rewards:
return sorted { ($0.apr ?? 0) > ($1.apr ?? 0) }
case .minStake:
return sorted { $0.minRewardableStake < $1.minRewardableStake }
case .totalStake:
return sorted { $0.totalStake > $1.totalStake }
case .ownStake:
return sorted { $0.ownStake > $1.ownStake }
func sortedByType(
_ type: CollatorsSortType,
preferredCollators: Set<AccountId>
) -> [CollatorSelectionInfo] {
sorted { item1, item2 in
CompoundComparator.compare(list: [{
let isItem1Pref = preferredCollators.contains(item1.accountId)
let isItem2Pref = preferredCollators.contains(item2.accountId)

if isItem1Pref, !isItem2Pref {
return .orderedAscending
} else if !isItem1Pref, isItem2Pref {
return .orderedDescending
} else {
return .orderedSame
}
}, {
switch type {
case .rewards:
return (item1.apr ?? 0) > (item2.apr ?? 0) ? .orderedAscending : .orderedDescending
case .minStake:
return item1.minRewardableStake < item2.minRewardableStake ? .orderedAscending :
.orderedDescending
case .totalStake:
return item1.totalStake > item2.totalStake ? .orderedAscending :
.orderedDescending
case .ownStake:
return item1.ownStake > item2.ownStake ? .orderedAscending :
.orderedDescending
}
}])
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ final class ParaStkSelectCollatorsPresenter {

let chainAsset: ChainAsset
let balanceViewModelFactory: BalanceViewModelFactoryProtocol
let preferredCollators: Set<AccountId>
let logger: LoggerProtocol

init(
interactor: ParaStkSelectCollatorsInteractorInputProtocol,
wireframe: ParaStkSelectCollatorsWireframeProtocol,
delegate: ParaStkSelectCollatorsDelegate,
preferredCollators: Set<AccountId>,
chainAsset: ChainAsset,
balanceViewModelFactory: BalanceViewModelFactoryProtocol,
localizationManager: LocalizationManagerProtocol,
Expand All @@ -34,6 +36,7 @@ final class ParaStkSelectCollatorsPresenter {
self.interactor = interactor
self.wireframe = wireframe
self.delegate = delegate
self.preferredCollators = preferredCollators
self.chainAsset = chainAsset
self.balanceViewModelFactory = balanceViewModelFactory
self.logger = logger
Expand Down Expand Up @@ -206,7 +209,7 @@ final class ParaStkSelectCollatorsPresenter {

private func applySortingAndSaveResult(_ result: Result<[CollatorSelectionInfo], Error>) {
collatorsInfoResult = result.map {
$0.sortedByType(sorting)
$0.sortedByType(sorting, preferredCollators: preferredCollators)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ struct ParaStkSelectCollatorsViewFactory {

let localizationManager = LocalizationManager.shared

let preferredCollators = Set(StakingConstants.preferredValidatorIds(for: chainAsset.chain))

let presenter = ParaStkSelectCollatorsPresenter(
interactor: interactor,
wireframe: wireframe,
delegate: delegate,
preferredCollators: preferredCollators,
chainAsset: chainAsset,
balanceViewModelFactory: balanceViewModelFactory,
localizationManager: localizationManager,
Expand Down

0 comments on commit 9223284

Please sign in to comment.