Skip to content

Commit

Permalink
Merge branch 'fix/swap-corner-cases' into base/crosschain-swaps
Browse files Browse the repository at this point in the history
  • Loading branch information
ERussel committed Dec 17, 2024
2 parents ee98d5a + bd1cd38 commit 6a366cf
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 210 deletions.
8 changes: 4 additions & 4 deletions novawallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,6 @@
0C962F8A2AA8614500C0B551 /* TransactionHistoryLocalFilterFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C962F892AA8614500C0B551 /* TransactionHistoryLocalFilterFactory.swift */; };
0C9680F12A8A85BB006A411B /* TokenAddValidationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C9680F02A8A85BB006A411B /* TokenAddValidationFactory.swift */; };
0C9680F32A8AC2F2006A411B /* EvmTokenAddResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C9680F22A8AC2F2006A411B /* EvmTokenAddResult.swift */; };
0C97B21F2CE65D170071047C /* SwapsValidationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C97B21E2CE65D170071047C /* SwapsValidationTests.swift */; };
0C992C342B5184F100ACC129 /* EraValidatorsUpdating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C992C332B5184F100ACC129 /* EraValidatorsUpdating.swift */; };
0C992C392B5187A800ACC129 /* EraStakersRemoteKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C992C382B5187A800ACC129 /* EraStakersRemoteKey.swift */; };
0C992C3B2B51A61D00ACC129 /* EraStakersPagedRemoteKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C992C3A2B51A61D00ACC129 /* EraStakersPagedRemoteKey.swift */; };
Expand Down Expand Up @@ -880,6 +879,7 @@
0CFA161C2B0CE851007AF885 /* Utility+Calls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA161B2B0CE851007AF885 /* Utility+Calls.swift */; };
0CFA161E2B0CED07007AF885 /* GovTreasurySpentLocalHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA161D2B0CED07007AF885 /* GovTreasurySpentLocalHandler.swift */; };
0CFA16202B0CEF31007AF885 /* GovTreasuryApproveHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA161F2B0CEF31007AF885 /* GovTreasuryApproveHandler.swift */; };
0CFFB9D32D11A67C00172E8C /* XcmTokensArrivalDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFFB9D22D11A67C00172E8C /* XcmTokensArrivalDetector.swift */; };
0D5245ED354CC52A842C85A0 /* TransferConfirmViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD8B98AB03AAF06AA891695 /* TransferConfirmViewLayout.swift */; };
0D8213272889988B78188D9A /* DAppWalletAuthInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 337EC62037D657258BCBC02F /* DAppWalletAuthInteractor.swift */; };
0DACB56C0BDD4C984FE3C15C /* AssetReceiveWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C1179A25C22AF0875A1ADCD /* AssetReceiveWireframe.swift */; };
Expand Down Expand Up @@ -5837,7 +5837,6 @@
0C962F892AA8614500C0B551 /* TransactionHistoryLocalFilterFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionHistoryLocalFilterFactory.swift; sourceTree = "<group>"; };
0C9680F02A8A85BB006A411B /* TokenAddValidationFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenAddValidationFactory.swift; sourceTree = "<group>"; };
0C9680F22A8AC2F2006A411B /* EvmTokenAddResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EvmTokenAddResult.swift; sourceTree = "<group>"; };
0C97B21E2CE65D170071047C /* SwapsValidationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwapsValidationTests.swift; sourceTree = "<group>"; };
0C992C332B5184F100ACC129 /* EraValidatorsUpdating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EraValidatorsUpdating.swift; sourceTree = "<group>"; };
0C992C382B5187A800ACC129 /* EraStakersRemoteKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EraStakersRemoteKey.swift; sourceTree = "<group>"; };
0C992C3A2B51A61D00ACC129 /* EraStakersPagedRemoteKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EraStakersPagedRemoteKey.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6211,6 +6210,7 @@
0CFA161B2B0CE851007AF885 /* Utility+Calls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Utility+Calls.swift"; sourceTree = "<group>"; };
0CFA161D2B0CED07007AF885 /* GovTreasurySpentLocalHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GovTreasurySpentLocalHandler.swift; sourceTree = "<group>"; };
0CFA161F2B0CEF31007AF885 /* GovTreasuryApproveHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GovTreasuryApproveHandler.swift; sourceTree = "<group>"; };
0CFFB9D22D11A67C00172E8C /* XcmTokensArrivalDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcmTokensArrivalDetector.swift; sourceTree = "<group>"; };
0D37CF4AFB06AF3AC2F78057 /* ImportCloudPasswordPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ImportCloudPasswordPresenter.swift; sourceTree = "<group>"; };
0D3FE2CE7F9F2836755DBA63 /* GovernanceUnlockConfirmProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GovernanceUnlockConfirmProtocols.swift; sourceTree = "<group>"; };
0D65686560E2E6C18A5C34CB /* StartStakingInfoWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StartStakingInfoWireframe.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -14368,7 +14368,6 @@
771901912AE2425400D9C918 /* Swaps */ = {
isa = PBXGroup;
children = (
0C97B21E2CE65D170071047C /* SwapsValidationTests.swift */,
0C3976B22C33BFB700998DD6 /* HydraPoolAccountTests.swift */,
);
path = Swaps;
Expand Down Expand Up @@ -20658,6 +20657,7 @@
84C1DBBB29C0A18000F295A5 /* XcmTransferService+Compose.swift */,
0CA8AD552CE06FA000ED9746 /* XcmTransactService.swift */,
0CA8AD682CE0904D00ED9746 /* XcmDepositMonitoringService.swift */,
0CFFB9D22D11A67C00172E8C /* XcmTokensArrivalDetector.swift */,
);
path = Xcm;
sourceTree = "<group>";
Expand Down Expand Up @@ -29370,6 +29370,7 @@
F35B520D7955A70588AB593C /* ReferendumVoteConfirmWireframe.swift in Sources */,
F0ADB63765A8EAA19D85C30B /* ReferendumVoteConfirmPresenter.swift in Sources */,
84C9CF3D291AF1B1002BF328 /* GovernanceOffchainApi.swift in Sources */,
0CFFB9D32D11A67C00172E8C /* XcmTokensArrivalDetector.swift in Sources */,
77C3D7D52B5E7E7800997BA0 /* StakingRemoveProxyInteractor.swift in Sources */,
84BAD21A293B18EC00C55C49 /* RemoteAssetModel.swift in Sources */,
DE52F23521D54A07F558EB1B /* ReferendumVoteConfirmInteractor.swift in Sources */,
Expand Down Expand Up @@ -30209,7 +30210,6 @@
84BEE63026CBFDBC00757009 /* ChainRegistryTests.swift in Sources */,
84B7C73C289BFA79001A3566 /* StakingRewardPayoutsTests.swift in Sources */,
84B7C747289BFA79001A3566 /* AccountManagementTests.swift in Sources */,
0C97B21F2CE65D170071047C /* SwapsValidationTests.swift in Sources */,
843612CB279011B400DC739E /* SigningWrapperFactoryStub.swift in Sources */,
8846F73829D6F57700B8B776 /* MultibaseTests.swift in Sources */,
84300B2F26C1112300D64514 /* ConnectionPoolTests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ protocol AssetsExchangePathCostEstimating: AnyObject {
) -> CompoundOperationWrapper<AssetsExchangePathCost>
}

enum AssetsExchangePathCostEstimatorError: Error {
case amountConversion
}

struct AssetsExchangePathCost {
let amountInAssetIn: Balance
let amountInAssetOut: Balance
Expand Down Expand Up @@ -60,17 +56,15 @@ extension AssetsExchangePathCostEstimator: AssetsExchangePathCostEstimating {
return .zero
}

guard
let assetInCost = usdtConverter.convertToAssetInPlankFromUsdt(
amount: totalCostInUsdt,
asset: assetIn
),
let assetOutCost = usdtConverter.convertToAssetInPlankFromUsdt(
amount: totalCostInUsdt,
asset: assetOut
) else {
throw AssetsExchangePathCostEstimatorError.amountConversion
}
let assetInCost = usdtConverter.convertToAssetInPlankFromUsdt(
amount: totalCostInUsdt,
asset: assetIn
) ?? .zero

let assetOutCost = usdtConverter.convertToAssetInPlankFromUsdt(
amount: totalCostInUsdt,
asset: assetOut
) ?? .zero

return AssetsExchangePathCost(amountInAssetIn: assetInCost, amountInAssetOut: assetOutCost)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@ import Operation_iOS
import SubstrateSdk

protocol BlockEventsQueryFactoryProtocol {
func queryExtrinsicEventsWrapper(
func queryBlockDetailsWrapper(
from connection: JSONRPCEngine,
runtimeProvider: RuntimeProviderProtocol,
blockHash: Data
) -> CompoundOperationWrapper<[SubstrateExtrinsicEvents]>

func queryInherentEventsWrapper(
from connection: JSONRPCEngine,
runtimeProvider: RuntimeProviderProtocol,
blockHash: Data
) -> CompoundOperationWrapper<SubstrateInherentsEvents>
) -> CompoundOperationWrapper<SubstrateBlockDetails>
}

final class BlockEventsQueryFactory {
Expand Down Expand Up @@ -67,7 +61,7 @@ final class BlockEventsQueryFactory {
blockOperation: BaseOperation<SignedBlock>,
repository: SubstrateEventsRepositoryProtocol,
logger: LoggerProtocol
) -> BaseOperation<[SubstrateExtrinsicEvents]> {
) -> BaseOperation<SubstrateBlockDetails> {
ClosureOperation {
let block = try blockOperation.extractNoCancellableResultData().block

Expand All @@ -77,31 +71,23 @@ final class BlockEventsQueryFactory {

logger.debug("Events received: \(eventRecords)")

return repository.getExtrinsicsEvents(from: block, eventRecords: eventRecords)
}
}
let extrinsicsWithEvents = repository.getExtrinsicsEvents(from: block, eventRecords: eventRecords)
let inherentEvents = repository.getInherentEvents(from: eventRecords)

private func createParsingInherentEventsOperation(
dependingOn eventsOperation: BaseOperation<StorageResponse<[EventRecord]>>,
repository: SubstrateEventsRepositoryProtocol,
logger: LoggerProtocol
) -> BaseOperation<SubstrateInherentsEvents> {
ClosureOperation {
let eventRecords = try eventsOperation.extractNoCancellableResultData().value ?? []

logger.debug("Events received: \(eventRecords)")

return repository.getInherentEvents(from: eventRecords)
return SubstrateBlockDetails(
extrinsicsWithEvents: extrinsicsWithEvents,
inherentsEvents: inherentEvents
)
}
}
}

extension BlockEventsQueryFactory: BlockEventsQueryFactoryProtocol {
func queryExtrinsicEventsWrapper(
func queryBlockDetailsWrapper(
from connection: JSONRPCEngine,
runtimeProvider: RuntimeProviderProtocol,
blockHash: Data
) -> CompoundOperationWrapper<[SubstrateExtrinsicEvents]> {
) -> CompoundOperationWrapper<SubstrateBlockDetails> {
let codingFactoryOperation = runtimeProvider.fetchCoderFactoryOperation()

let eventsWrapper = createEventsWrapper(
Expand Down Expand Up @@ -132,30 +118,4 @@ extension BlockEventsQueryFactory: BlockEventsQueryFactoryProtocol {
.insertingTail(operation: blockFetchOperation)
.insertingTail(operation: parsingOperation)
}

func queryInherentEventsWrapper(
from connection: JSONRPCEngine,
runtimeProvider: RuntimeProviderProtocol,
blockHash: Data
) -> CompoundOperationWrapper<SubstrateInherentsEvents> {
let codingFactoryOperation = runtimeProvider.fetchCoderFactoryOperation()

let eventsWrapper = createEventsWrapper(
dependingOn: codingFactoryOperation,
connection: connection,
blockHash: blockHash
)

let parsingOperation = createParsingInherentEventsOperation(
dependingOn: eventsWrapper.targetOperation,
repository: eventsRepository,
logger: logger
)

parsingOperation.addDependency(eventsWrapper.targetOperation)

return eventsWrapper
.insertingHead(operations: [codingFactoryOperation])
.insertingTail(operation: parsingOperation)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ final class ExtrinsicStatusService {
}

private func createMatchingWrapper(
dependingOn queryOperation: BaseOperation<[SubstrateExtrinsicEvents]>,
dependingOn queryOperation: BaseOperation<SubstrateBlockDetails>,
runtimeProvider: RuntimeProviderProtocol,
extrinsicHash: Data,
blockHash: BlockHash,
Expand All @@ -41,36 +41,45 @@ final class ExtrinsicStatusService {

let mappingOperation = ClosureOperation<SubstrateExtrinsicStatus> {
let codingFactory = try codingFactoryOperation.extractNoCancellableResultData()
let extrinsicEventsList = try queryOperation.extractNoCancellableResultData()
let extrinsicEventsList = try queryOperation.extractNoCancellableResultData().extrinsicsWithEvents

guard let extrinsicEvents = extrinsicEventsList.first(where: { $0.extrinsicHash == extrinsicHash }) else {
guard let extrinsicEvents = extrinsicEventsList
.first(where: { $0.extrinsicHash == extrinsicHash }) else {
throw ExtrinsicStatusServiceError.extrinsicNotFound(extrinsicHash)
}

let successMatcher = ExtrinsicSuccessEventMatcher()

if extrinsicEvents.events.contains(where: { successMatcher.match(event: $0, using: codingFactory) }) {
if extrinsicEvents.eventRecords.contains(
where: { successMatcher.match(event: $0.event, using: codingFactory) }
) {
let extString = extrinsicHash.toHex(includePrefix: true)

let events: [Event] = if let interstedEventsMatcher {
extrinsicEvents.events.filter { interstedEventsMatcher.match(event: $0, using: codingFactory) }
extrinsicEvents.eventRecords.filter {
interstedEventsMatcher.match(
event: $0.event,
using: codingFactory
)
}.map(\.event)
} else {
[]
}

return .success(.init(
extrinsicHash: extString,
blockHash: blockHash,
interestedEvents: events
)
return .success(
.init(
extrinsicHash: extString,
blockHash: blockHash,
interestedEvents: events
)
)
}

let failMatcher = ExtrinsicFailureEventMatcher()

if let failureEvent = extrinsicEvents.events.first(
where: { failMatcher.match(event: $0, using: codingFactory) }
) {
if let failureEvent = extrinsicEvents.eventRecords.first(
where: { failMatcher.match(event: $0.event, using: codingFactory) }
)?.event {
let dispatchError = try failureEvent.params.map(
to: ExtrinsicFailedEventParams.self,
with: codingFactory.createRuntimeJsonContext().toRawContext()
Expand Down Expand Up @@ -102,7 +111,7 @@ extension ExtrinsicStatusService: ExtrinsicStatusServiceProtocol {
let extHashData = try Data(hexString: extrinsicHash)
let blockHashData = try Data(hexString: blockHash)

let eventsQueryWrapper = eventsQueryFactory.queryExtrinsicEventsWrapper(
let eventsQueryWrapper = eventsQueryFactory.queryBlockDetailsWrapper(
from: connection,
runtimeProvider: runtimeProvider,
blockHash: blockHashData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import SubstrateSdk

protocol SubstrateEventsRepositoryProtocol {
func getInherentEvents(from eventRecords: [EventRecord]) -> SubstrateInherentsEvents
func getExtrinsicsEvents(from block: Block, eventRecords: [EventRecord]) -> [SubstrateExtrinsicEvents]

func getExtrinsicsEvents(
from block: Block,
eventRecords: [EventRecord]
) -> [SubstrateExtrinsicEvents]
}

final class SubstrateEventsRepository: SubstrateEventsRepositoryProtocol {
Expand All @@ -16,14 +20,14 @@ final class SubstrateEventsRepository: SubstrateEventsRepositoryProtocol {

func getExtrinsicsEvents(from block: Block, eventRecords: [EventRecord]) -> [SubstrateExtrinsicEvents] {
let eventsByExtrinsicIndex = eventRecords.reduce(
into: [ExtrinsicIndex: [Event]]()
into: [ExtrinsicIndex: [EventRecord]]()
) { accum, record in
guard let extrinsicIndex = record.extrinsicIndex else {
return
}

let currentEvents = accum[extrinsicIndex] ?? []
accum[extrinsicIndex] = currentEvents + [record.event]
accum[extrinsicIndex] = currentEvents + [record]
}

return block.extrinsics.enumerated().compactMap { index, hexExtrinsic in
Expand All @@ -33,7 +37,8 @@ final class SubstrateEventsRepository: SubstrateEventsRepositoryProtocol {

return SubstrateExtrinsicEvents(
extrinsicHash: extrinsicHash,
events: eventsByExtrinsicIndex[ExtrinsicIndex(index)] ?? []
extrinsicData: data,
eventRecords: eventsByExtrinsicIndex[ExtrinsicIndex(index)] ?? []
)

} catch {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import Foundation
import SubstrateSdk

struct SubstrateBlockDetails {
let extrinsicsWithEvents: SubstrateExtrinsicsEvents
let inherentsEvents: SubstrateInherentsEvents
}

struct SubstrateExtrinsicEvents {
let extrinsicHash: Data
let events: [Event]
let extrinsicData: Data
let eventRecords: [EventRecord]
}

typealias SubstrateExtrinsicsEvents = [SubstrateExtrinsicEvents]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,33 +105,30 @@ final class XcmDepositMonitoringService {
) {
let codingFactoryOperation = runtimeProvider.fetchCoderFactoryOperation()

let eventsWrapper = blockEventsQueryFactory.queryInherentEventsWrapper(
let blockDetailsWrapper = blockEventsQueryFactory.queryBlockDetailsWrapper(
from: connection,
runtimeProvider: runtimeProvider,
blockHash: hash
)

let detector = XcmTokensArrivalDetector(logger: logger)

let matchingOperation = ClosureOperation<TokenDepositEvent?> {
let events = try eventsWrapper.targetOperation.extractNoCancellableResultData()
let blockDetails = try blockDetailsWrapper.targetOperation.extractNoCancellableResultData()
let codingFactory = try codingFactoryOperation.extractNoCancellableResultData()

let allEvents = events.initialization + events.finalization

for event in allEvents {
if
let deposit = eventMatcher.matchDeposit(event: event, using: codingFactory),
deposit.accountId == accountId {
return deposit
}
}

return nil
return detector.searchForXcmArrival(
in: blockDetails,
eventMatcher: eventMatcher,
accountId: accountId,
codingFactory: codingFactory
)
}

matchingOperation.addDependency(codingFactoryOperation)
matchingOperation.addDependency(eventsWrapper.targetOperation)
matchingOperation.addDependency(blockDetailsWrapper.targetOperation)

let totalWrapper = eventsWrapper
let totalWrapper = blockDetailsWrapper
.insertingHead(operations: [codingFactoryOperation])
.insertingTail(operation: matchingOperation)

Expand Down
Loading

0 comments on commit 6a366cf

Please sign in to comment.