Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ allprojects {
}

group = "exchange.dydx.abacus"
version = "1.14.14"
version = "1.14.15"

repositories {
google()
Expand Down
34 changes: 34 additions & 0 deletions src/commonMain/kotlin/exchange.dydx.abacus/output/Leaderboard.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package exchange.dydx.abacus.output

import exchange.dydx.abacus.utils.IList
import kollections.JsExport
import kotlinx.serialization.Serializable

@JsExport
@Serializable
data class FeeLeaderboardEntry(
val address: String,
val rank: Int,
val totalFees: Double
)

@JsExport
@Serializable
data class FeeLeaderboard(
val leaderboard: IList<FeeLeaderboardEntry>
)

@JsExport
@Serializable
data class RebateLeaderboardEntry(
val address: String,
val pnl: Double,
val rank: Int,
val dollarReward: Double
)

@JsExport
@Serializable
data class RebateLeaderboard(
val leaderboard: IList<RebateLeaderboardEntry>
)
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ data class PerpetualState(
val restriction: UsageRestriction?,
val launchIncentive: LaunchIncentive?,
val compliance: Compliance?,
val vault: Vault?
val vault: Vault?,
val feeLeaderboard: FeeLeaderboard?,
val rebateLeaderboard: RebateLeaderboard?
) {
internal companion object {
fun newState(): PerpetualState {
Expand All @@ -70,6 +72,8 @@ data class PerpetualState(
launchIncentive = null,
compliance = null,
vault = null,
feeLeaderboard = null,
rebateLeaderboard = null
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package exchange.dydx.abacus.processor.leaderboards

import exchange.dydx.abacus.output.FeeLeaderboardEntry
import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.InternalFeeLeaderboardState
import exchange.dydx.abacus.state.machine.FeeLeaderboardResponse

internal class FeeLeaderboardProcessor(
parser: ParserProtocol
): BaseProcessor(parser) {
fun processLeaderboard(existing: InternalFeeLeaderboardState, payload: FeeLeaderboardResponse?): InternalFeeLeaderboardState {
existing.leaderboard = payload?.data?.map { FeeLeaderboardEntry(it.address, it.rank, it.total_fees) }
return existing
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package exchange.dydx.abacus.processor.leaderboards

import exchange.dydx.abacus.output.RebateLeaderboardEntry
import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.InternalRebateLeaderboardState
import exchange.dydx.abacus.state.machine.RebateLeaderboardResponse

internal class RebateLeaderboardProcessor(
parser: ParserProtocol
): BaseProcessor(parser) {
fun processLeaderboard(existing: InternalRebateLeaderboardState, payload: RebateLeaderboardResponse?): InternalRebateLeaderboardState? {
existing.leaderboard = payload?.data?.map { RebateLeaderboardEntry(address = it.address, pnl = it.pnl, rank = it.position, dollarReward = it.dollarReward) }
return existing
}
}
12 changes: 12 additions & 0 deletions src/commonMain/kotlin/exchange.dydx.abacus/state/InternalState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import exchange.dydx.abacus.output.MarketHistoricalFunding
import exchange.dydx.abacus.output.MarketOrderbook
import exchange.dydx.abacus.output.MarketTrade
import exchange.dydx.abacus.output.PerpetualMarket
import exchange.dydx.abacus.output.FeeLeaderboardEntry
import exchange.dydx.abacus.output.RebateLeaderboardEntry
import exchange.dydx.abacus.output.WithdrawalGating
import exchange.dydx.abacus.output.account.PositionSide
import exchange.dydx.abacus.output.account.StakingRewards
Expand Down Expand Up @@ -75,6 +77,8 @@ internal data class InternalState(
val marketsSummary: InternalMarketSummaryState = InternalMarketSummaryState(),
val input: InternalInputState = InternalInputState(),
var vault: InternalVaultState? = null,
val feeLeaderboard: InternalFeeLeaderboardState = InternalFeeLeaderboardState(),
val rebateLeaderboard: InternalRebateLeaderboardState = InternalRebateLeaderboardState()
)

internal data class InternalInputState(
Expand Down Expand Up @@ -488,6 +492,14 @@ internal data class InternalLaunchIncentiveState(
var seasons: List<LaunchIncentiveSeason>? = null,
)

internal data class InternalFeeLeaderboardState(
var leaderboard: List<FeeLeaderboardEntry>? = null
)

internal data class InternalRebateLeaderboardState(
var leaderboard: List<RebateLeaderboardEntry>? = null
)

internal fun TradeInputSize.Companion.safeCreate(existing: TradeInputSize?): TradeInputSize {
return existing ?: TradeInputSize(
size = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ enum class Changes(val rawValue: String) {

launchIncentive("launchIncentive"),
vault("vault"),
feeLeaderboard("feeLeaderboard"),
rebateLeaderboard("rebateLeaderboard")
;

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package exchange.dydx.abacus.state.machine

import exchange.dydx.abacus.protocols.asTypedObject
import exchange.dydx.abacus.state.Changes
import exchange.dydx.abacus.state.StateChanges
import kollections.iListOf

@Suppress("ConstructorParameterNaming")
data class FeeLeaderboardEntryResponse(
val address: String,
val rank: Int,
val total_fees: Double
)

data class FeeLeaderboardResponse(
val data: List<FeeLeaderboardEntryResponse>
)

internal fun TradingStateMachine.feeLeaderboard(payload: String): StateChanges {
val leaderboard = parser.asTypedObject<FeeLeaderboardResponse>(payload)
val oldState = internalState.feeLeaderboard.copy()
feeLeaderboardProcessor.processLeaderboard(
internalState.feeLeaderboard,
leaderboard
)
return if (oldState != internalState.feeLeaderboard) {
StateChanges(iListOf(Changes.feeLeaderboard))
} else {
StateChanges.noChange
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package exchange.dydx.abacus.state.machine

import exchange.dydx.abacus.protocols.asTypedObject
import exchange.dydx.abacus.state.Changes
import exchange.dydx.abacus.state.StateChanges
import kollections.iListOf

@Suppress("ConstructorParameterNaming")
data class RebateLeaderboardEntryResponse(
val address: String,
val pnl: Double,
val position: Int,
val dollarReward: Double
)

data class RebateLeaderboardResponse(
val data: List<RebateLeaderboardEntryResponse>
)

internal fun TradingStateMachine.rebateLeaderboard(payload: String): StateChanges {
val leaderboard = parser.asTypedObject<RebateLeaderboardResponse>(payload)
val oldState = internalState.rebateLeaderboard.copy()
rebateLeaderboardProcessor.processLeaderboard(
internalState.rebateLeaderboard,
leaderboard
)
return if (oldState != internalState.rebateLeaderboard) {
StateChanges(iListOf(Changes.rebateLeaderboard))
} else {
StateChanges.noChange
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import exchange.dydx.abacus.output.MarketCandle
import exchange.dydx.abacus.output.MarketCandles
import exchange.dydx.abacus.output.PerpetualMarketSummary
import exchange.dydx.abacus.output.PerpetualState
import exchange.dydx.abacus.output.FeeLeaderboard
import exchange.dydx.abacus.output.RebateLeaderboard
import exchange.dydx.abacus.output.TransferStatus
import exchange.dydx.abacus.output.Vault
import exchange.dydx.abacus.output.Wallet
Expand All @@ -35,6 +37,8 @@ import exchange.dydx.abacus.processor.configs.RewardsParamsProcessor
import exchange.dydx.abacus.processor.input.ClosePositionInputProcessor
import exchange.dydx.abacus.processor.input.TradeInputProcessor
import exchange.dydx.abacus.processor.launchIncentive.LaunchIncentiveProcessor
import exchange.dydx.abacus.processor.leaderboards.FeeLeaderboardProcessor
import exchange.dydx.abacus.processor.leaderboards.RebateLeaderboardProcessor
import exchange.dydx.abacus.processor.markets.MarketsSummaryProcessor
import exchange.dydx.abacus.processor.router.skip.SkipProcessor
import exchange.dydx.abacus.processor.vault.VaultProcessor
Expand Down Expand Up @@ -118,6 +122,8 @@ open class TradingStateMachine(
internal val launchIncentiveProcessor = LaunchIncentiveProcessor(parser)
internal val tradeInputProcessor = TradeInputProcessor(parser)
internal val closePositionInputProcessor = ClosePositionInputProcessor(parser)
internal val feeLeaderboardProcessor = FeeLeaderboardProcessor(parser)
internal val rebateLeaderboardProcessor = RebateLeaderboardProcessor(parser)

internal val marketsCalculator = MarketCalculator(parser)
internal val accountCalculator = AccountCalculator(parser, useParentSubaccount)
Expand Down Expand Up @@ -384,7 +390,9 @@ open class TradingStateMachine(
Changes.trackStatuses,
Changes.orderbook,
Changes.launchIncentive,
Changes.vault
Changes.vault,
Changes.feeLeaderboard,
Changes.rebateLeaderboard
-> true

Changes.wallet -> state?.wallet != wallet
Expand Down Expand Up @@ -599,6 +607,8 @@ open class TradingStateMachine(
var launchIncentive = state?.launchIncentive
val geo = state?.compliance
var vault = state?.vault
var surgeLeaderboard = state?.feeLeaderboard
var rebateLeaderboard = state?.rebateLeaderboard

if (changes.changes.contains(Changes.markets)) {
marketsSummary =
Expand Down Expand Up @@ -856,6 +866,16 @@ open class TradingStateMachine(
),
)
}
if (changes.changes.contains(Changes.feeLeaderboard)) {
surgeLeaderboard = FeeLeaderboard(
leaderboard = internalState.feeLeaderboard.leaderboard?.toIList() ?: iListOf()
)
}
if (changes.changes.contains(Changes.rebateLeaderboard)) {
rebateLeaderboard = RebateLeaderboard(
leaderboard = internalState.rebateLeaderboard.leaderboard?.toIList() ?: iListOf()
)
}
if (changes.changes.contains(Changes.vault) || changes.changes.contains(Changes.markets)) {
if (internalState.vault != null) {
val positions = VaultCalculator.calculateVaultPositionsInternal(
Expand Down Expand Up @@ -903,6 +923,8 @@ open class TradingStateMachine(
launchIncentive = launchIncentive,
compliance = geo,
vault = vault,
feeLeaderboard = surgeLeaderboard,
rebateLeaderboard = rebateLeaderboard
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import exchange.dydx.abacus.state.machine.onChainUnbonding
import exchange.dydx.abacus.state.machine.onChainUserFeeTier
import exchange.dydx.abacus.state.machine.onChainUserStakingTier
import exchange.dydx.abacus.state.machine.onChainUserStats
import exchange.dydx.abacus.state.machine.feeLeaderboard
import exchange.dydx.abacus.state.manager.ApiData
import exchange.dydx.abacus.state.manager.AutoSweepConfig
import exchange.dydx.abacus.state.manager.BlockAndTime
Expand Down Expand Up @@ -220,6 +221,9 @@ internal open class AccountSupervisor(
if (configs.retrieveLaunchIncentivePoints) {
retrieveLaunchIncentivePoints()
}
if (configs.retrieveFeeLeaderboard) {
retrieveFeeLeaderboard()
}
}
}

Expand Down Expand Up @@ -552,6 +556,19 @@ internal open class AccountSupervisor(
}
}

private fun retrieveFeeLeaderboard() {
val url = "https://pp-external-api-ffb2ad95ef03.herokuapp.com/api/dydx-fee-leaderboard"
helper.get(
url = url,
params = iMapOf("perPage" to "100", "address" to accountAddress)
) { _, response, httpCode, _ ->
if (helper.success(httpCode) && response != null) {
val oldState = stateMachine.state
update(stateMachine.feeLeaderboard(response), oldState)
}
}
}

private fun canConnectTo(subaccountNumber: Int): Boolean {
return stateMachine.state?.subaccount(subaccountNumber) != null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ data class SystemConfigs(
val retrieveRewardsParams: Boolean,
val retrieveLaunchIncentiveSeasons: Boolean,
val retrieveWithdrawSafetyChecks: Boolean,
val retrieveRebateLeaderboard: Boolean
) {
companion object {
val forApp = SystemConfigs(
Expand All @@ -23,6 +24,7 @@ data class SystemConfigs(
retrieveRewardsParams = true,
retrieveLaunchIncentiveSeasons = true,
retrieveWithdrawSafetyChecks = true,
retrieveRebateLeaderboard = true
)
val forProgrammaticTraders = SystemConfigs(
retrieveServerTime = true,
Expand All @@ -33,6 +35,7 @@ data class SystemConfigs(
retrieveRewardsParams = false,
retrieveLaunchIncentiveSeasons = false,
retrieveWithdrawSafetyChecks = false,
retrieveRebateLeaderboard = false
)
}
}
Expand Down Expand Up @@ -137,6 +140,7 @@ data class AccountConfigs(
val retrieveUserStakingTier: Boolean,
val transferNobleBalances: Boolean,
val subaccountConfigs: SubaccountConfigs,
val retrieveFeeLeaderboard: Boolean

) {
companion object {
Expand All @@ -150,6 +154,7 @@ data class AccountConfigs(
retrieveUserStakingTier = true,
transferNobleBalances = true,
subaccountConfigs = SubaccountConfigs.forApp,
retrieveFeeLeaderboard = true
)
val forAppWithIsolatedMargins = AccountConfigs(
retrieveUserFeeTier = true,
Expand All @@ -161,6 +166,7 @@ data class AccountConfigs(
retrieveUserStakingTier = true,
transferNobleBalances = true,
subaccountConfigs = SubaccountConfigs.forAppWithIsolatedMargins,
retrieveFeeLeaderboard = true
)
val forProgrammaticTraders = AccountConfigs(
retrieveUserFeeTier = true,
Expand All @@ -172,6 +178,7 @@ data class AccountConfigs(
retrieveUserStakingTier = true,
transferNobleBalances = true,
subaccountConfigs = SubaccountConfigs.forProgrammaticTraders,
retrieveFeeLeaderboard = false
)
}
}
Expand Down
Loading
Loading