-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ANCHOR-362] SEP-6: Update reference server to set required_customer_info_updates #1161
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,23 @@ class Sep6End2EndTest(val config: TestConfig, val jwt: String) { | |
companion object { | ||
private val USDC = | ||
IssuedAssetId("USDC", "GDQOE23CFSUMSVQK4Y5JHPPYK73VYCNHZHA7ENKCV37P6SUEO6XQBKPP") | ||
private val basicInfoFields = listOf("first_name", "last_name", "email_address") | ||
private val customerInfo = | ||
mapOf( | ||
"first_name" to "John", | ||
"last_name" to "Doe", | ||
"address" to "123 Bay Street", | ||
"email_address" to "[email protected]", | ||
"id_type" to "drivers_license", | ||
"id_country_code" to "CAN", | ||
"id_issue_date" to "2023-01-01T05:00:00Z", | ||
"id_expiration_date" to "2099-01-01T05:00:00Z", | ||
"id_number" to "1234567890", | ||
"bank_account_number" to "13719713158835300", | ||
"bank_account_type" to "checking", | ||
"bank_number" to "123", | ||
"bank_branch_number" to "121122676" | ||
) | ||
} | ||
|
||
private fun `test typical deposit end-to-end flow`() = runBlocking { | ||
|
@@ -58,9 +75,7 @@ class Sep6End2EndTest(val config: TestConfig, val jwt: String) { | |
val sep6Client = Sep6Client("${config.env["anchor.domain"]}/sep6", token.token) | ||
|
||
// Create a customer before starting the transaction | ||
anchor | ||
.customer(token) | ||
.add(mapOf("first_name" to "John", "last_name" to "Doe", "email_address" to "[email protected]")) | ||
anchor.customer(token).add(basicInfoFields.associateWith { customerInfo[it]!! }) | ||
|
||
val deposit = | ||
sep6Client.deposit( | ||
|
@@ -74,7 +89,9 @@ class Sep6End2EndTest(val config: TestConfig, val jwt: String) { | |
waitStatus(deposit.id, "pending_customer_info_update", sep6Client) | ||
|
||
// Supply missing KYC info to continue with the transaction | ||
anchor.customer(token).add(mapOf("email_address" to "[email protected]")) | ||
val additionalRequiredFields = | ||
sep6Client.getTransaction(mapOf("id" to deposit.id)).transaction.requiredCustomerInfoUpdates | ||
anchor.customer(token).add(additionalRequiredFields.associateWith { customerInfo[it]!! }) | ||
waitStatus(deposit.id, "completed", sep6Client) | ||
|
||
val completedDepositTxn = sep6Client.getTransaction(mapOf("id" to deposit.id)) | ||
|
@@ -99,8 +116,7 @@ class Sep6End2EndTest(val config: TestConfig, val jwt: String) { | |
) | ||
assertEquals(completedDepositTxn.transaction.id, transactionByStellarId.transaction.id) | ||
|
||
val expectedStatuses = | ||
listOf("incomplete", "pending_anchor", "pending_customer_info_update", "completed") | ||
val expectedStatuses = listOf("incomplete", "pending_customer_info_update", "completed") | ||
assertAnchorReceivedStatuses(deposit.id, expectedStatuses) | ||
assertWalletReceivedStatuses(deposit.id, expectedStatuses) | ||
} | ||
|
@@ -111,9 +127,7 @@ class Sep6End2EndTest(val config: TestConfig, val jwt: String) { | |
val sep6Client = Sep6Client("${config.env["anchor.domain"]}/sep6", token.token) | ||
|
||
// Create a customer before starting the transaction | ||
anchor | ||
.customer(token) | ||
.add(mapOf("first_name" to "John", "last_name" to "Doe", "email_address" to "[email protected]")) | ||
anchor.customer(token).add(basicInfoFields.associateWith { customerInfo[it]!! }) | ||
|
||
val withdraw = | ||
sep6Client.withdraw( | ||
|
@@ -122,15 +136,9 @@ class Sep6End2EndTest(val config: TestConfig, val jwt: String) { | |
waitStatus(withdraw.id, "pending_customer_info_update", sep6Client) | ||
|
||
// Supply missing financial account info to continue with the transaction | ||
anchor | ||
.customer(token) | ||
.add( | ||
mapOf( | ||
"bank_account_type" to "checking", | ||
"bank_account_number" to "121122676", | ||
"bank_number" to "13719713158835300", | ||
) | ||
) | ||
val additionalRequiredFields = | ||
sep6Client.getTransaction(mapOf("id" to withdraw.id)).transaction.requiredCustomerInfoUpdates | ||
anchor.customer(token).add(additionalRequiredFields.associateWith { customerInfo[it]!! }) | ||
waitStatus(withdraw.id, "pending_user_transfer_start", sep6Client) | ||
|
||
// Transfer the withdrawal amount to the Anchor | ||
|
@@ -142,7 +150,6 @@ class Sep6End2EndTest(val config: TestConfig, val jwt: String) { | |
.build() | ||
transfer.sign(keypair) | ||
wallet.stellar().submitTransaction(transfer) | ||
|
||
waitStatus(withdraw.id, "completed", sep6Client) | ||
|
||
val expectedStatuses = | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,11 +55,18 @@ class CustomerService(private val customerRepository: CustomerRepository) { | |
customer.copy( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Is there anything like BeanUtils in Kotlin? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or use I think this is for the reference and does not require critical performance but rather explanations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wrote it this way since I don't want |
||
firstName = request.firstName ?: customer.firstName, | ||
lastName = request.lastName ?: customer.lastName, | ||
address = request.address ?: customer.address, | ||
emailAddress = request.emailAddress ?: customer.emailAddress, | ||
bankAccountNumber = request.bankAccountNumber ?: customer.bankAccountNumber, | ||
bankAccountType = request.bankAccountType ?: customer.bankAccountType, | ||
bankRoutingNumber = request.bankNumber ?: customer.bankRoutingNumber, | ||
clabeNumber = request.clabeNumber ?: customer.clabeNumber | ||
bankNumber = request.bankNumber ?: customer.bankNumber, | ||
bankBranchNumber = request.bankBranchNumber ?: customer.bankBranchNumber, | ||
clabeNumber = request.clabeNumber ?: customer.clabeNumber, | ||
idType = request.idType ?: customer.idType, | ||
idCountryCode = request.idCountryCode ?: customer.idCountryCode, | ||
idIssueDate = request.idIssueDate ?: customer.idIssueDate, | ||
idExpirationDate = request.idExpirationDate ?: customer.idExpirationDate, | ||
idNumber = request.idNumber ?: customer.idNumber, | ||
) | ||
) | ||
return PutCustomerResponse(customer.id) | ||
|
@@ -73,11 +80,18 @@ class CustomerService(private val customerRepository: CustomerRepository) { | |
memoType = request.memoType, | ||
firstName = request.firstName, | ||
lastName = request.lastName, | ||
address = request.address, | ||
emailAddress = request.emailAddress, | ||
bankAccountNumber = request.bankAccountNumber, | ||
bankAccountType = request.bankAccountType, | ||
bankRoutingNumber = request.bankNumber, | ||
clabeNumber = request.clabeNumber | ||
bankNumber = request.bankNumber, | ||
bankBranchNumber = request.bankBranchNumber, | ||
clabeNumber = request.clabeNumber, | ||
idType = request.idType, | ||
idCountryCode = request.idCountryCode, | ||
idIssueDate = request.idIssueDate, | ||
idExpirationDate = request.idExpirationDate, | ||
idNumber = request.idNumber, | ||
) | ||
) | ||
return PutCustomerResponse(id) | ||
|
@@ -100,33 +114,82 @@ class CustomerService(private val customerRepository: CustomerRepository) { | |
val providedFields = mutableMapOf<String, ProvidedCustomerField>() | ||
val missingFields = mutableMapOf<String, CustomerField>() | ||
|
||
val commonFields = | ||
val fields = | ||
mapOf( | ||
"first_name" to createField(customer.firstName, "string", "The customer's first name"), | ||
"last_name" to createField(customer.lastName, "string", "The customer's last name"), | ||
"address" to | ||
createField(customer.address, "string", "The customer's address", optional = true), | ||
"email_address" to | ||
createField(customer.emailAddress, "string", "The customer's email address"), | ||
) | ||
val sep31ReceiverFields = | ||
mapOf( | ||
"bank_account_number" to | ||
createField(customer.bankAccountNumber, "string", "The customer's bank account number"), | ||
createField( | ||
customer.bankAccountNumber, | ||
"string", | ||
"The customer's bank account number", | ||
optional = type != "sep31-receiver" | ||
), | ||
"bank_account_type" to | ||
createField( | ||
customer.bankAccountType, | ||
"string", | ||
"The customer's bank account type", | ||
choices = listOf("checking", "savings") | ||
choices = listOf("checking", "savings"), | ||
optional = type != "sep31-receiver" | ||
), | ||
"bank_number" to | ||
createField(customer.bankRoutingNumber, "string", "The customer's bank routing number"), | ||
"clabe_number" to createField(customer.clabeNumber, "string", "The customer's CLABE number") | ||
createField( | ||
customer.bankNumber, | ||
"string", | ||
"The customer's bank routing number", | ||
optional = type != "sep31-receiver" | ||
), | ||
"bank_branch_number" to | ||
createField( | ||
customer.bankBranchNumber, | ||
"string", | ||
"The customer's bank branch number", | ||
optional = true | ||
), | ||
"clabe_number" to | ||
createField( | ||
customer.clabeNumber, | ||
"string", | ||
"The customer's CLABE number", | ||
optional = type != "sep31-receiver" | ||
), | ||
"id_type" to | ||
createField( | ||
customer.idType, | ||
"string", | ||
"The customer's ID type", | ||
optional = true, | ||
choices = listOf("drivers_license", "passport", "national_id") | ||
), | ||
"id_country_code" to | ||
createField( | ||
customer.idCountryCode, | ||
"string", | ||
"The customer's ID country code", | ||
optional = true | ||
), | ||
"id_issue_date" to | ||
createField( | ||
customer.idIssueDate, | ||
"string", | ||
"The customer's ID issue date", | ||
optional = true | ||
), | ||
"id_expiration_date" to | ||
createField( | ||
customer.idExpirationDate, | ||
"string", | ||
"The customer's ID expiration date", | ||
optional = true | ||
), | ||
"id_number" to | ||
createField(customer.idNumber, "string", "The customer's ID number", optional = true) | ||
) | ||
val fields = | ||
when (type) { | ||
"sep31-receiver" -> commonFields.plus(sep31ReceiverFields) | ||
else -> commonFields | ||
} | ||
|
||
// Extract fields from customer | ||
fields.forEach( | ||
|
@@ -140,7 +203,7 @@ class CustomerService(private val customerRepository: CustomerRepository) { | |
|
||
val status = | ||
when { | ||
missingFields.isNotEmpty() -> Status.NEEDS_INFO | ||
missingFields.filter { !it.value.optional }.isNotEmpty() -> Status.NEEDS_INFO | ||
else -> Status.ACCEPTED | ||
}.toString() | ||
|
||
|
@@ -154,8 +217,10 @@ class CustomerService(private val customerRepository: CustomerRepository) { | |
|
||
sealed class Field { | ||
class Provided(val field: ProvidedCustomerField) : Field() | ||
|
||
class Missing(val field: CustomerField) : Field() | ||
} | ||
|
||
private fun createField( | ||
value: Any?, | ||
type: String, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Can we use the
enum
here?