Beispiel #1
0
def test_transaction_filtering_no_result(
    client,
    acc1_usd_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Succeeds with expected response if invalid combo of ids provided."""
    deposit = acc1_usd_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        (f"{sep24_endpoint}?id={deposit.id}"
         f"&external_transaction_id={withdrawal.external_transaction_id}"
         f"&stellar_transaction_id={withdrawal.stellar_transaction_id}"),
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    assert response.status_code == 404
    assert content.get("error") is not None
Beispiel #2
0
def test_transaction_claimable_balance_id_result(
    client,
    acc2_eth_CB_deposit_transaction_factory,
):
    """Succeeds with expected response if claimable_balance_id provided."""
    deposit = acc2_eth_CB_deposit_transaction_factory(client_address)

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        (f"{sep24_endpoint}?id={deposit.id}"),
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    assert response.status_code == 200

    deposit_claimable_balance_transaction = content.get("transaction")

    # Verifying the deposit claimable balance transaction data:
    assert deposit.claimable_balance_supported
    assert isinstance(deposit_claimable_balance_transaction["id"], str)
    assert deposit_claimable_balance_transaction["kind"] == "deposit"
    assert (deposit_claimable_balance_transaction["status"] ==
            Transaction.STATUS.completed)
    assert deposit_claimable_balance_transaction["claimable_balance_id"]
Beispiel #3
0
def test_transactions_authenticated_success(
    client,
    acc2_eth_withdrawal_transaction_factory,
    acc2_eth_deposit_transaction_factory,
):
    """
    Response has correct length and status code, if the SEP 10 authentication
    token is required.
    """
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)
    acc2_eth_deposit_transaction_factory(client_address)
    encoded_jwt = sep10(client, client_address, client_seed)

    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        f"/transactions?asset_code={withdrawal.asset.code}",
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    assert len(content.get("transactions")) == 2
    assert response.status_code == 200
Beispiel #4
0
def test_transaction_stellar_filter(
    client,
    acc1_usd_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Succeeds with expected response if `stellar_transaction_id` provided."""
    acc1_usd_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        f"{sep24_endpoint}?stellar_transaction_id={withdrawal.stellar_transaction_id}",
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    assert response.status_code == 200

    withdrawal_transaction = content.get("transaction")
    assert withdrawal_transaction["kind"] == "withdrawal"
    assert withdrawal_transaction["status"] == Transaction.STATUS.completed
def test_transaction_external_filter(
    client,
    acc1_usd_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Succeeds with expected response if `external_transaction_id` provided."""
    deposit = acc1_usd_deposit_transaction_factory(client_address)
    acc2_eth_withdrawal_transaction_factory(client_address)

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        f"/transaction?external_transaction_id={deposit.external_transaction_id}",
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    assert response.status_code == 200

    withdrawal_transaction = content.get("transaction")
    assert withdrawal_transaction["kind"] == "deposit"
    assert (withdrawal_transaction["status"] ==
            Transaction.STATUS.pending_user_transfer_start)
def test_no_older_than_filter(
    client,
    acc2_eth_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Valid `no_older_than` succeeds."""
    withdrawal_transaction = acc2_eth_withdrawal_transaction_factory(
        client_address
    )  # older transaction
    deposit_transaction = acc2_eth_deposit_transaction_factory(
        client_address
    )  # newer transaction

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    urlencoded_datetime = urllib.parse.quote(deposit_transaction.started_at.isoformat())
    response = client.get(
        (
            f"{endpoint}?asset_code={withdrawal_transaction.asset.code}"
            f"&no_older_than={urlencoded_datetime}"
        ),
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    assert response.status_code == 200
    assert len(content.get("transactions")) == 1
    assert content.get("transactions")[0]["kind"] == "deposit"
def test_transactions_order(
    client,
    acc2_eth_withdrawal_transaction_factory,
    acc2_eth_deposit_transaction_factory,
):
    """Transactions are serialized in expected order."""
    acc2_eth_deposit_transaction_factory(client_address)  # older transaction
    withdrawal = acc2_eth_withdrawal_transaction_factory(
        client_address
    )  # newer transaction

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        f"{endpoint}?asset_code={withdrawal.asset.code}", follow=True, **header
    )
    content = json.loads(response.content)

    # Withdrawal comes first, since transactions are ordered by -id
    withdrawal_transaction = content.get("transactions")[0]
    deposit_transaction = content.get("transactions")[1]

    assert withdrawal_transaction["kind"] == "withdrawal"
    assert deposit_transaction["kind"] == "deposit"
def test_limit(
    client,
    acc2_eth_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Valid `limit` succeeds."""
    acc2_eth_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)  # newest

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        f"{endpoint}?asset_code={withdrawal.asset.code}" "&limit=1",
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    # By providing the paging_id = w.id, we're looking for entries older than `w`
    # which only leaves us with the deposit transaction.
    assert len(content.get("transactions")) == 1
    assert content.get("transactions")[0]["kind"] == "withdrawal"
def test_paging_id(
    client,
    acc2_eth_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Only return transactions chronologically after a `paging_id`, if provided."""
    acc2_eth_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        (
            f"{endpoint}?asset_code={withdrawal.asset.code}"
            f"&paging_id={withdrawal.id}"
        ),
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    # By providing the paging_id = w.id, we're looking for entries older than `w`
    # which only leaves us with the deposit transaction.
    assert len(content.get("transactions")) == 1
    assert content.get("transactions")[0]["kind"] == "deposit"
Beispiel #10
0
def test_transaction_authenticated_success(
    client,
    acc1_usd_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """
    Succeeds with expected response if authentication required.
    Though it filters using the stellar transaction ID, the logic
    should apply in any case.
    """
    acc1_usd_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)
    withdrawal.stellar_address = client_address
    withdrawal.save()

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        f"{sep24_endpoint}?stellar_transaction_id={withdrawal.stellar_transaction_id}",
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    assert response.status_code == 200

    withdrawal_transaction = content.get("transaction")
    assert withdrawal_transaction["kind"] == "withdrawal"
    assert withdrawal_transaction["status"] == Transaction.STATUS.completed
def test_transaction_multiple_filters(
    client,
    acc1_usd_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Succeeds with expected response if multiple valid ids provided."""
    acc1_usd_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.get(
        (f"/transaction?id={withdrawal.id}"
         f"&external_transaction_id={withdrawal.external_transaction_id}"
         f"&stellar_transaction_id={withdrawal.stellar_transaction_id}"),
        follow=True,
        **header,
    )
    content = json.loads(response.content)

    assert response.status_code == 200

    withdrawal_transaction = content.get("transaction")

    # Verifying the withdrawal transaction data:
    assert isinstance(withdrawal_transaction["id"], str)
    assert withdrawal_transaction["kind"] == "withdrawal"
    assert withdrawal_transaction["status"] == Transaction.STATUS.completed
def test_transaction_bad_uuid(client):
    encoded_jwt = sep10(client, client_address, client_seed)
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}
    response = client.get(f"/transaction?id=NOTAREALID", follow=True, **header)
    content = json.loads(response.content)

    assert response.status_code == 400
    assert content == {"error": "[\"'NOTAREALID' is not a valid UUID.\"]"}
Beispiel #13
0
def test_more_info_required_fields(client,
                                   acc1_usd_deposit_transaction_factory):
    """Fails if no required fields are provided."""
    acc1_usd_deposit_transaction_factory(client_address)
    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}
    response = client.get(f"/transaction/more_info", follow=True, **header)
    assert response.status_code == 400
Beispiel #14
0
def test_transaction_id_filter_and_format(
    client,
    acc1_usd_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Succeeds with expected response if `id` provided."""
    acc1_usd_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    w_started_at = withdrawal.started_at.isoformat().replace("+00:00", "Z")
    w_completed_at = withdrawal.completed_at.isoformat().replace("+00:00", "Z")

    response = client.get(f"/transaction?id={withdrawal.id}", follow=True, **header)
    content = json.loads(response.content)

    assert response.status_code == 200

    withdrawal_transaction = content.get("transaction")

    # Verifying the withdrawal transaction data:
    assert isinstance(withdrawal_transaction["id"], str)
    assert withdrawal_transaction["kind"] == "withdrawal"
    assert withdrawal_transaction["status"] == "completed"
    assert withdrawal_transaction["status_eta"] == 3600
    assert withdrawal_transaction["amount_in"] == "500.0"
    assert withdrawal_transaction["amount_out"] == "495.0"
    assert withdrawal_transaction["amount_fee"] == "3.0"
    assert withdrawal_transaction["started_at"] == w_started_at
    assert withdrawal_transaction["completed_at"] == w_completed_at
    assert (
        withdrawal_transaction["stellar_transaction_id"]
        == "17a670bc424ff5ce3b386dbfaae9990b66a2a37b4fbe51547e8794962a3f9e6a"
    )
    assert (
        withdrawal_transaction["external_transaction_id"]
        == "2dd16cb409513026fbe7defc0c6f826c2d2c65c3da993f747d09bf7dafd31094"
    )
    assert withdrawal_transaction["from"] is None
    assert withdrawal_transaction["to"] is None
    assert withdrawal_transaction["external_extra"] is None
    assert withdrawal_transaction["external_extra_text"] is None
    assert withdrawal_transaction["deposit_memo"] is None
    assert withdrawal_transaction["deposit_memo_type"] == withdrawal.deposit_memo_type
    assert (
        withdrawal_transaction["withdraw_anchor_account"]
        == withdrawal.withdraw_anchor_account
    )
    assert withdrawal_transaction["withdraw_memo"] == withdrawal.withdraw_memo
    assert withdrawal_transaction["withdraw_memo_type"] == withdrawal.withdraw_memo_type
Beispiel #15
0
def test_more_info_id_filter(client, acc1_usd_deposit_transaction_factory):
    """Succeeds if a valid transaction ID is provided."""
    deposit = acc1_usd_deposit_transaction_factory(client_address)
    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}
    response = client.get(f"/transaction/more_info?id={deposit.id}",
                          follow=True,
                          **header)

    assert response.status_code == 200
def test_deposit_interactive_confirm_success(
    mock_check_middleware,
    mock_submit,
    mock_base_fee,
    client,
    acc1_usd_deposit_transaction_factory,
):
    """
    `GET /deposit` and `GET /transactions/deposit/webapp` succeed with valid `account`
    and `asset_code`.
    """
    del mock_submit, mock_base_fee, mock_check_middleware
    deposit = acc1_usd_deposit_transaction_factory()

    encoded_jwt = sep10(client, deposit.stellar_account,
                        STELLAR_ACCOUNT_1_SEED)
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    response = client.post(
        DEPOSIT_PATH,
        {
            "asset_code": "USD",
            "account": deposit.stellar_account
        },
        follow=True,
        **header,
    )
    content = json.loads(response.content)
    assert response.status_code == 200
    assert content["type"] == "interactive_customer_info_needed"

    transaction_id = content["id"]
    url = content["url"]
    # Authenticate session
    response = client.get(url)
    assert response.status_code == 200
    assert client.session["authenticated"] is True

    amount = 20
    url, args_str = url.split("?")
    response = client.post(url + "/submit?" + args_str, {"amount": amount})
    assert response.status_code == 302
    assert (Transaction.objects.get(id=transaction_id).status ==
            Transaction.STATUS.pending_user_transfer_start)

    transaction = Transaction.objects.get(id=transaction_id)
    execute_deposit(transaction)

    # We've mocked submit_transaction, but the status should be marked as
    # completed after executing the function above.
    transaction.refresh_from_db()
    assert float(transaction.amount_in) == amount
    assert transaction.status == Transaction.STATUS.completed
Beispiel #17
0
def test_more_info_multiple_filters(client,
                                    acc1_usd_deposit_transaction_factory):
    """Succeeds if a valid combination of IDs is provided."""
    deposit = acc1_usd_deposit_transaction_factory(client_address)
    deposit.stellar_transaction_id = "test_stellar_id"
    deposit.save()
    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}
    response = client.get(
        f"/transaction/more_info?id={deposit.id}"
        f"&external_transaction_id={deposit.external_transaction_id}"
        f"&stellar_transaction_id={deposit.stellar_transaction_id}",
        follow=True,
        **header,
    )
    assert response.status_code == 200
Beispiel #18
0
def test_more_info_no_result(
    client,
    acc1_usd_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """Fails if an invalid combination of IDs is provided."""
    deposit = acc1_usd_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)
    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}
    response = client.get(
        f"/transaction/more_info?id={deposit.id}"
        f"&external_transaction_id={withdrawal.external_transaction_id}"
        f"&stellar_transaction_id={withdrawal.stellar_transaction_id}",
        follow=True,
        **header,
    )
    assert response.status_code == 404
def test_transactions_content(
    client,
    acc2_eth_deposit_transaction_factory,
    acc2_eth_withdrawal_transaction_factory,
):
    """
    This expected response was adapted from the example SEP-0024 response on
    https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0024.md#transaction-history
    Some changes have been applied, to ensure the data we provide is in a consistent format and
    in accordance with design decisions from this reference implementation:

    - amounts are floats, so values like "500" are displayed as "500.0"
    - nullable fields are displayed, but with a null value
    """
    deposit = acc2_eth_deposit_transaction_factory(client_address)
    withdrawal = acc2_eth_withdrawal_transaction_factory(client_address)

    encoded_jwt = sep10(client, client_address, client_seed)
    # For testing, we make the key `HTTP_AUTHORIZATION`. This is the value that
    # we expect due to the middleware.
    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}

    d_started_at = deposit.started_at.isoformat().replace("+00:00", "Z")
    w_started_at = withdrawal.started_at.isoformat().replace("+00:00", "Z")
    w_completed_at = withdrawal.completed_at.isoformat().replace("+00:00", "Z")

    response = client.get(
        f"{endpoint}?asset_code={withdrawal.asset.code}", follow=True, **header
    )
    content = json.loads(response.content)

    withdrawal_transaction = content.get("transactions")[0]
    deposit_transaction = content.get("transactions")[1]
    withdrawal_asset = withdrawal.asset
    deposit_asset = deposit.asset

    # update amount_* fields to the correct number of decimals
    withdrawal.refresh_from_db()
    deposit.refresh_from_db()

    # Verifying the withdrawal transaction data:
    assert withdrawal_transaction["id"] == str(withdrawal.id)
    assert withdrawal_transaction["kind"] == withdrawal.kind
    assert withdrawal_transaction["status"] == withdrawal.status
    assert not withdrawal_transaction["status_eta"]
    assert withdrawal_transaction["amount_in"] == str(
        round(withdrawal.amount_in, withdrawal_asset.significant_decimals)
    )
    assert withdrawal_transaction["amount_out"] == str(
        round(withdrawal.amount_out, withdrawal_asset.significant_decimals)
    )
    assert withdrawal_transaction["amount_fee"] == str(
        round(withdrawal.amount_fee, withdrawal_asset.significant_decimals)
    )
    assert withdrawal_transaction["started_at"] == w_started_at
    assert withdrawal_transaction["completed_at"] == w_completed_at
    assert (
        withdrawal_transaction["stellar_transaction_id"]
        == withdrawal.stellar_transaction_id
    )
    assert (
        withdrawal_transaction["external_transaction_id"]
        == withdrawal.external_transaction_id
    )
    assert withdrawal_transaction["from"] is None
    assert withdrawal_transaction["to"] is None
    assert (
        withdrawal_transaction["withdraw_anchor_account"]
        == withdrawal.receiving_anchor_account
    )
    assert withdrawal_transaction["withdraw_memo"] == withdrawal.memo
    assert withdrawal_transaction["withdraw_memo_type"] == withdrawal.memo_type

    # Verifying the deposit transaction data:
    assert deposit_transaction["id"] == str(deposit.id)
    assert deposit_transaction["kind"] == deposit.kind
    assert deposit_transaction["status"] == deposit.status
    assert deposit_transaction["status_eta"] == deposit.status_eta
    assert deposit_transaction["amount_in"] == str(
        round(deposit.amount_in, deposit_asset.significant_decimals)
    )
    assert deposit_transaction["amount_out"] == str(
        round(deposit.amount_out, deposit_asset.significant_decimals)
    )
    assert deposit_transaction["amount_fee"] == str(
        round(deposit.amount_fee, deposit_asset.significant_decimals)
    )
    assert deposit_transaction["started_at"] == d_started_at
    assert deposit_transaction["completed_at"] is None
    assert deposit_transaction["stellar_transaction_id"] is None
    assert (
        deposit_transaction["external_transaction_id"]
        == deposit.external_transaction_id
    )
    assert deposit_transaction["from"] is None
    assert deposit_transaction["to"] is None
    assert deposit_transaction["deposit_memo"] == deposit.memo
    assert deposit_transaction["deposit_memo_type"] == deposit.memo_type

    # stellar_account and asset should not be exposed:
    with pytest.raises(KeyError):
        assert withdrawal_transaction["stellar_account"]
    with pytest.raises(KeyError):
        assert withdrawal_transaction["asset"]
    with pytest.raises(KeyError):
        assert deposit_transaction["stellar_account"]
    with pytest.raises(KeyError):
        assert deposit_transaction["asset"]