#Deprecation Notice
For most use cases, we actually recommend the workflow specified in SEP-0024 instead of SEP-0003
#Simple Summary
Complying with Anti-Money Laundering (AML) laws requires financial institutions (FIs) to know not only who their customers are sending money to but who their customers are receiving money from. In some jurisdictions banks are able to trust the AML procedures of other licensed banks. In other jurisdictions each bank must do its own sanction checking of both the sender and the receiver. The Compliance Protocol handles all these scenarios.
#Abstract
The Compliance Protocol is an additional step after federation. In this step
the sending FI contacts the receiving FI to get permission to send the
transaction. To do this the receiving FI creates an AUTH_SERVER and adds an
AUTH_SERVER entry to its stellar.toml.
SEP-9 specifies standard customer information fields that are exchanged between FIs via the Compliance Protocol. The most common fields are:
- First name
- Last name
- Date of birth
- Physical address
#Specification
To send transaction data to the receiving organization, send HTTP POST to
AUTH_SERVER with Content-Type equal application/x-www-form-urlencoded and
the following body:
data=<data value>&sig=<sig value>
data is a block of JSON that contains the following fields:
| Name | Data Type | Description |
|---|---|---|
sender | string | The payment address of the customer that is initiating the send. Ex. bob*bank.com |
need_info | boolean | If the caller needs the recipient's AML info in order to send the payment. |
tx | string: base64 encoded xdr.Transaction | The transaction that the sender would like to send in XDR format. This transaction is unsigned and it's sequence number should be equal 0. |
attachment | string | The full text of the attachment. The hash of this attachment is included as a memo in the transaction. The attachment field follows the Stellar Attachment Convention and should contain at least enough information of the sender to allow the receiving FI to do their sanction check. |
sig is the signature of the data block made by the sending FI. The
receiving institution should check that this signature is valid against the
public signature key that is posted in the sending FI's
stellar.toml
(SIGNING_KEY field).
Example request body (please note it contains both parameters data and
sig):
data=%7B%22sender%22%3A%22aldi%2AbankA.com%22%2C%22need_info%22%3Atrue%2C%22tx%22%3A%22AAAAAEhAArfpmUJYq%2FQ9SFAH3YDzNLJEBI9i9TXmJ7s608xbAAAAZAAMon0AAAAJAAAAAAAAAAPUg1%2FwDrMDozn8yfiCA8LLC0wF10q5n5lo0GiFQXpPsAAAAAEAAAAAAAAAAQAAAADdvkoXq6TXDV9IpguvNHyAXaUH4AcCLqhToJpaG6cCyQAAAAAAAAAAAJiWgAAAAAA%3D%22%2C%22attachment%22%3A%22%7B%5C%22nonce%5C%22%3A%5C%221488805458327055805%5C%22%2C%5C%22transaction%5C%22%3A%7B%5C%22sender_info%5C%22%3A%7B%5C%22address%5C%22%3A%5C%22678+Mission+St%5C%22%2C%5C%22city%5C%22%3A%5C%22San+Francisco%5C%22%2C%5C%22country%5C%22%3A%5C%22US%5C%22%2C%5C%22first_name%5C%22%3A%5C%22Aldi%5C%22%2C%5C%22last_name%5C%22%3A%5C%22Dobbs%5C%22%7D%2C%5C%22route%5C%22%3A%5C%221%5C%22%2C%5C%22note%5C%22%3A%5C%22%5C%22%2C%5C%22extra%5C%22%3A%5C%22%5C%22%7D%2C%5C%22operations%5C%22%3Anull%7D%22%7D&sig=KgvyQTZsZQoaMy8jdwCUfLayfgfFMUdZJ%2B0BIvEwiH5aJhBXvhV%2BipRok1asjSCUS%2FUaGeGKDoizS1%2BtFiiyAA%3D%3D
After decoding the data parameter it has a following form:
{
"sender": "aldi*bankA.com",
"need_info": true,
"tx": "AAAAAEhAArfpmUJYq/Q9SFAH3YDzNLJEBI9i9TXmJ7s608xbAAAAZAAMon0AAAAJAAAAAAAAAAPUg1/wDrMDozn8yfiCA8LLC0wF10q5n5lo0GiFQXpPsAAAAAEAAAAAAAAAAQAAAADdvkoXq6TXDV9IpguvNHyAXaUH4AcCLqhToJpaG6cCyQAAAAAAAAAAAJiWgAAAAAA=",
"attachment": "{\"nonce\":\"1488805458327055805\",\"transaction\":{\"sender_info\":{\"address\":\"678 Mission St\",\"city\":\"San Francisco\",\"country\":\"US\",\"first_name\":\"Aldi\",\"last_name\":\"Dobbs\"},\"route\":\"1\",\"note\":\"\",\"extra\":\"\"},\"operations\":null}"
}
A few things to note:
- memo value of
txis a sha256 hash of the attachment - nonce is unique to each individual transaction. When a transaction on the
receiving end is
pending, the samenonceshould be sent to fetch updates about thependingtransaction
AUTH_SERVER will return a JSON object with the following fields:
| Name | Data Type | Description |
|---|---|---|
info_status | ok, denied, pending | If this FI is willing to share AML information or not. |
tx_status | ok, denied, pending | If this FI is willing to accept this transaction. |
dest_info | string | (only present if info_status is ok) Marshalled JSON of the recipient's AML information. |
error | string | (only present if info_status or tx_status is error or for internal server errors) Error message |
pending | integer | (only present if info_status or tx_status is pending) Estimated number of seconds till the sender can check back for a change in status. The sender should just resubmit this request after the given number of seconds. |
HTTP status code must be equal:
200 OKif bothinfo_statusandtx_statusareok.202 Acceptedif both statuses arependingor one ispendingand secondok.400 Bad Requestif data sent by the sender is invalid.403 Forbiddenif any ofinfo_statusandtx_statusaredenied.500 Internal Server Errorfor server side errors.
Examples:
200 OK
{
"info_status": "ok",
"tx_status": "ok",
"dest_info": "{\"name\": \"John Doe\"}"
}
202 Accepted
{
"info_status": "ok",
"tx_status": "pending",
"dest_info": "{\"name\": \"John Doe\"}",
"pending": 3600
}
400 Bad Request
{
"info_status": "ok",
"tx_status": "error",
"error": "Invalid country code."
}
403 Forbidden
{
"info_status": "deny",
"tx_status": "ok"
}
500 Internal Server Error
{
"error": "Internal server error"
}
#Test Cases
Use GoStellar application to check if Compliance protocol was implemented correctly.
#Reference implementations
- Reference Compliance server developed by Stellar Development Foundation.
- Compliance structures.