Skip to content

Commit

Permalink
feat(Compliance): query for geo and compliance/screen during onboardi…
Browse files Browse the repository at this point in the history
…ng (#295)

* feat(Compliance): query for geo and compliance/screen during onboarding

* bump
  • Loading branch information
rosepuppy authored Apr 9, 2024
1 parent 3e662f9 commit 9334057
Show file tree
Hide file tree
Showing 13 changed files with 186 additions and 11 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ allprojects {
}

group = "exchange.dydx.abacus"
version = "1.6.34"
version = "1.6.35"

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

import kotlinx.serialization.Serializable
import kotlin.js.JsExport

@JsExport
@Serializable
enum class ComplianceStatus(val rawValue: String?) {
COMPLIANT("COMPLIANT"),
FIRST_STRIKE("FIRST_STRIKE"),
CLOSE_ONLY("CLOSE_ONLY"),
BLOCKED("BLOCKED"),
UNKNOWN("UNKNOWN"),
;

companion object {
operator fun invoke(rawValue: String?) =
ComplianceStatus.values().firstOrNull { it.rawValue == rawValue }
}
}

@JsExport
@Serializable
data class Compliance(
val geo: String?,
val status: ComplianceStatus,
)
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ data class PerpetualState(
val transferStatuses: IMap<String, TransferStatus>?,
val restriction: UsageRestriction?,
val launchIncentive: LaunchIncentive?,
val compliance: Compliance?,
) {
fun assetIds(): IList<String>? {
return assets?.keys?.toIList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ enum class Changes(val rawValue: String) {
transferStatuses("transferStatuses"),
input("input"),
restriction("restriction"),
compliance("compliance"),

launchIncentive("launchIncentive"),
;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package exchange.dydx.abacus.state.manager

import exchange.dydx.abacus.output.Notification
import exchange.dydx.abacus.output.PerpetualState
import exchange.dydx.abacus.output.Restriction
import exchange.dydx.abacus.output.SubaccountOrder
import exchange.dydx.abacus.output.TransferRecordType
import exchange.dydx.abacus.output.UsageRestriction
import exchange.dydx.abacus.output.*
import exchange.dydx.abacus.output.input.OrderType
import exchange.dydx.abacus.output.input.TradeInputGoodUntil
import exchange.dydx.abacus.output.input.TriggerOrder
Expand Down Expand Up @@ -250,6 +245,14 @@ open class StateManagerAdaptor(
}
}

private var compliance: Compliance = Compliance(null, ComplianceStatus.COMPLIANT)
set(value) {
if (field != value) {
field = value
didSetCompliance(value)
}
}

var subaccountNumber: Int = 0
internal set(value) {
if (field != value) {
Expand Down Expand Up @@ -402,6 +405,7 @@ open class StateManagerAdaptor(
open fun didSetReadyToConnect(readyToConnect: Boolean) {
if (readyToConnect) {
bestEffortConnectIndexer()
fetchGeo()
} else {
indexerConfig = null
}
Expand Down Expand Up @@ -432,9 +436,11 @@ open class StateManagerAdaptor(
}
if (sourceAddress != null) {
screenSourceAddress()
sourceAddress?.let { complianceScreen(it) }
}
if (accountAddress != null) {
screenAccountAddress()
accountAddress?.let { complianceScreen(it) }
retrieveAccount()
retrieveAccountHistoricalTradingRewards()
}
Expand Down Expand Up @@ -480,6 +486,7 @@ open class StateManagerAdaptor(

subaccountsTimer = null
screenAccountAddress()
accountAddress?.let { complianceScreen(it) }
retrieveAccountHistoricalTradingRewards()
}

Expand All @@ -491,6 +498,7 @@ open class StateManagerAdaptor(
sourceAddressTimer = null
sourceAddressRestriction = null
screenSourceAddress()
sourceAddress?.let { complianceScreen(it) }
}

internal open fun didSetSubaccountNumber(subaccountNumber: Int) {
Expand Down Expand Up @@ -1394,6 +1402,18 @@ open class StateManagerAdaptor(
return null
}

open fun complianceScreenUrl(address: String): String? {
return null
}

open fun complianceGeoblockUrl(): String? {
return null
}

open fun geoUrl(): String? {
return null
}

open fun historicalTradingRewardAggregationsUrl(): String? {
return null
}
Expand Down Expand Up @@ -2342,6 +2362,60 @@ open class StateManagerAdaptor(
}
}

open fun fetchGeo() {
val url = geoUrl()
if (url != null) {
get(
url,
null,
null,
callback = { _, response, httpCode, _ ->
compliance = if (success(httpCode) && response != null) {
val payload = parser.decodeJsonObject(response)?.toIMap()
if (payload != null) {
val country = parser.asString(parser.value(payload, "geo.country"))
Compliance(country, compliance.status)
} else {
Compliance(null, compliance.status)
}
} else {
Compliance(null, compliance.status)
}
},
)
}
}

open fun complianceCheck() {

}


open fun complianceScreen(address: String) {
val url = complianceScreenUrl(address)
if (url != null) {
get(
url,
null,
null,
callback = { _, response, httpCode, _ ->
compliance = if (success(httpCode) && response != null) {
val payload = parser.decodeJsonObject(response)?.toIMap()
if (payload != null) {
val status = parser.asString(payload["status"])
val complianceStatus = ComplianceStatus.invoke(status) ?: ComplianceStatus.UNKNOWN
Compliance(compliance?.geo, complianceStatus)
} else {
Compliance(compliance?.geo, ComplianceStatus.UNKNOWN)
}
} else {
Compliance(compliance?.geo, ComplianceStatus.UNKNOWN)
}
},
)
}
}

open fun screenAccountAddress() {
val address = accountAddress
if (address != null) {
Expand Down Expand Up @@ -2468,6 +2542,7 @@ open class StateManagerAdaptor(
state?.transferStatuses,
restriction,
state?.launchIncentive,
state?.compliance,
)
ioImplementations.threading?.async(ThreadingType.main) {
stateNotification?.stateChanged(
Expand All @@ -2479,6 +2554,39 @@ open class StateManagerAdaptor(
}
}

private fun didSetCompliance(compliance: Compliance?) {
val state = stateMachine.state
stateMachine.state = PerpetualState(
state?.assets,
state?.marketsSummary,
state?.orderbooks,
state?.candles,
state?.trades,
state?.historicalFundings,
state?.wallet,
state?.account,
state?.historicalPnl,
state?.fills,
state?.transfers,
state?.fundingPayments,
state?.configs,
state?.input,
state?.availableSubaccountNumbers ?: iListOf(),
state?.transferStatuses,
state?.restriction,
state?.launchIncentive,
compliance,
)
ioImplementations.threading?.async(ThreadingType.main) {
stateNotification?.stateChanged(
stateMachine.state,
StateChanges(
iListOf(Changes.compliance),
),
)
}
}

internal open fun dispose() {
stateNotification = null
dataNotification = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,19 @@ class V4StateManagerAdaptor(
return configs.publicApiUrl("screen")
}

override fun geoUrl(): String {
return "https://api.dydx.exchange/v4/geo"
}

override fun complianceScreenUrl(address: String): String? {
val url = configs.publicApiUrl("complianceScreen") ?: return null
return "$url/$address"
}

override fun complianceGeoblockUrl(): String? {
return configs.publicApiUrl("complianceGeoblock")
}

override fun historicalTradingRewardAggregationsUrl(): String? {
val url = configs.privateApiUrl("historicalTradingRewardAggregations")
return if (accountAddress != null && url != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class V4StateManagerConfigs(
"account":"/v4/addresses",
"time":"/v4/time",
"screen":"/v4/screen",
"complianceScreen":"/v4/compliance/screen",
"complianceGeoblock":"/v4/compliance/geoblock",
"height":"/v4/height"
},
"private":{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,10 @@ open class TradingStateMachine(
Logger.d { "Restriction is handled separately and shouldn't have gone through here" }
false
}
Changes.compliance -> {
Logger.d { "Compliance is handled separately and shouldn't have gone through here" }
false
}
}
if (didChange) {
realChanges.add(change)
Expand Down Expand Up @@ -969,6 +973,7 @@ open class TradingStateMachine(
var transferStatuses = state?.transferStatuses?.toIMutableMap()
val restriction = state?.restriction
var launchIncentive = state?.launchIncentive
val geo = state?.compliance

if (changes.changes.contains(Changes.markets)) {
parser.asNativeMap(data?.get("markets"))?.let {
Expand Down Expand Up @@ -1255,6 +1260,7 @@ open class TradingStateMachine(
transferStatuses,
restriction,
launchIncentive,
geo,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ internal class StateManagerAdaptorV2(
state?.transferStatuses,
restriction,
state?.launchIncentive,
state?.compliance,
)
ioImplementations.threading?.async(ThreadingType.main) {
stateNotification?.stateChanged(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ internal open class AccountSupervisor(
state?.transferStatuses,
restriction,
state?.launchIncentive,
state?.compliance,
)
helper.ioImplementations.threading?.async(ThreadingType.main) {
helper.stateNotification?.stateChanged(
Expand Down
Loading

0 comments on commit 9334057

Please sign in to comment.