Skip to content

Commit

Permalink
confirm screen states (#248)
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-dydx authored Sep 16, 2024
1 parent c1512e0 commit 1d63576
Show file tree
Hide file tree
Showing 10 changed files with 413 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ private class DismissAction: NSObject, NavigableProtocol {
@objc open func navigate(to request: RoutingRequest?, animated: Bool, completion: RoutingCompletionBlock?) {
if request?.path == "/action/dismiss" {
let viewController = UIViewController.topmost()
if viewController?.navigationController?.topViewController == viewController,
if let shouldPrioritizeDismiss = request?.params?["shouldPrioritizeDismiss"] as? Bool,
shouldPrioritizeDismiss && viewController?.presentingViewController !== nil {
viewController?.dismiss(animated: animated, completion: {
completion?(nil, true)
})
} else if viewController?.navigationController?.topViewController == viewController,
viewController?.navigationController?.viewControllers.count ?? 0 > 1 {
viewController?.navigationController?.popViewController(animated: animated)
} else if viewController?.presentingViewController !== nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import dydxStateManager
import FloatingPanel
import PlatformRouting
import dydxFormatter
import Combine
import class Abacus.Subaccount

public class dydxVaultDepositWithdrawConfirmationViewBuilder: NSObject, ObjectBuilderProtocol {
public func build<T>() -> T? {
Expand All @@ -29,6 +31,7 @@ private class dydxVaultDepositWithdrawConfirmationViewController: HostingViewCon

override public func arrive(to request: RoutingRequest?, animated: Bool) -> Bool {
let presenter = presenter as? dydxVaultDepositWithdrawConfirmationViewPresenterProtocol
presenter?.amount = request?.params?["amount"] as? Double
if request?.path == "/vault/deposit_confirm" {
presenter?.transferType = .deposit
return true
Expand All @@ -43,63 +46,138 @@ private class dydxVaultDepositWithdrawConfirmationViewController: HostingViewCon

private protocol dydxVaultDepositWithdrawConfirmationViewPresenterProtocol: HostedViewPresenterProtocol {
var viewModel: dydxVaultDepositWithdrawConfirmationViewModel? { get }
var transferType: VaultTransferType { get set }
var transferType: VaultTransferType? { get set }
var amount: Double? { get set }
}

private class dydxVaultDepositWithdrawConfirmationViewPresenter: HostedViewPresenter<dydxVaultDepositWithdrawConfirmationViewModel>, dydxVaultDepositWithdrawConfirmationViewPresenterProtocol {
var transferType: VaultTransferType = .deposit {
didSet {
viewModel?.transferType = transferType
}
}
static let slippageAcknowledgementThreshold = 0.01

var transferType: VaultTransferType?
var amount: Double?

override init() {

super.init()

viewModel = dydxVaultDepositWithdrawConfirmationViewModel()
}

let viewModel = dydxVaultDepositWithdrawConfirmationViewModel(transferType: transferType)
override func start() {
super.start()

guard let viewModel else { return }

viewModel.amount = amount
viewModel.faqUrl = AbacusStateManager.shared.environment?.links?.vaultLearnMore ?? ""
viewModel.transferType = transferType

initializeSubmitState()

viewModel.cancelAction = {
Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true, completion: nil)
}

viewModel.submitAction = { [weak self] in
//TO-DO replace with v4-clients call to submit deposit, this just simulates it
self?.viewModel?.submitState = .submitting
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if Int.random(in: 1...6) == 1 {
// success
Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss", params: ["shouldPrioritizeDismiss": true]), animated: true, completion: nil)
} else {
// failure
self?.viewModel?.isFirstSubmission = false
self?.viewModel?.submitState = .enabled
}
}
}

// TODO: replace
viewModel.elevatedSlippageAmount = 4.20
viewModel.requiresAcknowledgeHighSlippage = true

self.viewModel = viewModel
// handle slippage toggling
viewModel.$hasAcknowledgedHighSlippage
.sink {[weak self] hasAcknowledged in
self?.update(newHasAcknowledged: hasAcknowledged)
}
.store(in: &subscriptions)

AbacusStateManager.shared.state.selectedSubaccount
.sink { [weak self] selectedSubaccount in
self?.update(subaccount: selectedSubaccount)
}
.store(in: &subscriptions)
}

override func start() {
super.start()

// TODO: replace with real hooks from abacus
update()

private func initializeSubmitState() {
guard let viewModel, let transferType else { return }
switch transferType {
case .deposit:
viewModel.submitState = .enabled
case .withdraw:
viewModel.submitState = .loading
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
//TO-DO replace fetch actual slippage and update view model
let slippage = Double.random(in: 0...0.02) // replace random with actual slippage
let requiresAcknowledgeHighSlippage = transferType == .withdraw && slippage >= Self.slippageAcknowledgementThreshold
viewModel.requiresAcknowledgeHighSlippage = requiresAcknowledgeHighSlippage
viewModel.slippage = slippage
if requiresAcknowledgeHighSlippage && !viewModel.hasAcknowledgedHighSlippage {
self.viewModel?.submitState = .disabled
} else {
self.viewModel?.submitState = .enabled
}
}
}
}

// TODO: replace with real data from abacus
func update() {
let crossFreeCollateralReceiptItem = dydxReceiptChangeItemView(title: DataLocalizer.localize(path: "APP.GENERAL.CROSS_FREE_COLLATERAL"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02)))
let yourVaultBalanceReceiptItem = dydxReceiptChangeItemView(title: DataLocalizer.localize(path: "APP.VAULTS.YOUR_VAULT_BALANCE"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02)))
let estSlippageReceiptItem = dydxReceiptChangeItemView(title: DataLocalizer.localize(path: "APP.VAULTS.EST_SLIPPAGE"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02)))
let expectedAmountReceivedItem = dydxReceiptChangeItemView(title: DataLocalizer.localize(path: "APP.WITHDRAW_MODAL.EXPECTED_AMOUNT_RECEIVED"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02)))
let crossMarginUsageItem = dydxReceiptChangeItemView(title: DataLocalizer.localize(path: "APP.GENERAL.CROSS_MARGIN_USAGE"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02)))

func update(subaccount: Subaccount?) {
guard let amount,
let transferType,
amount > 0,
// TODO: replace
let curVaultBalance = Optional(420.0),
let curFreeCollateral = subaccount?.freeCollateral?.current?.doubleValue,
let curMarginUsage = subaccount?.marginUsage?.current?.doubleValue
else {
// assertionFailure()
return
}

viewModel?.curMarginUsage = curMarginUsage
viewModel?.curFreeCollateral = curFreeCollateral
viewModel?.curVaultBalance = curVaultBalance

switch transferType {
case .deposit:
viewModel?.postVaultBalance = curVaultBalance + amount
viewModel?.postFreeCollateral = curFreeCollateral - amount
viewModel?.postMarginUsage = curMarginUsage - amount
case .withdraw:
viewModel?.postVaultBalance = curVaultBalance - amount
viewModel?.postFreeCollateral = curFreeCollateral + amount
viewModel?.postMarginUsage = curMarginUsage + amount
}
}

private func update(newHasAcknowledged: Bool) {
guard let viewModel, newHasAcknowledged else { return }
switch viewModel.submitState {
case .enabled, .disabled:
viewModel.submitState = newHasAcknowledged ? .enabled : .disabled
case .submitting, .loading:
return
}
}

private func updateSubmitState(slippage: Double?, transferType: VaultTransferType) {
switch transferType {
case .deposit:
viewModel?.receiptItems = [crossFreeCollateralReceiptItem, crossMarginUsageItem, yourVaultBalanceReceiptItem]
case .withdraw:
viewModel?.receiptItems = [crossFreeCollateralReceiptItem, yourVaultBalanceReceiptItem, estSlippageReceiptItem, expectedAmountReceivedItem]
case .deposit:
viewModel?.submitState = .enabled
case .withdraw:
if let slippage = slippage, viewModel?.requiresAcknowledgeHighSlippage == false || viewModel?.hasAcknowledgedHighSlippage == true {
viewModel?.submitState = .enabled
} else {
viewModel?.submitState = .disabled
}
}
}
}
Loading

0 comments on commit 1d63576

Please sign in to comment.