Skip to content

Commit

Permalink
Call compliance API to update compliance state during onboarding (#311)
Browse files Browse the repository at this point in the history
* Call compliance API to update compliance state

* revert imports

* fix lint

* fix callback

* make private

* address comments

* address comments

* address comments

* address comments

* tostring

* bump version
  • Loading branch information
rosepuppy authored Apr 25, 2024
1 parent 652704f commit 0480274
Show file tree
Hide file tree
Showing 17 changed files with 194 additions and 87 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ allprojects {
}

group = "exchange.dydx.abacus"
version = "1.6.46"
version = "1.6.47"

repositories {
google()
Expand Down
1 change: 1 addition & 0 deletions detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@
<ID>InvalidPackageDeclaration:MarketsProcessor.kt$package exchange.dydx.abacus.processor.markets</ID>
<ID>InvalidPackageDeclaration:MarketsSummaryProcessor.kt$package exchange.dydx.abacus.processor.markets</ID>
<ID>InvalidPackageDeclaration:MarketsSupervisor.kt$package exchange.dydx.abacus.state.v2.supervisor</ID>
<ID>InvalidPackageDeclaration:Address.kt$package exchange.dydx.abacus.state.manager.utils</ID>
<ID>InvalidPackageDeclaration:Network.kt$package exchange.dydx.abacus.state.manager</ID>
<ID>InvalidPackageDeclaration:NetworkConfigsProcessor.kt$package exchange.dydx.abacus.processor.configs</ID>
<ID>InvalidPackageDeclaration:NetworkHelper.kt$package exchange.dydx.abacus.state.v2.supervisor</ID>
Expand Down
4 changes: 2 additions & 2 deletions integration/iOS/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ EXTERNAL SOURCES:
:path: "~/v4-abacus"

SPEC CHECKSUMS:
abacus: 46f62be6dc9b3f888093eb2c9952d0267ab40670
abacus: a57d55b0ca0d3514389573a87c47507f88eb6b0a
CryptoSwift: 562f8eceb40e80796fffc668b0cad9313284cfa6

PODFILE CHECKSUM: 37d72c15b180e62a4c42b8fb41b4836c89aa63c9

COCOAPODS: 1.15.2
COCOAPODS: 1.12.1
1 change: 0 additions & 1 deletion integration/iOS/Pods/Local Podspecs/abacus.podspec.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions integration/iOS/Pods/Manifest.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 43 additions & 43 deletions integration/iOS/Pods/Pods.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 15 additions & 11 deletions src/commonMain/kotlin/exchange.dydx.abacus/output/Compliance.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ 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"),
;
enum class ComplianceStatus {
COMPLIANT,
FIRST_STRIKE,
FIRST_STRIKE_CLOSE_ONLY,
CLOSE_ONLY,
BLOCKED,
UNKNOWN;
}

companion object {
operator fun invoke(rawValue: String?) =
ComplianceStatus.values().firstOrNull { it.rawValue == rawValue }
}
@JsExport
@Serializable
enum class ComplianceAction {
ONBOARD,
CONNECT,
VALID_SURVEY,
INVALID_SURVEY;
}

@JsExport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ enum class TransactionType(val rawValue: String) {
simulateTransferNativeToken("simulateTransferNativeToken"),
SendNobleIBC("sendNobleIBC"),
WithdrawToNobleIBC("withdrawToNobleIBC"),
CctpWithdraw("cctpWithdraw");
CctpWithdraw("cctpWithdraw"),
SignCompliancePayload("signCompliancePayload");

companion object {
operator fun invoke(rawValue: String) =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package exchange.dydx.abacus.state.manager

import exchange.dydx.abacus.output.Compliance
import exchange.dydx.abacus.output.ComplianceAction
import exchange.dydx.abacus.output.ComplianceStatus
import exchange.dydx.abacus.output.Notification
import exchange.dydx.abacus.output.PerpetualState
Expand All @@ -17,6 +18,7 @@ import exchange.dydx.abacus.protocols.LocalTimerProtocol
import exchange.dydx.abacus.protocols.StateNotificationProtocol
import exchange.dydx.abacus.protocols.ThreadingType
import exchange.dydx.abacus.protocols.TransactionCallback
import exchange.dydx.abacus.protocols.TransactionType
import exchange.dydx.abacus.responses.ParsingError
import exchange.dydx.abacus.responses.ParsingErrorType
import exchange.dydx.abacus.responses.ParsingException
Expand All @@ -27,6 +29,9 @@ 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.utils.Address
import exchange.dydx.abacus.state.manager.utils.DydxAddress
import exchange.dydx.abacus.state.manager.utils.EvmAddress
import exchange.dydx.abacus.state.model.ClosePositionInputField
import exchange.dydx.abacus.state.model.PerpTradingStateMachine
import exchange.dydx.abacus.state.model.TradeInputField
Expand Down Expand Up @@ -77,6 +82,7 @@ import exchange.dydx.abacus.utils.ServerTime
import exchange.dydx.abacus.utils.UIImplementations
import exchange.dydx.abacus.utils.iMapOf
import exchange.dydx.abacus.utils.mutable
import exchange.dydx.abacus.utils.toJsonPrettyPrint
import exchange.dydx.abacus.utils.values
import kollections.JsExport
import kollections.iListOf
Expand All @@ -92,6 +98,7 @@ import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlin.collections.mutableMapOf
import kotlin.random.Random
import kotlin.time.Duration
import kotlin.time.Duration.Companion.days
Expand Down Expand Up @@ -443,11 +450,13 @@ open class StateManagerAdaptor(
}
if (sourceAddress != null) {
screenSourceAddress()
sourceAddress?.let { complianceScreen(it) }
sourceAddress?.let { complianceScreen(EvmAddress(it)) }
}
if (accountAddress != null) {
screenAccountAddress()
accountAddress?.let { complianceScreen(it) }
accountAddress?.let {
complianceScreen(DydxAddress(it))
}
retrieveAccount()
retrieveAccountHistoricalTradingRewards()
}
Expand Down Expand Up @@ -493,7 +502,9 @@ open class StateManagerAdaptor(

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

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

internal open fun didSetSubaccountNumber(subaccountNumber: Int) {
Expand Down Expand Up @@ -1140,6 +1151,13 @@ open class StateManagerAdaptor(
}
}

@Throws(Exception::class)
internal open fun transaction(
type: TransactionType,
paramsInJson: String?,
callback: (response: String) -> Unit,
) {}

internal open fun trackApiCall() {
}

Expand Down Expand Up @@ -2374,7 +2392,7 @@ open class StateManagerAdaptor(
}
}

open fun fetchGeo() {
private fun fetchGeo() {
val url = geoUrl()
if (url != null) {
get(
Expand All @@ -2398,28 +2416,99 @@ open class StateManagerAdaptor(
}
}

open fun complianceCheck() {
private fun handleComplianceResponse(response: String?, httpCode: Int): ComplianceStatus {
compliance = if (success(httpCode) && response != null) {
val res = parser.decodeJsonObject(response)?.toIMap()
if (res != null) {
val status = parser.asString(res["status"])
val complianceStatus =
if (status != null) {
ComplianceStatus.valueOf(status)
} else {
ComplianceStatus.UNKNOWN
}
Compliance(compliance?.geo, complianceStatus)
} else {
Compliance(compliance?.geo, ComplianceStatus.UNKNOWN)
}
} else {
Compliance(compliance?.geo, ComplianceStatus.UNKNOWN)
}
return compliance.status
}

open fun complianceScreen(address: String) {
val url = complianceScreenUrl(address)
private fun updateCompliance(address: DydxAddress, status: ComplianceStatus) {
val message = "Compliance verification message"
val action = if ((stateMachine.state?.account?.subaccounts?.size ?: 0) > 0) {
ComplianceAction.CONNECT
} else {
ComplianceAction.ONBOARD
}
val payload = jsonEncoder.encode(
mapOf(
"message" to message,
"action" to action.toString(),
"status" to status.toString(),
),
)
transaction(
TransactionType.SignCompliancePayload,
payload,
) { additionalPayload ->
val error = parseTransactionResponse(additionalPayload)
val result = parser.decodeJsonObject(additionalPayload)

if (error == null && result != null) {
val url = complianceGeoblockUrl()
val signedMessage = parser.asString(result["signedMessage"])
val publicKey = parser.asString(result["publicKey"])
val timestamp = parser.asString(result["timestamp"])

val isUrlAndKeysPresent =
url != null && signedMessage != null && publicKey != null && timestamp != null
val isStatusValid = status != ComplianceStatus.UNKNOWN

if (isUrlAndKeysPresent && isStatusValid) {
val body: IMap<String, String> = iMapOf(
"address" to address.rawAddress,
"message" to message,
"currentStatus" to status.toString(),
"action" to action.toString(),
"signedMessage" to signedMessage!!,
"pubkey" to publicKey!!,
"timestamp" to timestamp!!,
)
val header = iMapOf(
"Content-Type" to "application/json",
)
post(
url!!,
header,
body.toJsonPrettyPrint(),
callback = { _, response, httpCode, _ ->
handleComplianceResponse(response, httpCode)
},
)
} else {
compliance = Compliance(compliance?.geo, ComplianceStatus.UNKNOWN)
}
} else {
compliance = Compliance(compliance?.geo, ComplianceStatus.UNKNOWN)
}
}
}

private fun complianceScreen(address: Address) {
val url = complianceScreenUrl(address.rawAddress)
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)
val complianceStatus = handleComplianceResponse(response, httpCode)
if (address is DydxAddress) {
updateCompliance(address, complianceStatus)
}
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ class V4StateManagerAdaptor(
}

@Throws(Exception::class)
fun transaction(
override fun transaction(
type: TransactionType,
paramsInJson: String?,
callback: (response: String) -> Unit,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package exchange.dydx.abacus.state.manager.utils

import kotlin.jvm.JvmInline

sealed interface Address {
val rawAddress: String
}

@JvmInline
value class EvmAddress(override val rawAddress: String) : Address

@JvmInline
value class DydxAddress(override val rawAddress: String) : Address
2 changes: 1 addition & 1 deletion v4_abacus.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'v4_abacus'
spec.version = '1.6.46'
spec.version = '1.6.47'
spec.homepage = 'https://github.com/dydxprotocol/v4-abacus'
spec.source = { :http=> ''}
spec.authors = ''
Expand Down

0 comments on commit 0480274

Please sign in to comment.