-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Xiao Li
committed
Dec 19, 2020
1 parent
d4cecfc
commit e671444
Showing
29 changed files
with
3,514 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright (c) The Diem Core Contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from .wallet import WalletApp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Copyright (c) The Diem Core Contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from . import WalletApp | ||
import pytest, typing | ||
|
||
|
||
def launch_wallet_app(name: str) -> WalletApp: | ||
app = WalletApp.generate(f"{name}'s wallet app") | ||
app.start_server() | ||
return app | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def wallet_apps() -> typing.List[WalletApp]: | ||
return {name: launch_wallet_app(name) for name in ["sender", "receiver"]} | ||
|
||
|
||
@pytest.fixture | ||
def sender_app(wallet_apps): | ||
yield from with_users(wallet_apps["sender"], ["foo", "user-x", "hello"]) | ||
|
||
|
||
@pytest.fixture | ||
def receiver_app(wallet_apps): | ||
yield from with_users(wallet_apps["receiver"], ["bar", "user-y", "world"]) | ||
|
||
|
||
def with_users(app, users): | ||
for user in users: | ||
app.add_user(user) | ||
yield app | ||
app.clear_data() | ||
|
||
|
||
@pytest.fixture() | ||
def assert_final_status(sender_app, receiver_app): | ||
sender_vasp_balance = sender_app.vasp_balance() | ||
receiver_vasp_balance = receiver_app.vasp_balance() | ||
|
||
def assert_fn( | ||
final_status: typing.Dict[str, str], | ||
balance_change: typing.Optional[int] = 0, | ||
) -> None: | ||
|
||
sender_cmd = sender_app.saved_commands | ||
receiver_cmd = receiver_app.saved_commands | ||
assert len(sender_cmd) == 1 | ||
assert len(receiver_cmd) == 1 | ||
|
||
ref_id = list(sender_cmd.keys())[0] | ||
sender_record = sender_cmd[ref_id] | ||
assert sender_record.cid == receiver_cmd[ref_id].cid | ||
assert sender_record.payment == receiver_cmd[ref_id].payment | ||
|
||
assert sender_record.payment.sender.status.status == final_status["sender"] | ||
assert sender_record.payment.receiver.status.status == final_status["receiver"] | ||
|
||
assert sender_app.vasp_balance() == sender_vasp_balance - balance_change | ||
assert receiver_app.vasp_balance() == receiver_vasp_balance + balance_change | ||
|
||
# nothing left | ||
assert sender_app.run_once_background_job() is None | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
return assert_fn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,321 @@ | ||
# Copyright (c) The Diem Core Contributors | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from diem.offchain import Status, Action | ||
from .wallet import ActionResult | ||
|
||
|
||
AMOUNT = 1_000_000_000 | ||
BOTH_READY = { | ||
"sender": Status.ready_for_settlement, | ||
"receiver": Status.ready_for_settlement, | ||
} | ||
|
||
|
||
def test_travel_rule_data_exchange_happy_path(sender_app, receiver_app, assert_final_status): | ||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert len(sender_app.saved_commands) == 1 | ||
assert len(receiver_app.saved_commands) == 0 | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert len(receiver_app.saved_commands) == 1 | ||
|
||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert sender_app.run_once_background_job() is None | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert receiver_app.run_once_background_job() is None | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() is None | ||
assert sender_app.run_once_background_job() == ( | ||
Action.SUBMIT_TXN, | ||
ActionResult.TXN_EXECUTED, | ||
) | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert_final_status(BOTH_READY, AMOUNT) | ||
|
||
|
||
def test_travel_rule_data_exchange_receiver_reject_sender_kyc_data(sender_app, receiver_app, assert_final_status): | ||
receiver_app.evaluate_kyc_data_result = {"foo": ActionResult.REJECT} | ||
|
||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.REJECT, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
|
||
assert_final_status({"sender": Status.needs_kyc_data, "receiver": Status.abort}) | ||
|
||
|
||
def test_travel_rule_data_exchange_receiver_soft_match_reject(sender_app, receiver_app, assert_final_status): | ||
receiver_app.evaluate_kyc_data_result = {"foo": ActionResult.SOFT_MATCH} | ||
receiver_app.manual_review_result = {"foo": ActionResult.REJECT} | ||
|
||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.SOFT_MATCH, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.CLEAR_SOFT_MATCH, | ||
ActionResult.SENT_ADDITIONAL_KYC_DATA, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.REVIEW_KYC_DATA, | ||
ActionResult.REJECT, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
|
||
assert_final_status({"sender": Status.needs_kyc_data, "receiver": Status.abort}) | ||
|
||
|
||
def test_travel_rule_data_exchange_receiver_soft_match_pass(sender_app, receiver_app, assert_final_status): | ||
receiver_app.evaluate_kyc_data_result = {"foo": ActionResult.SOFT_MATCH} | ||
receiver_app.manual_review_result = {"foo": ActionResult.PASS} | ||
|
||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.SOFT_MATCH, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.CLEAR_SOFT_MATCH, | ||
ActionResult.SENT_ADDITIONAL_KYC_DATA, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.REVIEW_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert sender_app.run_once_background_job() == ( | ||
Action.SUBMIT_TXN, | ||
ActionResult.TXN_EXECUTED, | ||
) | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert_final_status(BOTH_READY, AMOUNT) | ||
|
||
|
||
def test_travel_rule_data_exchange_sender_rejects_receiver_kyc_data(sender_app, receiver_app, assert_final_status): | ||
sender_app.evaluate_kyc_data_result = {"bar": ActionResult.REJECT} | ||
|
||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.REJECT, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert_final_status({"sender": Status.abort, "receiver": Status.ready_for_settlement}) | ||
|
||
|
||
def test_travel_rule_data_exchange_sender_soft_match_reject(sender_app, receiver_app, assert_final_status): | ||
sender_app.evaluate_kyc_data_result = {"bar": ActionResult.SOFT_MATCH} | ||
sender_app.manual_review_result = {"bar": ActionResult.REJECT} | ||
|
||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.SOFT_MATCH, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.CLEAR_SOFT_MATCH, | ||
ActionResult.SENT_ADDITIONAL_KYC_DATA, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.REVIEW_KYC_DATA, | ||
ActionResult.REJECT, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert_final_status({"sender": Status.abort, "receiver": Status.ready_for_settlement}) | ||
|
||
|
||
def test_travel_rule_data_exchange_sender_soft_match_pass(sender_app, receiver_app, assert_final_status): | ||
sender_app.evaluate_kyc_data_result = {"bar": ActionResult.SOFT_MATCH} | ||
sender_app.manual_review_result = {"bar": ActionResult.PASS} | ||
|
||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.SOFT_MATCH, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.CLEAR_SOFT_MATCH, | ||
ActionResult.SENT_ADDITIONAL_KYC_DATA, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.REVIEW_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() is None | ||
assert sender_app.run_once_background_job() == ( | ||
Action.SUBMIT_TXN, | ||
ActionResult.TXN_EXECUTED, | ||
) | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert_final_status(BOTH_READY, AMOUNT) | ||
|
||
|
||
def test_travel_rule_data_exchange_receiver_soft_match_pass_sender_soft_match_reject( | ||
sender_app, receiver_app, assert_final_status | ||
): | ||
receiver_app.evaluate_kyc_data_result = {"foo": ActionResult.SOFT_MATCH} | ||
receiver_app.manual_review_result = {"foo": ActionResult.PASS} | ||
sender_app.evaluate_kyc_data_result = {"bar": ActionResult.SOFT_MATCH} | ||
sender_app.manual_review_result = {"bar": ActionResult.REJECT} | ||
|
||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.SOFT_MATCH, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.CLEAR_SOFT_MATCH, | ||
ActionResult.SENT_ADDITIONAL_KYC_DATA, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.REVIEW_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
|
||
assert sender_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.SOFT_MATCH, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.CLEAR_SOFT_MATCH, | ||
ActionResult.SENT_ADDITIONAL_KYC_DATA, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.REVIEW_KYC_DATA, | ||
ActionResult.REJECT, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert_final_status({"sender": Status.abort, "receiver": Status.ready_for_settlement}) | ||
|
||
|
||
def test_travel_rule_data_exchange_receiver_soft_match_pass_sender_soft_match_pass( | ||
sender_app, receiver_app, assert_final_status | ||
): | ||
receiver_app.evaluate_kyc_data_result = {"foo": ActionResult.SOFT_MATCH} | ||
receiver_app.manual_review_result = {"foo": ActionResult.PASS} | ||
sender_app.evaluate_kyc_data_result = {"bar": ActionResult.SOFT_MATCH} | ||
sender_app.manual_review_result = {"bar": ActionResult.PASS} | ||
|
||
intent_id = receiver_app.gen_intent_id("bar", AMOUNT) | ||
sender_app.pay("foo", intent_id) | ||
|
||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.SOFT_MATCH, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.CLEAR_SOFT_MATCH, | ||
ActionResult.SENT_ADDITIONAL_KYC_DATA, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.REVIEW_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
|
||
assert sender_app.run_once_background_job() == ( | ||
Action.EVALUATE_KYC_DATA, | ||
ActionResult.SOFT_MATCH, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() == ( | ||
Action.CLEAR_SOFT_MATCH, | ||
ActionResult.SENT_ADDITIONAL_KYC_DATA, | ||
) | ||
assert receiver_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert sender_app.run_once_background_job() == ( | ||
Action.REVIEW_KYC_DATA, | ||
ActionResult.PASS, | ||
) | ||
assert sender_app.run_once_background_job() == ActionResult.SEND_REQUEST_SUCCESS | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert sender_app.run_once_background_job() == ( | ||
Action.SUBMIT_TXN, | ||
ActionResult.TXN_EXECUTED, | ||
) | ||
assert receiver_app.run_once_background_job() is None | ||
|
||
assert_final_status(BOTH_READY, AMOUNT) |
Oops, something went wrong.