Skip to content

How would you feel if there were an application on Solana for you to track your expenses? Great, right? That is the goal of this tutorial – to build an expense tracking program with Anchor. Anchor is quite a dynamic language for any developer to express their ideas and build them into products on Solana. Apart from the use case, this tutorial will also help you become more comfortable with Anchor and also learn more about the language along the way. Scope of this Tutorial This tutorial is more of a CRUD onchain application. It enables users to create an expense, modify, or delete it. In the process of creating this application, you will also learn more about both Anchor and how SVM works. For instance, you’d get to know more about the practical application of seed bumps, contexts, PDA and so on. After writing the program, you’d also test it with a TypeScript client to be sure the program works as expected. Obviously, this will also make you more comfortable with TypeScript. Setting Up Anchor Before you can build a program with Anchor, you obviously should have it running on your machine. It’s so simple to setup. Simply run this command in your Ubuntu [or perhaps Bash]: It will not only install Anchor, but every other dependency you need to have it run. This includes: Once you are done running this, you should have this printed on your terminal: Step-by-step Guide on Building An Expense Tracker with Anchor Now that you have Anchor setup, it’s time to commence writing our program. For this tutorial, I’ll recommend using the Solana playground online IDE. You can create a program file with lib.rs In this program, we will be utilizing structs to pack our application’s features. Step 1: Importing Anchor and Kickstarting the Program In the first line above, we imported the prelude of Anchor. Essentially, this acts more like a library that contains everything we need to build our program with Anchor. Remember that we are not using native Rust, so prelude importation gives us access to types and macros we will need to use Anchor conveniently and without have an unduly verbose program. Some of the types and macros in prelude include #[program], Context, system and so on. Immediately after importing Anchor, we declared [or rather set] our program ID – this is the public key of your program. If it were to be in the EVM world, program ID could have been called contract address. Hope you get it. Now, your program ID will be needed to generate Program Derived Address (PDA) and also for validation when you are writing a client test. In a test project like this, Solana playground automatically supplies one. All you have to do is just put the ””. The #[program] macro we wrote next tells the compiler [and SVM by extension] that the block of code next to this should be treated as the core part of the code. These are the functions that users can call and interact with. Once that was done, we went ahead to create the etracker public module. Meanwhile, the way pub works in SVM is similar to public functions on Ethereum. Mod there refers to a module, which is more like a packet for functions and or instructions. And here is where you must pay attention: use super::* has a close connection with the anchor prelude we set at the beginning of the program. It allows our local functions to use the types that anchor prelude imported. Step 2: Creating the Initialize Expense Function This is a public function named initialize_expense. It has 2 main parameters: context and ID. The work of Context above is deeper than it appears. It is an Anchor type, which works on account validation and access security constraints before a user can call a public function. NB: You can read more about Context here or I might write another technical blog on it soon. The id contains the details a user must pass into the function as arguments. In the instant case, we demand id, name, and amount. We want this function to return something, hence the reason we included Result. This is why we have Ok(()) at the end of the program. We could have gone on another route of error handling, where we set the error in case anything in the function fails. Moving on, we created a variable called expense_account within the initialize_expense function, and made it mutable so we can modify it later as we want. Subsequently, we assigned the parameters of the function to their respective types. But if you notice, we set the owner to *ctx.accounts.authority.key. This simply means the owner has access to the authority key of the context accounts. Step 3: Creating a Modification Function This is a function that modifies expenses. It takes in some parameters like id, name, and amount. Then these parameters were assigned in the body of the function. For context, this function makes it possible to change anything on an already initialized expense. Step 4: Creating the Initialize Expense Struct We have created an initialize expense function above. Nonetheless, we will also create an initialize expense struct. Don’t confuse both of them. The first one defines what accounts can do when they call the function, while the latter is more about the accounts that can interact in the first place. #[derive(Accounts)] is a macro in Anchor that deals more with the cryptographic security of the interacting accounts. It validates accounts, verifies signatures, and does general safety-check. #[instruction(id: u64)] essentially passes args into the #[derive] struct. The id that the instruction passes will be used in the struct of accounts. Then we created a public struct called InitializeExpense and passed info as a lifetime annotation. Since info has quite an infinite duration, it makes the struct enjoy the same attribute. Then we created a mutable account, meaning we can change its state, and gave the Signer public authority. Once

John Fawole
May 19, 2025

Proper tracking of monetary flows is always helpful in personal finance. I participated in a recent hackathon where I built an MVP that users can utilize in visualizing their bank statements. This blog is a break-down of this feature. You’ll learn how you can also build the same with Python for backend and Nextjs for frontend. Interestingly, you’ll learn how to use some python libraries for data visualization, which are quite impressive. Building the Backend Let’s write our backend with Python. You can create a folder, and then a file called app.py for the program. Step 1: Dependency Installation Head to your terminal and install . Step 2: Import Dependencies Once these deps are installed via the terminal, they should also be imported into the program. These are important libraries in our application. For those who are not aware, Flask is a web framework for Python applications. In the instant case, it will be useful for building our API routes and connecting them with the web successfully. We will also be using Request, a native Python library for efficient HTTP interaction. It will be useful for accepting data from API routes that are sending information. Along this line, Jsonify helps us in communicating back to the API we will create so our frontend and backend can communicate effectively well. Now, you should bear in mind that we want our API to be accessible from any point, and this is where Cross-Origin-Resource Sharing becomes useful. By the way, browsers block this to checkmate security threats, but we are enabling it intentionally for what we want to do. Moving on to Re and Counter, their main purposes is largely for pattern matching. Step 3: App Initialization This is where we initialize our Flask application where name is passed as the root path. Then we enabled CORS. Step 4: Transaction Extraction This function helps us extract the data we need from the provided bank statements. The sample bank statement we have has “send to” and “received from” pre-fixes for fund flows. As a result, we are incorporating that into our program for easier catching. We created an POST API route for it called /paste . Step 5: Paste Transaction Now, many bank statements have various formats of pdf and formatting that our program might not catch. Therefore, it is better to request customers paste their statements rather than upload them. On this note, here is a function that does that. Immediately after declaring the function, we also ran the application. Here is the full code: Creating the Pie Component Add a PieCharts.js component. Here is the first slice of our frontend part. Step 1: Initialize Nextjs Run this in your terminal: npx create-next-app@latest my-next-app Step 2: Install Recharts We have to install Recharts for our pie data representation: Step 3: Chart UI The stage is set to build our pie-chart UI: In the code above, we installed the necessary things we need from recharts, then set the colors and layout of our application. Here is the full code: Transaction Pasteing Interface Create a PasteBankStatement.js page. You can paste this code: Here is a brief rundown of what went on here: Demo Run both the Python application and Nextjs program. Open your localhost, then paste this sample bank statement. You should have something like this: ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1743384519290/64b66485-cbd7-442a-92a7-d4a98a47d4c7.png align=”center”) That’s it! Leave a comment if you find it helpful…

John Fawole
March 31, 2025

Any production-worthy codebase must be secure and safe for its users. Imagine a financial application where the users’ passwords are plainly available in the database. Such a product is way more susceptible to malicious attacks. Not long ago, threat actors stole over 8 million passwords of DailyQuiz users because they were in plaintext. In this short tutorial, we will go over how to hash passwords from the backend for higher security. We will leverage Bcrypt, a cryptographic password hashing library to do this. Whether you are a more advanced Node.js developer or a junior, this tutorial will be simple enough for you to follow and replicate the same thing. A Brief Note on Bcrypt There is a popular belief that cryptography is mainly applicable in decentralized finance and popular tokens such as Bitcoin and Ethereum. While this is right, it is not holistically true. Cryptography has been a bedrock of privacy in engineering, including the zero-knowledge space. That cleared, Bcrypt is a cryptographic library that complicates passwords. For instance, if a password is plainly “PharaohOfTech,” it will be encrypted as “$2a$12$kB5WhlAaQfzQYUoNPBjgXe6QlbCF/Ciofp1U3/d4TaQa9drfMXPei.” How does it work? Bcrypt takes in a human-readable password and transforms it into a 72-byte alphanumeric characters. Within a single encrypted password is a hash algorithm identifier, rounds identifier, salt, and computed by hash; in that order. With the way it encrypts passwords, it protects against brute-force searching and rainbow table attacks. In fact, big companies like Linux adopted it for some of their products. At the moment, Bcrypt does not have detailed documentation. Anyone who wants to know more about it should read and probably contribute to it on the NPM website. Requirements Project Initialization Run this command to initialize your project: It should initialize a JSON package, which you can modify if you want to. Install Express and Bcrypt Express is a Node.js framework, which we will be using. As mentioned earlier, Bcrypt is a password privacy library. Enter this command to have them both in your script: Rest Client This is a VS Code extension we will use to test our routes. Download on the VS Code extension marketplace. Step-by-Step Guide: Building a Secure Node.js Application with Bcrypt Create a file named server.js in which you will write the code in the subsequent subheading. Step 1: Setting Up Express and Bcrypt Libraries Express is a popular JavaScript framework we will use in this application. Therefore, we had to import it into our application using require. Having set-up Express, the second line helps us create an Express application. You might wonder how. Check Node Modules, search for Express, click on Lib, then check out express.js. Notice there is a createApplication function there with an app variable. Thus, the const app = express() done above implements the inner function explained above. Moving on, we set up the Bcrypt library in the third line. Step 2: Creation of User Array and JSON Settings JSON is a human-readable method of storing, displaying, and communicating data across several applications. We want the usernames and passwords of the users to be rendered in JSON eventually. Therefore, the first line is a declaration that Express should process and display data in JSON format. Data of who? The users. This prompted us to create an array of users. A quick digression here: this approach is not a smart engineering decision for production applications. Integrate your data into a database software like Supabase. We only used this approach because this is simply an extremely basic application. In relation to the above, the GET function stores data from the users array created earlier. Step 3: Creation of User Routes This is a POST request with a predefined /users URL indicating user’s path. We made the request asynchronous within the parameters for concurrent request and response interaction. The main idea of the rest of this code block is that the user should be able to create their usernames and hashed passwords. This was implemented with a try/catch. The first line in the try is for salt generation. Recall that salt, in the instance case, is a cryptographic add-on that makes hashed passwords harder to crack. Then we spelt out that the users must supply their name and passwords, which will be turned to a hashed password at the backend for security reasons. Once this is done, the user is pushed into the user array created successfully at the state. Peradventure, the activities do not flow as defined above, there is a catch statement to return an error 500, which is an HTTP status code that shows the request cannot be generated. Step 4: Creating the Login Route At this stage, the users can create their usernames and passwords but cannot log in yet. This POST request predefines the users/login route. For authentication, we compared every user.name with the req.body.name. Within the if statement, ‘||’ is a the logical Or operator which checks the truism of operands and returns the boolean true or false as the case may be. The statement checks whether a user is null or undefined; if true, it returns a bad request with error 400. Having taken care of the users, it is time to fraud-proof the password. We created a isPassword variable to compare if the provided password actually matches the password of the purported user within the database. If this is true, the user should be given access into their account. Otherwise, access should be denied. The last line is a statement that makes the server listens to the connection on port 3000. At the end of the day, your server.js should be like this: Testing the API with Rest Client Run this command on your command line to run the server: Then create a file named request.rest where you will create a port for each route thus: Note: You can use other usernames and passwords for testing your API. Once you have this in your VS Code, you will see a “Send Request” link on top of each of

John Fawole
November 3, 2023

I began my Ethereum smart contract engineering journey some years back. My main motivation was to increase my technical proficiency in the Web3 space. The first question I asked was, “Which language do I need to learn?” Everyone I reached out to recommended Solidity. After over a year of writing Solidity, I got to know that there is another popular language in the Ethereum ecosystem called Vyper. When I heard the word “Vyper,” my mind mapped it with Python, a popular Web2 language. I became interested in this new language, and took about a month to enter its rabbit hole. I really enjoyed writing Vyper because it was a simple and easily readable language. I must also admit that my knowledge of Solidity and Python helped me grasp it faster. Months after I took interest in Vyper, the Curve Finance hack happened. In this hack, the attackers exploited a compiler bug in Vyper and siphoned funds from various projects. This was the time Vyper got the attention of a greater number of developers in the space. Enough with the backstory, the main reason I am writing this is to explain that the Web3 ecosystem needs more Vyper developers. Then, I will teach you the basics of writing a smart contract with Vyper to make you comfortable with the language. I will split this article into two parts: the first one for explaining conceptual underpinnings and the second part for code. In a way, this is a short handbook for developers who want to understand and become good at writing Vyper contracts. Let’s have some fun. What Vyper is all about? Vyper is a high-level programming language for building smart contracts on the Ethereum blockchain, and any other blockchain that supports the Ethereum Virtual Machine. I have noticed that the language was created to enhance accessibility into the Ethereum smart contract development scene. This is why I said that: A greater percentage of Web2 developers can build projects with Python, or at least they have a good idea of the language’s syntax and how it works. Vyper has a similar syntax to Python. Therefore, Python developers can easily build Ethereum smart contracts with it. The main engineering philosophies behind the language are: How Vyper is Different From Solidity? The difference between both languages goes beyond the individual names. To be clear, I will point out some operations and possibilities that Solidity supports but Vyper does not: Yul or Assembly We can optimize the storage of a Solidity contract in the EVM slot stack with Yul, which some other developers call Julia. Yul is simply the possible integration of the Assembly language into smart contracts. It is often written inline. I have written in-line assembly to optimize my Solidity contracts in the past. However, Vyper does not support the concept of using inline assembly for smart contracts. The reasoning behind it, according to the documentation, is that in-line assembly can be quite hard to search and trace for variable names. Function Overloading If you are a JavaScript developer, you should be familiar with the concept of function overloading, which is also applicable in Solidity. This is what function overloading means: Using the same name for two or more functions. Vyper does not support it for two basic reasons. First, it makes code easier to read; anyone might mix up the particular function being called at a given instance. Secondly, it can even be used to write manipulative or misleading code. Operator Overloading The concept behind operator overloading is giving an operator, such as a + or -, more than one responsibility in an operation. The Vyper creators believe operator overloading will lead to more complexities, which is against the ethos of simplicity. Binary-fixed Points Vyper is a language that loves things to be exact. However, binary-fixed points do not always give exact results. Instead, you will get some approximations. In contrast, Vyper supports decimal-fixed points as they give greater precision. Modifiers The concept of function modifiers is popularly understood among Solidity developers. We often use modifiers to introduce security checks or business logic to functions in a contract. Vyper does not support modifiers due to auditability and execution reasons. Personally, I do not really admire this engineering decision, and I disagree with the Vyper creators on this. Will Vyper replace Solidity? No, the intention behind Vyper is not to replace Solidity. Instead, it was designed to be an alternative. This is not really a new thing in engineering. For instance, Android development developers can use either Kotlin or Java to build their applications. Back to Vyper and Solidity, I must emphasize that each language has its trade-offs. As a result, engineers can pick the particular language that suits their needs per time. The presence of language choice is fun as it gives engineers the possibility of preference. After all, variety is the spice of life. I strongly believe that Vyper will not replace Solidity, and both languages will thrive in the ecosystem. Why should you learn Vyper? Solidity is the most popular language in the Ethereum ecosystem, and only a tiny fraction uses Vyper in production. So you might wonder why you should learn Vyper. This is why you should consider learning it: The Best Entry Point for Python Developers As I mentioned earlier, Vyper has good syntactical similarities with Python. So, if you are a Web2 dev coming to Web3, Vyper will be the easier language for you to pick. Become more EVM-native I am quite proficient with Solidity as well. But I wanted to be comfortable with more EVM languages, and Vyper was the best option. Knowing Vyper will help you to become a more proficient developer in the ecosystem as you have more languages under your belt. Become a Better Auditor As an auditor, you have to be familiar with many languages in the space to review contracts written in such languages. If you only know Solidity, you might find it quite hard to review the security of

John Fawole
September 28, 2023

Understanding Solidity is the most popularly adopted language for writing smart contracts among EVM-compatible chains. Anyone who wants to be proficient at writing Solidity smart contracts for several use cases needs to understand an important concept — functions. Functions form the larger part of most smart contracts in Solidity. They help define business logic and several other important terms. Whether you are a complete beginner or an intermediate smart contract developer, I wrote this blog post to teach you how you can confidently define functions yourself. I will start from the fundamentals, then teach you how to do more fantastic operations with functions. That leads us to the question, what is a function? What is a Solidity function? A function in Solidity is a block of code that generally starts with the keyword function and outlines the modality for executing an action. Let me explain with a couple of real-world scenarios: Why do you use your phone? I guess one of the main reasons is to receive calls. Then communication is one of the functions of your phone. You cannot enter your house with your door locked unless you have the key or remote, then the function of those items is to give you access to your house. Do you get the idea? Now, let’s talk code: The purpose of the function above is to send an order. It is a public function, and it can receive ether due to adding the payable keyword. It has a require statement that only a customer can be the msg.sender, which is the address that makes a call. Then it passes some details into an array once a customer creates an order. Don’t worry if you didn’t understand what was playing out here. The main point I want you to know is that this function helps customers of a platform create an order. Can you see how we use functions in smart contracts? What is the syntactical format of a Solidity function? There is a format for writing a Solidity function. This is it: The Solidity compiler will only recognize a function as one if and only if it starts with the function keyword. This is something you must always bear in mind as a developer. Then you must name your Solidity functions following the Camel Casing Convention. It must start with a lower case, then other words can start with capital letters, and there must be no space in between. Examples include theFunctionName instead of TheFunctionName. Moving on, you can define parameters if you need them as local variables within your function. Here is what I mean: Let us use the earlier function as an example: When we were done, we realized burgerMenu and quantity were not recognized locally, hence the reason we defined them as parameters after naming our function. You can include some other details like visibility, mutability, payability, and modifiers after the parameters. You can also have a returning parameter if you write a getter function. A returning parameter is the data type or the detail you want a function to send back once you call it. Consider this example: The function above has these returning parameters: address customer, uint orderNo, uint invoice_date. When you call this function, you can get these details—which are the returning parameters—about a customer. Free Functions and Contract-based Functions As a developer, you can write functions in two major locations, either within or outside a contract. This is an example of functions written inside a contract: We wrote functions increase, decrease, and getTimes within a contract named Mentation. Let us examine the one written outside of a contract: We didn’t write myBalance within a contract. Hold this in your left palm: Functions declared outside a contract are called Free Functions. You might wonder, “How do free and contract-based functions operate? Are there any differences?” There is really no glaring difference between a free function and a contract-based one. But there are a few ones on a closer look. First, free contracts do not enjoy the benefits of leveraging state variables, which are variables created outside of any function in a contract. Secondly, you cannot use the keyword this in them, as in address(this).balance. Understanding Function Visibility in Solidity You might have seen a couple of cases where developers marked some contracts as external, public, private, or internal. Those keywords specify the extent to which other contracts can interact with those functions. The more you write smart contracts, the more you will understand how to classify functions based on their sensitivity or use. There is no brick-and-mortar rule on this; you, the developer, are in charge, and everything is at your discretion. We will examine the four possible forms of visibility in Solidity: Public Public functions have an open design. They are visible to every other contract to call. This is an example: Private Private functions are like shaving sticks; you don’t share them with others. Once a developer declares a function private, it will not be callable whenever other contracts inherit it. The reason is simple: it is private to the actual contract where it was defined. External You cannot call external functions within a contract. External functions are declared to be called by other contracts. Hence, the name external. Internal Internal functions can only be accessed within the contract they are created or an inheriting contract. The difference between internal and private functions is that the latter remains invisible even in inheriting contracts. About Getter Functions and Their Mutability Specification Functions with returning parameters are getter functions. These functions can often alter the current data or condition—better put as the state—of a smart contract. As a developer, you are in charge of deciding which getter function can affect the mutability of the state. We have two major mutability-related specifications. View A function marked with view can read and alter the state of the smart contract. It can update the current data, or even the logic. For instance, a function that sends ether or

John Fawole
August 8, 2023