def test_check_trustlines(
    mock_account,
    mock_submit,
    mock_get,
    mock_sequence,
    mock_fee,
    client,
    acc1_usd_deposit_transaction_factory,
):
    d = acc1_usd_deposit_transaction_factory()
    d.status = Transaction.STATUS.pending_trust
    d.save()
    assert Transaction.objects.get(id=d.id).status == Transaction.STATUS.pending_trust
    check_trustlines()
    assert Transaction.objects.get(id=d.id).status == Transaction.STATUS.completed
def test_deposit_check_trustlines_success(
    mock_account,
    mock_submit,
    mock_base_fee,
    client,
    acc1_usd_deposit_transaction_factory,
):
    """
    Creates a transaction with status `pending_trust` and checks that
    `check_trustlines` changes its status to `completed`. All the necessary
    functionality and conditions are mocked for determinism.
    """
    del mock_account, mock_submit, mock_base_fee, client
    deposit = acc1_usd_deposit_transaction_factory()
    deposit.status = Transaction.STATUS.pending_trust
    deposit.save()
    assert (Transaction.objects.get(
        id=deposit.id).status == Transaction.STATUS.pending_trust)
    check_trustlines()
    assert Transaction.objects.get(
        id=deposit.id).status == Transaction.STATUS.completed
def test_deposit_check_trustlines_horizon(
        mock_delay, client, acc1_usd_deposit_transaction_factory):
    """
    Tests the `check_trustlines` function's various logical paths. Note that the Stellar
    deposit is created synchronously. This makes Horizon calls, so it is skipped by the CI.
    """
    del mock_delay
    # Initiate a transaction with a new Stellar account.
    print("Creating initial deposit.")
    deposit = acc1_usd_deposit_transaction_factory()

    from stellar_base.keypair import Keypair

    keypair = Keypair.random()
    deposit.stellar_account = keypair.address().decode()
    response = client.get(
        f"/deposit?asset_code=USD&account={deposit.stellar_account}",
        follow=True)
    content = json.loads(response.content)
    assert response.status_code == 403
    assert content["type"] == "interactive_customer_info_needed"

    # Complete the interactive deposit. The transaction should be set
    # to pending_external, since external confirmation has not happened.
    print("Completing interactive deposit.")
    transaction_id = content["id"]
    url = content["url"]
    amount = 20
    response = client.post(url, {"amount": amount})
    assert response.status_code == 200
    assert (Transaction.objects.get(
        id=transaction_id).status == Transaction.STATUS.pending_external)

    # As a result of this external confirmation, the transaction should
    # be `pending_trust`. This will trigger a synchronous call to
    # `create_stellar_deposit`, which will register the account on testnet.
    # Since the account will not have a trustline, the status will still
    # be `pending_trust`.
    response = client.get(
        f"/deposit/confirm_transaction?amount={amount}&transaction_id={transaction_id}",
        follow=True,
    )
    assert response.status_code == 200
    content = json.loads(response.content)
    transaction = content["transaction"]
    assert transaction
    assert transaction["status"] == Transaction.STATUS.pending_anchor
    assert float(transaction["amount_in"]) == amount

    # The Stellar account has not been registered, so
    # this should not change the status of the Transaction.
    print(
        "Check trustlines, try one. No trustline for account. Status should be pending_trust."
    )
    check_trustlines()
    assert (Transaction.objects.get(
        id=transaction_id).status == Transaction.STATUS.pending_trust)

    # Add a trustline for the transaction asset from the server
    # source account to the transaction account.
    from stellar_base.asset import Asset
    from stellar_base.builder import Builder

    print("Create trustline.")
    asset_code = deposit.asset.name
    asset_issuer = settings.STELLAR_ACCOUNT_ADDRESS
    Asset(code=asset_code, issuer=asset_issuer)
    builder = Builder(
        secret=keypair.seed(),
        horizon_uri=settings.HORIZON_URI,
        network=settings.STELLAR_NETWORK,
    ).append_change_trust_op(asset_code, asset_issuer)
    builder.sign()
    response = builder.submit()
    assert response[
        "result_xdr"] == "AAAAAAAAAGQAAAAAAAAAAQAAAAAAAAAGAAAAAAAAAAA="

    print("Check trustlines, try three. Status should be completed.")
    check_trustlines()
    completed_transaction = Transaction.objects.get(id=transaction_id)
    assert completed_transaction.status == Transaction.STATUS.completed
    assert (completed_transaction.stellar_transaction_id ==
            HORIZON_SUCCESS_RESPONSE["hash"])
def test_check_trustlines_horizon(
    mock_delay, client, acc1_usd_deposit_transaction_factory
):
    # Initiate a transaction with a new Stellar account.
    print("Creating initial deposit.")
    d = acc1_usd_deposit_transaction_factory()

    from stellar_base.keypair import Keypair

    keypair = Keypair.random()
    d.stellar_account = keypair.address().decode()
    response = client.get(
        f"/deposit?asset_code=USD&account={d.stellar_account}", follow=True
    )
    content = json.loads(response.content)
    assert response.status_code == 403
    assert content["type"] == "interactive_customer_info_needed"

    # Complete the interactive deposit. The transaction should be set
    # to pending_trust, as we have not actually created and funded the
    # generated Stellar account.
    print("Completing interactive deposit.")
    transaction_id = content["id"]
    url = content["url"]
    response = client.post(url, {"amount": 20})
    assert response.status_code == 200
    assert (
        Transaction.objects.get(id=transaction_id).status
        == Transaction.STATUS.pending_trust
    )

    # The Stellar account has not been registered, so
    # this should not change the status of the Transaction.
    print(
        "Check trustlines, try one. Account exists, trustline does not. Status should be pending_trust."
    )
    check_trustlines()
    assert (
        Transaction.objects.get(id=transaction_id).status
        == Transaction.STATUS.pending_trust
    )

    # Add a trustline for the transaction asset from the server
    # source account to the transaction account.
    print("Create trustline.")
    from stellar_base.asset import Asset

    asset_code = d.asset.name
    asset_issuer = settings.STELLAR_ACCOUNT_ADDRESS
    stellar_asset = Asset(code=asset_code, issuer=asset_issuer)
    builder = Builder(secret=keypair.seed()).append_change_trust_op(
        asset_code, asset_issuer
    )
    builder.sign()
    response = builder.submit()
    assert response["result_xdr"] == "AAAAAAAAAGQAAAAAAAAAAQAAAAAAAAAGAAAAAAAAAAA="

    print("Check trustlines, try three. Status should be completed.")
    check_trustlines()
    assert (
        Transaction.objects.get(id=transaction_id).status
        == Transaction.STATUS.completed
    )