def test_deposit_stellar_success( mock_submit, mock_base_fee, client, acc1_usd_deposit_transaction_factory, ): """ `create_stellar_deposit` succeeds if the provided transaction's `stellar_account` has a trustline to the issuer for its `asset`, and the Stellar transaction completes successfully. All of these conditions and actions are mocked in this test to avoid network calls. """ del mock_submit, mock_base_fee, client deposit = acc1_usd_deposit_transaction_factory() deposit.status = Transaction.STATUS.pending_anchor deposit.save() create_stellar_deposit(deposit.id) assert Transaction.objects.get(id=deposit.id).status == Transaction.STATUS.completed
def test_deposit_stellar_no_trustline( mock_submit, mock_base_fee, client, acc1_usd_deposit_transaction_factory, ): """ `create_stellar_deposit` sets the transaction with the provided `transaction_id` to status `pending_trust` if the provided transaction's Stellar account has no trustline for its asset. (We assume the asset's issuer is the server Stellar account.) """ del mock_submit, mock_base_fee, client deposit = acc1_usd_deposit_transaction_factory() deposit.status = Transaction.STATUS.pending_anchor deposit.save() create_stellar_deposit(deposit.id) assert ( Transaction.objects.get(id=deposit.id).status == Transaction.STATUS.pending_trust )
def test_deposit_stellar_no_account( mock_load_account, mock_base_fee, client, acc1_usd_deposit_transaction_factory, ): """ `create_stellar_deposit` sets the transaction with the provided `transaction_id` to status `pending_trust` if the provided transaction's `stellar_account` does not exist yet. This condition is mocked by throwing an error when attempting to load information for the provided account. Normally, this function creates the account. We have mocked out that functionality, as it relies on network calls to Horizon. """ del mock_load_account, mock_base_fee, client deposit = acc1_usd_deposit_transaction_factory() deposit.status = Transaction.STATUS.pending_anchor deposit.save() create_stellar_deposit(deposit.id) assert ( Transaction.objects.get(id=deposit.id).status == Transaction.STATUS.pending_trust )
def check_trustlines(): """ Create Stellar transaction for deposit transactions marked as pending trust, if a trustline has been created. """ transactions = Transaction.objects.filter( kind=Transaction.KIND.deposit, status=Transaction.STATUS.pending_trust) server = settings.HORIZON_SERVER for transaction in transactions: try: account = (server.accounts().account_id( transaction.stellar_account).call()) except BaseHorizonError: logger.warning( f"could not load account {transaction.stellar_account} using provided horizon URL" ) continue try: balances = account["balances"] except KeyError: logger.debug( f"horizon account {transaction.stellar_account} response had no balances" ) continue for balance in balances: try: asset_code = balance["asset_code"] asset_issuer = balance["asset_issuer"] except KeyError: logger.debug( f"Unable to retrieve asset info from balance object: {balance}" ) if balance.get("asset_type") != "native": logger.debug( f"horizon balance had no asset_code for account {account['id']}" ) continue if (asset_code == transaction.asset.code and asset_issuer == transaction.asset.issuer): logger.info( f"Account {account['id']} has established a trustline for {asset_code}, " f"initiating deposit for {transaction.id}") if create_stellar_deposit(transaction.id): transaction.refresh_from_db() try: rdi.after_deposit(transaction) except Exception: logger.exception( "An unexpected error was raised from " "after_deposit() in check_trustlines")
def execute_deposit(transaction: Transaction) -> bool: """ The external deposit has been completed, so the transaction status must now be updated to *pending_anchor*. Executes the transaction by calling :func:`create_stellar_deposit`. :param transaction: the transaction to be executed :returns a boolean of whether or not the transaction was completed successfully on the Stellar network. """ if transaction.kind != transaction.KIND.deposit: raise ValueError("Transaction not a deposit") elif transaction.status != transaction.STATUS.pending_user_transfer_start: raise ValueError( f"Unexpected transaction status: {transaction.status}, expecting " f"{transaction.STATUS.pending_user_transfer_start}") transaction.status = Transaction.STATUS.pending_anchor transaction.status_eta = 5 # Ledger close time. transaction.save() # launch the deposit Stellar transaction. return create_stellar_deposit(transaction.id)
def create_stellar_deposit(transaction_id): """Create and submit the Stellar transaction for the deposit.""" try: create_stellar_deposit(transaction_id) except Exception as e: raise CommandError(e)