Skip to content

Commit

Permalink
Merge pull request #1302 from novasamatech/feature/route-details
Browse files Browse the repository at this point in the history
Crosschain swap route details
  • Loading branch information
ERussel authored Dec 13, 2024
2 parents d48011b + 73760dc commit 10f63ce
Show file tree
Hide file tree
Showing 33 changed files with 1,008 additions and 0 deletions.
80 changes: 80 additions & 0 deletions novawallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x3B",
"green" : "0x2D",
"red" : "0x2B"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
16 changes: 16 additions & 0 deletions novawallet/Common/View/AssetAmountView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import UIKit

class AssetAmountView: GenericPairValueView<AssetIconView, UILabel> {
var assetIconView: AssetIconView { fView }
var amountLabel: UILabel { sView }

override init(frame: CGRect) {
super.init(frame: frame)

configure()
}

private func configure() {
setHorizontalAndSpacing(1)
}
}
51 changes: 51 additions & 0 deletions novawallet/Common/View/LinePatternView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Foundation
import SoraUI

final class LinePatternView: UIView {
var style: Style = .defaultStyle {
didSet {
setNeedsDisplay()
}
}

override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else {
return
}

context.setLineWidth(style.lineWidth)
context.setStrokeColor(style.color.cgColor)

if let pattern = style.pattern {
context.setLineDash(phase: pattern.phase, lengths: pattern.segments)
}

context.move(to: CGPoint(x: rect.midX, y: 0))
context.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
context.drawPath(using: .stroke)
}
}

extension LinePatternView {
struct Pattern {
let segments: [CGFloat]
let phase: CGFloat
}

struct Style {
let color: UIColor
let lineWidth: CGFloat
let pattern: Pattern?

static var defaultStyle: Style {
Style(
color: R.color.colorIconSecondary()!,
lineWidth: 1,
pattern: LinePatternView.Pattern(
segments: [2, 3],
phase: 0
)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ extension AssetIconViewModelFactoryProtocol {
defaultURL: defaultURL
)
}

func createAssetIconViewModel(from assetDisplayInfo: AssetBalanceDisplayInfo) -> ImageViewModelProtocol {
createAssetIconViewModel(
for: assetDisplayInfo.icon?.getPath(),
defaultURL: assetDisplayInfo.icon?.getURL()
)
}
}

class AssetIconViewModelFactory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ struct AssetExchangeOperationFee: Equatable {
func totalAmountIn(asset: ChainAssetId) -> Balance {
self.asset == asset ? amount : 0
}

func addAmount(to store: inout [ChainAssetId: Balance]) {
store[asset] = (store[asset] ?? 0) + amount
}
}

struct Submission: Equatable {
Expand Down Expand Up @@ -53,6 +57,10 @@ struct AssetExchangeOperationFee: Equatable {

return amountWithAsset.totalAmountIn(asset: asset)
}

func addAmount(to store: inout [ChainAssetId: Balance]) {
amountWithAsset.addAmount(to: &store)
}
}

struct AmountByPayer: Equatable {
Expand Down Expand Up @@ -81,6 +89,10 @@ struct AssetExchangeOperationFee: Equatable {

return amountWithAsset.totalAmountIn(asset: asset)
}

func addAmount(to store: inout [ChainAssetId: Balance]) {
amountWithAsset.addAmount(to: &store)
}
}

struct PostSubmission: Equatable {
Expand Down Expand Up @@ -161,6 +173,11 @@ struct AssetExchangeOperationFee: Equatable {

return totalByAccount + totalFromAmount
}

func addAmount(to store: inout [ChainAssetId: Balance]) {
paidByAccount.forEach { $0.amountWithAsset.addAmount(to: &store) }
paidFromAmount.forEach { $0.addAmount(to: &store) }
}
}

/**
Expand Down Expand Up @@ -227,6 +244,15 @@ extension AssetExchangeOperationFee {

return submissionTotal + postSubmissionTotal
}

func groupedAmountByAsset() -> [ChainAssetId: Balance] {
var store: [ChainAssetId: Balance] = [:]

submissionFee.addAmount(to: &store)
postSubmissionFee.addAmount(to: &store)

return store
}
}

extension AssetExchangeOperationFee.Submission: ExtrinsicFeeProtocol {
Expand Down
13 changes: 13 additions & 0 deletions novawallet/Modules/InAppUpdates/InAppUpdatesStyles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ extension BorderedLabelView {
}

extension BorderedLabelView.Style {
static let stepNumber = BorderedLabelView.Style(
text: .init(
textColor: R.color.colorTextSecondary()!,
font: .semiBoldCaps1
),
background: .init(
shadowOpacity: 0,
strokeWidth: 0,
fillColor: R.color.colorRouteNumberBackground()!,
highlightedFillColor: R.color.colorRouteNumberBackground()!
)
)

static let chipsText = BorderedLabelView.Style(
text: .init(
textColor: R.color.colorChipText()!,
Expand Down
12 changes: 12 additions & 0 deletions novawallet/Modules/Swaps/Confirm/SwapConfirmPresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,18 @@ extension SwapConfirmPresenter: SwapConfirmPresenterProtocol {
)
}

func showRouteDetails() {
guard let fee else {
return
}

wireframe.showRouteDetails(
from: view,
quote: initState.quote,
fee: fee
)
}

func confirm() {
guard let swapModel = getSwapModel() else {
return
Expand Down
7 changes: 7 additions & 0 deletions novawallet/Modules/Swaps/Confirm/SwapConfirmProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ protocol SwapConfirmPresenterProtocol: AnyObject {
func showPriceDifferenceInfo()
func showSlippageInfo()
func showNetworkFeeInfo()
func showRouteDetails()
func showAddressOptions()
func confirm()
}
Expand All @@ -34,4 +35,10 @@ protocol SwapConfirmWireframeProtocol: SwapBaseWireframeProtocol, AddressOptions
from view: SwapConfirmViewProtocol?,
model: SwapExecutionModel
)

func showRouteDetails(
from view: ControllerBackedProtocol?,
quote: AssetExchangeQuote,
fee: AssetExchangeFee
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ final class SwapConfirmViewController: UIViewController, ViewHolder {

private func setupHandlers() {
rootView.rateCell.addTarget(self, action: #selector(rateAction), for: .touchUpInside)
rootView.routeCell.addTarget(self, action: #selector(routeAction), for: .touchUpInside)
rootView.priceDifferenceCell.addTarget(self, action: #selector(priceDifferenceAction), for: .touchUpInside)
rootView.slippageCell.addTarget(self, action: #selector(slippageAction), for: .touchUpInside)
rootView.networkFeeCell.addTarget(self, action: #selector(networkFeeAction), for: .touchUpInside)
Expand All @@ -65,6 +66,10 @@ final class SwapConfirmViewController: UIViewController, ViewHolder {
presenter.showNetworkFeeInfo()
}

@objc private func routeAction() {
presenter.showRouteDetails()
}

@objc private func addressAction() {
presenter.showAddressOptions()
}
Expand Down
19 changes: 19 additions & 0 deletions novawallet/Modules/Swaps/Confirm/SwapConfirmWireframe.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,23 @@ final class SwapConfirmWireframe: SwapConfirmWireframeProtocol {
presenter?.present(swapExecutionView.controller, animated: true)
}
}

func showRouteDetails(
from view: ControllerBackedProtocol?,
quote: AssetExchangeQuote,
fee: AssetExchangeFee
) {
guard
let routeDetailsView = SwapRouteDetailsViewFactory.createView(
for: quote,
fee: fee,
state: flowState
) else {
return
}

let navigationController = NovaNavigationController(rootViewController: routeDetailsView.controller)

view?.controller.present(navigationController, animated: true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,14 @@ extension SwapExecutionPresenter: SwapExecutionPresenterProtocol {
wireframe.showRateInfo(from: view)
}

func showRouteDetails() {
wireframe.showRouteDetails(
from: view,
quote: model.quote,
fee: model.fee
)
}

func showPriceDifferenceInfo() {
let title = LocalizableResource {
R.string.localizable.swapsSetupPriceDifference(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ protocol SwapExecutionPresenterProtocol: AnyObject {
func showPriceDifferenceInfo()
func showSlippageInfo()
func showTotalFeeInfo()
func showRouteDetails()
func activateDone()
func activateTryAgain()
}
Expand All @@ -42,4 +43,10 @@ protocol SwapExecutionWireframeProtocol: ShortTextInfoPresentable, MessageSheetP
payChainAsset: ChainAsset,
receiveChainAsset: ChainAsset
)

func showRouteDetails(
from view: ControllerBackedProtocol?,
quote: AssetExchangeQuote,
fee: AssetExchangeFee
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ final class SwapExecutionViewController: UIViewController, ViewHolder {
rootView.detailsView.delegate = self

rootView.rateCell.addTarget(self, action: #selector(rateAction), for: .touchUpInside)
rootView.routeCell.addTarget(self, action: #selector(routeAction), for: .touchUpInside)
rootView.priceDifferenceCell.addTarget(self, action: #selector(priceDifferenceAction), for: .touchUpInside)
rootView.slippageCell.addTarget(self, action: #selector(slippageAction), for: .touchUpInside)
rootView.totalFeeCell.addTarget(self, action: #selector(totalFeeAction), for: .touchUpInside)
Expand All @@ -61,6 +62,10 @@ final class SwapExecutionViewController: UIViewController, ViewHolder {
presenter.showPriceDifferenceInfo()
}

@objc private func routeAction() {
presenter.showRouteDetails()
}

@objc private func slippageAction() {
presenter.showSlippageInfo()
}
Expand Down
19 changes: 19 additions & 0 deletions novawallet/Modules/Swaps/Execution/SwapExecutionWireframe.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,23 @@ final class SwapExecutionWireframe: SwapExecutionWireframeProtocol {
presenter?.present(navigationController, animated: true)
}
}

func showRouteDetails(
from view: ControllerBackedProtocol?,
quote: AssetExchangeQuote,
fee: AssetExchangeFee
) {
guard
let routeDetailsView = SwapRouteDetailsViewFactory.createView(
for: quote,
fee: fee,
state: flowState
) else {
return
}

let navigationController = NovaNavigationController(rootViewController: routeDetailsView.controller)

view?.controller.present(navigationController, animated: true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import UIKit

final class SwapRouteDetailsInteractor {
weak var presenter: SwapRouteDetailsInteractorOutputProtocol?
}

extension SwapRouteDetailsInteractor: SwapRouteDetailsInteractorInputProtocol {}
Loading

0 comments on commit 10f63ce

Please sign in to comment.