Python is the go-to software for many niche applications, especially in Data Science and Machine learning. Python has proven itself to be a sufficient software in building web solutions with numerous products and services utilizing Python. However python’s play on the web sometimes still revolves around Data Science and Machine learning. This is a half-truth and from my experience looking to build software with Python that does not revolve around these niches, I have not seen a lot of examples.
Maybe I am not looking hard enough, but some companies that seem to utilize Python at insane length include Instagram, Reddit and Google. In my ecosystem (Nigerian Techosphere) I am biased to believe that the less interesting problems are reserved for Python as such I only know of one major Fintech Company that uses Python as its core infra for its backend. From my discussion with other engineers that worked with some international banks like JP Morgan Chase they informed me that Python was used to build financial systems. Since then I have been looking forward to doing something fintech related.
Recently I was given a task by a potential employer to do something in social fintech. Below is the task information.
Having experience building solutions with Python and FastAPI, I felt this was a good place to explore Python and FastAPI for fintech, as I had come across a few roles at Fintech companies or companies having a fintech play that utilized FastAPI. These companies proved the possibility that Python is capable of delivering.
My Solution for the task above explored the social-fintech play, with this write up I will be showing code snippets and explaining the thought processes and not necessarily teaching how to build a fintech product.
This is the name I came up with for this product. Below is a structure of what the application looks like.
The entry point of the application is src/app/main.py, this file is the root of the server. The src/app is the application module and houses generic/core application logic such as Database, Base Repo, Config etc. These files are an extended copy of the logic presented in the FastAPI documentation. The Design pattern followed is the Repository design pattern as such there are ORMs for Tables and Services that perform logic, and data manipulation.
This is pretty straightforward, there is a need for a route for signup and login, here is what the models (DB table for a user).
The table provides logic for regular users and superusers, with the is_admin flag, thanks to SQLAlchemy we can lazy load account information such as account, which is the account balance record.
There are two routes for registration, we have one for regular users and another for superusers.
Based on the Task given there are two classes of users, Admin and regular users, and there was specific instruction to give new users a balance of 1000. Ideally, every user should have a default balance of 0. Here comes an Intricate portion of the software, there was a conversation that was had in an engineering community where people with fintech experience spoke about how to store numbers. There were a lot of solutions which I will not bore you with, but there was a consensus to not store money as an Int or a float. This lead me to do a mini research and I landed on a Reddit thread that spoke about how to store money with a package called Decimal which prevents the overflow that occurs with Float.
Here is how I created a default balance for regular users, after a new user record has been successfully created I created an account balance record.
Here is what the account table looks like.
This table suggests that we can have more than one record in the DB, for my implementation we only have a record but I will explain something I would do if I was building this as an actual company in the embers of this write-up.
We have completed two tasks mentioned above, user auth and a default balance.
Now we look at Transfers, the social fintech play is the ability to accept or reject a transfer.
There is something we need to talk about briefly it is called Race Condition.
A race condition is an undesirable situation that occurs when a device or system attempts to perform two or more operations at the same time.
I heard this is a frequent yet controllable action that occurs and is most visible in Fintechs. Some of the solutions I read was to lock the row during a write action, in fintech something I read suggested cross-checking the transact Id and seeing if the transaction has occurred already.
I attempted to prevent Race conditions using a few methods and I will highlight them,
One was a Pipe which was to prevent the ability to perform an overdraft type of transfer.
I believe this check is very important and could prevent race conditions from occurring and a negative balance.
I checked the balance and compared the possibility for the transfer again very similar to the pipe action. Here a transaction has occurred, with a default status of Sent and here is what the table for transactions looks like.
Here a transfer is sent, and the sender is deducted, however, the transfer fee is yet to be remitted to the sender’s account. For it to be remitted the sent funds would have to be accepted. There is a pipe to ensure that the actor of a sent fund is indeed the recipient of the transfer.
It also prevents an overwrite action, a recipient is allowed two actions Accept or Reject. Once a transaction is acted upon there is no further action that can be carried out.
This updates a transaction based on the decision of the recipient, the recipient either receives the fund or rejects and the sender receives a refund of the sent amount.
From the Task above carrying out transfers and accepting and rejecting a transfer are now complete.
Now let’s look at the last two actions. The ability for admin to revert transactions and ability to query for all users and their transactions.
is_reverted_dep pipe allows admin to revert transaction only if its status was accepted or sent and only these actions. This prevents a fraud attack of over-crediting a sender.
This Pipe allows actions to be carried out only if the logged-in user is an Admin.
With these fragments of core logic, I have demonstrated my thought process for a social-fintech approach. The code is available at /docs route (Thanks to FastAPI) and I also shipped a postman documentation in the read me of the repository.
This again shows to prove that Python’s application is wide and knows no bounds, only that which we define for it. The code for Finbanker is available Here.