Skip to content

Commit

Permalink
Parse delegations for account staking balances (#395)
Browse files Browse the repository at this point in the history
Co-authored-by: mobile-build-bot-git <[email protected]>
  • Loading branch information
2 people authored and yogurtandjam committed May 31, 2024
1 parent 99e667e commit 72cfc5e
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 25 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ allprojects {
}

group = "exchange.dydx.abacus"
version = "1.7.34"
version = "1.7.35"

repositories {
google()
Expand Down
124 changes: 104 additions & 20 deletions src/commonMain/kotlin/exchange.dydx.abacus/output/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,38 @@ data class AccountBalance(
}
}

@JsExport
@Serializable
data class StakingDelegation(
var validator: String,
var amount: String,
) {
companion object {
internal fun create(
existing: StakingDelegation?,
parser: ParserProtocol,
data: Map<String, Any>,
decimals: Int,
): StakingDelegation? {
Logger.d { "creating Staking Delegation\n" }

val validator = parser.asString(data["validator"])
val amount = parser.asDecimal(data["amount"])
if (validator != null && amount != null) {
val decimalAmount = amount * Numeric.decimal.TEN.pow(-1 * decimals)
val decimalAmountString = parser.asString(decimalAmount)!!
return if (existing?.validator != validator || existing.amount != decimalAmountString) {
StakingDelegation(validator, decimalAmountString)
} else {
existing
}
}
Logger.d { "Staking Delegation not valid" }
return null
}
}
}

@JsExport
@Serializable
data class HistoricalTradingReward(
Expand Down Expand Up @@ -2020,6 +2052,7 @@ data class TradingRewards(
data class Account(
var balances: IMap<String, AccountBalance>?,
var stakingBalances: IMap<String, AccountBalance>?,
var stakingDelegations: IList<StakingDelegation>?,
var subaccounts: IMap<String, Subaccount>?,
var groupedSubaccounts: IMap<String, Subaccount>?,
var tradingRewards: TradingRewards?,
Expand Down Expand Up @@ -2057,26 +2090,20 @@ data class Account(
}

val stakingBalances: IMutableMap<String, AccountBalance> =
iMutableMapOf()
val stakingBalancesData = parser.asMap(data["stakingBalances"])
if (stakingBalancesData != null) {
for ((key, value) in stakingBalancesData) {
// key is the denom
// It should be chain token denom here
val tokenInfo = findTokenInfo(tokensInfo, key)
if (tokenInfo != null) {
val balanceData = parser.asMap(value) ?: iMapOf()
AccountBalance.create(
existing?.stakingBalances?.get(key),
parser,
balanceData,
tokenInfo.decimals,
)?.let { balance ->
stakingBalances[key] = balance
}
}
}
}
processStakingBalance(
existing,
parser,
data,
tokensInfo,
)

val stakingDelegations: IMutableList<StakingDelegation> =
processStakingDelegations(
existing,
parser,
data,
tokensInfo,
)

val tradingRewardsData = parser.asMap(data["tradingRewards"])
val tradingRewards = if (tradingRewardsData != null) {
Expand Down Expand Up @@ -2132,6 +2159,7 @@ data class Account(
return Account(
balances,
stakingBalances,
stakingDelegations,
subaccounts,
groupedSubaccounts,
tradingRewards,
Expand All @@ -2142,5 +2170,61 @@ data class Account(
private fun findTokenInfo(tokensInfo: Map<String, TokenInfo>, denom: String): TokenInfo? {
return tokensInfo.firstNotNullOfOrNull { if (it.value.denom == denom) it.value else null }
}

private fun processStakingDelegations(
existing: Account?,
parser: ParserProtocol,
data: Map<String, Any>,
tokensInfo: Map<String, TokenInfo>,
): IMutableList<StakingDelegation> {
val stakingDelegations: IMutableList<StakingDelegation> =
iMutableListOf()
val stakingDelegationsData = parser.asList(data["stakingDelegations"])
stakingDelegationsData?.forEachIndexed { index, value ->
val stakingDelegationData = parser.asMap(value) ?: iMapOf()
val tokenInfo = findTokenInfo(tokensInfo, stakingDelegationData["denom"] as String)
if (tokenInfo != null) {
StakingDelegation.create(
existing?.stakingDelegations?.getOrNull(index),
parser,
stakingDelegationData,
tokenInfo.decimals,
)?.let { stakingDelegation ->
stakingDelegations.add(stakingDelegation)
}
}
}
return stakingDelegations
}

private fun processStakingBalance(
existing: Account?,
parser: ParserProtocol,
data: Map<String, Any>,
tokensInfo: Map<String, TokenInfo>,
): IMutableMap<String, AccountBalance> {
val stakingBalances: IMutableMap<String, AccountBalance> =
iMutableMapOf()
val stakingBalancesData = parser.asMap(data["stakingBalances"])
if (stakingBalancesData != null) {
for ((key, value) in stakingBalancesData) {
// key is the denom
// It should be chain token denom here
val tokenInfo = findTokenInfo(tokensInfo, key)
if (tokenInfo != null) {
val balanceData = parser.asMap(value) ?: iMapOf()
AccountBalance.create(
existing?.stakingBalances?.get(key),
parser,
balanceData,
tokenInfo.decimals,
)?.let { balance ->
stakingBalances[key] = balance
}
}
}
}
return stakingBalances
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -809,8 +809,9 @@ private class V4AccountDelegationsProcessor(parser: ParserProtocol) : BaseProces
return if (payload != null) {
val modified = mutableMapOf<String, Any>()
for (itemPayload in payload) {
val delegation = parser.asNativeMap(itemPayload)
val balance = parser.asNativeMap(delegation?.get("balance"))
val item = parser.asNativeMap(itemPayload)
val balance = parser.asNativeMap(item?.get("balance"))

if (balance != null) {
val denom = parser.asString(balance["denom"])
if (denom != null) {
Expand Down Expand Up @@ -842,6 +843,33 @@ private class V4AccountDelegationsProcessor(parser: ParserProtocol) : BaseProces
null
}
}

fun receivedDelegations(
existing: Map<String, Any>?,
payload: List<Any>?,
): List<Any>? {
return if (payload != null) {
val modified = mutableListOf<Any>()
for (itemPayload in payload) {
val item = parser.asNativeMap(itemPayload)
val validator = parser.asString(parser.value(item, "delegation.validatorAddress"))
val amount = parser.asDecimal(parser.value(item, "balance.amount"))
val denom = parser.asString(parser.value(item, "balance.denom"))
if (validator != null && amount != null) {
modified.add(
mapOf(
"validator" to validator,
"amount" to amount,
"denom" to denom,
),
)
}
}
return modified
} else {
null
}
}
}

private class V4AccountTradingRewardsProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
Expand Down Expand Up @@ -914,8 +942,10 @@ internal class V4AccountProcessor(parser: ParserProtocol) : BaseProcessor(parser
): Map<String, Any>? {
val modified = existing?.mutable() ?: mutableMapOf()
val delegations = parser.asNativeMap(parser.value(existing, "stakingBalances"))
val modifiedDelegations = delegationsProcessor.received(delegations, payload)
modified.safeSet("stakingBalances", modifiedDelegations)
val modifiedStakingBalance = delegationsProcessor.received(delegations, payload)
modified.safeSet("stakingBalances", modifiedStakingBalance)
val modifiedDelegations = delegationsProcessor.receivedDelegations(delegations, payload)
modified.safeSet("stakingDelegations", modifiedDelegations)
return modified
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,7 @@ open class TradingStateMachine(
Account(
account.balances,
account.stakingBalances,
account.stakingDelegations,
subaccounts,
groupedSubaccounts,
account.tradingRewards,
Expand Down

0 comments on commit 72cfc5e

Please sign in to comment.