13.64. DD 64: Algorithm for transactions with KYC checks#
13.64.1. Summary#
This design document specifies the algorithm that wallets and merchants should use for processing and (re-)trying transactions where KYC checks may apply.
13.64.2. Motivation#
The exchange requires the customer to pass KYC checks and satisfy AML rules for various transactions. However, the corresponding rules are dynamic and may also be hidden from the client for regulatory purposes.
13.64.3. Requirements#
Minimize the time time the user has to wait (=> long-poll efficiently)
Minimize the number of requests that the exchange has do process (=> do not quickly retry when it’s clear the the request is unlikely to succeed now)
13.64.4. Proposed Solution#
Steps for processing operation of type op and amount amt:
13.64.4.1. Initialization#
Initialize the following variables:
last_check_status := nullLast HTTP status of the kyc-check request. A status of
0indicates a network failure or request timeout and is distinct fromnull, which indicates that no check request has been made.
last_check_code := nullTaler error code of the last kyc-check request or
nullif no such request has been made or the last request didn’t return an error code.
last_rule_gen := nulllast_aml_review := nulllast_deny := if isZeroLimited(op, amt) then now() else nulllast_bad_kyc_auth := falseaccount_keypair := getCurrentAccountKeyPair(op)
13.64.4.2. Processing#
If
last_denyisnullor more than1hago, make a request foropat the exchange. Letrespbe the response.If the request succeeds, halt.
If the request fails with
451, setlast_deny := now()andlast_bad_kyc_auth := resp.bad_kyc_auth.Otherwise, finish processing operation with result
BACKOFF.
Request the
/kyc-check/...endpoint applicable foropwithaccount_keypairthe following parameters:If
last_check_status == null: Make request without long-polling.If
last_check_status in [403 Forbidden, 409 Conflict]orlast_bad_kyc_auth == true && last_check_status == 404: Long-poll. Add query parameterlpt=1If
last_aml_review == true: Long-poll. Add query parameterlpt=2. Iflast_rule_gen != null, add query parametermin_rule=last_rule_gen.Otherwise: Long-poll. If
last_rule_gen != null, addmin_rule=last_rule_gento the query parameters.
Handle the
/kyc-check/...response:Set
same_resp := resp.status == last_check_status and resp.code == last_check_status and resp.rule_gen == last_rule_gen.Set
last_check_status := resp.status,last_check_code := resp.code,last_rule_gen := resp.rule_genIf
same_resp == true: finish processing operation with resultBACKOFF.If
resp.status == 204 No Content: Setlast_deny := null. Finish processing operation with resultPROGRESS(effectively re-trying at step 1).If
resp.status == 200 Ok: Setlast_deny := null. Finish with resultPROGRESSIf
resp.status == 202 Accepted: Go to step 4.If
resp.status == 403 Forbidden: Check if the private key for the indicated public key is available. If, setaccount_keypairto that key pair and finish with resultPROGRESS. Otherwise, finish with resultBACKOFF.If
resp.status == 404 Not Found:If
last_bad_kyc_auth == true, finish processing with resultBACKOFF(transition asking the user for KYC auth).Otherwise, go to step 4, with exposed limits set to the default limits.
Otherwise (unhandled status), finish processing with result
BACKOFF.
Handle exposed limits applicable to the account:
If the exposed limits do not deny
op, setlast_deny := nulland finish processing operation with resultPROGRESS.If the exposed limits deny
opasverboten, setlast_deny := now()and transition the transaction to afailedstate (Showing an error message indicating that the operation is forbidden due to legal restrictions on the payment service provider). Finish processing operation with resultPROGRESS.Otherwise (merely a threshold over some timeframe is currently violated), compute the time
twhen the operation may be allowed again. Finish processing operation with resultAGAIN_AT(t).
KYC auth state: The user should be instructed to do a KYC auth transfer if
last_check_status in [403 Forbidden, 409 Conflict] or last_bad_kyc_auth == true && last_check_status == 404.
13.64.4.3. Additional Considerations#
Ensure the long-polling interval specified in the request works with the middleware. If we detect that a request timed out before the specified long-polling interval, use a shorter timeout argument in the HTTP request the next time (but do still keep exponentially backing off the actual request frequency).
Lower the retry back-off for the transaction to zero if:
the user manually reviews the KYC auth wire transfer instructions, or
the user manually reviews KYC information page instructions, or
if
opis a deposit andlpt=1and a withdraw succeeded from the same account
Especially in step 4 (limit violated in timeframe), the user should be offered the option to retry.
13.64.5. Definition of Done#
N/A
13.64.6. Alternatives#
N/A
13.64.7. Drawbacks#
N/A
13.64.8. Discussion / Q&A#
(This should be filled in with results from discussions on mailing lists / personal communication.)