Git Product home page Git Product logo

monarchmoney's People

Contributors

andrecloutier avatar calvinchancan avatar cciollaro avatar grablair avatar guillochon avatar hammem avatar jprouty avatar keegandahm avatar koepkejr avatar michaliksj21 avatar pazwicker avatar sanghviharshit avatar sean280zx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

monarchmoney's Issues

[Bug] 404 Error

Using the following code:

import asyncio
from monarchmoney import MonarchMoney

async def main():
    mm = MonarchMoney()
    try:
        print("Attempting interactive login...")
        await mm.interactive_login()
        print("Login successful")

        # Fetch account information
        accounts = await mm.get_accounts()
        print("Accounts fetched successfully")

        # Print account details
        for account in accounts:
            print(f"Account Name: {account['name']}")
            print(f"Balance: {account['balance']}")
            print("-" * 20)
    except Exception as e:
        print(f"An error occurred: {e}")

# Run the main function
asyncio.run(main())

When ran, I get the following error:

An error occurred: HTTP Code 404: Not Found

Edit:
Error happens between print("Attempting interactive login...") and print("Login successful")

GraphQL queries that support the logoUrl element should probably not include it by default for performance

If merchants or vendors have logos associated, the logoURL parameter in the GraphQL query pulls that in as (presumably) base64 encoded content in the query response, which are massive strings that are probably not going to be used for much of anything for most use cases of the various methods so all it's doing is greatly increasing the size of the response payload/memory consumption.

Feels like it makes sense for those to be excluded by default with an optional parameter in the function to include them.

Login function doesn't properly return an exception when no email or password is provided

When using interactiveLogin, if no email or password is provided an exception doesn't get raised by login. This like like it's due to the fact that input() is used to retrieve those values and entering nothing results in the variable being an empty string (i.e. '') instead of None.

In login():
...
if email is None or password is None:
raise LoginFailedException(
"Email and password are required to login when not using a saved session."
)

looks like this can be fixed by updating to check the variables being == '' instead of None, but not sure if there's something else going wrong prior to that

[Feature Request] Add additional filters to "get_transactions"

I'd like to see the ability to search by Merchant and Amount.

I'm trying to write a script to categorize my amazon transactions based on my downloaded amazon history. Finding a transaction by date, merchant and amount should allow me to identify most transactions programmatically.

Recent change to API causing error when calling get_transactions

Recently, after an API change, I've been getting an error when calling get_transactions. Can anyone else confirm if they're getting errors as well? After testing around with it, I've found that removing the account in the graphql query fixed the error but meaning the account is no longer in the response.

https://github.com/hammem/monarchmoney/blob/main/monarchmoney/monarchmoney.py#L1239

Stacktrace:

Traceback (most recent call last):
  File "C:\Users\cchan\PycharmProjects\monarchmoney\monarchmoney\monarchmoney.py", line 1321, in get_transactions
    return await self.gql_call(
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cchan\PycharmProjects\monarchmoney\monarchmoney\monarchmoney.py", line 2634, in gql_call
    return await self._get_graphql_client().execute_async(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cchan\PycharmProjects\monarchmoney\.venv\Lib\site-packages\gql\client.py", line 285, in execute_async
    return await session.execute(
           ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cchan\PycharmProjects\monarchmoney\.venv\Lib\site-packages\gql\client.py", line 1231, in execute
    raise TransportQueryError(
gql.transport.exceptions.TransportQueryError: {'message': "Something went wrong while processing: ['allTransactions', 'results', 4] on request_id: 107af4308b774b779d356d241c6d37ca.", 'locations': [{'line': 4, 'column': 5}], 'path': ['allTransactions', 'results', 4]}

Request: Add a transaction

It would be useful to be able to add a transaction to an account. This would basically open the door for custom syncing of external accounts programmatically.

(For me, modifying/deleting transactions are less important. My plan is to just add a "Balance Adjustment" transaction nightly to track the value of an asset.)

Add delete_session to delete saved session info

For security purposes, should add a delete_session function to the class MonarchMoney to enabling deleting the saved session file.

I'm new to Python/Git, but I think this is probably really straightforward:
def delete_session_file(self,filename: str = SESSION_FILE) -> None:
"""
Deletes Python pickle file of saved session info if it exists.
"""
if os.path.isfile(filename):
os.remove(filename)

Add unit test coverage

As this library grows and matures, it's going to need unit (and likely integration) tests. Otherwise, I'm sure I'll release a version to PyPI that breaks things for everyone!

I'm flexible on testing regimes we use. Resolving this issue should include tests for:

  • setting up a connection
  • getting accounts
  • searching transactions

Also, setup a workflow to run the tests when folks put up a PR or create a release.

upload_account_balance_history endpoint is not working as expected

Not sure if I'm doing it incorrectly or if the API is not performing as intended. I successfully created a CSV file with my code and uploaded it to the browser client, reading the data without any issues. However, I am unable to update the history with the provided csv_content. Also, I'm not receiving any errors after making the API call.

here is the format:

Date,Amount
2023-12-14,5424.360000000001
2023-12-15,10422.85
2023-12-17,15422.05
2023-12-18,20446.09
2023-12-19,25430.87
2023-12-20,30403.879999999997
2023-12-21,35318.729999999996
2023-12-22,40147.06999999999
2023-12-30,45135.23999999999
2024-01-02,50215.149999999994
2024-01-03,55224.479999999996
2024-01-08,60214.579999999994
2024-01-12,65208.729999999996
2024-01-14,70198.98
2024-01-16,75194.69
2024-01-17,80184.07
2024-01-18,85174.02
2024-01-20,90181.01000000001

Add Integration Testing

Along with adding unit testing that mocks gql responses (#48) and runs on every PR, it would be helpful for us to have integration test coverage. It would be run in one of two ways:

  1. Locally, by contributors, who provide their own credentials.
  2. As a (pre?)release action using some shared credentials (more on this later).
  3. (Optional) As a PR step using the same shared credentials?

How it would work is:

  1. Create a dummy manual account with a random name (such as INTEG-1234567890abcdef) that is not visible in any way.
  2. Run testing against every feature the client provides. New PRs would be required to write such tests.
  3. Delete the dummy account, along with any other account that matches the INTEG-[0-9]+ regex, along with everything inside (we could also delete all dummy accounts at the beginning of the test run)

Running it locally is fairly straightforward; the contributor just needs to provide their own credentials, and the testing will happen in their own account. The testing should clean itself up, and the manual account should not be included in budgets, cashflow, etc based on the configuration, so the user shouldn't be affected if artifacts inadvertently get left behind.

Running it programmatically as an Action is a bit different... we'd either need:

  1. A maintainer to provide their own credentials (or a pickle session file). This is suboptimal for obvious reasons (security, risk of account closure, etc). I don't think this should be considered.
  2. An account gets created for the sole purpose of running automated testing against. The downsides here are obvious: $100 / yr.
  3. Same as above: using a dedicated account, but we ask Monarch to give it to us for free since we are really just providing additional incentive for customers to use their product. ๐Ÿ˜‚ (only half joking here, I don't actually think this is that out of the realm of possibility)

I think, at least for now, we can forgo automated testing. We should still write the integ tests so that contributors can manually run them prior to publishing a PR, and a maintainer can manually run them prior to a release.

Add methods to delete Categories

Does this api have methods to list the Categories and delete some of them? I've imported my Mint data into Monarch and ended up with 3000 custom categories in "Other" group. Their support isn't helpful to clean it up.

Login fails with "HTTP Code 404: Not Found" when using a complex password

Passwords such as the following cause login to fail with a 404 (not my real password, but an example that actually fails):

Ab[1C*[Def`'&]2g,/H%3I}J'_KLmn`o

I had to change my password to alphanumeric (i.e., no symbols) to get login to work properly. The example password has both quotes and a forward slash, so that might be the cause.

Missing transactions

if MonarchMoney marks a transaction as Recurring, it does not come down as part of the get_transactions function and you have to call get_transactions twice: once with is_recurring=true and once with it as false in order to get all transactions.

Is there a way to make get_transactions NOT filter on recurring if thats what the user wants?

Similar issue on all of the Boolean parameters to get_transactions: has_attachments, has_notes, hidden_from_reports, is_split

But only recurring seems to be something that MonarchMoney sets by itself on a transaction, the rest get downloaded unless I have done something to the transaction, so I can control that.

No attribute 'update_account'

When I run the following:

import asyncio
from monarchmoney import MonarchMoney
import traceback

async def main():
    email = 'email-here'
    password = 'password-here'

    mm = MonarchMoney()
    try:
        print("Attempting to login...")
        await mm.login(email, password)
        print("Login successful")

        # Fetch account information
        accounts_data = await mm.get_accounts()
        print("Accounts fetched successfully")

        # Access the list of accounts within the returned dictionary
        accounts = accounts_data['accounts']

        # Specify the account name you want to find
        account_name_to_find = 'test'  # Replace with the actual account name

        # Search for the account by name
        account_id_to_update = None
        for account in accounts:
            if account['displayName'] == account_name_to_find:
                account_id_to_update = account['id']
                break

        if account_id_to_update:
            print(f"Account ID for '{account_name_to_find}' found: {account_id_to_update}")

            # Attempt to update account balance
            print("Attempting to update account balance...")
            new_balance = 1000.0  # Replace with the new balance you want to set
            try:
                update_response = await mm.update_account(account_id_to_update, balance=new_balance)
                print(f"\nAccount update response: {update_response}")
            except Exception as e:
                print(f"An error occurred while updating the account: {e}")
                traceback.print_exc()  # Print the full traceback for bug reporting

        else:
            print(f"Account with name '{account_name_to_find}' not found.")

    except Exception as e:
        print(f"An error occurred: {e}")
        traceback.print_exc()  # Print the full traceback for bug reporting

# Run the main function
asyncio.run(main())

It spits out an error stating 'MonarchMoney' object has no attribute 'update_account':

Traceback (most recent call last):
  File "/Users/trevoroler/Desktop/antminer/./monarch.py", line 41, in main
    update_response = await mm.update_account(account_id_to_update, balance=new_balance)
                            ^^^^^^^^^^^^^^^^^
AttributeError: 'MonarchMoney' object has no attribute 'update_account'. Did you mean: 'delete_account'?

I even tried checking the attributes:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_get_current_date', '_get_end_of_current_month', '_get_graphql_client', '_get_start_of_current_month', '_headers', '_login_user', '_multi_factor_authenticate', '_session_file', '_timeout', '_token', 'create_manual_account', 'create_transaction', 'create_transaction_category', 'create_transaction_tag', 'delete_account', 'delete_session', 'delete_transaction', 'delete_transaction_categories', 'delete_transaction_category', 'get_account_history', 'get_account_holdings', 'get_account_snapshots_by_type', 'get_account_type_options', 'get_accounts', 'get_aggregate_snapshots', 'get_budgets', 'get_cashflow', 'get_cashflow_summary', 'get_institutions', 'get_recent_account_balances', 'get_recurring_transactions', 'get_subscription_details', 'get_transaction_categories', 'get_transaction_category_groups', 'get_transaction_details', 'get_transaction_splits', 'get_transaction_tags', 'get_transactions', 'get_transactions_summary', 'gql_call', 'interactive_login', 'is_accounts_refresh_complete', 'load_session', 'login', 'multi_factor_authenticate', 'request_accounts_refresh', 'request_accounts_refresh_and_wait', 'save_session', 'set_budget_amount', 'set_timeout', 'set_token', 'set_transaction_tags', 'timeout', 'token', 'update_transaction', 'update_transaction_splits', 'upload_account_balance_history']

I do not see the attribute anywhere. I even tried to take the login token and request the data directly from the API and nothing. Was this function removed?

Transfer categories not present in `get_transaction_categories` response

Transfer categories are present in ManageGetCategoryGroups response, if requested:

query ManageGetCategoryGroups {
  categoryGroups {
    id
    name
    order
    type
    __typename
  }
  categories(includeDisabledSystemCategories: true) {
    id
    name
    order
    icon
    isSystemCategory
    systemCategory
    isDisabled
    group {
      id
      type
      name
      __typename
    }
    __typename
  }
}

add Account ID to the get_transactions() function

Would it be possible to add an account ID/name to the get_transactions() function? I have tried to play around with it myself and haven't found a way to do it, but I have never worked with gql, so I'm hoping your expertise can resolve it.

If adding a new field isn't an option, would pulling transactions for specific account IDs be an option?

[Feature] Upload Transaction History

Not trying to add onto your plate. I'm volunteering myself to implement this endpoint. I'm just not a Python expert like you all; I'm more of a Node.js developer myself. Upon reviewing the code, it seems that we need to define the endpoint inside MonarchMoneyEndpoints:

@classmethod
    def getAccountTransactionHistoryUploadEndpoint(cls) -> str:
        return cls.BASE_URL + "/account-transaction-history/upload/" 

and just copy/paste and rename the async def upload_account_balance_history method to new async def upload_account_transaction_history`. is that correct? Am I missing anything?

Frequent 404s with MFA login

I'm not sure what Monarch's API rate limits are, but I'm getting frequent 404's on login:

Traceback (most recent call last):
  File "/var/lib/homebridge/monarch.py", line 26, in <module>
    asyncio.run(main(), debug=True)
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/var/lib/homebridge/monarch.py", line 14, in main
    await mm.login(
  File "/home/pi/.local/lib/python3.9/site-packages/monarchmoney/monarchmoney.py", line 108, in login
    await self._login_user(email, password, mfa_secret_key)
  File "/home/pi/.local/lib/python3.9/site-packages/monarchmoney/monarchmoney.py", line 768, in _login_user
    raise LoginFailedException(
monarchmoney.monarchmoney.LoginFailedException: HTTP Code 404: Not Found

I'm speculating that this is hitting some sort of rate limit, but I am not sure if that's actually what's happening. Regardless, handling this more gracefully would be nice, or at least documenting the default API rate limits.

Code I used:

import asyncio

from monarchmoney import MonarchMoney

with open("monarch-creds.json", "r") as f:
    creds = json.load(f)

async def main():
    mm = MonarchMoney()

    await mm.login(
        email=creds["email"],
        password=creds["password"],
        save_session=False,
        use_saved_session=False,
        mfa_secret_key=creds["mfa_secret_key"],
    )

asyncio.run(main(), debug=True)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.