Skip to content

Commit

Permalink
Lots of bug fixes and vault clean-ups (#290)
Browse files Browse the repository at this point in the history
* Clear the close position box after submission

* Adjust Isolated Margin editor triggered from Portfolio

* Adding alert indicator

* Add y axis to Vault chart

* Fix inconsistent tabbar icon opacity.

* TRA-833: Vault font size increase

* Vault: Update text to "Holding"

* TRA-837 Holding count

* Fix theming change issue

* 1D -> 90D

* Fixing input formatting issue with non-english locale

* TRA-859 None position

* Fixing regression of incorrect market oracle price
  • Loading branch information
ruixhuang authored Nov 8, 2024
1 parent c2a6574 commit 295c39e
Show file tree
Hide file tree
Showing 26 changed files with 208 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,29 +326,35 @@ public enum ClipStyle {
}

private struct BorderAndClipModifier: ViewModifier {
@EnvironmentObject var themeSettings: ThemeSettings

let style: ClipStyle
let borderColor: ThemeColor.SemanticColor
let lineWidth: CGFloat

func body(content: Content) -> some View {
let color = themeSettings.themeConfig.themeColor.color(of: borderColor)
switch style {
case .circle:
content
.clipShape(Circle())
.overlay(Circle()
.strokeBorder(borderColor.color, lineWidth: lineWidth))
.strokeBorder(color, lineWidth: lineWidth))
.environmentObject(themeSettings)

case .cornerRadius(let cornerRadius):
content
.clipShape(.rect(cornerRadius: cornerRadius))
.overlay(RoundedRectangle(cornerRadius: cornerRadius)
.strokeBorder(borderColor.color, lineWidth: lineWidth))
.strokeBorder(color, lineWidth: lineWidth))
.environmentObject(themeSettings)

case .capsule:
content
.clipShape(Capsule())
.overlay(Capsule()
.strokeBorder(borderColor.color, lineWidth: lineWidth))
.strokeBorder(color, lineWidth: lineWidth))
.environmentObject(themeSettings)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ private class dydxMarketsViewPresenter: HostedViewPresenter<dydxMarketsViewModel
iconUrl: asset?.resources?.imageUrl,
volume24H: market.perpetual?.volume24H?.doubleValue ?? 0,
sparkline: market.perpetual?.line?.map(\.doubleValue) ?? [],
price: market.oraclePrice?.doubleValue ?? 0,
price: dydxFormatter.shared.dollar(number: market.oraclePrice?.doubleValue, digits: market.configs?.displayTickSizeDecimals?.intValue ?? 2),
change: market.priceChange24HPercent?.doubleValue ?? 0,
isFavorite: dydxFavoriteStore.shared.isFavorite(marketId: market.id)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import ParticlesKit
import PlatformUI
import dydxStateManager
import dydxFormatter
import Combine

protocol dydxProfileSecondaryButtonsViewPresenterProtocol: HostedViewPresenterProtocol {
var viewModel: dydxProfileSecondaryButtonsViewModel? { get }
}

class dydxProfileSecondaryButtonsViewPresenter: HostedViewPresenter<dydxProfileSecondaryButtonsViewModel>, dydxProfileSecondaryButtonsViewPresenterProtocol {

init(viewModel: dydxProfileSecondaryButtonsViewModel) {
super.init()

Expand All @@ -31,16 +33,23 @@ class dydxProfileSecondaryButtonsViewPresenter: HostedViewPresenter<dydxProfileS
viewModel.helpAction = {
Router.shared?.navigate(to: RoutingRequest(path: "/help"), animated: true, completion: nil)
}
}

AbacusStateManager.shared.state.onboarded
.sink { [weak self] onboarded in
override func start() {
super.start()

Publishers
.CombineLatest(
AbacusStateManager.shared.state.onboarded,
AbacusStateManager.shared.state.alerts)
.sink { [weak self] onboarded, alerts in
// do not show alerts if wallet not connected
if onboarded && dydxBoolFeatureFlag.isVaultEnabled.isEnabled {
self?.viewModel?.alertsAction = {
Router.shared?.navigate(to: RoutingRequest(path: "/alerts"), animated: true, completion: nil)
}
self?.viewModel?.hasNewAlerts = alerts.count > 0
}

}
.store(in: &self.subscriptions)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter<dydxAdjust
super.start()
guard let marketId, let childSubaccountNumber else { return }

AbacusStateManager.shared.setMarket(market: marketId)
AbacusStateManager.shared.adjustIsolatedMargin(input: marketId, type: .market)
AbacusStateManager.shared.adjustIsolatedMargin(input: childSubaccountNumber, type: .childsubaccountnumber)

Publishers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,31 @@ private class dydxTradeStatusViewPresenter: HostedViewPresenter<dydxTradeStatusV
submitOrder()
}()

private let doneAction: (() -> Void) = {
private lazy var doneAction: (() -> Void) = { [weak self] in
let notificationPermission = NotificationService.shared?.authorization
if notificationPermission?.authorization == .notDetermined {
Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true, completion: { _, _ in
self?.dismissView {
Router.shared?.navigate(to: RoutingRequest(path: "/authorization/notification", params: nil), animated: true, completion: nil)
})
}
} else {
Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true, completion: nil)
self?.dismissView(completion: nil)
}
}

private func dismissView(completion: (() -> Void)?) {
switch tradeType {
case .trade:
Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true) {
_, _ in
completion?()
}
case .closePosition:
Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true) {
_, _ in
Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true) { _, _ in
completion?()
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,24 +73,38 @@ private class dydxVaultDepositWithdrawViewPresenter: HostedViewPresenter<dydxVau
// do not need debouncing/throttling for deposit since there are no slippage fetches
// for withdrawal, refetch slippage every ~2 seconds if subaccount or vault changes during a 2 second period
// for withdrawal, refetch slippage after input changes (debounced)
let vaultAndSubaccountPublisher = Publishers.CombineLatest(AbacusStateManager.shared.state.selectedSubaccount,
AbacusStateManager.shared.state.vault.compactMap({ $0 }))
.map { (subaccount: $0, vault: $1) }
.throttle(for: transferType == .deposit ? 0 : 2, scheduler: DispatchQueue.main, latest: true)
let vaultAndSubaccountPublisher =
Publishers
.CombineLatest(
AbacusStateManager.shared.state.selectedSubaccount,
AbacusStateManager.shared.state.vault.compactMap({ $0 })
)
.map { (subaccount: $0, vault: $1) }
.throttle(for: transferType == .deposit ? 0 : 2, scheduler: DispatchQueue.main, latest: true)

let amountPublisher = viewModel.$amount
.debounce(for: transferType == .deposit ? 0 : 0.5, scheduler: DispatchQueue.main).removeDuplicates()

self?.aggregatePublisherCancellable = Publishers.CombineLatest3(vaultAndSubaccountPublisher, AbacusStateManager.shared.state.onboarded, amountPublisher)
.sink(receiveValue: { vaultAndSubaccount, onboarded, amount in
self?.update(subaccount: vaultAndSubaccount.subaccount, vault: vaultAndSubaccount.vault, hasOnboarded: onboarded, amount: amount ?? 0, transferType: transferType)
})
}
.store(in: &subscriptions)
self?.aggregatePublisherCancellable =
Publishers
.CombineLatest3(
vaultAndSubaccountPublisher,
AbacusStateManager.shared.state.onboarded,
amountPublisher
)
.sink { vaultAndSubaccount, onboarded, amount in
self?.update(subaccount: vaultAndSubaccount.subaccount, vault: vaultAndSubaccount.vault, hasOnboarded: onboarded, amount: amount ?? 0, transferType: transferType)
}
}
.store(in: &subscriptions)

}

private func update(subaccount: Subaccount?, vault: Abacus.Vault, hasOnboarded: Bool, amount: Double, transferType: dydxViews.VaultTransferType) {
private func update(subaccount: Subaccount?,
vault: Abacus.Vault,
hasOnboarded: Bool,
amount: Double,
transferType: dydxViews.VaultTransferType) {
formValidationRequest?.cancel()

let accountData = Abacus.VaultFormAccountData(marginUsage: subaccount?.marginUsage?.current ?? 0,
Expand Down Expand Up @@ -158,7 +172,12 @@ private class dydxVaultDepositWithdrawViewPresenter: HostedViewPresenter<dydxVau
}
}

private func update(subaccount: Subaccount?, vault: Abacus.Vault, hasOnboarded: Bool, amount: Double, transferType: dydxViews.VaultTransferType, formValidationResult: VaultFormValidationResult) {
private func update(subaccount: Subaccount?,
vault: Abacus.Vault,
hasOnboarded: Bool,
amount: Double,
transferType: dydxViews.VaultTransferType,
formValidationResult: VaultFormValidationResult) {
updateMaxAmount(subaccount: subaccount, vault: vault, transferType: transferType)
updateSubmitState(formValidationResult: formValidationResult)
updateReceiptItems(formValidationResult: formValidationResult, subaccount: subaccount, vault: vault, amount: amount, transferType: transferType)
Expand All @@ -179,19 +198,19 @@ private class dydxVaultDepositWithdrawViewPresenter: HostedViewPresenter<dydxVau
viewModel?.submitState = formValidationResult.errors.isEmpty ? .enabled : .disabled
}

private func updateReceiptItems(formValidationResult: VaultFormValidationResult, subaccount: Abacus.Subaccount?, vault: Abacus.Vault, amount: Double, transferType: dydxViews.VaultTransferType) {
private func updateReceiptItems(formValidationResult: VaultFormValidationResult,
subaccount: Abacus.Subaccount?,
vault: Abacus.Vault,
amount: Double,
transferType: dydxViews.VaultTransferType) {
viewModel?.curVaultBalance = vault.account?.roundedWithdrawableUsdc ?? 0
viewModel?.curFreeCollateral = subaccount?.roundedFreeCollateral ?? 0
viewModel?.curMarginUsage = subaccount?.marginUsage?.current?.doubleValue ?? 0

viewModel?.postVaultBalance =
dydxFormatter.shared.raw(number: vault.account?.roundedWithdrawableUsdc, digits: 2) ==
dydxFormatter.shared.raw(number: formValidationResult.summaryData.vaultBalance?.doubleValue, digits: 2)
? nil : formValidationResult.summaryData.vaultBalance?.doubleValue
viewModel?.postFreeCollateral =
dydxFormatter.shared.raw(number: subaccount?.roundedFreeCollateral, digits: 2) ==
dydxFormatter.shared.raw(number: formValidationResult.summaryData.freeCollateral?.doubleValue, digits: 2)
? nil : formValidationResult.summaryData.freeCollateral?.doubleValue
vault.account?.roundedWithdrawableUsdc == formValidationResult.summaryData.roundedVaultBalance
? nil : formValidationResult.summaryData.roundedVaultBalance
viewModel?.postFreeCollateral = subaccount?.roundedFreeCollateral == formValidationResult.summaryData.roundedFreeCollateral ? nil : formValidationResult.summaryData.freeCollateral?.doubleValue
viewModel?.postMarginUsage = viewModel?.curMarginUsage == formValidationResult.summaryData.marginUsage?.doubleValue ? nil : formValidationResult.summaryData.marginUsage?.doubleValue

viewModel?.slippage = formValidationResult.summaryData.estimatedSlippage?.doubleValue
Expand Down Expand Up @@ -241,3 +260,13 @@ extension Abacus.Subaccount {
freeCollateral?.current?.doubleValue.round(to: 2, rule: .towardZero)
}
}

extension VaultFormSummaryData {
var roundedVaultBalance: Double? {
vaultBalance?.doubleValue.round(to: 2, rule: .towardZero)
}

var roundedFreeCollateral: Double? {
freeCollateral?.doubleValue.round(to: 2, rule: .towardZero)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,20 @@ private class dydxVaultViewBuilderPresenter: HostedViewPresenter<dydxVaultViewMo
}
return lhs.marginUsdc?.doubleValue ?? 0 > rhs.marginUsdc?.doubleValue ?? 0
}
.map { (position) -> dydxVaultPositionViewModel? in
.compactMap { (position) -> dydxVaultPositionViewModel? in
guard
let marketId = position.marketId,
// special case for fake USDC market to show unused margin
let assetId = marketId == "UNALLOCATEDUSDC-USD" ? "USDC" : marketMap[marketId]?.assetId
let marketId = position.marketId
else { return nil }

// special case for fake USDC market to show unused margin
let assetId = marketId == "UNALLOCATEDUSDC-USD" ? "USDC" : marketMap[marketId]?.assetId
let leverage = position.currentLeverageMultiple?.doubleValue
let asset = assetMap[assetId]
let asset: Asset?
if let assetId = assetId {
asset = assetMap[assetId]
} else {
asset = nil
}
let equity = position.marginUsdc?.doubleValue ?? 0
let notionalValue = position.currentPosition?.usdc?.doubleValue ?? 0
let positionSize = position.currentPosition?.asset?.doubleValue ?? 0
Expand All @@ -129,7 +134,7 @@ private class dydxVaultViewBuilderPresenter: HostedViewPresenter<dydxVaultViewMo
tokenUnitPrecision = 2
assetName = "USDC"
} else {
iconType = .init(url: URL(string: assetMap[assetId]?.resources?.imageUrl ?? ""), placeholderText: assetId.first?.uppercased())
iconType = .init(url: URL(string: asset?.resources?.imageUrl ?? ""), placeholderText: asset?.displayableAssetId.first?.uppercased())
tokenUnitPrecision = marketMap[marketId]?.configs?.displayStepSizeDecimals?.intValue ?? 2
assetName = asset?.name
}
Expand Down Expand Up @@ -159,7 +164,6 @@ private class dydxVaultViewBuilderPresenter: HostedViewPresenter<dydxVaultViewMo
pnlPercentage: position.thirtyDayPnl?.percent?.doubleValue,
sparklineValues: position.thirtyDayPnl?.sparklinePoints?.map({ $0.doubleValue }))
}
.compactMap { $0 }

viewModel?.positions = newPositions
}
Expand All @@ -170,12 +174,12 @@ private class dydxVaultViewBuilderPresenter: HostedViewPresenter<dydxVaultViewMo
let secondsSince1970 = (entry.date?.doubleValue ?? 0) / 1000.0
let minSecondsSince1970: Double
switch timeType {
case .oneDay:
minSecondsSince1970 = Date().addingTimeInterval(-24 * 60 * 60).timeIntervalSince1970
case .sevenDays:
minSecondsSince1970 = Date().addingTimeInterval(-7 * 24 * 60 * 60).timeIntervalSince1970
case .thirtyDays:
minSecondsSince1970 = Date().addingTimeInterval(-30 * 24 * 60 * 60).timeIntervalSince1970
case .ninetyDays:
minSecondsSince1970 = Date().addingTimeInterval(-90 * 24 * 60 * 60).timeIntervalSince1970
}

if minSecondsSince1970 <= secondsSince1970,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "icon_earn.pdf",
"filename" : "Group 1577.svg",
"idiom" : "universal"
}
],
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "icon_market.pdf",
"filename" : "Vector.svg",
"idiom" : "universal"
}
],
Expand Down
Loading

0 comments on commit 295c39e

Please sign in to comment.