From 38f29c26a5b6bd9ea4ffb15e7bf3fe642eb5560c Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 26 Apr 2024 11:30:30 -0700 Subject: [PATCH 1/8] Refactoring NotificationsProvider --- .../state/manager/NotificationsProvider.kt | 593 ------------------ .../state/manager/StateManagerAdaptor.kt | 1 + .../notification/NotificationsProvider.kt | 74 +++ .../BlockRewardNotificationProvider.kt | 87 +++ .../providers/FillsNotificationProvider.kt | 302 +++++++++ .../OrderStatusChangesNotificationProvider.kt | 151 +++++ .../PositionsNotificationProvider.kt | 82 +++ .../v2/supervisor/SubaccountSupervisor.kt | 2 +- .../payload/v4/V4AccountTests.kt | 2 +- 9 files changed, 699 insertions(+), 595 deletions(-) delete mode 100644 src/commonMain/kotlin/exchange.dydx.abacus/state/manager/NotificationsProvider.kt create mode 100644 src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt create mode 100644 src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/BlockRewardNotificationProvider.kt create mode 100644 src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt create mode 100644 src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt create mode 100644 src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/NotificationsProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/NotificationsProvider.kt deleted file mode 100644 index dc2a0976e..000000000 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/NotificationsProvider.kt +++ /dev/null @@ -1,593 +0,0 @@ -package exchange.dydx.abacus.state.manager - -import exchange.dydx.abacus.output.Asset -import exchange.dydx.abacus.output.BlockReward -import exchange.dydx.abacus.output.Notification -import exchange.dydx.abacus.output.NotificationPriority -import exchange.dydx.abacus.output.NotificationType -import exchange.dydx.abacus.output.PerpetualMarket -import exchange.dydx.abacus.output.SubaccountFill -import exchange.dydx.abacus.output.SubaccountOrder -import exchange.dydx.abacus.output.input.OrderStatus -import exchange.dydx.abacus.output.input.OrderType -import exchange.dydx.abacus.protocols.ParserProtocol -import exchange.dydx.abacus.state.model.TradingStateMachine -import exchange.dydx.abacus.utils.IList -import exchange.dydx.abacus.utils.IMap -import exchange.dydx.abacus.utils.IMutableList -import exchange.dydx.abacus.utils.JsonEncoder -import exchange.dydx.abacus.utils.Numeric -import exchange.dydx.abacus.utils.ParsingHelper -import exchange.dydx.abacus.utils.Rounder -import exchange.dydx.abacus.utils.UIImplementations -import exchange.dydx.abacus.utils.iMapOf -import exchange.dydx.abacus.utils.mutableMapOf -import exchange.dydx.abacus.utils.typedSafeSet -import kollections.iListOf -import kollections.iMutableListOf -import kollections.toIMap - -class NotificationsProvider( - private val uiImplementations: UIImplementations, - private val environment: V4Environment, - private val parser: ParserProtocol, - private val jsonEncoder: JsonEncoder, - private val useParentSubaccount: Boolean = false, -) { - internal fun buildNotifications( - stateMachine: TradingStateMachine, - subaccountNumber: Int - ): IMap { - val blockRewardsNotifications = - buildBlockRewardsNotifications(stateMachine) - val fillsNotifications = buildFillsNotifications(stateMachine, subaccountNumber) - val positionsNotifications = buildPositionsNotifications(stateMachine, subaccountNumber) - val orderStatusChangesNotifications = - buildOrderStatusChangesNotifications(stateMachine, subaccountNumber) - val merged1 = ParsingHelper.merge( - fillsNotifications, - positionsNotifications, - ) - val merged2 = ParsingHelper.merge( - merged1, - orderStatusChangesNotifications, - ) - val merged3 = ParsingHelper.merge( - merged2, - blockRewardsNotifications, - ) - return (merged3 as? Map)!!.toIMap() - } - - private fun asset(marketId: String): String { - return marketId.split("-").first() - } - - private fun buildBlockRewardsNotifications( - stateMachine: TradingStateMachine, - ): Map { - /* - We have to go through fills instead of orders, because - 1. Order doesn't have an updatedAt timestamp - 2. Order doesn't have an average filled price - */ - val account = - stateMachine.state?.account ?: return kollections.iMapOf() - - val notifications = mutableMapOf() - val accountBlockRewards = account.tradingRewards?.blockRewards - val token = environment.tokens["chain"]?.name - if (accountBlockRewards != null && token != null) { - for (blockReward in accountBlockRewards) { - createBlockRewardNotification(stateMachine, blockReward, token)?.let { - notifications.typedSafeSet( - it.id, - it, - ) - } - } - } - return notifications - } - - private fun createBlockRewardNotification( - stateMachine: TradingStateMachine, - blockReward: BlockReward, - token: String, - ): Notification? { - val blockHeight = blockReward.createdAtHeight - val blockRewardAmount = blockReward.tradingReward - val params = iMapOf( - "BLOCK_REWARD_HEIGHT" to blockHeight, - "TOKEN_NAME" to token, - "BLOCK_REWARD_AMOUNT" to blockRewardAmount, - "BLOCK_REWARD_TIME_MILLISECONDS" to blockReward.createdAtMilliseconds, - ).toIMap() - val paramsAsJson = jsonEncoder.encode(params) - - val title = - uiImplementations.localizer?.localize("NOTIFICATIONS.BLOCK_REWARD.TITLE") - ?: return null - val text = - uiImplementations.localizer?.localize( - "NOTIFICATIONS.BLOCK_REWARD.BODY", - paramsAsJson, - ) - - val notificationId = "blockReward:$blockHeight" - return Notification( - notificationId, - NotificationType.INFO, - NotificationPriority.NORMAL, - null, - title, - text, - null, - paramsAsJson, - blockReward.createdAtMilliseconds, - ) - } - - private fun buildFillsNotifications( - stateMachine: TradingStateMachine, - subaccountNumber: Int - ): Map { - /* - We have to go through fills instead of orders, because - 1. Order doesn't have an updatedAt timestamp - 2. Order doesn't have an average filled price - */ - val notifications = mutableMapOf() - val subaccount = - stateMachine.state?.subaccount(subaccountNumber) ?: return kollections.iMapOf() - - val subaccountFills = stateMachine.state?.fills?.get("$subaccountNumber") - if (subaccountFills != null) { - // Cache the orders - val orders = mutableMapOf() - for (order in subaccount.orders ?: iListOf()) { - orders[order.id] = order - } - // Cache the fills - val fills = mutableMapOf>() - val fillsList = iMutableListOf() - - for (fill in subaccountFills) { - val orderId = fill.orderId - if (orderId != null) { - val order = orders[orderId] - if (order != null) { - val fillsForOrder = fills[orderId] ?: iMutableListOf() - fillsForOrder.add(fill) - fills[orderId] = fillsForOrder - } - } else { - fillsList.add(fill) - } - } - - // Create notifications - // - for ((orderId, fillsForOrder) in fills) { - val order = orders[orderId] ?: continue - val notificationId = "order:$orderId" - notifications.typedSafeSet( - notificationId, - createFillNotification(stateMachine, fillsForOrder, order), - ) - } - - for (fill in fillsList) { - val fillId = fill.id - val notificationId = "fill:$fillId" - notifications.typedSafeSet( - notificationId, - createNotificationForFill(stateMachine, fill), - ) - } - } - return notifications - } - - private fun market(stateMachine: TradingStateMachine, marketId: String): PerpetualMarket? { - return stateMachine.state?.market(marketId) - } - - private fun asset(stateMachine: TradingStateMachine, marketId: String): Asset? { - val market = stateMachine.state?.market(marketId) ?: return null - val assetId = market.assetId - return stateMachine.state?.asset(assetId) - } - - private fun createFillNotification( - stateMachine: TradingStateMachine, - fillsForOrder: IList, - order: SubaccountOrder, - ): Notification? { - // Fills are in reverse chronological order - // First in the list is the newest fill - val fill = fillsForOrder.firstOrNull() ?: return null - val orderId = order.id - val marketId = fill.marketId - val market = market(stateMachine, marketId) ?: return null - val tickSize = market.configs?.tickSize ?: return null - val asset = asset(stateMachine, marketId) - val assetText = asset?.name ?: marketId - val marketImageUrl = asset?.resources?.imageUrl - val side = fill.side.rawValue - val sideText = uiImplementations.localizer?.localize("APP.GENERAL.$side") - val amountText = parser.asString(order.size) - val filledAmountText = parser.asString(order.totalFilled) - val priceText = priceText(fill.price, tickSize) - val averagePriceText = parser.asString(averagePrice(fillsForOrder)) - val orderType = order.type.rawValue - val orderTypeText = text(orderType) - val params = ( - iMapOf( - "MARKET" to marketId, - "ASSET" to assetText, - "SIDE" to sideText, - "AMOUNT" to amountText, - "FILLED_AMOUNT" to filledAmountText, - "PRICE" to priceText, - "AVERAGE_PRICE" to averagePriceText, - "ORDER_TYPE" to orderType, - "ORDER_TYPE_TEXT" to orderTypeText, - "ORDER_STATUS" to order.status.rawValue, - ).filterValues { it != null } as Map - ).toIMap() - val paramsAsJson = jsonEncoder.encode(params) - - val title = orderStatusTitle(order.status) ?: return null - val text = orderStatusText(order.status, paramsAsJson) - - val notificationId = "order:$orderId" - return Notification( - notificationId, - NotificationType.INFO, - NotificationPriority.NORMAL, - marketImageUrl, - title, - text, - "/orders/$orderId", - paramsAsJson, - fill.createdAtMilliseconds, - ) - } - - private fun priceText(price: Double, tickSize: Double): String { - val rounded = Rounder.round(price, tickSize, Rounder.RoundingMode.NEAREST) - return "$rounded" - } - - private fun averagePrice(fillsForOrder: IList): Double? { - var total = 0.0 - var totalSize = 0.0 - for (fill in fillsForOrder) { - total += fill.price * fill.size - totalSize += fill.size - } - return if (totalSize != 0.0) total / totalSize else null - } - - private fun orderStatusTitle(status: OrderStatus): String? { - return when (status) { - OrderStatus.filled -> { - uiImplementations.localizer?.localize("NOTIFICATIONS.ORDER_FILL.TITLE") - } - - OrderStatus.partiallyFilled -> { - uiImplementations.localizer?.localize("NOTIFICATIONS.ORDER_PARTIAL_FILL.TITLE") - } - - OrderStatus.cancelled -> { - uiImplementations.localizer?.localize("NOTIFICATIONS.ORDER_CANCEL.TITLE") - } - - else -> null - } - } - - private fun orderStatusText(status: OrderStatus, paramsAsJson: String?): String? { - return when (status) { - OrderStatus.filled -> { - uiImplementations.localizer?.localize( - "NOTIFICATIONS.ORDER_FILL.BODY", - paramsAsJson, - ) - } - - OrderStatus.partiallyFilled -> { - uiImplementations.localizer?.localize( - "NOTIFICATIONS.ORDER_PARTIAL_FILL.BODY", - paramsAsJson, - ) - } - - OrderStatus.cancelled -> { - uiImplementations.localizer?.localize( - "NOTIFICATIONS.ORDER_CANCEL.BODY", - paramsAsJson, - ) - } - - else -> null - } - } - - private fun createNotificationForFill( - stateMachine: TradingStateMachine, - fill: SubaccountFill, - ): Notification? { - val fillId = fill.id - val marketId = fill.marketId - val asset = asset(stateMachine, marketId) ?: return null - val assetText = asset.name - val marketImageUrl = asset.resources?.imageUrl - val side = fill.side.rawValue - val sideText = uiImplementations.localizer?.localize("APP.GENERAL.$side") - val amountText = parser.asString(fill.size) - val priceText = parser.asString(fill.price) - val fillType = fill.type.rawValue - val fillTypeText = text(fillType) - val params = ( - iMapOf( - "MARKET" to marketId, - "ASSET" to assetText, - "SIDE" to sideText, - "AMOUNT" to amountText, - "PRICE" to priceText, - "FILL_TYPE" to fillType, - "FILL_TYPE_TEXT" to fillTypeText, - ).filterValues { it != null } as Map - ).toIMap() - val paramsAsJson = jsonEncoder.encode(params) - - var title: String? = null - var text: String? = null - - when (fill.type) { - OrderType.deleveraged -> { - title = uiImplementations.localizer?.localize("NOTIFICATIONS.DELEVERAGED.TITLE") - ?: return null - text = uiImplementations.localizer?.localize( - "NOTIFICATIONS.DELEVERAGED.BODY", - paramsAsJson, - ) - } - - OrderType.finalSettlement -> { - title = - uiImplementations.localizer?.localize("NOTIFICATIONS.FINAL_SETTLEMENT.TITLE") - ?: return null - text = uiImplementations.localizer?.localize( - "NOTIFICATIONS.FINAL_SETTLEMENT.BODY", - paramsAsJson, - ) - } - - OrderType.liquidation -> { - title = uiImplementations.localizer?.localize("NOTIFICATIONS.LIQUIDATION.TITLE") - ?: return null - text = uiImplementations.localizer?.localize( - "NOTIFICATIONS.LIQUIDATION.BODY", - paramsAsJson, - ) - } - - OrderType.offsetting -> { - title = uiImplementations.localizer?.localize("NOTIFICATIONS.OFFSETTING.TITLE") - ?: return null - text = uiImplementations.localizer?.localize( - "NOTIFICATIONS.OFFSETTING.BODY", - paramsAsJson, - ) - } - - else -> return null - } - - val notificationId = "fill:$fillId" - return Notification( - notificationId, - NotificationType.INFO, - NotificationPriority.NORMAL, - marketImageUrl, - title, - text, - null, - paramsAsJson, - fill.createdAtMilliseconds, - ) - } - - private fun buildPositionsNotifications( - stateMachine: TradingStateMachine, - subaccountNumber: Int - ): Map { - /* - We have to go to the dynamic data to find closed positions - Struct contains open positions only - */ - val notifications = mutableMapOf() - val positions = parser.asMap( - parser.value( - stateMachine.data, - if (useParentSubaccount) { - "wallet.account.groupedSubaccounts.$subaccountNumber.positions" - } else { - "wallet.account.subaccounts.$subaccountNumber.positions" - }, - ), - ) - - if (positions != null) { - for ((marketId, data) in positions) { - val position = parser.asMap(data) ?: continue - val positionStatus = parser.asString(position["status"]) - if (positionStatus == "CLOSED") { - val closedAt = parser.asDatetime(position["closedAt"]) ?: continue - val asset = asset(stateMachine, marketId) ?: continue - val assetText = asset.name - val marketImageUrl = asset.resources?.imageUrl - val params = ( - iMapOf( - "MARKET" to marketId, - "ASSET" to assetText, - ).filterValues { it != null } as Map - ).toIMap() - val paramsAsJson = jsonEncoder.encode(params) - - val title = - uiImplementations.localizer?.localize("NOTIFICATIONS.POSITION_CLOSED.TITLE") - ?: continue - val text = uiImplementations.localizer?.localize( - "NOTIFICATIONS.POSITION_CLOSED.BODY", - paramsAsJson, - ) - - val notificationId = "position:$marketId" - notifications[notificationId] = Notification( - notificationId, - NotificationType.INFO, - NotificationPriority.NORMAL, - marketImageUrl, - title, - text, - null, - paramsAsJson, - closedAt.toEpochMilliseconds().toDouble(), - ) - } - } - } - return notifications - } - - private fun buildOrderStatusChangesNotifications( - stateMachine: TradingStateMachine, - subaccountNumber: Int - ): Map { - /* - We have to go through fills instead of orders, because - 1. Order doesn't have an updatedAt timestamp - 2. Order doesn't have an average filled price - */ - val notifications = mutableMapOf() - val subaccount = stateMachine.state?.subaccount(subaccountNumber) ?: return kollections.iMapOf() - subaccount.orders - - val subaccountOrders = subaccount.orders - - if (subaccountOrders != null) { - for (order in subaccountOrders) { - val orderStatusNotification = createOrderStatusNotification(stateMachine, order) - if (orderStatusNotification != null) { - val orderId = order.id - val notificationId = "order_status:$orderId" - notifications.typedSafeSet(notificationId, orderStatusNotification) - } - } - } - return notifications - } - - private fun createOrderStatusNotification( - stateMachine: TradingStateMachine, - order: SubaccountOrder, - ): Notification? { - var timestamp: Double? = null - val statusNotificationStringKey = when (order.status) { - OrderStatus.open -> { - when (order.type) { - OrderType.stopLimit, OrderType.stopMarket, OrderType.takeProfitLimit, OrderType.takeProfitMarket -> { - timestamp = order.updatedAtMilliseconds - if (timestamp != null && order.totalFilled == Numeric.double.ZERO) { - "NOTIFICATIONS.ORDER_TRIGGERED" - } else { - null - } - } - - OrderType.limit, OrderType.market -> { - /* - Short term orders should get filled/partially filled immediately, so we don't need to handle OPENED notification - And it doesn't have a timestamp - */ - timestamp = order.createdAtMilliseconds - if (timestamp != null && order.totalFilled == Numeric.double.ZERO) { - "NOTIFICATIONS.ORDER_OPENED" - } else { - null - } - } - - else -> null - } - } - - OrderStatus.cancelled -> { - if ((order.totalFilled ?: Numeric.double.ZERO) > Numeric.double.ZERO) { - "NOTIFICATIONS.ORDER_CANCEL_WITH_PARTIAL_FILL" - } else { - "NOTIFICATIONS.ORDER_CANCEL" - } - } - - else -> null - } - return if (statusNotificationStringKey != null && timestamp != null) { - val marketId = order.marketId - val asset = asset(stateMachine, marketId) ?: return null - val marketImageUrl = asset.resources?.imageUrl - val side = order.side.rawValue - val sideText = uiImplementations.localizer?.localize("APP.GENERAL.$side") - val amountText = parser.asString(order.size) - val totalFilled = parser.asString(order.totalFilled) - val orderType = order.type.rawValue - val orderTypeText = text(orderType) - val params = ( - iMapOf( - "MARKET" to marketId, - "SIDE" to sideText, - "AMOUNT" to amountText, - "TOTAL_FILLED" to totalFilled, - "ORDER_TYPE" to orderType, - "ORDER_TYPE_TEXT" to orderTypeText, - "ORDER_STATUS" to order.status.rawValue, - ).filterValues { it != null } as Map - ).toIMap() - val paramsAsJson = jsonEncoder.encode(params) - - val title = - uiImplementations.localizer?.localize("$statusNotificationStringKey.TITLE") - ?: return null - val text = - uiImplementations.localizer?.localize( - "$statusNotificationStringKey.BODY", - paramsAsJson, - ) - - val orderId = order.id - val notificationId = "orderstatus:$orderId" - return Notification( - notificationId, - NotificationType.INFO, - NotificationPriority.NORMAL, - marketImageUrl, - title, - text, - "/orders/$orderId", - paramsAsJson, - timestamp, - ) - } else { - null - } - } - - private fun text(orderType: String): String? { - return uiImplementations.localizer?.localize("APP.ENUMS.ORDER_TYPE.$orderType") - ?: return null - } -} diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt index 6ebc05891..1ebe72964 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt @@ -29,6 +29,7 @@ import exchange.dydx.abacus.state.changes.Changes import exchange.dydx.abacus.state.changes.Changes.candles import exchange.dydx.abacus.state.changes.StateChanges import exchange.dydx.abacus.state.manager.configs.StateManagerConfigs +import exchange.dydx.abacus.state.manager.notification.NotificationsProvider import exchange.dydx.abacus.state.manager.utils.Address import exchange.dydx.abacus.state.manager.utils.DydxAddress import exchange.dydx.abacus.state.manager.utils.EvmAddress diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt new file mode 100644 index 000000000..7f5c72080 --- /dev/null +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt @@ -0,0 +1,74 @@ +package exchange.dydx.abacus.state.manager.notification + +import exchange.dydx.abacus.output.Asset +import exchange.dydx.abacus.output.Notification +import exchange.dydx.abacus.protocols.ParserProtocol +import exchange.dydx.abacus.state.manager.V4Environment +import exchange.dydx.abacus.state.manager.notification.providers.BlockRewardNotificationProvider +import exchange.dydx.abacus.state.manager.notification.providers.OrderStatusChangesNotificationProvider +import exchange.dydx.abacus.state.model.TradingStateMachine +import exchange.dydx.abacus.utils.IMap +import exchange.dydx.abacus.utils.JsonEncoder +import exchange.dydx.abacus.utils.ParsingHelper +import exchange.dydx.abacus.utils.UIImplementations +import kollections.toIMap + +interface NotificationsProviderProtocol { + fun buildNotifications( + stateMachine: TradingStateMachine, + subaccountNumber: Int + ): IMap + + fun asset(stateMachine: TradingStateMachine, marketId: String): Asset? { + val market = stateMachine.state?.market(marketId) ?: return null + val assetId = market.assetId + return stateMachine.state?.asset(assetId) + } +} + +class NotificationsProvider( + private val uiImplementations: UIImplementations, + private val environment: V4Environment, + private val parser: ParserProtocol, + private val jsonEncoder: JsonEncoder, + private val useParentSubaccount: Boolean = false, +) : NotificationsProviderProtocol { + + private val providers = listOf( + BlockRewardNotificationProvider( + uiImplementations, + environment, + jsonEncoder, + ), + FillsNotificationProvider( + uiImplementations, + parser, + jsonEncoder, + ), + PositionsNotificationProvider( + uiImplementations, + parser, + jsonEncoder, + useParentSubaccount, + ), + OrderStatusChangesNotificationProvider( + uiImplementations, + parser, + jsonEncoder, + ), + ) + + override fun buildNotifications( + stateMachine: TradingStateMachine, + subaccountNumber: Int + ): IMap { + var merged: Map? = null + + providers.forEach { provider -> + val notifications = provider.buildNotifications(stateMachine, subaccountNumber) + merged = ParsingHelper.merge(merged, notifications) as? Map + } + + return merged?.toIMap() ?: kollections.iMapOf() + } +} diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/BlockRewardNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/BlockRewardNotificationProvider.kt new file mode 100644 index 000000000..3de04782a --- /dev/null +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/BlockRewardNotificationProvider.kt @@ -0,0 +1,87 @@ +package exchange.dydx.abacus.state.manager.notification.providers + +import exchange.dydx.abacus.output.BlockReward +import exchange.dydx.abacus.output.Notification +import exchange.dydx.abacus.output.NotificationPriority +import exchange.dydx.abacus.output.NotificationType +import exchange.dydx.abacus.state.manager.V4Environment +import exchange.dydx.abacus.state.manager.notification.NotificationsProviderProtocol +import exchange.dydx.abacus.state.model.TradingStateMachine +import exchange.dydx.abacus.utils.IMap +import exchange.dydx.abacus.utils.JsonEncoder +import exchange.dydx.abacus.utils.UIImplementations +import exchange.dydx.abacus.utils.iMapOf +import exchange.dydx.abacus.utils.typedSafeSet +import kollections.toIMap + +class BlockRewardNotificationProvider( + private val uiImplementations: UIImplementations, + private val environment: V4Environment, + private val jsonEncoder: JsonEncoder, +) : NotificationsProviderProtocol { + override fun buildNotifications( + stateMachine: TradingStateMachine, + subaccountNumber: Int + ): IMap { + /* + We have to go through fills instead of orders, because + 1. Order doesn't have an updatedAt timestamp + 2. Order doesn't have an average filled price + */ + val account = + stateMachine.state?.account ?: return kollections.iMapOf() + + val notifications = exchange.dydx.abacus.utils.mutableMapOf() + val accountBlockRewards = account.tradingRewards?.blockRewards + val token = environment.tokens["chain"]?.name + if (accountBlockRewards != null && token != null) { + for (blockReward in accountBlockRewards) { + createBlockRewardNotification(stateMachine, blockReward, token)?.let { + notifications.typedSafeSet( + it.id, + it, + ) + } + } + } + return notifications + } + + private fun createBlockRewardNotification( + stateMachine: TradingStateMachine, + blockReward: BlockReward, + token: String, + ): Notification? { + val blockHeight = blockReward.createdAtHeight + val blockRewardAmount = blockReward.tradingReward + val params = iMapOf( + "BLOCK_REWARD_HEIGHT" to blockHeight, + "TOKEN_NAME" to token, + "BLOCK_REWARD_AMOUNT" to blockRewardAmount, + "BLOCK_REWARD_TIME_MILLISECONDS" to blockReward.createdAtMilliseconds, + ).toIMap() + val paramsAsJson = jsonEncoder.encode(params) + + val title = + uiImplementations.localizer?.localize("NOTIFICATIONS.BLOCK_REWARD.TITLE") + ?: return null + val text = + uiImplementations.localizer?.localize( + "NOTIFICATIONS.BLOCK_REWARD.BODY", + paramsAsJson, + ) + + val notificationId = "blockReward:$blockHeight" + return Notification( + notificationId, + NotificationType.INFO, + NotificationPriority.NORMAL, + null, + title, + text, + null, + paramsAsJson, + blockReward.createdAtMilliseconds, + ) + } +} diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt new file mode 100644 index 000000000..2daf8884b --- /dev/null +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt @@ -0,0 +1,302 @@ +package exchange.dydx.abacus.state.manager.notification + +import exchange.dydx.abacus.output.Notification +import exchange.dydx.abacus.output.NotificationPriority +import exchange.dydx.abacus.output.NotificationType +import exchange.dydx.abacus.output.PerpetualMarket +import exchange.dydx.abacus.output.SubaccountFill +import exchange.dydx.abacus.output.SubaccountOrder +import exchange.dydx.abacus.output.input.OrderStatus +import exchange.dydx.abacus.output.input.OrderType +import exchange.dydx.abacus.protocols.ParserProtocol +import exchange.dydx.abacus.state.model.TradingStateMachine +import exchange.dydx.abacus.utils.IList +import exchange.dydx.abacus.utils.IMap +import exchange.dydx.abacus.utils.IMutableList +import exchange.dydx.abacus.utils.JsonEncoder +import exchange.dydx.abacus.utils.Rounder +import exchange.dydx.abacus.utils.UIImplementations +import exchange.dydx.abacus.utils.iMapOf +import exchange.dydx.abacus.utils.typedSafeSet +import kollections.iListOf +import kollections.iMutableListOf +import kollections.toIMap + +class FillsNotificationProvider( + private val uiImplementations: UIImplementations, + private val parser: ParserProtocol, + private val jsonEncoder: JsonEncoder, +) : NotificationsProviderProtocol { + override fun buildNotifications( + stateMachine: TradingStateMachine, + subaccountNumber: Int + ): IMap { + /* + We have to go through fills instead of orders, because + 1. Order doesn't have an updatedAt timestamp + 2. Order doesn't have an average filled price + */ + val notifications = exchange.dydx.abacus.utils.mutableMapOf() + val subaccount = + stateMachine.state?.subaccount(subaccountNumber) ?: return kollections.iMapOf() + + val subaccountFills = stateMachine.state?.fills?.get("$subaccountNumber") + if (subaccountFills != null) { + // Cache the orders + val orders = exchange.dydx.abacus.utils.mutableMapOf() + for (order in subaccount.orders ?: iListOf()) { + orders[order.id] = order + } + // Cache the fills + val fills = + exchange.dydx.abacus.utils.mutableMapOf>() + val fillsList = iMutableListOf() + + for (fill in subaccountFills) { + val orderId = fill.orderId + if (orderId != null) { + val order = orders[orderId] + if (order != null) { + val fillsForOrder = fills[orderId] ?: iMutableListOf() + fillsForOrder.add(fill) + fills[orderId] = fillsForOrder + } + } else { + fillsList.add(fill) + } + } + + // Create notifications + // + for ((orderId, fillsForOrder) in fills) { + val order = orders[orderId] ?: continue + val notificationId = "order:$orderId" + notifications.typedSafeSet( + notificationId, + createFillNotification(stateMachine, fillsForOrder, order), + ) + } + + for (fill in fillsList) { + val fillId = fill.id + val notificationId = "fill:$fillId" + notifications.typedSafeSet( + notificationId, + createNotificationForFill(stateMachine, fill), + ) + } + } + return notifications + } + + private fun createFillNotification( + stateMachine: TradingStateMachine, + fillsForOrder: IList, + order: SubaccountOrder, + ): Notification? { + // Fills are in reverse chronological order + // First in the list is the newest fill + val fill = fillsForOrder.firstOrNull() ?: return null + val orderId = order.id + val marketId = fill.marketId + val market = market(stateMachine, marketId) ?: return null + val tickSize = market.configs?.tickSize ?: return null + val asset = asset(stateMachine, marketId) + val assetText = asset?.name ?: marketId + val marketImageUrl = asset?.resources?.imageUrl + val side = fill.side.rawValue + val sideText = uiImplementations.localizer?.localize("APP.GENERAL.$side") + val amountText = parser.asString(order.size) + val filledAmountText = parser.asString(order.totalFilled) + val priceText = priceText(fill.price, tickSize) + val averagePriceText = parser.asString(averagePrice(fillsForOrder)) + val orderType = order.type.rawValue + val orderTypeText = text(orderType) + val params = ( + iMapOf( + "MARKET" to marketId, + "ASSET" to assetText, + "SIDE" to sideText, + "AMOUNT" to amountText, + "FILLED_AMOUNT" to filledAmountText, + "PRICE" to priceText, + "AVERAGE_PRICE" to averagePriceText, + "ORDER_TYPE" to orderType, + "ORDER_TYPE_TEXT" to orderTypeText, + "ORDER_STATUS" to order.status.rawValue, + ).filterValues { it != null } as Map + ).toIMap() + val paramsAsJson = jsonEncoder.encode(params) + + val title = orderStatusTitle(order.status) ?: return null + val text = orderStatusText(order.status, paramsAsJson) + + val notificationId = "order:$orderId" + return Notification( + notificationId, + NotificationType.INFO, + NotificationPriority.NORMAL, + marketImageUrl, + title, + text, + "/orders/$orderId", + paramsAsJson, + fill.createdAtMilliseconds, + ) + } + + private fun createNotificationForFill( + stateMachine: TradingStateMachine, + fill: SubaccountFill, + ): Notification? { + val fillId = fill.id + val marketId = fill.marketId + val asset = asset(stateMachine, marketId) ?: return null + val assetText = asset.name + val marketImageUrl = asset.resources?.imageUrl + val side = fill.side.rawValue + val sideText = uiImplementations.localizer?.localize("APP.GENERAL.$side") + val amountText = parser.asString(fill.size) + val priceText = parser.asString(fill.price) + val fillType = fill.type.rawValue + val fillTypeText = text(fillType) + val params = ( + iMapOf( + "MARKET" to marketId, + "ASSET" to assetText, + "SIDE" to sideText, + "AMOUNT" to amountText, + "PRICE" to priceText, + "FILL_TYPE" to fillType, + "FILL_TYPE_TEXT" to fillTypeText, + ).filterValues { it != null } as Map + ).toIMap() + val paramsAsJson = jsonEncoder.encode(params) + + var title: String? = null + var text: String? = null + + when (fill.type) { + OrderType.deleveraged -> { + title = uiImplementations.localizer?.localize("NOTIFICATIONS.DELEVERAGED.TITLE") + ?: return null + text = uiImplementations.localizer?.localize( + "NOTIFICATIONS.DELEVERAGED.BODY", + paramsAsJson, + ) + } + + OrderType.finalSettlement -> { + title = + uiImplementations.localizer?.localize("NOTIFICATIONS.FINAL_SETTLEMENT.TITLE") + ?: return null + text = uiImplementations.localizer?.localize( + "NOTIFICATIONS.FINAL_SETTLEMENT.BODY", + paramsAsJson, + ) + } + + OrderType.liquidation -> { + title = uiImplementations.localizer?.localize("NOTIFICATIONS.LIQUIDATION.TITLE") + ?: return null + text = uiImplementations.localizer?.localize( + "NOTIFICATIONS.LIQUIDATION.BODY", + paramsAsJson, + ) + } + + OrderType.offsetting -> { + title = uiImplementations.localizer?.localize("NOTIFICATIONS.OFFSETTING.TITLE") + ?: return null + text = uiImplementations.localizer?.localize( + "NOTIFICATIONS.OFFSETTING.BODY", + paramsAsJson, + ) + } + + else -> return null + } + + val notificationId = "fill:$fillId" + return Notification( + notificationId, + NotificationType.INFO, + NotificationPriority.NORMAL, + marketImageUrl, + title, + text, + null, + paramsAsJson, + fill.createdAtMilliseconds, + ) + } + + private fun market(stateMachine: TradingStateMachine, marketId: String): PerpetualMarket? { + return stateMachine.state?.market(marketId) + } + + private fun priceText(price: Double, tickSize: Double): String { + val rounded = Rounder.round(price, tickSize, Rounder.RoundingMode.NEAREST) + return "$rounded" + } + + private fun averagePrice(fillsForOrder: IList): Double? { + var total = 0.0 + var totalSize = 0.0 + for (fill in fillsForOrder) { + total += fill.price * fill.size + totalSize += fill.size + } + return if (totalSize != 0.0) total / totalSize else null + } + + private fun orderStatusTitle(status: OrderStatus): String? { + return when (status) { + OrderStatus.filled -> { + uiImplementations.localizer?.localize("NOTIFICATIONS.ORDER_FILL.TITLE") + } + + OrderStatus.partiallyFilled -> { + uiImplementations.localizer?.localize("NOTIFICATIONS.ORDER_PARTIAL_FILL.TITLE") + } + + OrderStatus.cancelled -> { + uiImplementations.localizer?.localize("NOTIFICATIONS.ORDER_CANCEL.TITLE") + } + + else -> null + } + } + + private fun orderStatusText(status: OrderStatus, paramsAsJson: String?): String? { + return when (status) { + OrderStatus.filled -> { + uiImplementations.localizer?.localize( + "NOTIFICATIONS.ORDER_FILL.BODY", + paramsAsJson, + ) + } + + OrderStatus.partiallyFilled -> { + uiImplementations.localizer?.localize( + "NOTIFICATIONS.ORDER_PARTIAL_FILL.BODY", + paramsAsJson, + ) + } + + OrderStatus.cancelled -> { + uiImplementations.localizer?.localize( + "NOTIFICATIONS.ORDER_CANCEL.BODY", + paramsAsJson, + ) + } + + else -> null + } + } + + private fun text(orderType: String): String? { + return uiImplementations.localizer?.localize("APP.ENUMS.ORDER_TYPE.$orderType") + ?: return null + } +} diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt new file mode 100644 index 000000000..5dca3a0a2 --- /dev/null +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt @@ -0,0 +1,151 @@ +package exchange.dydx.abacus.state.manager.notification.providers + +import exchange.dydx.abacus.output.Notification +import exchange.dydx.abacus.output.NotificationPriority +import exchange.dydx.abacus.output.NotificationType +import exchange.dydx.abacus.output.SubaccountOrder +import exchange.dydx.abacus.output.input.OrderStatus +import exchange.dydx.abacus.output.input.OrderType +import exchange.dydx.abacus.protocols.ParserProtocol +import exchange.dydx.abacus.state.manager.notification.NotificationsProviderProtocol +import exchange.dydx.abacus.state.model.TradingStateMachine +import exchange.dydx.abacus.utils.IMap +import exchange.dydx.abacus.utils.JsonEncoder +import exchange.dydx.abacus.utils.Numeric +import exchange.dydx.abacus.utils.UIImplementations +import exchange.dydx.abacus.utils.iMapOf +import exchange.dydx.abacus.utils.typedSafeSet +import kollections.toIMap + +class OrderStatusChangesNotificationProvider( + private val uiImplementations: UIImplementations, + private val parser: ParserProtocol, + private val jsonEncoder: JsonEncoder, +) : NotificationsProviderProtocol { + override fun buildNotifications( + stateMachine: TradingStateMachine, + subaccountNumber: Int + ): IMap { + /* + We have to go through fills instead of orders, because + 1. Order doesn't have an updatedAt timestamp + 2. Order doesn't have an average filled price + */ + val notifications = exchange.dydx.abacus.utils.mutableMapOf() + val subaccount = stateMachine.state?.subaccount(subaccountNumber) ?: return kollections.iMapOf() + subaccount.orders + + val subaccountOrders = subaccount.orders + + if (subaccountOrders != null) { + for (order in subaccountOrders) { + val orderStatusNotification = createOrderStatusNotification(stateMachine, order) + if (orderStatusNotification != null) { + val orderId = order.id + val notificationId = "order_status:$orderId" + notifications.typedSafeSet(notificationId, orderStatusNotification) + } + } + } + return notifications + } + + private fun createOrderStatusNotification( + stateMachine: TradingStateMachine, + order: SubaccountOrder, + ): Notification? { + var timestamp: Double? = null + val statusNotificationStringKey = when (order.status) { + OrderStatus.open -> { + when (order.type) { + OrderType.stopLimit, OrderType.stopMarket, OrderType.takeProfitLimit, OrderType.takeProfitMarket -> { + timestamp = order.updatedAtMilliseconds + if (timestamp != null && order.totalFilled == Numeric.double.ZERO) { + "NOTIFICATIONS.ORDER_TRIGGERED" + } else { + null + } + } + + OrderType.limit, OrderType.market -> { + /* + Short term orders should get filled/partially filled immediately, so we don't need to handle OPENED notification + And it doesn't have a timestamp + */ + timestamp = order.createdAtMilliseconds + if (timestamp != null && order.totalFilled == Numeric.double.ZERO) { + "NOTIFICATIONS.ORDER_OPENED" + } else { + null + } + } + + else -> null + } + } + + OrderStatus.cancelled -> { + if ((order.totalFilled ?: Numeric.double.ZERO) > Numeric.double.ZERO) { + "NOTIFICATIONS.ORDER_CANCEL_WITH_PARTIAL_FILL" + } else { + "NOTIFICATIONS.ORDER_CANCEL" + } + } + + else -> null + } + return if (statusNotificationStringKey != null && timestamp != null) { + val marketId = order.marketId + val asset = asset(stateMachine, marketId) ?: return null + val marketImageUrl = asset.resources?.imageUrl + val side = order.side.rawValue + val sideText = uiImplementations.localizer?.localize("APP.GENERAL.$side") + val amountText = parser.asString(order.size) + val totalFilled = parser.asString(order.totalFilled) + val orderType = order.type.rawValue + val orderTypeText = text(orderType) + val params = ( + iMapOf( + "MARKET" to marketId, + "SIDE" to sideText, + "AMOUNT" to amountText, + "TOTAL_FILLED" to totalFilled, + "ORDER_TYPE" to orderType, + "ORDER_TYPE_TEXT" to orderTypeText, + "ORDER_STATUS" to order.status.rawValue, + ).filterValues { it != null } as Map + ).toIMap() + val paramsAsJson = jsonEncoder.encode(params) + + val title = + uiImplementations.localizer?.localize("$statusNotificationStringKey.TITLE") + ?: return null + val text = + uiImplementations.localizer?.localize( + "$statusNotificationStringKey.BODY", + paramsAsJson, + ) + + val orderId = order.id + val notificationId = "orderstatus:$orderId" + return Notification( + notificationId, + NotificationType.INFO, + NotificationPriority.NORMAL, + marketImageUrl, + title, + text, + "/orders/$orderId", + paramsAsJson, + timestamp, + ) + } else { + null + } + } + + private fun text(orderType: String): String? { + return uiImplementations.localizer?.localize("APP.ENUMS.ORDER_TYPE.$orderType") + ?: return null + } +} diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt new file mode 100644 index 000000000..95336830a --- /dev/null +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt @@ -0,0 +1,82 @@ +package exchange.dydx.abacus.state.manager.notification + +import exchange.dydx.abacus.output.Notification +import exchange.dydx.abacus.output.NotificationPriority +import exchange.dydx.abacus.output.NotificationType +import exchange.dydx.abacus.protocols.ParserProtocol +import exchange.dydx.abacus.state.model.TradingStateMachine +import exchange.dydx.abacus.utils.IMap +import exchange.dydx.abacus.utils.JsonEncoder +import exchange.dydx.abacus.utils.UIImplementations +import exchange.dydx.abacus.utils.iMapOf +import kollections.toIMap + +class PositionsNotificationProvider( + private val uiImplementations: UIImplementations, + private val parser: ParserProtocol, + private val jsonEncoder: JsonEncoder, + private val useParentSubaccount: Boolean = false, +) : NotificationsProviderProtocol { + override fun buildNotifications( + stateMachine: TradingStateMachine, + subaccountNumber: Int + ): IMap { + /* + We have to go to the dynamic data to find closed positions + Struct contains open positions only + */ + val notifications = exchange.dydx.abacus.utils.mutableMapOf() + val positions = parser.asMap( + parser.value( + stateMachine.data, + if (useParentSubaccount) { + "wallet.account.groupedSubaccounts.$subaccountNumber.positions" + } else { + "wallet.account.subaccounts.$subaccountNumber.positions" + }, + ), + ) + + if (positions != null) { + for ((marketId, data) in positions) { + val position = parser.asMap(data) ?: continue + val positionStatus = parser.asString(position["status"]) + if (positionStatus == "CLOSED") { + val closedAt = parser.asDatetime(position["closedAt"]) ?: continue + val asset = asset(stateMachine, marketId) ?: continue + val assetText = asset.name + val marketImageUrl = asset.resources?.imageUrl + val params = ( + iMapOf( + "MARKET" to marketId, + "ASSET" to assetText, + ).filterValues { it != null } as Map + ).toIMap() + val paramsAsJson = jsonEncoder.encode(params) + + val title = + uiImplementations.localizer?.localize("NOTIFICATIONS.POSITION_CLOSED.TITLE") + ?: continue + val text = uiImplementations.localizer?.localize( + "NOTIFICATIONS.POSITION_CLOSED.BODY", + paramsAsJson, + ) + + val notificationId = "position:$marketId" + notifications[notificationId] = Notification( + notificationId, + NotificationType.INFO, + NotificationPriority.NORMAL, + marketImageUrl, + title, + text, + null, + paramsAsJson, + closedAt.toEpochMilliseconds().toDouble(), + ) + } + } + } + return notifications + } +} diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt index 44416eb40..907b69b1d 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt @@ -28,11 +28,11 @@ import exchange.dydx.abacus.state.manager.HumanReadablePlaceOrderPayload import exchange.dydx.abacus.state.manager.HumanReadableSubaccountTransferPayload import exchange.dydx.abacus.state.manager.HumanReadableTriggerOrdersPayload import exchange.dydx.abacus.state.manager.HumanReadableWithdrawPayload -import exchange.dydx.abacus.state.manager.NotificationsProvider import exchange.dydx.abacus.state.manager.PlaceOrderMarketInfo import exchange.dydx.abacus.state.manager.PlaceOrderRecord import exchange.dydx.abacus.state.manager.TransactionParams import exchange.dydx.abacus.state.manager.TransactionQueue +import exchange.dydx.abacus.state.manager.notification.NotificationsProvider import exchange.dydx.abacus.state.model.ClosePositionInputField import exchange.dydx.abacus.state.model.TradeInputField import exchange.dydx.abacus.state.model.TradingStateMachine diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4AccountTests.kt b/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4AccountTests.kt index f19930dc6..42da74e67 100644 --- a/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4AccountTests.kt +++ b/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4AccountTests.kt @@ -4,7 +4,7 @@ import exchange.dydx.abacus.payload.BaseTests import exchange.dydx.abacus.responses.StateResponse import exchange.dydx.abacus.state.app.adaptors.AbUrl import exchange.dydx.abacus.state.manager.BlockAndTime -import exchange.dydx.abacus.state.manager.NotificationsProvider +import exchange.dydx.abacus.state.manager.notification.NotificationsProvider import exchange.dydx.abacus.state.model.historicalTradingRewards import exchange.dydx.abacus.state.model.onChainAccountBalances import exchange.dydx.abacus.state.model.onChainDelegations From 2eae366be8659f50d59fae9576d7cd75fadac56b Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 26 Apr 2024 11:37:15 -0700 Subject: [PATCH 2/8] Bump Version --- build.gradle.kts | 2 +- .../iOS/Pods/Pods.xcodeproj/project.pbxproj | 226 ++++++++---------- v4_abacus.podspec | 2 +- 3 files changed, 105 insertions(+), 125 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index cd9af0445..da568286c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,7 +49,7 @@ allprojects { } group = "exchange.dydx.abacus" -version = "1.6.49" +version = "1.6.50" repositories { google() diff --git a/integration/iOS/Pods/Pods.xcodeproj/project.pbxproj b/integration/iOS/Pods/Pods.xcodeproj/project.pbxproj index b070c6fbb..91fd3461a 100644 --- a/integration/iOS/Pods/Pods.xcodeproj/project.pbxproj +++ b/integration/iOS/Pods/Pods.xcodeproj/project.pbxproj @@ -9,10 +9,9 @@ /* Begin PBXAggregateTarget section */ 4084846DAF1774840D25DF1BF2460325 /* abacus */ = { isa = PBXAggregateTarget; - buildConfigurationList = 127F9C06E33E9DC2AB3876F089264EB1 /* Build configuration list for PBXAggregateTarget "abacus" */; + buildConfigurationList = B36D4FC54F44832C64D6BFCFC7EF4665 /* Build configuration list for PBXAggregateTarget "abacus" */; buildPhases = ( - DB36ACE8A857E9B93C25EA309FF42C2A /* [CP-User] Build abacus */, - 903ECA29140368245E4B69BE2D0DBCA4 /* [CP] Copy dSYMs */, + 1403E0AEBF8A2087DF8CACA188B609E8 /* [CP-User] Build abacus */, ); dependencies = ( ); @@ -143,13 +142,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 174DE097054DE7A0410C57AF4AEF5A1A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 469F25E790D19440507BF938A40578A7; - remoteInfo = "Pods-abacus.ios"; - }; 8437FCB39ECA4A44D93FCDCBF6066E92 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; @@ -164,6 +156,13 @@ remoteGlobalIDString = 4084846DAF1774840D25DF1BF2460325; remoteInfo = abacus; }; + F99C8B5A9E9146040BECE7ABFD8E196E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 469F25E790D19440507BF938A40578A7; + remoteInfo = "Pods-abacus.ios"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -174,7 +173,6 @@ 05F962230C27EB8320B3F9DACAB26666 /* Random.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Random.swift; path = Sources/CryptoSwift/CS_BigInt/Random.swift; sourceTree = ""; }; 068F760AEB5D19F06497CBD5A01D4B17 /* PBKDF1.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PBKDF1.swift; path = Sources/CryptoSwift/PKCS/PBKDF1.swift; sourceTree = ""; }; 0744F3E2DBB3A6893AC7B625FCBA2151 /* Generics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Generics.swift; path = Sources/CryptoSwift/Generics.swift; sourceTree = ""; }; - 090DA5F6297DCDBC49F0E90B1755BD86 /* abacus.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = abacus.debug.xcconfig; sourceTree = ""; }; 0A52523A80E0465BAEC42025DAD553B2 /* Pods-abacus.iosTests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-abacus.iosTests-Info.plist"; sourceTree = ""; }; 0D4EF333478AFFA4893B29F877CE2E3B /* Pods-abacus.iosTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-abacus.iosTests.modulemap"; sourceTree = ""; }; 0ECEA0D8830DCE37C7297C5F1342B08E /* Pods-abacus.ios.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-abacus.ios.release.xcconfig"; sourceTree = ""; }; @@ -190,13 +188,13 @@ 1CF2318F38D1207A2F8BF92B7B8A294E /* Array+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Array+Extension.swift"; path = "Sources/CryptoSwift/Array+Extension.swift"; sourceTree = ""; }; 1DE302C0F83772A905581CC7090CA123 /* Collection+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Collection+Extension.swift"; path = "Sources/CryptoSwift/Collection+Extension.swift"; sourceTree = ""; }; 1E34A6EC8D702D85DFC8AB0BCA04D225 /* Pods-abacus.iosTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-abacus.iosTests-acknowledgements.markdown"; sourceTree = ""; }; - 22D53E07C1490EFA54F3AF6C8BECA5EE /* Abacus.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Abacus.framework; path = build/cocoapods/framework/Abacus.framework; sourceTree = ""; }; 233CC871C3B5E5D1C643AA3F5362558A /* DigestType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DigestType.swift; path = Sources/CryptoSwift/DigestType.swift; sourceTree = ""; }; 236DF73D92D4D71C82089CF882764244 /* NoPadding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NoPadding.swift; path = Sources/CryptoSwift/NoPadding.swift; sourceTree = ""; }; 2653766C82503F31D9367F8E622F8258 /* PBKDF2.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PBKDF2.swift; path = Sources/CryptoSwift/PKCS/PBKDF2.swift; sourceTree = ""; }; 289CF4084C8BCFCA379CCF7847F8D1F8 /* Blowfish.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Blowfish.swift; path = Sources/CryptoSwift/Blowfish.swift; sourceTree = ""; }; 295A5EFDE6FBDDF94AEC568618EF25FE /* Hashable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Hashable.swift; path = Sources/CryptoSwift/CS_BigInt/Hashable.swift; sourceTree = ""; }; 2A89356D96E998228A503AA1A6E9C626 /* Int+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Int+Extension.swift"; path = "Sources/CryptoSwift/Int+Extension.swift"; sourceTree = ""; }; + 2CD43E4678524A1BE3B0D8269170C92D /* abacus.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = abacus.debug.xcconfig; sourceTree = ""; }; 311456A9BE6AD331F084E1FCE9FD2109 /* BigUInt.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BigUInt.swift; path = Sources/CryptoSwift/CS_BigInt/BigUInt.swift; sourceTree = ""; }; 322DD78557BFE4B398A18CBAA3C8A353 /* BlockEncryptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BlockEncryptor.swift; path = Sources/CryptoSwift/BlockEncryptor.swift; sourceTree = ""; }; 33400747830CD0D31E461E6DE1F4500B /* String Conversion.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "String Conversion.swift"; path = "Sources/CryptoSwift/CS_BigInt/String Conversion.swift"; sourceTree = ""; }; @@ -208,6 +206,7 @@ 3E0AAD4392F812C1C216CCFB8F6C83F1 /* HMAC.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HMAC.swift; path = Sources/CryptoSwift/HMAC.swift; sourceTree = ""; }; 3EA11A675218D8EC495F817C58CD7850 /* RSA+Cipher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "RSA+Cipher.swift"; path = "Sources/CryptoSwift/RSA/RSA+Cipher.swift"; sourceTree = ""; }; 4020CF7A5E8D043073442B14C262B52D /* CBCMAC.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CBCMAC.swift; path = Sources/CryptoSwift/CBCMAC.swift; sourceTree = ""; }; + 42F8B97BD09516D0EBF4D5CEAB3F0C9A /* abacus.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = abacus.release.xcconfig; sourceTree = ""; }; 4557C8EB08F67FA9FE5EF603C935E183 /* Cryptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Cryptor.swift; path = Sources/CryptoSwift/Cryptor.swift; sourceTree = ""; }; 466CB280E8CD811A98491B57B02D1B46 /* AES+Foundation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AES+Foundation.swift"; path = "Sources/CryptoSwift/Foundation/AES+Foundation.swift"; sourceTree = ""; }; 47CAE619028B011ED98D7F74CF7215A1 /* Operators.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Operators.swift; path = Sources/CryptoSwift/Operators.swift; sourceTree = ""; }; @@ -231,7 +230,6 @@ 72ED5A3746B04AD8516BAA07DEB0AFFB /* Rabbit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Rabbit.swift; path = Sources/CryptoSwift/Rabbit.swift; sourceTree = ""; }; 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 75EBB1F2A3091B11F34E2303C5FF61FF /* Integer Conversion.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Integer Conversion.swift"; path = "Sources/CryptoSwift/CS_BigInt/Integer Conversion.swift"; sourceTree = ""; }; - 76313B4F25B46ECF4D9B73229E4C7ED0 /* abacus.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = abacus.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 770402A5FA60DB3BB6604065DEAF7112 /* Updatable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Updatable.swift; path = Sources/CryptoSwift/Updatable.swift; sourceTree = ""; }; 77C0EE24E7443418813C133F648727B2 /* BigInt.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BigInt.swift; path = Sources/CryptoSwift/CS_BigInt/BigInt.swift; sourceTree = ""; }; 78AB32080590FEF8DC83D622EA15A854 /* RSA+Signature.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "RSA+Signature.swift"; path = "Sources/CryptoSwift/RSA/RSA+Signature.swift"; sourceTree = ""; }; @@ -260,12 +258,10 @@ A4C6589A1E607B41E22C6DD7EB51E767 /* PKCS7.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PKCS7.swift; path = Sources/CryptoSwift/PKCS/PKCS7.swift; sourceTree = ""; }; A733B31476683686BA90BD0C8D25900E /* CMAC.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CMAC.swift; path = Sources/CryptoSwift/CMAC.swift; sourceTree = ""; }; A7F75F1F8D19379B77CB9B5F20147724 /* Floating Point Conversion.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Floating Point Conversion.swift"; path = "Sources/CryptoSwift/CS_BigInt/Floating Point Conversion.swift"; sourceTree = ""; }; - AB0528C62889C935129CB660F9A01AE6 /* abacus-copy-dsyms.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "abacus-copy-dsyms.sh"; sourceTree = ""; }; AD93A59528068EF859CFB769EA8A6B21 /* StreamEncryptor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StreamEncryptor.swift; path = Sources/CryptoSwift/StreamEncryptor.swift; sourceTree = ""; }; AE9EA384CA84DA00859213076C156601 /* Rabbit+Foundation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Rabbit+Foundation.swift"; path = "Sources/CryptoSwift/Foundation/Rabbit+Foundation.swift"; sourceTree = ""; }; B008B6FE49BB00A27F5C3A8793251FA6 /* Comparable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Comparable.swift; path = Sources/CryptoSwift/CS_BigInt/Comparable.swift; sourceTree = ""; }; B08BBA0B72E8D4BE9811F9B7F68AA02C /* Blowfish+Foundation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Blowfish+Foundation.swift"; path = "Sources/CryptoSwift/Foundation/Blowfish+Foundation.swift"; sourceTree = ""; }; - B0C66B8604EC7A57445E8E921B57B7E6 /* abacus.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = abacus.release.xcconfig; sourceTree = ""; }; B26CFCBE4B1911C8EC2A1C029CEB4E75 /* String+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "String+Extension.swift"; path = "Sources/CryptoSwift/String+Extension.swift"; sourceTree = ""; }; B4190E33292A68FD34FE52C6E5F07C60 /* AEAD.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AEAD.swift; path = Sources/CryptoSwift/AEAD/AEAD.swift; sourceTree = ""; }; BA40B51A627278CB13C358186114CC93 /* ZeroPadding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ZeroPadding.swift; path = Sources/CryptoSwift/ZeroPadding.swift; sourceTree = ""; }; @@ -285,6 +281,7 @@ CF791D3ED0FED5736405B0F135A4B7DA /* Signature.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Signature.swift; path = Sources/CryptoSwift/Signature.swift; sourceTree = ""; }; D0DF4F835FF3BD92DE8F28EF66D11155 /* Pods-abacus.ios-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-abacus.ios-frameworks.sh"; sourceTree = ""; }; D16CC219F5813A4740742BFCB5F17BB3 /* PKCS1v15.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PKCS1v15.swift; path = Sources/CryptoSwift/PKCS/PKCS1v15.swift; sourceTree = ""; }; + D59039BF87AE1CED0087C97D4DED2A63 /* abacus.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = abacus.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; D77AE99D144C7A6A8EA245FA4D5D94BF /* Multiplication.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Multiplication.swift; path = Sources/CryptoSwift/CS_BigInt/Multiplication.swift; sourceTree = ""; }; DADCE07683E515BD771C00BBC9393EF3 /* DER.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DER.swift; path = Sources/CryptoSwift/PEM/DER.swift; sourceTree = ""; }; DBCFEA3C88E1F6CD86C88C84A6979B86 /* ChaCha20+Foundation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ChaCha20+Foundation.swift"; path = "Sources/CryptoSwift/Foundation/ChaCha20+Foundation.swift"; sourceTree = ""; }; @@ -303,6 +300,7 @@ EBE2877F7E8A200D74C4E18847B81123 /* CompactMap.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CompactMap.swift; path = Sources/CryptoSwift/CompactMap.swift; sourceTree = ""; }; ED147C179BB27BE9D0AA43E406100179 /* HKDF.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HKDF.swift; path = Sources/CryptoSwift/HKDF.swift; sourceTree = ""; }; EE3BBB66D7173C016DB618A76707AAD3 /* UInt16+Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UInt16+Extension.swift"; path = "Sources/CryptoSwift/UInt16+Extension.swift"; sourceTree = ""; }; + EF29B887E7CBAB45C95B300123980FC5 /* Abacus.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Abacus.framework; path = build/cocoapods/framework/Abacus.framework; sourceTree = ""; }; EF5AB0E7CC9AF239517DD7DF9245C8FF /* Array+Foundation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Array+Foundation.swift"; path = "Sources/CryptoSwift/Foundation/Array+Foundation.swift"; sourceTree = ""; }; EFF7D0D9D63091066805D424BE501AF6 /* CBC.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CBC.swift; path = Sources/CryptoSwift/BlockMode/CBC.swift; sourceTree = ""; }; F147AFFBAF5C8233E7152D1F827C039C /* CryptoSwift-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CryptoSwift-dummy.m"; sourceTree = ""; }; @@ -341,25 +339,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 2688F84B4660F52027C786880EC322DF /* abacus */ = { - isa = PBXGroup; - children = ( - 6F56BA8B17CC7EF668B3D7A9789967EA /* Frameworks */, - D6A6ECB0085D67FB2666A8D4B1C169E8 /* Pod */, - B6AA512E295A9A9CF2A7556E67DA5851 /* Support Files */, - ); - name = abacus; - path = "/Users/mike/v4-abacus"; - sourceTree = ""; - }; - 3DE7A03CBA192FF20EB8C91418025A95 /* Development Pods */ = { - isa = PBXGroup; - children = ( - 2688F84B4660F52027C786880EC322DF /* abacus */, - ); - name = "Development Pods"; - sourceTree = ""; - }; 578452D2E740E91742655AC8F1636D1F /* iOS */ = { isa = PBXGroup; children = ( @@ -368,14 +347,6 @@ name = iOS; sourceTree = ""; }; - 6F56BA8B17CC7EF668B3D7A9789967EA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 22D53E07C1490EFA54F3AF6C8BECA5EE /* Abacus.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; 77BFA6027665EBACC42B94A7C2372871 /* Pods-abacus.iosTests */ = { isa = PBXGroup; children = ( @@ -402,6 +373,25 @@ name = Products; sourceTree = ""; }; + 90A2ECA4CB85E9B524F94B07F44602BA /* Development Pods */ = { + isa = PBXGroup; + children = ( + 90EDD76926101DC4F3EA3CB210AD782B /* abacus */, + ); + name = "Development Pods"; + sourceTree = ""; + }; + 90EDD76926101DC4F3EA3CB210AD782B /* abacus */ = { + isa = PBXGroup; + children = ( + FE925A01FE4CC24BC13D7294AA9341F0 /* Frameworks */, + F91A9C8581D5144BABA03A418A7A1BBB /* Pod */, + DEF004F52F2F2D30519CC77F4A88FEF2 /* Support Files */, + ); + name = abacus; + path = "/Users/ruihuang/v4-abacus"; + sourceTree = ""; + }; 915C28C583640C124E56AE6BB9F0DAB2 /* CryptoSwift */ = { isa = PBXGroup; children = ( @@ -547,22 +537,11 @@ name = "Targets Support Files"; sourceTree = ""; }; - B6AA512E295A9A9CF2A7556E67DA5851 /* Support Files */ = { - isa = PBXGroup; - children = ( - AB0528C62889C935129CB660F9A01AE6 /* abacus-copy-dsyms.sh */, - 090DA5F6297DCDBC49F0E90B1755BD86 /* abacus.debug.xcconfig */, - B0C66B8604EC7A57445E8E921B57B7E6 /* abacus.release.xcconfig */, - ); - name = "Support Files"; - path = "integration/iOS/Pods/Target Support Files/abacus"; - sourceTree = ""; - }; CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - 3DE7A03CBA192FF20EB8C91418025A95 /* Development Pods */, + 90A2ECA4CB85E9B524F94B07F44602BA /* Development Pods */, D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, DA389CCA0C382AECE0DD24ED555B7245 /* Pods */, 7D94CDF401128D689D2B11EDCC7ECD3A /* Products */, @@ -578,20 +557,22 @@ name = Frameworks; sourceTree = ""; }; - D6A6ECB0085D67FB2666A8D4B1C169E8 /* Pod */ = { + DA389CCA0C382AECE0DD24ED555B7245 /* Pods */ = { isa = PBXGroup; children = ( - 76313B4F25B46ECF4D9B73229E4C7ED0 /* abacus.podspec */, + 915C28C583640C124E56AE6BB9F0DAB2 /* CryptoSwift */, ); - name = Pod; + name = Pods; sourceTree = ""; }; - DA389CCA0C382AECE0DD24ED555B7245 /* Pods */ = { + DEF004F52F2F2D30519CC77F4A88FEF2 /* Support Files */ = { isa = PBXGroup; children = ( - 915C28C583640C124E56AE6BB9F0DAB2 /* CryptoSwift */, + 2CD43E4678524A1BE3B0D8269170C92D /* abacus.debug.xcconfig */, + 42F8B97BD09516D0EBF4D5CEAB3F0C9A /* abacus.release.xcconfig */, ); - name = Pods; + name = "Support Files"; + path = "integration/iOS/Pods/Target Support Files/abacus"; sourceTree = ""; }; E9E61B37C0B4F06FB4820B121A729EA0 /* Support Files */ = { @@ -609,6 +590,22 @@ path = "../Target Support Files/CryptoSwift"; sourceTree = ""; }; + F91A9C8581D5144BABA03A418A7A1BBB /* Pod */ = { + isa = PBXGroup; + children = ( + D59039BF87AE1CED0087C97D4DED2A63 /* abacus.podspec */, + ); + name = Pod; + sourceTree = ""; + }; + FE925A01FE4CC24BC13D7294AA9341F0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + EF29B887E7CBAB45C95B300123980FC5 /* Abacus.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -671,7 +668,7 @@ buildRules = ( ); dependencies = ( - 1F67D19EAC36A41088EB458D7432B293 /* PBXTargetDependency */, + AC2EBD83354400DAA47E7F9069901F4A /* PBXTargetDependency */, ); name = "Pods-abacus.iosTests"; productName = Pods_abacus_iosTests; @@ -751,24 +748,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 903ECA29140368245E4B69BE2D0DBCA4 /* [CP] Copy dSYMs */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/abacus/abacus-copy-dsyms-input-files.xcfilelist", - ); - name = "[CP] Copy dSYMs"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/abacus/abacus-copy-dsyms-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/abacus/abacus-copy-dsyms.sh\"\n"; - showEnvVarsInLog = 0; - }; - DB36ACE8A857E9B93C25EA309FF42C2A /* [CP-User] Build abacus */ = { + 1403E0AEBF8A2087DF8CACA188B609E8 /* [CP-User] Build abacus */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -918,11 +898,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 1F67D19EAC36A41088EB458D7432B293 /* PBXTargetDependency */ = { + AC2EBD83354400DAA47E7F9069901F4A /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Pods-abacus.ios"; target = 469F25E790D19440507BF938A40578A7 /* Pods-abacus.ios */; - targetProxy = 174DE097054DE7A0410C57AF4AEF5A1A /* PBXContainerItemProxy */; + targetProxy = F99C8B5A9E9146040BECE7ABFD8E196E /* PBXContainerItemProxy */; }; CF848ADCA9D462971E67CA041BBB55DD /* PBXTargetDependency */ = { isa = PBXTargetDependency; @@ -976,6 +956,23 @@ }; name = Debug; }; + 22B0388248EDA44270493DDECC58CF78 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 42F8B97BD09516D0EBF4D5CEAB3F0C9A /* abacus.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; 4C06C857647A16E5CF368D22DFA55BAF /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0ECEA0D8830DCE37C7297C5F1342B08E /* Pods-abacus.ios.release.xcconfig */; @@ -1049,6 +1046,22 @@ }; name = Debug; }; + 5B331F72A7F4402311EBC4A06282E60D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2CD43E4678524A1BE3B0D8269170C92D /* abacus.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; 5D1E4AA7093DAD0F254B24C6406C303C /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7996373D44C9A5554EA9135984BC01DB /* Pods-abacus.iosTests.release.xcconfig */; @@ -1215,39 +1228,6 @@ }; name = Debug; }; - 96B05028328C5704FCE6A41A515364C0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 090DA5F6297DCDBC49F0E90B1755BD86 /* abacus.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - B0264023D64B16BF2F6C8B4C076E862A /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B0C66B8604EC7A57445E8E921B57B7E6 /* abacus.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; F3A0E769E09875E7B65318E499E93FAC /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5E828917FF2AA3CC6B23ECF8A598B684 /* CryptoSwift.release.xcconfig */; @@ -1324,15 +1304,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 127F9C06E33E9DC2AB3876F089264EB1 /* Build configuration list for PBXAggregateTarget "abacus" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 96B05028328C5704FCE6A41A515364C0 /* Debug */, - B0264023D64B16BF2F6C8B4C076E862A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 2ECD87CECC0DF0128DB6EE0BDC2D9E8A /* Build configuration list for PBXNativeTarget "CryptoSwift" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1351,6 +1322,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + B36D4FC54F44832C64D6BFCFC7EF4665 /* Build configuration list for PBXAggregateTarget "abacus" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5B331F72A7F4402311EBC4A06282E60D /* Debug */, + 22B0388248EDA44270493DDECC58CF78 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D5458BD03143642191683A4348FED1F8 /* Build configuration list for PBXNativeTarget "Pods-abacus.ios" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/v4_abacus.podspec b/v4_abacus.podspec index 0cc9f6ce5..88643c456 100644 --- a/v4_abacus.podspec +++ b/v4_abacus.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'v4_abacus' - spec.version = '1.6.49' + spec.version = '1.6.50' spec.homepage = 'https://github.com/dydxprotocol/v4-abacus' spec.source = { :http=> ''} spec.authors = '' From 5260c99fcdff16f339b2144bca5fe179675f97fe Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 26 Apr 2024 15:01:59 -0700 Subject: [PATCH 3/8] Pass stateMachine: TradingStateMachine into constructor --- .../state/manager/StateManagerAdaptor.kt | 6 +++--- .../notification/NotificationsProvider.kt | 16 +++++++++------- .../providers/BlockRewardNotificationProvider.kt | 5 ++--- .../providers/FillsNotificationProvider.kt | 2 +- .../OrderStatusChangesNotificationProvider.kt | 2 +- .../providers/PositionsNotificationProvider.kt | 2 +- .../state/v2/supervisor/SubaccountSupervisor.kt | 3 ++- .../payload/v4/V4AccountTests.kt | 3 ++- 8 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt index 1ebe72964..e66939bc4 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt @@ -124,7 +124,7 @@ open class StateManagerAdaptor( @Suppress("LocalVariableName", "PropertyName") private val TRIGGER_ORDER_DEFAULT_DURATION_DAYS = 28.0 - var stateMachine: TradingStateMachine = PerpTradingStateMachine( + val stateMachine: TradingStateMachine = PerpTradingStateMachine( environment, uiImplementations.localizer, Formatter(uiImplementations.formatter), @@ -152,7 +152,7 @@ open class StateManagerAdaptor( internal val jsonEncoder = JsonEncoder() internal val parser = Parser() private val notificationsProvider = - NotificationsProvider(uiImplementations, environment, parser, jsonEncoder) + NotificationsProvider(stateMachine, uiImplementations, environment, parser, jsonEncoder) private var subaccountsTimer: LocalTimerProtocol? = null set(value) { @@ -2197,7 +2197,7 @@ open class StateManagerAdaptor( } private fun updateNotifications() { - val notifications = notificationsProvider.buildNotifications(stateMachine, subaccountNumber) + val notifications = notificationsProvider.buildNotifications(subaccountNumber) consolidateNotifications(notifications) } diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt index 7f5c72080..8521b5cbc 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt @@ -15,7 +15,6 @@ import kollections.toIMap interface NotificationsProviderProtocol { fun buildNotifications( - stateMachine: TradingStateMachine, subaccountNumber: Int ): IMap @@ -27,45 +26,48 @@ interface NotificationsProviderProtocol { } class NotificationsProvider( + private val stateMachine: TradingStateMachine, private val uiImplementations: UIImplementations, private val environment: V4Environment, private val parser: ParserProtocol, private val jsonEncoder: JsonEncoder, private val useParentSubaccount: Boolean = false, -) : NotificationsProviderProtocol { - - private val providers = listOf( + private val providers: List = listOf( BlockRewardNotificationProvider( + stateMachine, uiImplementations, environment, jsonEncoder, ), FillsNotificationProvider( + stateMachine, uiImplementations, parser, jsonEncoder, ), PositionsNotificationProvider( + stateMachine, uiImplementations, parser, jsonEncoder, useParentSubaccount, ), OrderStatusChangesNotificationProvider( + stateMachine, uiImplementations, parser, jsonEncoder, ), - ) + ), +) : NotificationsProviderProtocol { override fun buildNotifications( - stateMachine: TradingStateMachine, subaccountNumber: Int ): IMap { var merged: Map? = null providers.forEach { provider -> - val notifications = provider.buildNotifications(stateMachine, subaccountNumber) + val notifications = provider.buildNotifications(subaccountNumber) merged = ParsingHelper.merge(merged, notifications) as? Map } diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/BlockRewardNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/BlockRewardNotificationProvider.kt index 3de04782a..04c961e9b 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/BlockRewardNotificationProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/BlockRewardNotificationProvider.kt @@ -15,12 +15,12 @@ import exchange.dydx.abacus.utils.typedSafeSet import kollections.toIMap class BlockRewardNotificationProvider( + private val stateMachine: TradingStateMachine, private val uiImplementations: UIImplementations, private val environment: V4Environment, private val jsonEncoder: JsonEncoder, ) : NotificationsProviderProtocol { override fun buildNotifications( - stateMachine: TradingStateMachine, subaccountNumber: Int ): IMap { /* @@ -36,7 +36,7 @@ class BlockRewardNotificationProvider( val token = environment.tokens["chain"]?.name if (accountBlockRewards != null && token != null) { for (blockReward in accountBlockRewards) { - createBlockRewardNotification(stateMachine, blockReward, token)?.let { + createBlockRewardNotification(blockReward, token)?.let { notifications.typedSafeSet( it.id, it, @@ -48,7 +48,6 @@ class BlockRewardNotificationProvider( } private fun createBlockRewardNotification( - stateMachine: TradingStateMachine, blockReward: BlockReward, token: String, ): Notification? { diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt index 2daf8884b..1b924a70f 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt @@ -23,12 +23,12 @@ import kollections.iMutableListOf import kollections.toIMap class FillsNotificationProvider( + private val stateMachine: TradingStateMachine, private val uiImplementations: UIImplementations, private val parser: ParserProtocol, private val jsonEncoder: JsonEncoder, ) : NotificationsProviderProtocol { override fun buildNotifications( - stateMachine: TradingStateMachine, subaccountNumber: Int ): IMap { /* diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt index 5dca3a0a2..2088134c4 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt @@ -18,12 +18,12 @@ import exchange.dydx.abacus.utils.typedSafeSet import kollections.toIMap class OrderStatusChangesNotificationProvider( + private val stateMachine: TradingStateMachine, private val uiImplementations: UIImplementations, private val parser: ParserProtocol, private val jsonEncoder: JsonEncoder, ) : NotificationsProviderProtocol { override fun buildNotifications( - stateMachine: TradingStateMachine, subaccountNumber: Int ): IMap { /* diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt index 95336830a..28f00be72 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt @@ -12,13 +12,13 @@ import exchange.dydx.abacus.utils.iMapOf import kollections.toIMap class PositionsNotificationProvider( + private val stateMachine: TradingStateMachine, private val uiImplementations: UIImplementations, private val parser: ParserProtocol, private val jsonEncoder: JsonEncoder, private val useParentSubaccount: Boolean = false, ) : NotificationsProviderProtocol { override fun buildNotifications( - stateMachine: TradingStateMachine, subaccountNumber: Int ): IMap { /* diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt index 907b69b1d..55a30d3d3 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt @@ -146,6 +146,7 @@ internal class SubaccountSupervisor( } private val notificationsProvider = NotificationsProvider( + stateMachine, helper.uiImplementations, helper.environment, helper.parser, @@ -1243,7 +1244,7 @@ internal class SubaccountSupervisor( } override fun updateNotifications() { - val notifications = notificationsProvider.buildNotifications(stateMachine, subaccountNumber) + val notifications = notificationsProvider.buildNotifications(subaccountNumber) consolidateNotifications(notifications) } diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4AccountTests.kt b/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4AccountTests.kt index 42da74e67..8121e9b2c 100644 --- a/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4AccountTests.kt +++ b/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4AccountTests.kt @@ -850,12 +850,13 @@ class V4AccountTests : V4BaseTests() { val uiImplementations = BaseTests.testUIImplementations(localizer) val notificationsProvider = NotificationsProvider( + perp, uiImplementations, environment = mock.v4Environment, Parser(), JsonEncoder(), ) - val notifications = notificationsProvider.buildNotifications(perp, 0) + val notifications = notificationsProvider.buildNotifications(0) assertEquals( 6, notifications.size, From 519678e51c602afbb2ae091b1360eb999e3b6223 Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 26 Apr 2024 15:02:57 -0700 Subject: [PATCH 4/8] Update version --- build.gradle.kts | 2 +- v4_abacus.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index da568286c..246c44c89 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,7 +49,7 @@ allprojects { } group = "exchange.dydx.abacus" -version = "1.6.50" +version = "1.6.51" repositories { google() diff --git a/v4_abacus.podspec b/v4_abacus.podspec index 88643c456..8f60f0b1a 100644 --- a/v4_abacus.podspec +++ b/v4_abacus.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'v4_abacus' - spec.version = '1.6.50' + spec.version = '1.6.51' spec.homepage = 'https://github.com/dydxprotocol/v4-abacus' spec.source = { :http=> ''} spec.authors = '' From 964ebceaa8bb3d04ad97d3b65b43470956254bb1 Mon Sep 17 00:00:00 2001 From: Rui Date: Mon, 29 Apr 2024 10:05:55 -0700 Subject: [PATCH 5/8] Add assetOfMarket() to PerpetualState --- .../kotlin/exchange.dydx.abacus/output/PerpetualState.kt | 5 +++++ .../state/manager/notification/NotificationsProvider.kt | 7 ------- .../notification/providers/FillsNotificationProvider.kt | 5 +++-- .../providers/OrderStatusChangesNotificationProvider.kt | 2 +- .../providers/PositionsNotificationProvider.kt | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/output/PerpetualState.kt b/src/commonMain/kotlin/exchange.dydx.abacus/output/PerpetualState.kt index 25d7936e3..af1872a7d 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/output/PerpetualState.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/output/PerpetualState.kt @@ -41,6 +41,11 @@ data class PerpetualState( return assets?.get(assetId) } + fun assetOfMarket(marketId: String): Asset? { + val assetId = market(marketId)?.assetId ?: return null + return assets?.get(assetId) + } + fun marketIds(): IList? { return marketsSummary?.marketIds() } diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt index 8521b5cbc..7e4886bed 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/NotificationsProvider.kt @@ -1,6 +1,5 @@ package exchange.dydx.abacus.state.manager.notification -import exchange.dydx.abacus.output.Asset import exchange.dydx.abacus.output.Notification import exchange.dydx.abacus.protocols.ParserProtocol import exchange.dydx.abacus.state.manager.V4Environment @@ -17,12 +16,6 @@ interface NotificationsProviderProtocol { fun buildNotifications( subaccountNumber: Int ): IMap - - fun asset(stateMachine: TradingStateMachine, marketId: String): Asset? { - val market = stateMachine.state?.market(marketId) ?: return null - val assetId = market.assetId - return stateMachine.state?.asset(assetId) - } } class NotificationsProvider( diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt index 1b924a70f..02b719a69 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/FillsNotificationProvider.kt @@ -14,6 +14,7 @@ import exchange.dydx.abacus.utils.IList import exchange.dydx.abacus.utils.IMap import exchange.dydx.abacus.utils.IMutableList import exchange.dydx.abacus.utils.JsonEncoder +import exchange.dydx.abacus.utils.ParsingHelper.Companion.asset import exchange.dydx.abacus.utils.Rounder import exchange.dydx.abacus.utils.UIImplementations import exchange.dydx.abacus.utils.iMapOf @@ -101,7 +102,7 @@ class FillsNotificationProvider( val marketId = fill.marketId val market = market(stateMachine, marketId) ?: return null val tickSize = market.configs?.tickSize ?: return null - val asset = asset(stateMachine, marketId) + val asset = stateMachine.state?.assetOfMarket(marketId) val assetText = asset?.name ?: marketId val marketImageUrl = asset?.resources?.imageUrl val side = fill.side.rawValue @@ -151,7 +152,7 @@ class FillsNotificationProvider( ): Notification? { val fillId = fill.id val marketId = fill.marketId - val asset = asset(stateMachine, marketId) ?: return null + val asset = stateMachine.state?.assetOfMarket(marketId) ?: return null val assetText = asset.name val marketImageUrl = asset.resources?.imageUrl val side = fill.side.rawValue diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt index 2088134c4..db1de4d35 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/OrderStatusChangesNotificationProvider.kt @@ -96,7 +96,7 @@ class OrderStatusChangesNotificationProvider( } return if (statusNotificationStringKey != null && timestamp != null) { val marketId = order.marketId - val asset = asset(stateMachine, marketId) ?: return null + val asset = stateMachine.state?.assetOfMarket(marketId) ?: return null val marketImageUrl = asset.resources?.imageUrl val side = order.side.rawValue val sideText = uiImplementations.localizer?.localize("APP.GENERAL.$side") diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt index 28f00be72..54248d63f 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/notification/providers/PositionsNotificationProvider.kt @@ -43,7 +43,7 @@ class PositionsNotificationProvider( val positionStatus = parser.asString(position["status"]) if (positionStatus == "CLOSED") { val closedAt = parser.asDatetime(position["closedAt"]) ?: continue - val asset = asset(stateMachine, marketId) ?: continue + val asset = stateMachine.state?.assetOfMarket(marketId) ?: continue val assetText = asset.name val marketImageUrl = asset.resources?.imageUrl val params = ( From fd17732213c43fa59aeb53aae3e20b601932404d Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 30 Apr 2024 09:57:00 -0700 Subject: [PATCH 6/8] Disable more rules --- detekt.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/detekt.yml b/detekt.yml index 71d42717d..a2d201bf0 100644 --- a/detekt.yml +++ b/detekt.yml @@ -20,3 +20,13 @@ complexity: threshold: 100 # up from 60 TooManyFunctions: active: false + ReturnCount: + active: false + MaxLineLength: + active: false + NestedBlockDepth: + active: false + +style: + LoopWithTooManyJumpStatements: + active: false From 3b38ebbf61d77e19656a1540c5dd99f1c8b8e8c4 Mon Sep 17 00:00:00 2001 From: Rui Date: Tue, 30 Apr 2024 09:59:05 -0700 Subject: [PATCH 7/8] Revert "Disable more rules" This reverts commit fd17732213c43fa59aeb53aae3e20b601932404d. --- detekt.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/detekt.yml b/detekt.yml index a2d201bf0..71d42717d 100644 --- a/detekt.yml +++ b/detekt.yml @@ -20,13 +20,3 @@ complexity: threshold: 100 # up from 60 TooManyFunctions: active: false - ReturnCount: - active: false - MaxLineLength: - active: false - NestedBlockDepth: - active: false - -style: - LoopWithTooManyJumpStatements: - active: false From f3579e63a2987a37e6799b539f81a3d212b325cd Mon Sep 17 00:00:00 2001 From: Rui Date: Fri, 10 May 2024 11:09:14 -0700 Subject: [PATCH 8/8] Merge conflicts --- build.gradle.kts | 2 +- .../state/v2/supervisor/SubaccountSupervisor.kt | 1 + v4_abacus.podspec | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 7c5b417fd..e6c3bc7ff 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,7 +49,7 @@ allprojects { } group = "exchange.dydx.abacus" -version = "1.7.7" +version = "1.7.8" repositories { google() diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt index b89453cb8..f63c14737 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt @@ -33,6 +33,7 @@ import exchange.dydx.abacus.state.manager.PlaceOrderMarketInfo import exchange.dydx.abacus.state.manager.PlaceOrderRecord import exchange.dydx.abacus.state.manager.TransactionParams import exchange.dydx.abacus.state.manager.TransactionQueue +import exchange.dydx.abacus.state.manager.notification.NotificationsProvider import exchange.dydx.abacus.state.model.AdjustIsolatedMarginInputField import exchange.dydx.abacus.state.model.ClosePositionInputField import exchange.dydx.abacus.state.model.TradeInputField diff --git a/v4_abacus.podspec b/v4_abacus.podspec index dcfc5a3e6..bb378e2f7 100644 --- a/v4_abacus.podspec +++ b/v4_abacus.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'v4_abacus' - spec.version = '1.7.7' + spec.version = '1.7.8' spec.homepage = 'https://github.com/dydxprotocol/v4-abacus' spec.source = { :http=> ''} spec.authors = ''