The Bitcoin Developer Course - Build Your Own Bitcoin Wallet! | Humberto Cezar | Skillshare

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

The Bitcoin Developer Course - Build Your Own Bitcoin Wallet!

teacher avatar Humberto Cezar, Software Developer & Bitcoin Pleb

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Introduction

      7:10

    • 2.

      Downloading, Configuring and Running the Bitcoin Core Node and IntelliJ IDEA Download

      6:33

    • 3.

      What is Bitcoin?

      3:03

    • 4.

      Bitcoin Transactions and Private Keys

      6:32

    • 5.

      Bitcoin Wallets, the Blockchain and Mining

      3:51

    • 6.

      The Bitcoin Network, Ecosystem and Principles

      5:49

    • 7.

      Starting the Project

      2:59

    • 8.

      Configuring the GUI

      9:55

    • 9.

      Creating our First Test

      10:18

    • 10.

      Mnemonic Seeds

      2:11

    • 11.

      Create Wallet Dialog Window

      11:56

    • 12.

      Creating the Mnemonic Seed

      7:33

    • 13.

      Create Wallet Dialog Window Buttons and Validations

      10:30

    • 14.

      The Current Wallet Observable

      11:16

    • 15.

      The Receive Bitcoin Tab

      8:29

    • 16.

      Bitcoin Addresses and HD Wallets

      13:52

    • 17.

      Creating our wallet’s extended public keys

      16:40

    • 18.

      Generating Segwit Addresses

      10:19

    • 19.

      Understanding Segwit Addresses and Introduction to Bitcoin Network Environments

      4:34

    • 20.

      Generating Segwit Addresses – Part II

      9:10

    • 21.

      Adding Support for Main Net, Test Net, and Reg Test Environments

      7:41

    • 22.

      Preparing our Bitcoin Core Node for Communicating With Our Wallet

      3:13

    • 23.

      Creating the Node Client for Creating and Listing Wallets

      15:06

    • 24.

      Node Clients for Loading a Wallet, Get a New Address, Checking our Balance and Mining Bitcoins

      11:21

    • 25.

      Sending Bitcoins From the Node to the Application

      14:25

    • 26.

      The Addresses Table

      8:42

    • 27.

      Importing our Application Addresses to Our Bitcoin Node

      10:18

    • 28.

      Calling our Bitcoin Node Asynchronously

      9:50

    • 29.

      Listening for Transactions from the Node with ZeroMQ

      14:09

    • 30.

      Bitcoin Transactions: Inputs, Outputs, Scripts, and the UTXO Set

      18:31

    • 31.

      Obtaining UTXOs from the Node and Filtering Them

      11:46

    • 32.

      Updating the Current Wallet Addresses

      11:07

    • 33.

      Showing Address Information in the Addresses Table

      13:21

    • 34.

      More Test Scenarios For Receiving Bitcoins and Avoiding Address Reuse

      14:09

    • 35.

      Improving Receiving Bitcoin Tests. Receiving More Transactions Than Addresses

      10:33

    • 36.

      Generating More Addresses

      15:50

    • 37.

      Testing Confirmations

      7:33

    • 38.

      The Transactions Table

      8:03

    • 39.

      Populating the Transactions Table

      14:03

    • 40.

      Improving Tests for the Transactions Table and Running Our Application on the Test Net

      17:10

    • 41.

      Listening for Blocks and Formatting Balances

      12:55

    • 42.

      The Total Wallet’s Balance

      5:50

    • 43.

      Calculating and Showing the Wallet’s Total Balance

      8:57

    • 44.

      Adding More Tests for the Total Balance Feature

      3:37

    • 45.

      The Send Bitcoin Tab

      11:11

    • 46.

      Transaction Fees and Sizes

      6:48

    • 47.

      Creating the Transaction Size Calculator and The Node Estimate Smart Fee Client

      13:33

    • 48.

      Coin Selection and Dust

      6:08

    • 49.

      Implementing the Dust Calculator and Other Utilities

      9:24

    • 50.

      Implementing the Single Random Draw Coin Selector

      8:40

    • 51.

      How Segwit Transactions are Built and Validated

      7:44

    • 52.

      Implementing the Transaction Creator

      14:03

    • 53.

      The Send Transaction Dialog Window

      14:21

    • 54.

      Showing Transaction Data in the Send Bitcoin Dialog Window

      15:43

    • 55.

      How Transaction Signatures Work

      5:25

    • 56.

      How Our Wallet and Node Will Handle Sent Transactions

      3:25

    • 57.

      Signing and Sending Segwit Transactions

      16:49

    • 58.

      Fixing Transaction and Addresses Tables and Balances

      18:13

    • 59.

      Changing Change Addresses. Adding Error Alert for Wrong Passwords

      20:53

    • 60.

      More Error Messages and Tests for the Send Bitcoin Feature

      14:55

    • 61.

      A Necessary Refactor

      17:39

    • 62.

      A Necessary Refactor Part II

      26:45

    • 63.

      Nested Segwit Addresses

      7:50

    • 64.

      Receiving Bitcoin in Nested Segwit Addresses

      17:01

    • 65.

      Sending Bitcoin to Nested Segwit Addresses and Testing our Wallet on the Test Net

      9:54

    • 66.

      Sending Bitcoin to Legacy Addresses

      14:23

    • 67.

      Saving and Encrypting our Wallet

      16:31

    • 68.

      The Load Wallet Menu

      14:03

    • 69.

      Loading a Wallet

      11:47

    • 70.

      Plausible Deniability, Refactoring and More Tests for the Load Wallet Feature

      19:08

    • 71.

      Fixing Addresses, Transactions and Balances

      12:13

    • 72.

      Updating the Number of Generated Addresses and Optimizing Tests

      11:54

    • 73.

      Importing a Wallet with the Mnemonic Seed

      19:27

    • 74.

      Validating Addresses

      19:24

    • 75.

      Creating a Progress Bar

      13:27

    • 76.

      Updating Dependencies

      7:17

    • 77.

      Running our Wallet on the Main Net Environment

      7:46

    • 78.

      Extra class - Bitcoin Core v26

      3:14

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

90

Students

--

Project

About This Class

Welcome to the Bitcoin Developer Course! My name is Humberto, and I’m happy to present you with the first and only course where you’ll learn Bitcoin by building a desktop Bitcoin wallet!

In this course, you’ll learn how Bitcoin works from a technical point of view. More specifically, you’ll learn how a Bitcoin wallet works in detail. Also, you’ll learn how a Bitcoin node works and how to run it. We’ll see how it interacts with our wallet and other nodes. We’ll also learn how the Bitcoin network works and how it achieves consensus.

Key Bitcoin concepts we’ll learn include transactions, addresses, seeds, keys, balances, the blockchain, mining, and wallet.

Since we’ll build a desktop application along the course, the student will have the opportunity to practice the following software engineering skills, which are in high demand in the software industry:

  • The Object-Oriented Programming paradigm, on which our wallet is based on.
  • Test-Driven Development (TDD). Most of the features we’ll build will follow the TDD way of doing things. As the name of this approach suggests, for each feature, we’ll build the tests first, and they will guide the features’ further development.
  • Application Security Best Practices. We’ll worry a lot about application security best practices and treat the application as a mission-critical system. I personally have skin in the game on this application, and I put a lot of effort into minimizing the chance of someone losing funds with this application.
  • Best Programming Practices. SOLID principles and Clean Code permeate the culture of our code. This course has plenty of best programming practices examples.

Learn by doing. About 17% of this course is composed of theory. The rest is composed of practical classes. The course is heavily code-focused, intercalated with some presentations when needed. Below every video, you can find additional links and study material in the Projects & Resources page. You’ll build a desktop Bitcoin Wallet, learning important Bitcoin concepts while doing so.

It’s recommended that the student has a good knowledge of Object-Oriented Programming before taking this course. Java or similar languages knowledge is needed. Although this course presents different software engineering concepts, we focus on understanding Bitcoin. If the student wants to know in detail some of the software engineering concepts touched on in this course, they will have to use other sources along the course to understand them better.

Meet Your Teacher

Teacher Profile Image

Humberto Cezar

Software Developer & Bitcoin Pleb

Teacher

I have 5+ years of experience as a Professional Software Developer, working especially in the e-commerce industry.

I’ve been a bitcoin enthusiast since 2016. I’ve been heavily studying Bitcoin since then. I’ve developed the open-source bitcoin-java library.

I’ve built the Bitcoin Education initiative to concentrate on providing Bitcoin education for developers worldwide.

See full profile

Related Skills

Development Web Development
Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Introduction: Hi, Welcome to the Bitcoin developer course. My name is Alberto, and I'm happy to present you with the first and only course where you'll learn Bitcoin by building a desktop Bitcoin wallet. So let's start by explaining what you'll learn in this course. In short, you will learn how Bitcoin works from a technical point of view. More specifically, you'll learn how a Bitcoin wallet works in detail. Also, you'll learn how a Bitcoin node works and how to run it. We'll see how it interacts with our wallet and other nodes. Will also learn how the Bitcoin network works and how it achieves consensus. Concepts we'll learn include transactions, addresses, seeds, keys, balances, the blockchain, mining, and wallet. Since we'll build a desktop application along the course, the student will have the opportunity to practice the following software engineering skills which are in high demand in the software industry. The object oriented programming paradigm on which our wallet is based on. Most of the features will build, will follow the test-driven development way of doing things. As the name of this approach suggests, for each feature will build their tests first and the tests will guide the feature further development also will worry a lot about application security best practices, and treat the application as a mission critical system. I personally have skin in the game in this application, and I put a lot of effort into minimizing the chance of someone losing funds with it. Also, this course has plenty of best programming practices, examples, solid principles and clean code permeate the culture of our code. Now, let's see how you'll learn in this course. We'll follow the methodology of learning by doing. About 17% of this course is composed of theory, the rest is composed of practical classes. So the course has heavily code focused, intercalated with some presentations when needed. Below every video, you can find additional links and study material in the Projects and Resources page. You'll build a desktop Bitcoin wallet, learning important Bitcoin concepts while doing so. Now, let's list the recommended requirements for taking this course. It's recommended that the student has a good knowledge of object oriented programming. The student must know Java or similar languages before taking this course. Although this course presents different software engineering concepts, our focus is on understanding Bitcoin. If the student wants to know in detail some of the software engineering concepts touched on in this course. It will have to use other sources along the course to understand them better. You'll need a computer with Windows, macOS, or Linux with an Internet connection. We'll present this course using Windows. But since Java is cross-platform compatible, every code in this course will work the same way on these three operating systems. The only difference will be installing the necessary software on each platform, but you can easily find guides to install them on these operating systems. You'll need at least 30 gb of free-space to run the Bitcoin node on the test net environment. Optionally, if you intend to run the application on the main net environment, you'll need at least 430 gb of disk space to download the main net blockchain. But don't worry, we'll use the main net environment only in the last video of the course. So you'll have plenty of time to download it before needing it. Now, let's talk a little more about the wallet you'll build along the course. I'll refer to this wallet as BYOD W, an acronym for build your own wallet, will start developing this application with Java 16, but we'll update it later in the course. Diversion 19 will use the Spring Boot framework version 2.5, 0.4, which will provide a dependency injection container and many facilities to help us build our application. Later in the course, we'll update it to version 2.7, 0.5. We'll use Java FX version 16 in the project. We'll update it later to version 19. This library will provide classes that will help us build the applications graphical user interface, also known as gooey. For testing, we'll use Groovy, the Spark framework and test ethics to create wallets, seeds addresses, transactions, and other Bitcoin operations will use the open source Bitcoin Java library, which I built especially for this course. We'll use the Bitcoin Core Node version 22 for communication with the blockchain. Later in the course, we'll update it to version 23. Although the Bitcoin Core node can generate wallets and addresses, will use it only to retrieve data from and send data to the blockchain. Operations such as generating seeds, addresses, building and signing transactions will be done by our application. The exception will be for the tests. In these cases, we'll use the Bitcoin Core Node RPC API to generate addresses, send transactions, and mine blocks on the test environments, therefore, will get familiar with the most important Bitcoin Core Note RPC API methods and build a client to communicate with it from our application. As the database will use the SQL Java implementation H SQL DB will use it smooth integration with the Spring Boot Data JPA library to communicate with the database. Finally, we'll use IntelliJ idea as the IDE to build this project. All the code presented in this course is open source and is available on our GitHub page. For each practical class, the Projects and Resources page will contain a link with the code difference between the last two practical classes for the students convenience. Now, let's present who I am. My name is Alberto Salazar, and I'll be your instructor in this course. I have more than five years of experience as a professional software developer, working especially in the e-commerce industry. I've been a Bitcoin enthusiasts since 2016. I'd been heavily studying Bitcoins since then. I develop the open-source Bitcoin Java library, which we'll use in this course. I've built the Bitcoin education initiative to concentrate my efforts on providing Bitcoin education for developers around the world. Follow us on Twitter to receive our newest updates. I concentrated all the code for this course, including the Bitcoin Java library on our GitHub page. We also have a website whose address is www dot bitcoin education dot site. We have some technical articles there that can serve as additional study material. Check it out as a final word. I'd like to say that a lot of work was put into making this course. It took over two years in the making and almost all my free time during this period. So please, if you have any difficulty or encounter any problem with this course, contact me before giving it a low rating so that we can help you with your issue. I'll gladly do everything possible for you to have a great learning experience. Thank you very much for your attention and see you in the next video. 2. Downloading, Configuring and Running the Bitcoin Core Node and IntelliJ IDEA Download: In this video, we'll present the necessary software you'll have to download and install before proceeding to the next videos of the course. So let's begin with the Bitcoin Core Node. The Bitcoin Core Node is the original implementation of Bitcoin. It's responsible for communicating with the blockchain, creating, receiving, sending, and validating Bitcoin transactions, receiving blocks and more. As we've said in the previous video, the main functions will rely on the Bitcoin Core node are the ones related to communication with the blockchain. So let's go to the Bitcoin core.org website. Will install Bitcoin Core version 22. You may ask why not installing version 23? When I began making this course, the latest version available was 22. There's a small difference in the gRPC API in version 23 that will make a method of our application not work correctly. In one of the latest videos of the course, we'll update the Bitcoin node two version 23 and make our application compatible with it. But for now, let's install version 22. To do it, click on the release button at the top of the screen, then click on the Bitcoin Core 22 link. Next, click on this link on the page. This page contains installation files for each operating system. Since I'm using Windows, I'll download the one ending with dot EXE. If you're using macOS, you'll download the one ending with dot DNG. For Linux distributions, choose the suitable dot GZ file according to the distro you'll use on the Projects and Resources page, there are links with installation instructions for each operating system. For Windows, after downloading the file, open it and follow the installation instructions on the screen. I won't do that because I've already installed it on my machine. But it's a straightforward process. In the last phase of the installation, it will ask if you want to open the software. Don't open it yet. Will interact with the Bitcoin node through the command line interface. If you open the node by clicking on its icon, it will open a graphical user interface and start downloading the blockchain on the main net environment, which we don't want to do yet. Now, let's configure our Bitcoin node. To do that, we'll have to create a file named bitcoin.com and the appropriate folder of the Bitcoin application. This folder location depends on which operating system you're using. This website on the screen shows the default location where you have to create this file for each operating system. To create it, open a text file and save it with the name bitcoin.com from the appropriate folder for your OS. Now, write the same configuration you see on the screen in your file, or copy and paste the content from the Projects and Resources page into it. Don't worry, we'll explain what each line of this file means in a later video. For now, you'll have to decide where you want to store the blockchain data on your computer, you'll have to choose a path with access to at least 30 gb for the test net blockchain, or an additional 430 gb for the main net blockchain. Optionally set the data DIR configuration to the chosen path in this file. In my case, I decided to store the blockchain files in the E drive in the Bitcoin data folder, as you see on the screen. Now, if we run the Bitcoin node with this configuration, it will run on the main net and start downloading the main net blockchain. As its name suggests, the main net environment is the main bitcoin environment where the blockchain is big and the bitcoins have value, will only run the main net environment in the last video of the course. Before that will run it on the test net environment, which is used for tests. To run our note on the test net environment, let's add a line written test net equal one in the bitcoin.com file. Now using the terminal, let's go to the folder where you installed the Bitcoin Core Node. Inside the demon folder, run the Bitcoin D application like this. In the console logs. Notice that we're running indeed in the test net environment and all its data will be stored in the indicated folder. Good, that means our node is working with the configuration we've set in the bitcoin.com file. Now, let's wait for our node to connect to other nodes and start downloading and validating the blockchain. Okay, the lines starting with the text update tip indicates that it began downloading the blockchain. Each one of these lines indicates a block of Bitcoin transactions downloaded. The progress in each line indicates how much the blockchain is sink. In my case, it indicates that about 98% of the test net blockchain was downloaded. When this value is equal to one, it indicates that our copy of the blockchain is completely sync with the ones from other nodes. For the test net environment, it can take some hours for it to happen. You can leave it sinking while proceeding to watch the rest of the course, since we will use it only after some videos. To exit the application, you can press Control plus C or Command plus C if you're using Mac OS, if you start the note again, it will start downloading the blockchain where it stopped. After finishing downloading the test net environment, you can optionally change the bitcoin dot conf file and start downloading the main net blockchain by running the note on the main net environment, will only use the main net environment in the last video of the course, so you'll have plenty of time to download it. The other initial requirement of this course is the IntelliJ idea Java IDE. It's the software will use to write the code and run our application. If you don't have it, go to the website on the screen to download it. Download and install the community edition for your operating system by following the instructions on the website. 3. What is Bitcoin?: Hi, welcome back to the Bitcoin developer course. In this course section will give you an overview of Bitcoin. The concepts presented in this section, we will provide the basic knowledge necessary to understand what is coming in the rest of the course. So I will start with the question, what is Bitcoin? Bitcoin with an uppercase B is a communication protocol. This protocol is a set of rules that allows the exchange of messages between the entities participating in the Bitcoin network. Bitcoin with a lowercase b is a cryptocurrency. A cryptocurrency is a form of digital currency that we can exchange for goods or other assets. The crypto part of the name comes from cryptography, which protects transactions and other Bitcoin operations. Bitcoin is also a payment system. We can send and receive Bitcoin payments to and from other participants of the Bitcoin network. Speaking of networks, Bitcoin is also a peer to peer network, which means that it is composed of entities or nodes which communicate directly between them without the participation of centralized servers. The next question is, when was bitcoin invented? Bitcoin was invented in 2008 by Satoshi Nakamoto with the publication of the white paper, Bitcoin, uh, peer-to-peer electronic cash system. In this paper, which I highly recommend reading, Satoshi describes the basic parts of Bitcoin. Nobody knows who's Hitoshi Nakamoto really is, or if it is even a real name or multiple persons. Whoever Satoshi is, in 2009, he published the first Bitcoin block called the genesis block and put the Bitcoin network to work. If you do not know what a Bitcoin block is, do not worry. I will explain in short. So what is so great about Bitcoin? What is the innovation of Bitcoin? Bitcoin was the first, well succeeded digital currency. Before Bitcoin, there were some attempts to create digital currencies, but they all failed due to problems that Bitcoin solve later. One of these problems is the double-spending problem, which bitcoin was the first to solve in a decentralized way. It happens when a person spends two times a currency unit. So one of the transactions is invalidated later, making the recipient of the invalidated transaction lose money. Bitcoin was also responsible for inventing the blockchain, which was used to solve the double-spending problem. The blockchain is a data structure responsible for storing all Bitcoin transactions. It allows the validation of all its transactions to anyone with access to it, but more on that later. Bitcoin also introduced the concept of digital scarcity. It means that unlike files on your computer that can be copied and distributed indefinitely, Bitcoin can only be transferred by its owner and cannot be copied and distributed freely. 4. Bitcoin Transactions and Private Keys: Now we'll dive a little bit deeper into the inner details of Bitcoin. I will explain Bitcoin from micro to macro. That is, I will talk about Bitcoin transactions and private keys, then a little about blockchain and mining. Then I will finish the overview by explaining the Bitcoin ecosystem. So let us start with the question, where's the cryptocurrency and the system? Or in other words, where is the Bitcoin with a lowercase b in the system? The answer is, it is in a transaction. This figure shows a common Bitcoin transaction with one input and two outputs. A Bitcoin transaction can have many inputs and outputs, but in many cases, they have only one input and two outputs. In a Bitcoin transaction, we have the information from where the Bitcoin came in the input and where the Bitcoin is going in the output. In this example, input zero contains an instruction that says that this input came from John, was signed by John and contained one Bitcoin. The first output called the output zero, says to Mary contain 0.9 Bitcoin. In output one, it says to John contains 0.099 Bitcoin. This output is the change of the transaction. In most cases, we need to include a change because when you spend Bitcoin from a transaction, you have to spend all the units from the input. So this generates a necessity to create an additional output, which is the change. So if your input contains more bitcoins, then you want to send to another person, then you must create an additional output, the change to yourself. We have the concept of UTXO, which means unspent transaction output. A bitcoin is more specifically inside a UTXO. A transaction input must refer to a UTXO from a previous transaction to be able to spend that Bitcoin in this transaction. If you notice the sum of amounts of outputs is less than the amount in the input. Why is that? The difference is due to the minor fee. Every bitcoin transaction must separate an amount for the minor fee so that your transaction can be included in the blockchain by a minor. So the transaction fee amount is the difference between the sum of Bitcoins present in the outputs and the sum of Bitcoins present in the inputs. Another important piece of info is that Bitcoin can be divided into 100 million Satoshi's. Therefore, in this example transaction, we could have said that the inputs contained 100 million Satoshi's in the output zero contains 90 million Satoshi's and the output one contains 9,900,000 Satoshi's. The minor fee was 100,000 Satoshi's. These are other examples of Bitcoin transactions. I put them here just to show that you can have transactions with more than one input and one output. E.g. you can have a transaction with two inputs and one output. This transaction does not have a change. You can have a transaction with two inputs and two outputs. In this case, the transaction has inputs from two different persons and outputs for two different persons. This specific type of transaction is called a Coinjoin transaction, which is a type of transaction that increases privacy because you cannot link specific inputs to specific outputs. You can have a transaction with three inputs and two outputs. There are other types of transactions, such as multi-signature transactions that we won't talk about now, but we may include them later in an extra course section if there is enough demand. Let us see a little more about the details of a transaction. In this image, there are two transactions, transaction one and transaction two. Both transactions have an input and an output. The input has three fields, the previous transaction ID and output number from a previous transaction and a valid signature. The output has two fields, destiny, address and quantity, which refers to the Bitcoin amount inside the output. In this case, Transaction two input is spending output zero from transaction one. To do this, input one from transaction to must refer to the transaction ID from transaction one. It also must refer to the output number from transaction one, which in this case is zero. Finally, it must contain a valid signature produced with the private key used to derive the destiny address from output zero. We will see more details about this operation in the next slide. As you may notice, private keys are a fundamental part of Bitcoin. Private keys are used to receive and send bitcoins to receive. Private keys are transformed into public keys through elliptic curve multiplication. Then after a hash function, public keys are transformed into Bitcoin addresses. These are the Bitcoin addresses that you can show to other people to receive Bitcoins. Private keys are also used to assign Bitcoin transactions. Signatures are necessary to transfer Bitcoins from one address to another. In this image, we have an unsigned transaction. When we combine the private key with an insider transaction using the Elliptic Curve digital Signature Algorithm, ECDSA, we produce a signature that we include in that transaction. Thus, it becomes a signed transaction. The same private key that produced the address referred to an input zero is also used to unlock these funds and the current transaction by producing the signature. Thus, a private key is used indirectly to lock funds in an address and to unlock funds from the same address by producing a signature. Important thing about private keys and their transformations is that you cannot produce a private key from a public key, and you cannot produce a public key from a Bitcoin address. You also cannot produce a private key from a signature. These operations are only in one direction, just as these arrows show. Another important feature of Bitcoin transactions is that anyone with access to a transaction can validated signatures. This is possible because if you have a public key, the signature and the message, which in this case is the transaction. You can verify if a signature is valid for that public key. And a signature is valid for a public key only if it was produced with a private key that produced the same public key. 5. Bitcoin Wallets, the Blockchain and Mining: Now that you have a basic knowledge about private keys, we can start talking about wallets. A Bitcoin wallet is, in short, a collection of private keys. There are many types and standards of wallets. Wallets have independent development regarding other Bitcoin software such as nodes. A basic rule for Bitcoin owning isn't the mantra. Your keys, your bitcoins, not your keys, not your Bitcoins. This is because the owner of a private key can transfer Bitcoins locked by his private key and other transactions. What things do Bitcoin wallets have in common? They have a safe way to generate and store private keys. They can communicate with Bitcoin nodes. They can create, sign and send Bitcoin transactions. They can generate Bitcoin addresses. Notice that most of these abilities are possible thanks to private keys transformations. Every operation that uses private keys can be made offline. You only need to be online when communicating with Bitcoin nodes to fetch information from the blockchain and to send information to the blockchain. Speaking of blockchain, let us finally see what this buzzword means. The blockchain was used to solve the double-spending problem in a decentralized way. It does that by organizing the transactions in a chain of blocks so that valid blocks cannot contain transactions with a UTXO that appeared in the same block or in previous blocks. To understand what the blockchain is, let us look at this figure. These blocks represent blocks from the blockchain. Some of their data is represented in these smaller rectangles. Inside each block. A block is composed of many transactions, a field called previous hash, which as the name suggests, is the hash of the previous block. A field called timestamp, which stores the date where the block was created, and a field called the nonce, which we will talk about in the next slide. Each block produces a hash that is inserted in the next block. The blocks are created and added to the blockchain in a process called mining. Mining is the process where blocks are included in the blockchain. The nodes that do this process are called miners. To include blocks in the blockchain, miners must collect transactions and organize them in a block. Then minors must solve the Proof of Work, which is an algorithm necessary to produce valid blocks. Proof of work is composed of the following steps. First, a block is hashed, then the number of initial zeros of the resulting hash is verified. If this number is greater or equal to the necessary number of zeros to include the block in the blockchain. The block is included in the blockchain. If not, then the minor modifies the nonce and repeats the process. So this is the function of the nonce. Its only purpose is to provide variability for a block to produce different hashes. Proof-of-work has an interesting characteristic. The more zeros required for a valid proof of work, the more difficult is to find it. This makes mining difficulty easily adjustable. In Bitcoin, the mining difficulty is automatically adjusted, so the average time to mine a block is 10 min. When a minor minds a block, he earns a block reward and all block transaction fees. The block reward is the only way that new bitcoins are created. It decreases by one-half every four years in an event called having. So every four years the supply of new Bitcoins issued gets scarcer. And it is calculated that the last bitcoin will be mined in about 21:40 when the total Bitcoin supply will be equal to 21 million. 6. The Bitcoin Network, Ecosystem and Principles: Now let us talk about the Bitcoin network. Let us see the basic steps of how the Bitcoin network works. First, new transactions are sent to the nodes. Each miner gathers the transactions in a block. Each miner tries to find a block proof of work as fast as possible. When a miner finds proof-of-work, the minor broadcasts its mind block to the network. Other nodes verify if the block is valid. For a block to be valid, it must follow all the consensus rules, such as all the transactions and it must be valid and the previous block hash must be equal to the block cache of the last valid block. If the block is valid, nodes add it to their Blockchain. Copy. Minor start to work on new blocks using the hash field of the recently mind block as the previous hash. You may be wondering what happens if two miners mine a valid block at the same time. Well, when this happens, it causes a split in the network. Part of the nodes will contain one version of the blockchain with one block from a minor and the other part of the network will contain a block from the other minor. But this split is only temporary. When the next block is mined, the two groups of nodes will consider only the blockchain with more blocks as the real blockchain and the other blockchain is discarded, the probability that the network split persists decreases with time. So it is safe to assume that after six blocks a transaction is settled forever in the blockchain. The immutability and security of Bitcoin transactions rest on the fact that it is almost impossible to produce a valid blockchain with more blocks than the original one. Such a feat would require an immense amount of computational power needed to surpass the speed of block generation of the original network for a sufficient time. Now that we learned about various parts of Bitcoin, let us see how they interact inside the Bitcoin ecosystem. Bitcoin users control wallets. Wallets, as you learned, are collections of private keys. And these private keys can be used to sign transactions and to produce addresses to receive transactions. Exchanges can trade bitcoins for other cryptocurrencies and fiat currencies, such as the dollar. You can also trade bitcoins for goods from merchants. Whoever you transact with, all your transactions are sent to Bitcoin nodes. When a minor sees your transaction, he can include it in a block. The miner creates a block with many transactions and proceeds to mined the block. That is, he starts to calculate the block proof-of-work using his hardware. When a minor finally finds the block proof of work, he broadcasts the block to other Bitcoin nodes. The other nodes receive the recently mind block and validated. If the block is valid, the nodes add it to their copy of the blockchain. This way, the network achieves consensus on the current state of the blockchain. Let us talk about the Bitcoin principles. The Bitcoin principles are important to understand the technical decisions that were made during the Bitcoin development. One of these principles is the Bitcoin maximum supply of 21 million Bitcoins. This limit was set at the beginning of the project. Changing it would cause this arrangements in the Bitcoin economy. So it is important to keep it that way. Censorship resistance is another important Bitcoin principle. The fact that many people can run Bitcoin nodes makes it almost impossible for an authority to shut down the network. Bitcoin developers value a high censorship resistance. Being open source is another Bitcoin principle. You can find the Bitcoin Core software for free on the GitHub website. Like many other developers, you can verify the code and check it for bugs. You can also participate in its development. Bitcoin has a strong community of developers responsible for its security and new features. And being open source is what allows it. Bitcoin is permissionless, which means that anyone is allowed to run a Bitcoin node, mine and transact Bitcoins. That is one of the greatest strengths of Bitcoin and what makes it so popular today around the world. Bitcoin transactions are pseudonymous. That means no information present in a Bitcoin transaction can alone connected with people. Unlike the example from the beginning of the overview might have suggested Bitcoin transactions do not contain the names and IDs of recipients and senders. A Bitcoin transaction shows only transfers between bitcoin addresses, which looked like random collections of characters. If someone discovers that an address belongs to a specific person, they can track the amount of Bitcoin and other transactions of that person. But that's another story. Bitcoin aims for high fungibility. Fungibility is a characteristic that makes a unit of a currency be valued equally as any other unit of the same currency. That means that ideally every Bitcoin is valued and treated equally. It is often argued that Bitcoin is not fungible because Bitcoins from different transactions can be traced and treated differently. I would say that although it is true in practice, most bitcoins are treated equally and you have ways to make transactions more private and fungible. Irreversibility of transactions is another Bitcoin principle. Once a transaction is settled in the blockchain, it cannot be reversed. This is an important security feature because it makes Bitcoin hard to confiscate. But it also shifts the responsibility of a transaction to the Bitcoin center. Hence, the need to keep your private keys secure. 7. Starting the Project: In this video, we'll set up a new Spring Boot project that will be our Bitcoin wallet. To do that, we'll use the Spring initializer tool from the website start dot spring dot io. So enter the website. Choose Maven project. The language is Java, will use this version of Spring Boot, but if it's unavailable for you, you can choose the default one as the group name. You can set whatever name you like. In my case, I'll set it as BYOD w dot wallet. I'll use BYOD W as the artifact name, as the description. I'll use Bitcoin wallet. We'll use the latest version of Java. If you only know previous versions of Java, don't worry, older Java features still work on the latest version as Java is backward compatible. Finally, click on Generate to download the project, open it and extract its contents to the folder you want to. Now, we'll open the project using intelligent idea. After starting the program, click on Open, then choose the folder you just extracted. Click on Trust Project. Wait until IntelliJ idea indexes all project files. After that, you can explore the files that spring initializer created automatically. To verify if the project was set up correctly. Click on Maven on the right side of the screen. Then inside the life cycle folder, Double-click on Test. Oops, we got a maven error. To solve that error, Let's click on configuration dialog. Let's change Maven home path to bundled Maven three. Click on Apply then. Okay. Before clicking on test again, I'll check if my project structure was set up correctly. So I'll click on File. Then project structure makes sure the project SDK has the Java version you chosen the spring initializer. If it's not the case, click on Add SDK and download SDK, choose the correct Java version and one of its implementations click on download. In my case, I won't do that because I already have the right version. So I'll click on Cancel. Make sure that the project language level is also set to the correct Java version. Now, let's run the test again. Wait until the test passes. Great. The console indicates that the test has passed. We're ready to begin working on our wallet. 8. Configuring the GUI: In this video, we'll start building the first window of our wallet. To do that, we'll first add some dependencies to our project. Open the palm dot xml file at the root of the project. The palm dot xml file contains all external dependencies of the project. We'll add some Java FX dependencies. Java FX is a framework responsible for graphical user interface features. It's very well known in the Java community. The version is 16. The next dependency is JavaFX, FXML. The version is also 16. We'll also add a plugin. It's called Java FX Maven plugin. It's version is 0.0, 0.6. To load these dependencies in your project, click on this icon. Project has loaded all dependencies. Now let's make the code necessary for booting our application. This process requires some coordination between the ways that Spring Boot and Java effects start. To do that, we'll first make a new Java class called GUI application. This class must extend the application class from Java effects. And we must implement the start method from the same class. We'll add a private property with the type configurable application context. We'll use next. We'll add the init method here, which is executed before the start method, during the application initialization. The code I just type is responsible for initializing our Spring Boot application injected dependencies. Now let's go to the BYOD W application class. Let's modify the main method. The main method of this class is the first method called when we run our application. When the code I just type is executed, it will first call the init method of the GUI application class than the start method of the same class. Let's get back to the GUI application class. Let's continue implementing the start method. Now, we'll call the publish event method on the context property, passing a new GUI started event object, which will create next as its argument. Let's create the gooey started event class. We'll create it in a new events folder. Due to how we created this class, the ID already knew what class we had to extend and it automatically created the boilerplate code will need very handy, isn't it? Now we'll continue implementing our constructor. We'll call the super constructor passing a GUI application object as its argument. And we'll assign the argument primary stage to the stage. Private property will also make a listener for this event class inside a package called listeners. We'll add the component annotation to this class. You'll see this annotation a lot along the course. It's from Spring Boot and its purpose is to make an object of a class available for injection and other objects of the project will also implement the application listener interface for this class, passing the gooey started event as a type parameter. This is necessary for Spring Boot to interpret this class as an event listener for a gooey started event. Now we'll implement the required method of the interface. Will also need a constructor. This constructor will take a resource object with a value annotation pointing to a file called main window dot FXML, which will add later to the project. The constructor will also take an application context argument. Then we'll initialize to private properties with the same name as the constructor arguments. Will make both properties Final. Alright, now that we have our dependencies injected into this class, let's implement the code of the application event method. This code will be responsible for showing the main window of our wallet when we start the program. So we'll first instantiate an FXML loader object. Then we'll get the stage object from the GUI started event. To do that, we'll add the method gets stage to the gooey started event class. This method will return the stage object. We'll add a title to the wallet using the set title method of the stage object. It can be any string you want. I'll set it as BYOD W wallet. This text will be shown at the top bar of the programs window. Will also call the method set scene, passing a new scene object as its parameter instantiated with an object returned by a new method that will create called initialize FXML. This method will start declaring a variable of the type parent called root. Then inside a try catch block will use the set location method from the FXML loader variable passing the URL location of our FXML property. We'll set the controller factory of the FXML loader to a reference of the good bean method of the context property. This is necessary for the JavaFX framework to recognize controller classes annotated with the Component annotation. We'll also set the root variable to the result of calling the load method of the FXML loader will catch an IOException and throw it wrapped in a runtime exception. We'll return the root variable. Finally, in the non-application method will call the show method of the stage, which will cause the window to show up on the screen. Now we'll create the FXML file, but we referred on the value annotation of the FXML property of the listener constructor. And FXML file is a type of file used to encode GUI elements of a JavaFX application. Like an HTML file, encodes webpages, FXML files and code Java effects windows will create this file inside the new FXML path that will create. This directory will be located inside the resources path. We'll call it main underscore window dot FXML. Let's delete the auto-generated boilerplate. Let's add a border pane tag. We'll add some attributes to it. Will add an Fx ID that will allow referring to the border pane tag inside its controller class, which will create later. Let's add some attributes to set the window size. Finally, we'll add some metal attributes to set the file schema. That's it. Let's run the application to see if all went well. Inside the Maven tab, Let's click on plug-ins, Spring Boot and Spring Boot run. Great. The first window of our wallet has shown up on the screen. Good job. 9. Creating our First Test: In this video, we'll start building a test for the first feature of our wallet. The first feature of our wallet will be the option to create a wallet. More specifically, we'll create a menu with a button that when clicked, will make a dialog box pop up on the screen. That dialog box will initially contain a TextField where the user will define the wallet name and a Create button that when clicked, will generate a random mnemonic seed. Will learn what is the mnemonic seed. In the next video, we'll create every feature of our Wallet using the test-driven development or TDD approach. This approach consists of first creating an integration test, which is a test describing what we want to achieve for that feature. Then we'll implement the feature and run the test until it passes. During the implementation, we may encounter situations where we need to make new classes or methods to help us achieve our goals. If that's the case, we'll create unit tests for these classes were methods and implement them using TDD. At the end of each TDD cycle, we'll refactor our code if needed. Let's see how this works in practice. But first, let's add some dependencies to our project. We'll add some dependencies related to the Spark framework. The Spark framework is a testing framework in groovy, a programming language compatible with Java. It contains features that facilitate building tests, will also use a version of test FX compatible with Spock. Test fx is a framework that provides features for testing JavaFX applications. Now, let's add groovy version 3.0, 0.6 to our POM file. And let's add spock spring to it. The version will be 2.0, groovy 3.0. Its scope will be test. The next dependency will add is Spark Core. The version will be the same as Spock spring. The scope will be test. The next dependency will be test FX Spock. Its version will be 4.0, 0.16 alpha will also add a G Maven plugin. Okay, I forgot to put the right scope and the test FX dependency. We'll also add some goals in the GI Maven plugin. There'll be necessary for groovy to work correctly. Now, we'll make a change in the application dot properties file. Spring, by default creates a web server, but we won't need one in our application. So we must set this property to none. So spring won't create a web server when it boots. Now we'll create our first test. But first, let's delete this file BYOD W application test, which was auto-generated by the spring initializer, will create a package in this folder called gooey that will contain all our graphical user interface tests. Inside this package, Let's create the test. But first on the palm dot xml file, click on the load Maven Changes button. Now the IDE will allow us to create groovy classes. So let's create one called Create wallet test. We'll add to this class a Spring Boot test annotation will extend this class with the application spec class. This is necessary for both Spring Boot and test fx to consider this class as a test class. Every integration test must contain this annotation and extension. We must implement the start method from the application spec. We will also implement the unit and stop methods. Inside the init method will add this code which is necessary for test initialization. Inside the stop method will include a code necessary for stopping the test. Inside the stark method, we must include the code necessary for showing the first screen of our application. This code will be similar to the code present in the GUI started listener class. So we'll instantiate an FXML loader passing the FXML URL as its argument, will then create the FXML private property with the same value annotation present in the GUI started listener class. Groovy transforms every method with getter set in an object property, we can use this URL here. Instead of get URL will set the controller factory property to the context get bean method reference. Let's add the context field to the class. Above. It will put the auto wired annotation. This annotation is necessary for Spring Boot to inject the application context object from its dependency injection container to this variable. Next, we'll create the root variable using the load method from the FXML loader. Then we'll set the stage title, the scene and call the stage show method just as the code inside the gooey started listener. Okay, we're ready to work on the code of our first test. The name of the test will be should create wallet. The test will contain the requirements of the feature we want to implement, will use the keyword when to describe the actions the test user will make. So let's implement it. The user will click on a button with the text knew. Then you'll click on a button with the text wallet. Then on a text field with an FX id of name. When we want to refer to an FX id, we put the name of the ID after a pound sign like this. Then the user will write the words myText wallet. Then he'll click on a button with the create text. Next, the test will look up the contents of a text area field with an ethics ID of mnemonic seed. It will assign the contents of this field to the mnemonic seed variable. Finally, we'll use the keyword then to define what we expect to happen after the user makes all actions inside the wind block. We expect that the mnemonic seed variable contains a non-null value. To do that, we just put the mnemonic seed variable inside the then block. If the mnemonic seed is set, the block will evaluate to true and the test will pass. Otherwise, it'll evaluate to false and the test won't pass. Let's run this test to see what happens. First, we'll click on Build than on rebuild project to make sure the IDE loads all the changes we've made to the code. Then we'll click on Test inside the Maven Config tab. *****. The IDE complained about Maven again, let's fix that quickly. Now. Let's run the test again. The test has failed as expected. Did you notice that a window popped up quickly on the screen during the test? It shows our window opened, at least. Let's check the results of our tests on the console. It says that the query new return no nodes. The test opened our application, then tried to find an element with the text knew as it didn't find it, it quickly failed and close the application. In the next video, we'll learn what a mnemonic seed is. Then in the video after the next, we'll create our first wallet and make this test pass. See you. 10. Mnemonic Seeds: In this video, we'll learn more about mnemonic seeds. So what's the mnemonic seed? A mnemonic seed is a sentence containing 121-51-8201 or 24 words. It's used to derive all wallets, private keys, and addresses. The rules of mnemonic seed generation that we'll use are described in the Bitcoin Improvement Proposal 39 or BIP 39. Many wallets used the BIP 39 rules to generate mnemonic seeds. Mnemonic seeds are combined with the string mnemonic plus an optional password to produce a root seed represented here in hexadecimal format. The optional password is commonly referred to as passphrase, but we'll use the word password for simplicity. Then, using other algorithms, the roots seed generates private keys, public keys and addresses, will learn the details of these operations in a later video. Now, let's focus on how mnemonic seeds are generated. To generate a mnemonic seed, first, we must generate a random sequence of bits called entropy of length equal to 128 bits. If we want a mnemonic seed of 12 words, 160 bits, if we want one with 15 words, 192 bits, if we want one with 18 words, 224 bits if we want one with 21 words or 256 bits, if we want one with 24 words, then we calculate the checksum. To do this, we calculate the entropy length divided by 32 and obtain the checksum size. Then we get the first checksum size bits of the SHA-256 hash of the entropy. The result is the checksum. The checksum is used to check if a given mnemonic seed is valid. We append the checksum to the end of the initial entropy. The result is split into groups of 11 bits. Each group of 11 bits is converted to a number 0-2047. These numbers are used as indexes in a word list. The corresponding words form the mnemonic seed. 11. Create Wallet Dialog Window: In this video, we'll continue to implement the create wallet feature of our application. The first step is to add a button with the text new written on it. Let's do this. Open the main window dot FXML file. From now on, we'll use the IDE Scene Builder tool to create the windows of our project. Scene Builder allows us to create the graphical user interface of our application interactively and easily. Click on the Scene Builder button at the bottom of the screen. In my case, this window appeared. But if you don't have Java FX or Scene Builder installed a button to download them will appear on the top of your screen. After you download and install them, this window will show up. Now we'll add a top menu bar to the main window. To do this, we'll click on controls, then drag and drop the menu bar component to the top part of the border pane menu below. Now we'll have a menu bar with three menu items. Let's delete the edit and help ones. Let's change the file menu labeled two new. Great. Now we have our new button. Let's check our test to see what to do next. The next action our user will do is to click on the wallet button. Let's create it. Back to the main window. We'll add a menu item inside the new menu. In this case, we already have a menu item. So let's change its label to wallet. When the user clicks on the wallet button, a new dialog window must appear. Let's implement it in the Scene Builder. Click on the wallet menu item. We'll add an action to this button. Click on Code, type open create wallet dialogue. If we click on the Text button at the bottom of the screen and check the FXML file. We'll notice that the IDE has added the on action attribute in the menu item tag with the value we just typed. Now, to create an action for this button will need to create a controller. But first, let's do some refactoring in our code. We'll create a new package inside the BYOD W package. Let's call it gooey will transfer the events and listeners packages to it, will add all the classes related to the applications graphical user interface to this package. Back to the main window, will add an FX controller attribute to the border pane tag and set it to the new controller we'll create will create it inside a new controllers package. Inside the gooey package. Its name will be main window controller. Every FXML file can have a controller which is used to define the actions that happen in response to the user's interactions with the window encoded by that FXML. In our case, the main window controller will contain code that will define actions in response to events on the main window. Back to the main window dot FXML file. When we click on the Open create wallet dialogue attribute and press Alt plus enter, the IDE will show the option to create a method inside the main window controller. Click on this option. The IDE auto-generated the method in the main window controller. Let's delete the action event argument because we won't need it. In this method will include the code responsible for opening the create wallet dialogue. When we click on the wallet menu item, will first instantiate a dialogue object of type button type. Then we'll set the dialogues in it owner to the border pane window to indicate that the dialogue belongs to the border pane of the main window. Back to the main window dot FXML file. We can click on the ethics ID attribute of the border pane tag, press Alt plus Enter and create the border pane property inside the main window controller. The IDE auto-generated the property. Let's set it to private and include the FXML annotation above it to indicate that it refers to an FXML component. Then we'll set the dialogue title to create new wallet. Now, inside a try catch block will instantiate an FXML loader object. Passing these arguments. We'll then create the create wallet dialogue property and the context property. Then we'll create a constructor to initialize both properties. Both properties will be automatically injected by the Spring dependency injection container will add a value annotation to the create wallet dialogue constructor argument passing the path of an FXML file that will create next. Then we'll set the content of the dialogue pain to the result of calling the method load of the FXML loader will then catch an IOException and throw it as a runtime exception. Finally, we'll call the dialogue show and wait method to open the dialogue. Don't forget to add the component annotation to this class. Now, let's run our application to see what we have so far. In the Maven tab inside plugins and Spring Boot, click on Spring Boot run. We have our top menu bar with the New button and the wallet button. When we click on the wallet button, the application throws an exception. That is because it didn't find the create wallet dialog dot FXML file. Let's create it. After creating it, click on Scene Builder. Let's delete this anchor pane. Drag the dialogue pain, and drop it here. Good. Let's adjust the size of it. Click on Layout. Then in the pref height field type 500, in the pref width field type for 50. Then set use prep size on the fields min-width and min-height. Now let's add a header text to the window. In the header text field type. Give your wallet a name and click on Create. Let's add some padding around it. Good. Now let's add a grid pane. Drag and drop this component to the dialogue pain below. Inside the first cell of the grid pane will add a label like this. And this labelled will contain the text wallet name. We'll also add a text field to the grid pane. Let's change its coordinates, set its column index to one. Now let's add a button to the grid pane. Change its row index to one and its column index to one. Let's change its text to create. Let's get back to our test to check what else it requires. It'll try to click on a component with an ethics id of name. So let's add an Fx id of name to the text field. After that, it will try to write my text wallet in the text field. Then it will click on a component with the text Create on it, create with an uppercase C. When it clicks on it, the test will look up the contents of a text area with an FX idea of mnemonic seed. So let's create this text area. Drag it to the grid pane below. Then change its row index to two and its column span to two so that the mnemonic seed field takes up the space of two columns. Good. We'll also add a label for the mnemonic seed field. But first, let's add another row to the grid pane. Good. Let's increase the mnemonic seed field row index to three. Then we'll drag a label to the grid pane. Adjust its row index to two, change its text to mnemonic seed. Now let's add an Fx id of mnemonic seed to the text area. Now, let's run our application and see what happens. Rebuild the project first and click on Spring Boot run. Great. But when we click on Create, nothing happens. We also must handle the closing of our dialogue. For now, click on stop. The positioning of these fields is bothering me a bit. Let's fix that. Click on the Text button. We've included the grid pane inside the header tag of the dialogue pain. The correct place to include it is in the content tag. Let's change it. Let's check its appearance now on the Scene Builder. Great, now it looks way better. In the next video, we'll continue to implement the create wallet feature. See you. 12. Creating the Mnemonic Seed: In this video, we'll continue to implement the create wallet feature and finally, make our first GUI test pass. To do this, Let's add a dependency to the project. We'll add Bitcoin, Java, and open-source library made exclusively for this course. This library contains many Bitcoin related utilities, such as methods to generate random mnemonic seeds, build transactions, and many more. For the correct functioning of this library, we must add a plugin goal that will copy the file word list dot TXT from Bitcoin Java to the project during the compile phase of the applications building process. Wordless dot TXT contains all valid words for mnemonic seed generation. Now open the create wallet dialog dot FXML. Change to the text view. We'll add a controller to this FXML in order to add an action to the Create button. So let's add the FX controller attribute to the dialogue pain tag. The controller's name will be created wallet dialogue controller, and we'll add it to the controllers package. As with every controller, will add the component annotation to it. Let's create the mnemonic seed property in this controller. In the FXML, we'll add an action to the Create button. Let's add it here. We'll name the action as create mnemonic seed. And we'll create it in the corresponding controller. So when the user clicks on the Create button, this method will be called and the text area will show a random mnemonic seed. So we'll set the mnemonic seed texts to the result of the create method of the mnemonic seed service will create next. Let's inject the mnemonic seed service into this class. Now, let's create the mnemonic seed service class inside the new package called api dot services inside the BYOD W package. Basically, every business class not related to the graphical user interface will be placed inside the API package. Let's add the create method to the mnemonic seed service. Add the service annotation to this class. It's purpose is identical to the Component annotation, but it is more suited to service classes. Now, let's initialize the mnemonic seed service property in the create wallet constructor. Now, let's implement this method because we're using TDD to create our application. We'll first create a unit test for this class. Let's create an API package inside the test folder. Inside it, create a groovy class called mnemonic seed service test. As a unit test, this class only needs to extend the specification class from Spock. Now, we'll create a test called should return random mnemonic seed. And we'll expect that the mnemonic seed service returns a non null value. Let's instantiate the mnemonic seed service here. Let's run this test to check what happens. It's failed as expected. Let's implement this method. In order to do that, we'll use the generate random method of the mnemonic seed generator class from Bitcoin Java. We must pass the entropies number of bits that we want the mnemonic seed to have as an argument to this method, we'll use to 56. Remember that an entropy of 256 bits generates a mnemonic seed of 24 words. Finally, we'll call the get sentenced method on the return of this method and return the result. As with every job, a checked exception, we also need to add the sentence throws FileNotFoundException to the create method signature. We have to do the same to the create mnemonic seed method in the create wallet dialogue controller. Let's run this test again. Great, The test has passed. Now let's check what happens when we run our application. Whoops, and error occurred. Oh, it's overwrite with an uppercase W in this tag. This group ID tag is also wrong. Actually, it's just Bitcoin hyphen education. Let's run our application again. Great. We've successfully generated a mnemonic seed, but I want its text wrapped. Let's fix it. Let's go to the create wallet dialog dot FXML. In the Scene Builder, click on the text area and click on The Wrap Text checkbox. Let's run the project again. Okay, way better. Now, let's run all our tests. Great. They all have passed. 13. Create Wallet Dialog Window Buttons and Validations: In this video, we will further develop our applications create wallet feature. Will add an OK button and a cancel button to the create wallet dialogue. When the user clicks on the OK button, his wallet will be created and the wallets name will appear on the top of the screen. When he clicks on the Cancel button, the dialogue will just close. We'll also add a restriction to the Okay button so that it will be disabled by default and only be enabled when the name and the mnemonic seed fields are fulfilled. Finally, we'll add an optional password field so the user can only access its wallet and transact with it after providing the correct password. Let's add these new features first in our create wallet test. First, we will add a click on OK button action. Then we'll expect the stage title to be equal to the name of our application dash the name of our wallet, which is my test wallet. Now let's create the stage property. We'll initialize it in the start method. Now, let's create another test to verify what happens when the user tries to click on the Cancel button. For this, we'll create a test with the name should cancel wallet creation. So we expect that when the user clicks on new wallet and cancel, no exception will be thrown. Let's run these tests to see what happens. The tests have failed as expected. Let's implement these features. Go to the create wallet dialog dot FXML file. Click on the dialog pane on the left side. Then add an OK button and this button types field. Click on plus, then add a cancel button. Now we'll add the password field. But first, let's add another row in the grid pane. Now let's move the name, label and field to the first row. Then we'll add a password label and a password field in the next row. Let's also add an Fx idea of password to the password field. Now, let's change the dialogue header text to the following. While we're at it, let's make the mnemonic seed field not editable. This is a security measure because we don't want the user to change his mnemonic seed accidentally. Change to the text view. We'll add some changes to these buttons, tags in the Okay button, we'll add an Fx idea of okay. The Cancel button will erase its content and add an Fx idea of cancel. We'll also add the value of cancelled close to the Attribute button data. We'll also add the cancel string to the text attribute. This is needed because when we use the default cancel button, it's text gets translated to the computer's language, and we don't want that. Now, let's make some changes to the create dialogue controller. Will add a method called initialize to it. But first, let's get back to its FXML and add an Fx id of dialogue pain to the dialogue pain tag. Now, let's add the properties with an FX ID to the controller. Will do that with the properties password named dialog pain, OK, and Cancel. Now back to the initialized method. This method will be executed after the initialization of the dialogue. Will include code there to define the actions of each button. First, we'll define the action of the Cancel button. When a user clicks on it, the dialogue will hide. So we'll call the Lookup Button Method of the dialogue pain passing the cancel button as its argument. Then we'll add an event handler to it, passing the action argument and a callback that will call the hide method of the dialogue pains window. We'll do the same to the Okay button. But we'll call the method create wallet in the callback instead. Let's include the same code to hide the window when the create wallet method for now and run the application to see what happens. When we click on the Cancel button, the dialogue hides. The same happens when we click on the Okay button. Good. But when we click on the X on the side of the dialogue, nothing happens. Let's fix that. Go to the main window controller. Will need to include the following code to close the dialog window when we click on the X button. Now, let's run the application and try again. Good, that fixed it. Let's also change the show and wait method called on the dialogue to simply show that simplifies things a bit. Now, run the application again. Everything continues to work as expected. But there's another issue with the dialogue. It allows the creation of wallets without a name and a mnemonic seed. We want every wallet to have a name and a mnemonic seed. So we need to disable the Okay button if one is not fulfilled. Let's fix this. Go to the create wallet dialogue controller. Now, we'll create a private property of type Boolean binding called all required inputs are full. We'll set this property in the initialized method with the following code. Here we'll use a Java anonymous class that extends Boolean binding. Then we'll initialize the class with the bind method, passing the name and mnemonic seed text properties as its arguments. Then on the compute value method will include a code that will return true only if the name and mnemonic seed fields aren't empty. Now, we'll create a getter method for this property. Finally, we'll call the disabled property method on the Okay button. Then we'll call bind on the result and pass the get all required inputs are full method calling the method on it. Let's make a little fix in this method first, it must return a Boolean binding. And let's remove this, get after it. Good. Now let's run our application again. Okay, the Okay button is disabled by default. If we type something in the wallet name field, it stays disabled. But when we click on the Create button, it gets enabled. Great. Let's run our tests again. That should create wallet test has failed because we hadn't implemented the code to change the application title yet. Let's do that in the next video. 14. The Current Wallet Observable: In this video, we will implement a feature that will make the Application Load the wallet and show its name on the application's title. After the user creates, the wallet. Will create code that will be useful later when we want to show other wallets features such as addresses on the screen. After we implement this feature, this test will pass because the stage title will be equal to BYOD W wallet space, dash space, the wallets name. So let's implement it. First. We'll go to the create wallet controller. Then in this method, will create a Wallet using a new service called create wallet service and a method called create. We'll pass the wallets name, password, and mnemonic seed to the method. Now we'll create the wallet class. We'll add a new package inside BYOD W, call it domains. Inside it will add a new Java record called wallet. For now, we'll just add a string attribute called name to this record. A Java record is a recent feature of the language. Every record attribute has a built-in getter and a constructor, so we don't need to add them. Now, import the wallet record to the create wallet dialogue controller. Now, we'll inject the create wallet service into this class. And we'll create this class inside the API services package. Will add the component annotation to this class. Let's inject this service into this class's constructor. Now, we'll create the create method inside the create wallet service. For now, we will only return a new wallet passing the name as its parameter back to the Create wallet dialogue controller. Now that we've created the wallet will publish an event that will take the created wallet as a parameter. This event will be listened to by a class so that when the user creates a wallet, the listener will update the current wallet loaded by the application. Let's inject the application context into this class. Now, let's create the created wallet event inside the events package. Will then call the super constructor passing the create wallet dialogue controller. And we'll set a new wallet field, assigning the wallet constructor argument to it will also include a getter for this field. Now, let's create a listener for this event called created wallet listener. And we'll create it inside the listeners package. It will implement the application listener class with the created wallet event as its parameter. Will then implement the method on application event. It will call a method from a new service called update current wallet service. This method called update takes the events wallet as a parameter. Let's inject this new service into this class and create the service. We'll add it inside a new services package. Inside the gooey package. Will then create the update method in it. We'll also add a Service annotation to it. For now, the update method will only set the name of the current wallet to the newly created wallet name. Now, let's create a new package inside BYOD W called observables. Inside this package will create the current wallet class. Back to the Update Current wallet service will instantiate the current wallet in its constructor. In the current wallet class will include the Component annotation. This class will represent the current wallet loaded by the application. Every change the application makes to this class instance will appear in the applications graphical user interface. We included it in a package called observable, because every property of this class will be unobservable. And observable is a type of object in which every state change can be listened to, enacted upon by other objects. The first observable property we'll add to it is the name. It'll have the simple string property type. This type implements the observable interface and triggers a change event when it's string value changes. We'll instantiate it here. And we'll create a getter for this field. Intellij idea identified that it is an observable and created two getters. One for the property called name property, and the other for the property value called getName will also create a setter for this field to set the name property value. Let's make this field final. Will also make a test for this create wallet service class. We should have created the test before implementing this method, since we're using TDD. But considering we'll increment this methods functionality where forgiven. Let's create the test. Now. We'll first create a property for the create wallet service and instantiated inside the setup method that runs before each test. Then we'll create a test called should create wallet. Given we have a name, a password, and a mnemonic seed. When we call the method create from the create wallet service with these parameters. Then we will expect the wallet name to be equal to the name variable. Let's run the test. The test has passed. Now, let's recapitulate what we've done so far. When the user clicks on the OK button, the create wallet method from the create wallet dialogue controller will be called and the wallet will be created by the wallet service. To do that, it uses the method create, taking the name, the password, and the mnemonic seed the user has chosen. For now, this method only returns a new wallet with its name. Then we pass the created wallet to a new created wallet event and publish this event. When this happens, it will trigger the created wallet listener method on application event. It will receive the created wallet event as its parameter. We must add the component annotation to this class and inject the update current wallet service in its constructor. So the application event method will call the update method from the update current wallet service, passing the wallet from the event as its parameter. Finally, the update method. We'll set the name of the current wallet to the name of the newly created wallet. Now, let's go back to the main window controller. Here will create an initialized method which will be executed before the main application window shows up. Inside it, will add a listener to the current wallet property. Let's inject the current wallet into this class first. Inside the ad listener method will pass a callback that will take three parameters and observable and old value, and a new value in the callback body will get the Windows stage and assign it to the stage variable. We must cast its type to stage. Then we'll set its title to BYOD W wallet space, dash space, new value. The new value variable contains the new value of the name of the current wallet. Whenever the current wallet name changes, this change will be listened to by this callback and the stage title will also change to the sentence we've just said. Let's run the application to check if this works. We'll create a new wallet with the name test, then a mnemonic seed and click, Okay, great, it worked. The window title change to BYU OWL a dash test. Let's create another wallet with a different name to see what happens. As expected. It's changed to match the newly created wallet. Now, let's run all our tests. Great. All tests have passed. Good job. 15. The Receive Bitcoin Tab: In this video, we'll start to implement a feature that will allow us to create addresses that will be used later to receive Bitcoins. The first thing we'll do is to create the Receive tab. This tab will contain the derived addresses of our wallet. So go to the main window dot FXML file. In the Scene Builder will include a V box in the center of the border pane. Inside the V box will include a tab pane. Will delete the second tab that was created, automatically. Change the remaining tabs text to receive. Inside the VBox configuration menu will set the pref height to 300. Inside the Receive tab will include a grid pane. For some reason, we can't include a grid pane in a tab using the Scene Builder. No problem. We'll do it using the text editor. Instead. We'll include a label. It's text will be equal to receiving address. Inside it will add some tags to set its margins. Now, we'll include a text field. It won't be editable. It'll have 350 as it's pref width. And its column index will be equal to one, will include the same grid pane margin tags that we use previously. The scene Builder is not working anymore due to the grid pane we've included in the tab. No problem. We'll see how the application looks by running it. Great, our wallet is now ready to receive an address in this new field we've just created. Inside the create wallet test will include a code to check if an address was created and inserted in the receiving address field after the wallet is created. So after the test clicks on the OK button, it will click on the Receive tab. And the test will look up the content of the receiving address field and store it in the address variable. Then the test will assert, if the address is not know, let's run the test to see what happens. The test has failed as expected. Now, let's do some refactoring and our main window FXML file. We see now that our main FXML file is getting bigger, it's better to create a new FXML file only for the receiving tab, which are main window will refer to later. So let's create it. We'll name it Receive tab dot FXML will copy all the tab content to the Receive tab dot FXML. The only change we will make is to the tab tag. We'll change it to f x colon root. Then we'll use the tab class as the type attribute. We also need to include the Meta attribute XML and S colon FX. Now we'll import the other tags. Back to the main window dot FXML will delete the tab tag and all its content. Will include the tag Receive tab controller, which will create now. We'll create it inside the controllers package. And let's import it inside the main window dot FXML. Back to the Receive tab controller will add the component annotation to this class. We'll create a constructor passing a resource with a value annotation pointing to the Receive tab FXML file will also pass the application context. Here we will configure a new FXML loader instance with parameters similar to those we've used for the other controllers. Then we'll set its controller to this. We'll also set its route to this. Then we'll call the load method on it. Okay, we need to do one more thing to make it work. Inside the gooey started listener class, add the following code here. This code is necessary to tell Java FX how to build custom components, such as the Receive tab controller when it sees it inside the FXML files. This code will make Java FX use the context to get bean method to build a component when it sees a Receive tab controller tag. So whenever Java FX needs to build a Receive tab controller tag, it'll use the Receive tab controller class to build it. For other tags, it'll use the default Java FX builder. That's it. Now Java FX knows how to build our new customized FXML tag. Let's run our application to check if all goes well. ***** and error occurred. It's saying that the root controller isn't a tab instance. I know how to fix it. We must make the Receive tab controller extend the TAP class. Now, let's see if it works. Okay, it's working just as before. So when we create a new wallet, we expect the receiving address field to be filled with the new Bitcoin address. In the next couple of videos, we'll understand the process of deriving a Bitcoin address and implement this feature in our wallet. See, yeah. 16. Bitcoin Addresses and HD Wallets: In this video, we'll learn about HD wallets and Bitcoin addresses. So what is a Bitcoin address? A bitcoin address is a word encoding a public key, the hash of a public key or a script hash. It is used to receive bitcoins in a transaction. To receive Bitcoins through a Bitcoin transaction, you show your address to another person so that person can send bitcoins to your address. There are several types of Bitcoin addresses and the rules to generate them are in many VIPs, such as VIP, VIP 3d2 and BIP 44. Let's now talk about HD wallets. Hd wallets stand for hierarchical deterministic wallets. They're hierarchical because they're composed of many levels of keys, and they're deterministic because a single seed will always generate the same addresses and private keys. And HD Wallet is a type of wallet where from a single seed derivation pads are used to derive private keys, public keys and addresses. Hd wallets specifications were originally defined in BI P32 with other BIPs extending on that specification. Now let's recap a slide from our last ppt presentation. In this presentation, we learned how to generate a mnemonic seed. And we mentioned that by combining a mnemonic seed with an optional passphrase, we could generate a root seed using the algorithm P vk df two. From that root seed, we could generate private keys, public keys, and addresses. In this presentation, we'll dive into the details of that last part on how private and public keys and addresses are generated from a root seed. So beginning with a root seed, which has 512 bits in size, applying the HMAC SHA-512 hash algorithm to it, we obtain the master key, which also has 512 bits from the master key. By applying the function CKD, which stands for child key derivation, we can obtain different extended keys by using different indexes as parameters. If n is the index for that function, than n can vary 0-2 to the power of 32 minus one. Each extended key can generate more extended keys by using the CKD function and thus be the parent of many children keys. This derivation schema allows the formation of a tree of keys with an indefinite number of generations. Let's see more details about CKD functions. There are two types of extended keys. They can be extended private keys or extended public keys. And extended private key whose serialized version begins with x PRV, or another letter plus PRV is generated using the CKD private function. If the index pass to that function is equal to or greater than two to the power of 31, then it's a hardened derivation. And it said that the generated extended private key is a hardened child. Hardened keys have additional security features that we'll explain in short, it's possible to generate an extended public key by using the CKD public function. Attended public keys when serialized, begin with x pub, or another letter plus pub. It's also possible to generate an extended public key from another extended public key by using the CKD public function, two derivations aren't possible. Generating an extended private key from an extended public key and a hardened extended public key from an extended public key. So how do we get from extended keys to addresses? Starting with an extended private key, we extract a private key from it. A private key is part of an extended private key. So this extraction is a simple operation. Then by an operation called elliptic curve multiplication, we generate a public key from a private key. Finally, by hashing and encoding the public key, we obtain a Bitcoin address. There are different types of hashing and encoding of public keys to produce different types of addresses. We'll learn more about these operations in upcoming videos. We also use private keys to produce transaction signatures, to transfer Bitcoins to other addresses. Transaction signatures are produced by using the Elliptic Curve digital signature algorithm or ECDSA. You can also generate addresses with an extended public key. You do that by extracting the public key from it. Then a bitcoin address is generated from the public key through hashing and encoding, as explained before. Remember that a public key cannot be converted to a private key. Thus, it cannot be used to sign transactions and transfer Bitcoins. Now, let's understand the concept of derivation paths, starting with the master key, which has the depth of zero in a tree of extended keys. By deriving an extended key passing zero as the argument to a CKD function, we obtain an extended key with a depth of one. Repeating the process with the newly generated extended key, we obtain an extended key with a depth of two. Then we can repeat the process, passing one as the index and obtaining an extended key with a depth of three. From this last extended key, we can extract a public key and an address. It is said that this address has a derivation path of zero slash zero slash one because these were the index is used to derive the extended key that generated that address. Applying the same rationale. In this other example, we get an address with a derivation path of one slash zero slash two. This other example shows that you can use other numbers as indexes to CKD functions at any extended key in a tree of keys, allowing the generation of an almost infinite number of derivation paths and addresses. This other example shows the generation of a hardened child by using a single quote after the index, we can represent indexes that generate hardened children in a derivation path. Zero followed by a single quote, represents the first hardened index, which is two to the power of 3011, followed by a single quote is the second harden index and so on. This notation is used to facilitate the description of a derivation path so that we can use small numbers to describe them. It's important to add that. To spend Bitcoins from an address, it's necessary to produce a private key with the same derivation path used to derive that address. So you can use CKD public functions to produce extended public keys and addresses. But to spend funds from those addresses, you must use CKD private functions to produce extended private keys and private keys. Another characteristic of HD wallets and they're derivation paths is their death function relation. Each level in a tree of keys is assigned a function. Bi P32 defines the depth, one represents accounts depth two different chains and depth three different addresses. Bip 44 came with different definitions which are more used nowadays in most HD wallets. According to be at 44 depth one hardened extended keys represent different purposes. Depth to harden keys different coin types, depth three hardened keys, different accounts. Depth for defines if descendant addresses are to be used for change are not in a Boolean manner and death five represents different addresses. To better understand how that works in practice, Let's see some examples of derivation paths and their functions. And addressed with a derivation path of 84 quotes slash slash zero slash zero slash zero has a purpose to find and BIP A14. Vip 84 defines that addresses with a purpose of 84 must be P2 WP k h addresses, which stands for pay to witness public key hash addresses. We'll talk about different types of addresses in detail in upcoming videos. But in short, P2, WP k, h, aka segue, native addresses are the most common type of addresses in most updated modern wallets. This address also has a coin type of zero quote, which means that it's a Bitcoin address. It also has an account of zero, meaning that it's part of the first user's account. It's changed. Index is set to zero, meaning that it isn't a change address. Finally, it's address index is zero, meaning that it's the first users receiving address. The next example has a derivation path similar to the previous example, except that it's address index is one. So it's the second Bitcoin segue native receiving address of the first user's account, applying the same rationale. The third example is the first Bitcoin segue native change address of the first user's account. The index one in depth four indicates that it's a change address. The last example is similar to the first one, except it's purpose is 49 unquote. Vip 49 defines that addresses with that purpose must be P2 WP k-th nested in P2 SSH addresses. If that sounds complicated, don't worry, we will learn details about it in upcoming videos. Now, let's do an overview of HD Wallet features. With HD wallets, we can easily generate an almost infinite number of addresses from a single seed. This is great since we can avoid address reuse and loss of privacy. Hd wallets also allow multiple account structure where the parent extended private key has access to their children's key funds, but the children can transfer the parents funds. This schema can be useful for cases such as company owners having access to children's keys from their company's departments. Another useful feature that HD wallets allow is the creation of watch only wallets whose addresses can be generated and their funds audited using only extended public keys, but where no funds can be moved since no transactions can be signed. Another HD Wallet feature is the possibility of generating other cryptocurrency addresses from the same mnemonic seed. A list of different coin type indexes is described in slip 44, a BIP like proposal system from Satoshi labs, the company responsible for the truss or wallet. Another feature that HD wallets have is that their addresses and private keys can be reconstructed with their seeds and derivation paths. This allows you to import a mnemonic seed and passphrase into a compatible wallet to retrieve all your addresses and private keys. Security compartmentalization is another nice feature of HD wallets. If an extended private key leaks by accident, that would affect only the funds locked in addresses descending from the leaked key. Funds locked in a parent or siblings keys would be safe. Finally, HD wallets facilitate generating an organizing different types of Bitcoin addresses. Now let's see why hardened keys are necessary. During HD Wallet development, it was discovered that if an extended public key and a non-Hodgkin child private key from the next level leak, this would be equivalent to leaking apparent extended private key. This could lead to fund loss for every address descending from the leaked extended public key. Hence, pardon derivation was created to prevent that exploit from happening at account and lower depths. Finally, let's discuss how we'll implement the address derivation schema in our wallet. Will use the derivation path 84 quotes slash slash zero slash zero slash zero to generate our first receiving address. After receiving Bitcoins, the next receiving address will be changed by increasing the address index by one. So the next receiving addresses will have address indexes of 123 and so on. Doing so prevents us from using the same address to receive Bitcoins more than once. Will use the derivation path 84 quotes slash, slash, slash one slash zero to generate our first change address. After sending Bitcoins and receiving a change, the next change address is changed by increasing the address index by one. The same way we'll do for receiving addresses. You may ask why avoiding address reuse is important for two main reasons. First, by doing that, we increase our privacy. By doing so, if a third party discovers that an address belongs to us, that information won't replicate to other addresses we use. The other reason is security. If for some reason the private key for an address leaks that will affect only that address. The proverb that says, don't put all your eggs in one basket applies here. Having said that, we'll implement the derivation schema by first generating the extended public key with a path equal to 84 quotes slash zero slash zero slash zero for receiving addresses. And the extended public key with a path equal to 84 quotes slash slash zero slash one for change addresses. Then we'll derive their children extended public keys and addresses. By doing so, will generate all addresses we need without exposing any private keys to memory. So our main security policy is to avoid exposing seeds and private keys to memory as much as possible. Our private keys will be derived only when signing transactions using the same derivation pads used to produce the addresses from which such transactions are spending Bitcoins. 17. Creating our wallet’s extended public keys: In this video, we'll create the extended public keys that are wallet will need to create addresses. As we saw in the latest video, our wallets will initially have to extended keys, which will be the extended key for segment receiving addresses, and the extended key for segue change addresses. First, let's fix some issues with our GUI tests. If you try to run the create wallet test, now, you'll see that it will work. This is partly due to a premature instantiation of our new Receive tab controller class. To fix that, create a new package called Config inside the BYOD W test package. Then create a new class called test lazy being an IP configuration in it. This class will implement the bean factory post-processor will implement this required method with this code. This code will make every class during tests be initialized lazily. There's another piece of code that we must add in our create wallet test for it to work. We'll add to the FXML loader in the start method, the same builder factory we've set in our GUI started listener class. Now let's run our GUI tests. Great. Now the tests are working. We see that only they should cancel tests have passed and the other we still have to make it pass. Now, let's proceed to add the extended public keys to our wallet. The first thing we'll do is to adjust our create wallet service test will pass a valid mnemonic seed to this variable. You can obtain it on the Project and Resources page. Then we'll verify if the created wallet has extended public keys. Will assert if it has two extended public keys, since every wallet will have one extended public key for receiving addresses and one extended public key for change addresses. Now, we'll add a list of extended public keys to the wallet record. Let's create our extended pub key class. It will have a key and a type. Let's add them to a constructor. Both properties will have a getter. Now we'll create an address configuration class. First, let's create a new config package inside the API package. Then we'll create the address configuration class in it. Add the Configuration annotation to it. This annotation is necessary for Spring Boot to initialize all objects defined in this class during application startup. Now we'll create a domain class called address config. Actually, it'll be a record. It'll have an address type and the derivation path. Then create an enum called address type in the same package. It'll have two types, segment and segue with underscore change. Now back to the address configuration class. We'll create a beam for our segment address. In Spring Boot, a bean is just an object which can be injected into other project classes. Will instantiate this bean with these parameters. And add the Bean annotation to this method. Passing the segment string as its parameter will duplicate this method and modify it to be our change address config, change the Bean annotation parameter to segue change. The method name will be segue change config. The address type will be seg would change. And the derivation path will have a change index of one. Now, we'll use these configurations in our create wallet service. So let's inject a list of address configs into this class. By doing so, Spring Boot automatically identifies that there are two beans with the address config type, and it will inject both into this list. Now, in the create method will create a mnemonic seed variable. First, we'll change the mnemonic seed method parameter to mnemonic seeds string will then instantiate a mnemonic seed object passing the mnemonic seed string as its parameter. Then we'll create a master key, which is a type of extended private key. To do that, we'll call the mnemonic seed method to master key and pass the password and this constant as its parameters. But first, we have to update our Bitcoin Java version to 0.3, 0.0 in the POM file. Let's do it. Now. Click on Load Maven changes back to the create method. It now allows us to import the main net prefix constant, will pass its private prefix as a parameter. Now let's add this code, then I'll explain what it does next. This code starts converting the address config list into a stream. In Java eight or above, streams are used to apply functional operations to a collection of data. In this case, each address config from the list is being passed to this lambda function, which will use the extended pub key service will create next to return an extended pub key object. Each returned extended pub key will be collected in a list which will be stored in the extended pub keys variable, will then pass the extended pub keys list to the returned wallet. Now, let's inject the extended pub key service into this class. We'll have to create it. Now we can add it to the constructor. Now will create its create method. It'll return an extended pub key. Following the TDD. It's time to create a test for this method. Let's do it. Will create it inside the test API package. It must extend the specification class. Let's instantiate the extended pub key service here. We also need to add this piece of code to the setup method. And we'll create a test called should create extended key. When given a mnemonic seed and a master key derived from it. When we call the create method from the extended pub key service. Then we expect that the created extended pub key key is equal to the expected extended pub key. Okay, so how will we create these variables in gray? We'll pass them using the where clause like this. You may ask, where did I get these values? I got them on the EN Coleman io slash pip threonine website. This website is very useful for generating many types of extended keys and addresses. I'll copy and paste this mnemonic seed to the BIP 39 field on the website to demonstrate how it works. Immediately after we pasted the mnemonic seed, the tool calculated the root seed master key and extended keys to show the derived BIP AT for extended keys, click on this tab. We see that the expected pub key and the test is equal to this value on the website. By applying the CKD function to this extended public key with different numbers as indexes will later obtain extended public keys whose extracted public keys will be used to generate receiving addresses using the same website I created for more test cases. I'll paste them here and adjust the formatting. The last two test cases will generate extended pub keys that will be used to generate change addresses. You can copy them from this video's resources or make your own test cases using the Ian Coleman website. Using the where clause, the same test will run for each parameterization we created. Let's run the test. The test failed as expected. Let's now implement the method. First. We'll create a map here which will not address types to extended pub keys prefixes. Both address types will map to the same main net segment prefix. By doing so, we make it easy to extend this functionality if we need to add more addressed types later. Now in the create method will return a new extended pub key. Passing these parameters will pass the return of the CKD method from the master key, which will take a derivation path. False since it's not an extended private key and the prefix of the address type. Then we'll serialize the result. And the second extended pub key argument will be the address type and string form. Finally, let's not forget to add the service annotation here. Now, let's run the extended pub key service test again. Great, they've all passed. Now let's run our create wallet service tests. But first, let's make some changes to this test. We must add the security provider, which is necessary for the Bitcoin Java cryptography functions to work. We also have to set the correct arguments for the service. Let's build the address configs and the extended pub key service. Now let's run it. Great, the tests have passed. That means our wallet was created with a list of extended public keys of size two. Oops, the change index here is one. It won't affect this test since we're just asserting that the wallet will have to extended pub keys. But let's change it to one for the sake of correctness. 18. Generating Segwit Addresses: In this video, we'll create a dresses for each extended pub key that the Wallet makes. To do this, each extended pub key will be passed to the generated dresses method, which will create now. This method will set a list of addresses to the extended pub key record. Let's create this center. This list of addresses will be created by a new address sequential generator service that will create. It'll use a generate method which will take the extended pub key key and the extended pub key type. The address sequential generator service will have this name because it will generate a dresses with an increasing address derivation index. Let's inject the address sequential generator into this class and create it. Now, let's create its generate method which will return a list of addresses. Let's create the address record. This record will have an address field and an index field. Let's adjust the set addresses method from the extended pub key. It'll take a list of addresses and set the extended pub key addresses field. Let's create a test for the address sequential generator class. For now, it's method will return null. The test class will extend the specification class. We'll create a test called should generate 20 addresses, will use the address sequential generator in the wind block. So let's add it as a field to this class. When the generate method is called with these parameters, that is an extended public key in the segment type. Then we expect that the return that dresses list has a size of 20. You can copy the extended public key of this test from this lesson's resources. Let's instantiate the address sequential generator in the setup method and run the test. It failed as expected. Now let's implement the service will declare an extended pub key. Then inside a try catch block will and serialize the received key parameter. The ANS serialized method transforms the extended pub key key in the extended pub key object from Bitcoin Java will then wrap the IOException in a runtime exception in the catch block. Now we'll use the range method from the lungs stream class to loop from zero to an initial number of generated addresses variable that will set later. We'll inject this variable into this class. In the constructor will set a qualifier annotation for this variable, which will take the same variable name as a parameter, will change its type to hint, will map over each index and call the generate address method. So for each index, we'll call the generate address method, passing the return of the address generator factory Get method, the extended pub key and the index as its parameters. Finally, we will convert the result into a list. Let's create the generate addressed method. It'll take an address generator and extended pub key and an index. The address generator will be passed from an address generator factory, which will inject into this class and create now. Let's change the type parameter to address type. Now we'll create the address generator factory Get method. It'll return an address generator interface that will create now back to the generate address method from the address sequential generator. We'll first derive an extended child key from the extended pub key using the CKD method. This method will apply the child key derivation function we learned about two videos ago. It'll take an index which will define the child's derivation index. Now will return a new address record. It'll take the result of the generate method from the address generator. This method will take the extended child key and derive an address from it. The second address parameter will be the index. Now we'll add the generate method to the address generator interface. Now we'll implement the get method from the address generator factory. It'll return the result of the getMethod from an address generator map. This variable will be a field in this class and will be initialized in this class constructor. It'll be a map of strings as keys and address generators as values. In the constructor will pass a segment address generator service, which will create. Then we'll map each address type to the segment address generator. In the address generator map. The segment address generator will implement the address generator interface. Let's create the required interface method. Before implementing it, Let's create its test. It'll extend the specification class. Will instantiate the segment address generator here. In the setup method will add the security provider just like our other tests that need it. Then we'll create that should generate segment address test. In the given block will create an extended pub key using the extended pub key class on serialized method. The serialized method will take an extended pub key string, which will pass in the where block. Then we'll create an extended childcare calling the CKD method on the extended pub key variable. To this method will pass an index parameter which will pass through the web block. When the segment address generator generate method is called with the extended child key. Then we expect that the return address will be equal to the expected address. Now, let's use the where block to initialize the variables in gray will use test data they've taken from the E and Coleman website for it. You can copy these parameters from this lesson's resources. Let's run the test. It's failed as expected. In the next video, we'll learn more about sig what addresses. Then in the video after the next, we'll implement the segment address generator and the sequential address generator and make their tests pass. 19. Understanding Segwit Addresses and Introduction to Bitcoin Network Environments: In this presentation, we will learn more about Bitcoin segment addresses, which will be the default address type that our wallet will provide. So what is a Bitcoin segue, what address? Segment addresses are also known as segue native addresses back 32 addresses, segment version zero addresses or P2 WP k-th addresses, where P2 WP k h means pay to witness public key hash. Each of these terms is used to refer to the same thing. It was the most up-to-date type of Bitcoin address until November 2021. After November 2021 when the taproot upgrade was activated on the Bitcoin network, a newer type of Bitcoin address called taproot address, aka segue version one address became available. For now, let's focus on the segment address, which most modern wallet support segmented addresses became available in 2017 on the Bitcoin network after the segregated witness upgrade. This upgrade optionally allowed smaller transactions since the part of these newer transactions called witness is sent separately and is not included in the blockchain. The rules to generate segment addresses are described in VIP one-seventh three and are also implemented in methods of the Bitcoin Java library. Segment addresses allow Bitcoin senders to pay the cheapest fees for common transactions. The reason for that is because transactions that sends bitcoins to segment addresses are effective smaller in comparison to transactions that send to other types of addresses. But we'll learn more details about Bitcoin transactions in future videos. Because segment addresses are well-supported by most modern wallets and because they allow us to send cheaper transactions, we'll set them as the default address type of our wallet. Now, let's recapitulate a slide from the previous presentation about extended keys. In that video, we learned that we could obtain a public key from an extended private key or an extended public key. Then by hashing and encoding the public key, we could obtain an address. Now, let's see more details about this hashing and encoding process. Starting with a public key obtained as previously explained, by applying the SHA-256 and the right-hand 160 cryptographic hash functions to the public key, we obtain a public key hash with a size of 20 bytes. The SHA-256, combined with the right-hand 160 is called the hash 160 algorithm. Finally, the public key hash, combined with a prefix and a numeric version, generates a segment address through Beck 32 encoding. Back 32 encoding is reversible by the process called Beck 32 decoding. When building transactions, we must decode back 32 addresses to public key hashes before including them in transaction outputs. That's why this address type is also called pay to witness public key hash will revisit this topic in greater detail when talking about transactions for segment addresses. When Beck 32 encoding public key hashes, the version is set to zero when the prefix is set to BC unnamed net. Speaking about main net, let's quickly overview Bitcoin network environments. Each of these environments is a separate network with different blockchains and purposes, but similar rules. The Bitcoin may net is how it's called the main Bitcoin network. It's where the bitcoins have value. The blockchain is immutable and the mining difficulty is the highest. The test net environment is similar to the main net but has a lower mining difficulty and where bitcoins have no value, it is used to make tests in an environment where nodes interact while maintaining a shared blockchain. Test net has had different versions since it was created with different blockchains. Finally, the reg test environment is an individual network that can be run by any Bitcoin node user with a blockchain not shared with others. The blocks can be generated instantly, effortlessly and freely by the user. It is used to make faster and more automated tests in a controlled environment. Addresses on each network have different prefixes and are valid only in their environments. For segment addresses, these C is the prefix used for red dresses on the main net. Tb is used for addresses on the test net. And BCRP is the prefix used for red dresses on the reg test. As said before, version zero is used for segment addresses. Version one is used for taproot addresses. 20. Generating Segwit Addresses – Part II: In this video, we will make all tests we've created paths to do it will first implement the segment address generator method. To generate a segment address will convert an extended key to a public key. Let's change this parameter name to extended key. Then the public key will be converted to a segment address using this method as its parameter will pass a prefix. Let's pass this constant for now, which will make the address valid in the main net Bitcoin environment. Let's also add the service annotation to this class. Now, let's run the segment address generator test. It's failed because we have to bump the Bitcoin Java version to 0.4, 0.0, which contains the right CKD method for this operation to work. Let's do it. Click on Load Maven changes. Let's run the test again. Great, all tests have passed. Now let's adjust the address sequential generator test. We have two new constructor parameters that we have to pass to the service. First, let's instantiate the address generator factory. Passing a new seg would address generator. Then we'll pass 20 is the initial number of generated addresses. Now let's run this test again. Okay, we forgot to add the security provider in the setup method. Let's fix it. Run it again. Okay, The test has passed. Some services are missing the service annotation. Let's fix that. Okay, now let's add a new Bean, which will be the initial number of generated addresses for each extended key, will arbitrarily set it to 20. Now let's run our application to see how it's working. We got an error in the console indicating that our application is missing the security provider. Let's add it to the main method in the BYOD W application class. Let's run our application again. Okay, the error didn't occur, but the receiving address field is still missing an address. Let's change this. First. Let's run all our tests to check what other tests need to be fixed. The create wallet service tests are broken. Let's fix them. First, we have to include a valid address sequential generator object as its third parameter. Let's instantiate it passing 20 as the first parameter and an address generator factory as the second. Then we'll instantiate the factory just like the previous test. Now will ensure that the create wallet service is creating a wallet with two extended pub keys, each with 20 addresses. Will assert that the first extended pub key addresses field has a size of 20. Let's create a getter for this field. Will assert the same for the second extended pub key. Now let's run this test. Great, it's passed. Now let's make the create wallet test pass. Remember that we expect the receiving address TextField to contain an address after creating a wallet. So let's go to the receiving tab controller. Will add a method called initialize, which will run after the application initializes this controller. Then we'll inject the current wallet into this class. In the current wallet class will include a new simple string property field called receiving address, which will initialize right here, will create setters and getters for it. Now, let's go to the Receive tab. Fxml will add an Fx ID to the TextField. This ethics ID will be called receiving address, and we'll also add it to the receiving tab controller. Now, in the initialized method will bind the current wallet receiving address property to a listener that will take these three parameters in a Lambda function. In the Lambda body will set the receiving address field to the new value, which will be an address. Now in the update current wallet service will set the current wallet receiving address to the first address of the first wallet extended pub key. Now, when the receiving address is changed this way, it will trigger this listener that we've set here in the Receive tab controller. And hopefully it will add the address to the receiving address field. Now, let's run these tests to see if they work. Groups. It's failed. Let's find out why. Okay, the error happened because this method must be initialized, not initialized. Let's fix it and run the application. Great. The wallet did what we expected and fulfilled the receiving address field after we've created a wallet. Now, if we present this address to someone, they can send bitcoins to it. Now, let's run all application tests. Great, they've all passed. 21. Adding Support for Main Net, Test Net, and Reg Test Environments: In this video, we'll make a quick refactor in the segment address generator. Instead of hard-coding the main net segment prefix as the parameter for the segment address from compressed public key method will create a service that will allow us to create addresses for the test net and reg test environments. We'll call this service address prefix factory. It'll have a get method where we'll pass an address type and it'll return an address prefix. This returned value will be used as a parameter for the segment address from compressed public key method. Now we'll inject this service into this class and create it. Now we'll create It's GET method. To implement this method will need an auxiliary map, which will map address types to another map, mapping the three environments to their corresponding address prefixes. Let's build it and it'll become clear what I've meant. Now, let's change this parameter name to address type. In the getMethod will return an address prefix by using the address type as the first key. And a variable called Bitcoin environment as the second key of the map we've just created. The Bitcoin environment variable will be defined later in our application properties file, and we'll inject it into this class. Now. In the constructor, we'll add a value annotation before the variable to inject its value from the property file. Now, let's properly type the address type map field. Now let's add the Bitcoin environment configuration to the application dot properties file. We'll set it to reg test. Now let's fix some test files to handle the changes we've made so far. Beginning with the segment address generator test, will delete this part and instantiate the segment address generator in the setup method, passing in the address prefix factory as its parameter. Now we'll instantiate the address prefix factory, passing the main net constant as a parameter. Now let's run this test. Great, it continues working. Now let's fix the create wallet service test. We'll do the same as the last test. Just inject the address prefix factory into the segment address generator. Let's run the test. Great, It has passed. Now let's fix the address sequential generator test. We'll do the same as before. Now, let's run the test. Great, it's passed two. Now let's run all our tests. Some tests failed because the address prefix factory is missing an annotation. Let's fix it. Run the tests again. Great. All tests have passed. Now let's make this little refactor of adding static imports for these constants. Now, let's run the application to see what we've accomplished so far. Remember that now we expect that our wallet generates reg test compatible addresses since our Bitcoin environment property is set to reg test. Okay, as expected, our wallet generated addresses beginning with BCR t, since it's the prefix of segment addresses in the reg test environment. Now let's change the Bitcoin environment property two main net and run the application again. Now we have addresses beginning with BC, which is the segment address prefix for the main net. Finally, let's change the Bitcoin environment property to test net and try the same. Okay, Now we can generate addresses beginning with TB, which is the prefix for test net compatible addresses. Great, Now we have an easy way to change the network environment compatible with our wallet. 22. Preparing our Bitcoin Core Node for Communicating With Our Wallet: We now have a Bitcoin wallet capable of generating addresses compatible with different Bitcoin network environments which are reg, test, test net and main net. It's already possible to use these addresses to receive Bitcoins. To do that, you just need to show them to other bitcoin owners, which can use their wallets to send you Bitcoins, or most likely Satoshi, which are Bitcoin fractions. But for now, our wallet is enabled to detect these payments. So nothing will happen in our wallets user-interface after a transaction to one of our addresses. From now on, we aim to change that. We'll start to build a feature that will allow us to listen for transactions that arrive in our Bitcoin core node. Then we'll filter the transactions with outputs that match our current wallet addresses. Finally, we'll modify our wallet to show information about the amount of Bitcoin our wallet holds. Now let's make sure that our Bitcoin node is correctly configured and prepared to send and receive transaction information to our wallet. To do that, open the bitcoin.com file. The location of this file will depend on which OS you're using. Since I'm using Windows ten, my bitcoin.com file is located at the path on the screen. Open the file and make sure it looks like this. Let's review the meaning of each of these configurations. The first parameter, reg test is set to one to make our node run on the reg test environments. Since we'll use the reg test environment to help us develop our application. The second parameter, data there is set to the folder that you want the node to record blockchain and wallet information. I set mine to the colon backslash Bitcoin data, but you can choose any path you prefer. The server parameter is set to one to allow our node to receive API calls from our application. The RPC user and RPC password parameters can be set to whatever you like. For now, I'll choose BYUI W for both. But when using our application for real, It's highly advisable to choose safer values for these parameters. The TX index is set to one. This is necessary to enable our node to retrieve any transaction information from the blockchain. The fallback fee parameter can be set to 0.00 001. This value will be used for transaction fees that could not be calculated appropriately by the node. Finally, we'll set the z MQ pub Ratti x property to this value. This property sets the TCP address where the transaction information that arrives at the node goes. Our application, we'll listen to the same TCP address and capture new transactions sent to one of our Bitcoin addresses this way. Now, let's run our Bitcoin node with these configurations using the terminal, go to the folder where your Bitcoin application is installed. This depends on where you installed it and which OS you're using. Since I'm using Windows ten, I already opened my terminal and went to this folder on the screen. Now run the Bitcoin node by typing dot slash Bitcoin D and pressing Enter. Now your Bitcoin core node is running with the configurations. We said previously, we are now ready for the next classes. 23. Creating the Node Client for Creating and Listing Wallets: In this video, we'll create an HTTP client that will make some calls to our Bitcoin core node. This client will be necessary later when we'll use it to send and receive transactions. First, we will import a dependency in the POM file. This dependency is the Spring Boot starter web, which is necessary for the HTTP client implementation, will exclude a transitive dependency from this library by adding an exclusion tag. Excluded dependency will be the Spring Boot starter Tomcat. We'll do it to avoid starting a web server in our application. Now, click on the load Maven Changes button. Now let's make a configuration class for the node client. Create a class called Node client configuration inside the api dot config package at a configuration annotation to it. Now, we'll create some private properties in this class, all preceded by a value annotation. The first one we'll have this value annotation. And it'll be called node RPC URI. The next will have this value annotation. And it'll be the node RPC username will have another property with the following value annotation with the name equal node RPC password. All these properties will be injected from values will add later in the application dot properties file will also create a beam with the rest template class. It'll take a rest Template Builder as a parameter. We'll use this builder to return arrest template object with a root URI equal to the note RPC URI property. It will have a basic authentication with the note RPC username and the note RPC password properties. Then we'll call Build and return. Now let's assign the properties that will be injected into this class. Let's go to the application dot properties file. Let's assign the node dot RPC dot URI property the following address. This URI with port 18443 is the default URI for the Bitcoin Core Node RPC API for the reg test environment. As the node dot RPC dot username property, you have to choose the same value you've chosen for the RPC user configuration in your bitcoin.com file as the node dot RPC dot password property, choose the same value that you've set for the RPC password configuration in your bitcoin.com. Now inside the api dot services package, create the node package, incited, create the client package. Now let's create the node client class inside it. Let's add the service annotation to it. Now, let's inject the rest template bean into this class. We'll add the following method to make requests to the Bitcoin RPC API. As for its parameters, it'll take a string method, a parameterized type reference of type node client response, which will create next a string URL and zero or more objects. Let's now create the node pliant response inside the package domains dot node. Back to the node client method will instantiate a new node client request object. It'll take the method and params arguments in its constructor. Let's create this new class inside the domains, that node package. Let's create its constructor. Now, we'll wrap the request inside an HTTP entity object. Then we'll return the result of this method call, which will finally make a post request to the Bitcoin Core Node, will adjust the node client response class, will transform it into a record and add a result property to it will make a similar adjustment to the node client request, will transform it into a record and add these fields to it. We've forgotten to put a T right here. Now, we'll see how to make an important call to the Bitcoin Core Node API. Go to this website on the screen. It's a reference to the create wallet Bitcoin core RPC call. We see in the last line that this called takes a method key with the value create wallet in its body. Every Bitcoin API call has this format with the method key containing the name of the method. Bitcoin API calls also have a params key containing various types of data. In this case, it's value is an array with only one element. The wallet name, the create wallet called creates a wallet inside the Bitcoin Core and loads it. Many API calls we'll use later required. But our Bitcoin core node has a loaded wallet. Back to the node client. We can now understand why the make request method builds a request object which takes a string argument called method and a variable type argument called params. Now let's create a class called node create wallet client. Let's add a Service annotation to it. Will inject the node client into it. Now we'll create a method called create, which will take a string parameter. Now to make a call to the create wallet method of the Bitcoin Core API. We'll call them make request method of the node client like this, following the Bitcoin Core website reference. We'll now test this method for that. Let's run our Bitcoin Core Node in the terminal. Instead of using our traditional TDD way of doing things, we'll test this method differently. Back to the node create wallet client will create a method preceded by a post construct annotation. The Post construct annotation is useful for executing code when a spring application is starting. It's also useful for fast testing and Spring applications, almost like creating a main static method in a Java class, but with all the benefits of the beans managed by the application. Inside this method will call the create method passing any wallet name. Let's run the application. Okay, By watching the Bitcoin Core Node logs in the terminal, we see that our node created and loaded a wallet with the name we've said in the method call. With that, we know that our method is working and can remove this post construct method. Now, let's go to the Bitcoin Core website again and search for the list wallet DIR method. This method takes no parameters and returns all node wallets created so far. It returns a JSON structure with a wallets field. This field contains an array of objects, each one representing an existing wallet with a name field. Let's create a client for this method. We'll call it node list while it's client. Again, let's inject the node client into this class. Then we'll create the list all method, which will return a list of wallet names. Inside this method will call them make request method from the node client passing list wallet DIR as the method name. A new parameterized type reference and an empty URL. We won't pass any additional parameters. The returned object will be a node wallets record, which will create now, we'll create it inside the domains dot node package. This record will have only one field. It'll be a list of node wallets. Its name will be wallets. Let's create the node wallet record in the same package. It's only field will be a string name. Remember that we're modeling these objects based on this reference from the Bitcoin Core website. But wallets field on the node wallets record matches the name of this field on the JSON response of the API call. The same happens with the name field of the node wallet record. The wallets field from the response will have a list of objects with the name field. Each of these objects will be stored as NerdWallet records on the application back to the node list while it's client. From the list, all method will return a list of wallet names. To do that, we'll get the wallets from the node wallets. Then we'll call stream, then map passing a reference to the node wallet name field. Then we'll convert the result to a list and return it. Now, let's test the list all method using a method annotated with Post construct will print each element returned by the list all method call. We see by this line on the console that the application log the name of the node wallet we've created. Great. Now we'll implement another client to call the Node API method called list wallets. The difference between this method and the list wallet DIR is that the list wallets will return only the currently loaded wallets by the node. It also returns a list of wallet names without wrapping them in objects. Now let's create the list loaded method. It'll return a list of wallet names. To do that, we just have to return this method call. Now let's test it the same way we've tested the list. I'll call. We see from the console, but our application log two times the wallet name we've created. The first was due to the list all method call, and the second was due to the list loaded method call. Now, to see the difference between the two method calls, let's do the following. Terminate the Bitcoin Core Node application by pressing Control plus C on the terminal. Now start the Bitcoin Core Note again. Now let's do the same test. But first, add these lines before the method calls to differentiate between each method. From the console, we see that only the list all method call returned the created wallet. This demonstrates that after we start the Bitcoin Core Node application, we have to load the wallet will use, so we can make other API calls that need a node wallet loaded. But we'll see how that works in practice in the next videos. 24. Node Clients for Loading a Wallet, Get a New Address, Checking our Balance and Mining Bitcoins: In this video, we'll continue to implement more methods that will allow us to interact with our Bitcoin node from our application. The first one is a method that will load a node wallet. When you run your node, you need to load a wallet to be able to call many other node methods. So let's create the node load wallet client. As always, at a Service annotation to it. Now, we'll inject the node client into it. Then we'll create the load method, which will take the wallets name as its parameter. Then we'll simply call them make request method from the node client like this. Now, let's test this method using a post construct. First, let's remove this post construct method we've created before. Now we'll call the load method passing the name of the wallet we created. Before running it, let's run our Bitcoin node in the terminal. Okay, from the terminal logs, we see that our node correctly loaded our wallet. Now we'll create a useful service to load a node wallet if it already exists and is not loaded. If a wallet with that name already exists and is already loaded by the node than the method won't do anything and we'll return. Finally, if a wallet with that name doesn't exist, the method will create it and the node will automatically loaded since it loads a wallet after its creation. So in the services dot node package, Let's create a class name node load or create wallet service. Let's inject the following clients into it. The node create wallet client, the node load wallet client, and the node list while its client. Now let's create a method named load or create wallet. It'll take a name as its parameter. Inside it will call the list all method from the node list wallets client will store the result into a variable called all wallets. Then we'll call the list loaded method from the same client. And we'll store the result into the loaded wallets variable. Now, we'll add an if statement checking for the following condition. If this condition evaluates to true, it means that the wallet with that name already exists and it's loaded by the node. If that's the case, we don't need to do anything and can return. Now, we'll add the following if statement. If this statement returns true, it means that a wallet with that name already exists, but it's not loaded by the node. If that's the case, we'll call the load method from the node load wallet client passing the name of the wallet and return. Finally, if the code execution evaluates to false the previous IF statements, it means that a wallet with that name doesn't exist. In that case, we simply create the wallet, calling the create method from the node create wallet client and passing the wallets name. Okay, The method is finished. We'll use it in the next videos. Now let's create another useful client. It'll be called Node get new address client. As its name suggests, it'll be used to generate a new address from our loaded node wallet. So let's inject the node client into it. Now, we'll create a method named get new address. It will return the address in a string. And it'll take the wallet name as its parameter. Then we'll return to make request method call from the node client with these parameters. Notice that we've set the URL parameter to the string Wallet slash the name of the wallet. This is how we tell our node that we want an address from this specific wallet. Let's test this method. For that, we'll create the following Post construct annotated method will call the get new address method passing the name of a wallet we've loaded before as the parameter. If we call this method without loading this wallet First, it won't work and the node will return an error. We'll store the result of the method call in the address variable and we'll print it. Let's test it. The console log, show that it generated and printed a Bitcoin segment reg test address. Great. Take note of your generated address. We'll use it to test the method will implement next. Now, we'll create a method that will be used to mind some blocks producing Bitcoins to an address. This method only works on the reg test environment, and it'll be useful for us in some tests that need an initial number of coins to play with. Let's create a class called no degenerate to address client. As usual, we'll inject the node client into it. Then we'll create a method called generate to address. It'll take as parameters, a wallet name, a number of blocks, and an address. Then we'll call them make request method from the node client with the following parameters. Again, we'll pass the string Wallet slash the name variable. Then we'll pass the blocks parameter, which indicates the number of blocks you want to generate. Finally, we'll pass the address variable, which is the address that will receive the generated Bitcoins. Now, let's test this method. First. Let's remove the previous post construct annotated method. Now, we'll make this post construct method will call the generate to address method, passing the name of a loaded wallet. Again, if you pass the name of a wallet that doesn't exist or is not loaded, the method will work. We'll create 1,000 blocks and we'll pass the previously generated address. Let's run it. If we inspect our node logs, we see that it shows some lines indicating that our method called worked. The last client will create for this video will be called Node get balanced client. It will be used to check the balance of our wallets. Let's inject the node client into it. Then we'll create the get method, which will return the number of bitcoins our wallet holds. It'll take the wallet name as an argument. Then we'll return this method call. Like the previous methods. This method will send the Wallet slash the wallet name as the URL parameter to define the return of the balance of this specific wallet. Let's test this method using a post construct. Will call the get method passing the name of a previously loaded wallet. Again, this method won't work. If the past wallet isn't loaded by the node, then we'll store the result of the call in a variable and print it. Let's test it. Great. From the logs, we see that we now have thousands of Bitcoins. Of course, these bitcoins are only valid in our reg test environment. In the next videos, we'll use them for testing. 25. Sending Bitcoins From the Node to the Application: In this video, we'll build a client that will allow us to send Bitcoin from our node wallet to any other red dress we want. Then we'll use all the clients we've built so far to create a test to receive bitcoins to an address of our application wallet. So after removing any previous post construct methods from previous lessons, Let's create a class called nodes sent to address client. Now let's inject the node client into it. Then we'll create a method named send to address as parameters or wallet name and address and an amount. Then we'll call them make request method from the node client passing the following parameters. Again, we'll pass Wallet slash the wallet name variable. It'll be the wallet from where the bitcoins will be sent. It will also take an address to where the bitcoins will be sent and an amount, which is the amount being transferred in Bitcoins. Let's test this method. First, make sure that your node is running. In my case, I'll have to start it. Now, let's make sure that our node wallet is funded with Bitcoins so that we can send bitcoins from it will call the get balanced method to check that. But this time we'll call it from the terminal. Every API method that we can call from our application can be called from the terminal using the Bitcoin CLI application. Open another terminal window, go to the same folder where your node is installed. Then type the following command to load a previously created wallet and press Enter. In my case, after load wallet, I have to type testing wallet name, which is the name of the wallet I created between double-quotes. Okay, Now that our wallet is loaded, we can enter other commands that require it. So let's enter this command to check our wallet balance. Well, it's balanced, is zero. It looks like every time we restart the note and the reg test environment, our funds vanish. No problem. We'll fund our node wallet. Now using the command line interface. To do that, first, we get a new address from our node while it like this. Then we call the generate to address command to generate 1,000 blocks and destination the block rewards to the address we've just generated. Now, let's call the Get balanced command again. Great. We see that our wallet now contains thousands of Bitcoins. Again. Now back to the node send to address client. Let's make a post construct method to test the send to address method. Will call the send to address method, passing the loaded wallet name. The second parameter can be any reg test address. We'll use the Bitcoin CLI to generate a new address. Then we'll pass it as the second parameter to the send to address method. Then we'll choose one as the amount. Let's run it. Okay, if we call the Get balanced method from the Bitcoin CLI, we'll see that our balanced barely changed. There's a small difference between the current balance and the previous balance. This difference is due to the transaction fee since we transferred a Bitcoin to an address from the same node wallet, if we call the get received by address method from the CLI. Passing the address, we've sent a Bitcoin to the number zero as the second parameter, which indicates that we want the balance, including unconfirmed transactions, we obtain the value one, which is the amount we transfer it to this address. Okay, we've finished our CLI playing for now. Let's remove the Post construct method. Now inside the BYOD w dot gooey package will create the receive Bitcoin test. This test will need a lot of things in common with the create wallet test. So we'll make it extend an abstract class we'll create called GUI test. This class will have all methods common to any GUI test we need. So let's create it. In the create wallet test will cut all properties and methods except the last and transfer them to the GUI test class. Then we'll add the Spring Boot test annotation to it, and it'll extend the application spec class. We'll remove the same annotation from the create wallet test and make it extend the GUI test class. Let's remove all unused imports. Now will make all private properties in the GUI test protected and will include this security dot add provider call into it's start method. Finally, we'll make this class abstract. Now, let's test the create wallet test to see if everything continues to work as before on error occurred. My intuition says that it's an IntelliJ idea bug. To solve it, Let's call them maven clean lifecycle method. Let's also rebuild the project and run all application tests. All tests passed. So it was only an IDE bug. Now, let's continue building our receive Bitcoin test will inject the following beans into it. The node send to address client, the node load or create wallet service. The node get balanced, client. And the node get new address client. *****. It looks like we forgot to add the word client and the node get new address. Let's rename it. Now, let's create a setup method which will run before this class is tests. Inside it will call the load or create wallet method from the node load or create wallet service as its parameter will pass the string, test wallet and store it in the constant. Then we'll call the method create balance if necessary, that will create next. This method, we'll first check the balance of the test Wallet using the node get balanced client. If the balance is less than 100 Bitcoin, then we'll get a new address from the test wallet. Using the node generate to address client, which we've forgotten to inject into this class, and we'll do it now. We'll generate 1,000 blocks, thus funding our wallet. And we'll make this method private. With this method running before tests, we guarantee that we'll always have Bitcoins that we can use in our tests. Now, we'll create a test called should receive Bitcoin. It's when block will be similar to the wind block in the create wallet test, we'll call the following methods to create a new wallet. We'll click on the Receive tab. Then we'll look up the value in the receiving address input, which at this point will contain the first address of our wallet. And we'll store it in the address variable. Now, we'll call the send to address method from the node sent to address client. As its parameters will pass the test wallet name, the address we've generated with our application wallet, and the amount one. After receiving Bitcoins, we expect our application wallet to detect the transaction, but this process won't be immediate. It will take some seconds for that to happen. For this reason, we'll use a method called wait-for from test fx. As its parameters will pass ten, which will be the timeout value for the weight. The timeout in this context is the maximum time the application will wait before throwing a time-out exception. The second parameter indicates the time unit of the previous parameter. So we'll choose seconds. The last parameter will be a callback method. Inside it will look up a GUI component with an ID of addresses. Table, will query it has a TableView and store its result in a variable of the same type. Then we'll return the comparison between the TableView item size and one. This TableView with an ID of addresses table will be a component that will store a table containing rows, each with a funded address of our wallet. The callback method will run in a loop and will only stop if the comparison returns true or if the timeout is achieved. In summary, this weight for method call will do the following. It'll check if there is a table with one row filled in the screen. This will happen when our wallet detects that one of its addresses received a transaction and it filled one table row with that information. It will wait 10 s for that to happen or less. If the table gets filled with a row before, then we'll copy the table view lookup line and paste it here. Then block will check again if the TableView item size is equal to one. Let's store this timeout value in a constant. Now, let's run the test. As expected. The test failed because it didn't find the addresses table. In the next video, we'll start to implement this feature in our wallet. 26. The Addresses Table: In this video, we'll create a table showing information about our addresses. That table will contain each funded address, their amount in Bitcoin and the minimum number of confirmations that transactions to those addresses have. The idea is to fill that table just after our wallets detect transactions sent to our addresses. So in the main window dot FXML, if we click on the Scene Builder tab, we'll see that it's showing a message to download Java FX, even if we downloaded it before. This is happening because this IDE feature doesn't handle external components well, such as the Receive tab controller. So to be able to use the Scene Builder will create a new FXML file called playground. In this file, we'll paste all the contents from the main window dot FXML. But instead of using external components such as the Receive tab controller, will inline them in the file. So inside the resources dot FXML package, create the playground dot FXML file. Delete all its content. Then copy all the content from the main window dot FXML and paste it there. Now we'll substitute the content from the tag Receive tab controller with the content from the Receive tab dot FXML. And we'll modify the FX root tag with the tag tag. And let's delete its type attribute. Let's import the insets tag. Now, when we click on the Scene Builder, we can use it normally. Now, let's add a new tab pane to the VBox component. Now, let's delete one of the created tabs. Let's rename the remaining tab two addresses. Let's give it an FX id of addresses tab. Now, inside the Content tab, we'll add a table view component. Unfortunately, for buggy reasons, the Scene Builder does not allow us to add a table view to a tab. No problem. Let's add it using the text editor. Let's also add an Fx idea of addresses table here. Let's go back to the Scene Builder. It started to work again. Now we have an empty table inside the addresses tab. Now we'll add three columns to the table. We'll rename the first column two addresses, the second to balance, and the third two confirmations. Then we'll click on the table and change this configuration to constrained resize. Now, every column is the same size and they occupy the entire table area. Now let's click on each table column and de-select. They're editable and sortable checkboxes. Now, for each table column will set their max width to 100. This is just a necessary trick so we can adjust their size. Now, let's adjust their size using the mouse like this. The addresses column must be bigger since addresses will occupy a larger space, balance and confirmation columns can have the same size. Back to the text editor. Let's change the pref height attribute of the tab pane to 355. Returning to the Scene Builder, we can see that it looks better. Let's also change the placeholder message, which shows when the table is empty. To do that, we just need to add an empty label tag inside this placeholder tag. Now that our table component is ready in the playground, Let's create an FXML for it. Let's name it addresses table. Let's delete all it's boilerplate code. And let's copy all the content between the TableView tag and paste it there. Now, instead of using the table view tag, Let's use the FX root tag referencing the table view plants and the type attribute. Let's import the remaining tags. And let's add this XML and S attribute here. Now back to the playground FXML. The addresses tab is missing an FX ID. Let's add to it. This idea was already used in the VBox component by mistake. So let's remove it from there. Now, let's copy these four lines and paste them into the main window. Now, let's add the closing tags and the tags we copied. Now we'll delete the table view tag and add a content tag in its place. Inside it will add an addresses table controller tag. Now let's create this controller. Let's add a component annotation to it. It must extend the table view class with the address class as its type parameter. Now back to the main window. Let's import the recently created controller. In the addresses table controller, let's create a constructor. It will take an FXML parameter with a value annotation. The value annotation will reference the addresses table FXML. The second constructor parameter will be an application context object. In the constructor's body will create a new FXML loader object, initializing it with these parameters. Then we'll set its FXML controller to this. And we'll set its route to this. Then we'll call load on it. And we'll add a throws statement to the constructor. We need to do one more thing for it to work. Inside this if statement in the GUI started listener add the following code. This is needed for Java FX to build the addresses controller tag correctly. Now, let's run our application to see how it's working. Great, alright, dresses table is looking nice. In the next videos, we'll make it work for our wallets. 27. Importing our Application Addresses to Our Bitcoin Node: In this video, we will make our wallets start to interact with our Bitcoin nodes so that we can receive information about transactions sent to our addresses. Remember that when we create a wallet, we generate the first 20 addresses for it. But our Bitcoin node doesn't know yet about are generated addresses. Are Bitcoin node must know about our addresses to actively send information about their transactions to our application. Therefore, we need to import our wallet addresses to our node. For that, we'll create a new node client that will be responsible for it. So inside the node dot client package will create a class called node multi import address client. Like other clients, it will have a service annotation and we'll inject the node client service into it. Before we create its method, Let's check the Bitcoin Core website documentation for its API will use the import multi-method from the Bitcoin node API. We see here that it takes an array of objects as a parameter. Each object can have a lot of different keys, but we'll use just three of them. The script pub key, which can take as a value and object with an address which the node will import a timestamp, which is the date when the address was generated. This parameter is important to determine how far in the past the node will search for transactions with that address in the blockchain, will also set the watch only parameter to true since our node will only use our addresses to monitor transactions in the blockchain, but won't be able to sign transactions with those addresses. Only our application wallet will be able to sign outgoing transactions, but that's a topic for future videos. Back to the IDE, let's create a method called import addresses. It'll take as parameters a wallet name, a list of addresses, and a wallet creation date. Now we'll build a params object that will model the import multi-parameter we saw on the Bitcoin Core documentation. This object will be a list of a new object we'll create called node multi reimported dress params. Let's create it now. It'll be a record and we'll create it in the domains dot node package. It will have a new node multi reimported, respire him script pub key object will create. It will also have a long timestamp field and a Boolean watch only field. Let's create this class as a record. It will have only an address field. Back to the node multi import address client. Since the import addresses method receives a list of addresses, we must use the following code to convert it into a list of node multi reimported dress per ohms. Then we'll use the make request method from the node client like this. Now, let's test this code using a post construct method. We'll import addresses to the node wallet with the name testing wallet name. And we'll use the current date as the wallet creation date. As the addresses. Will use these three reg test addresses, which you can find in this class as resources. Before running this code, let's run our Bitcoin Core Node and load the wallet with the same name we'll use. To load it will use the Bitcoin CLI, just as we did in previous videos. Okay, By looking at the Bitcoin node logs, it seems like it worked. The last line of the log shows that the rescan was completed. The rescan happens by default after we import addresses into the node. The rescan search for transactions in the blockchain for the recently imported addresses. In this process, the node searches for transactions and blocks created up to 2 h before the date we've passed as the timestamp parameter. Let's remove the Post construct method. Now inside the gooey dot listeners package, Let's create a class called created wallet important listener. It'll have a component annotation, and it will implement the application listener class with a parameter of created wallet event. Let's implement its method. Just like the created wallet listener, this class is method will be called after a wallet creation. Let's inject the node load or create wallet service into it. Now, in the non-application event method will call the load or create wallet method from the injected service passing the name of the event wallet as the parameter. Let's also inject the node multi import address client into it. Let's make both injected services final. Now we'll call the import addresses method from the last injected service. But first, let's create a variable for the event wallet and use it in this method. Now in the import addresses call, Let's pass the wallet name. The wallet get addresses method, which will create the wallet created at property, which we will also create in the wallet record. Let's create the createdAt date property, will create it using the change signature IDE feature. Let's use a default value of new date. By doing so, the IDE will automatically add this third parameter in every instantiation of a wallet it finds in the project. Let's click on Refactor and import the date class. If we go to the create wallet service, we see that it added a new date as the third parameter in the wallet instantiation. This will make the wallet have the current date as its creation date. The create wallet dialogue controller will use the created wallet in the public event method call. This will trigger the on application event method call. Now let's create the get addresses method in the wallet record. It'll return a list of addresses by taking the addresses from its extended pub keys, like this. By calling the flatMap method on the stream of extended pub keys and returning the extended pub key addresses stream on this call will obtain a stream of all Address Objects from the wallet. Then we'll call the map method to convert the stream of address objects into a stream of address strings. Finally, we'll call the two list method on the result and return a list of all wallet addresses in string format. Okay, now after creating our wallet, we expect that our application loads were creates a wallet with the same name in our node. After that, our application will import all generated addresses into our node. Let's run our application to test it. Let's create a new wallet. I clicked on the Okay button, but it seems that nothing had happened. Let's check the node logs. Okay, after some time, it says the rescan was completed and the wallet finished its creation. In the next video, we will make this process asynchronous by running the calls to the node in another thread. By doing so, the gooey won't be stuck and the wallet creation will be smoother. Cia. 28. Calling our Bitcoin Node Asynchronously: In the last video, we made our Bitcoin node create and load our application wallet and importance addresses. But this process was taking some seconds and it was blocking the graphical user interface. In this video, we'll fix that by making the communication with the node run in another thread asynchronously inside the BYU OWL package. Let's create a new package called Config. Inside this package, Let's create a class called async config. This class will contain every configuration related to async code execution in the project. Let's add a configuration annotation to it. And an enabled async annotation to. This annotation is important to enable asynchronous features in the project. Now, let's create a method annotated with the Bean annotation. It'll return an ExecutorService. Let's call it default executor service. It'll return a new single thread executor from the executors class. This bean will provide a thread whenever we want to execute code in it. It'll be a single thread, which means that if two or more code sections are trying to run in this thread simultaneously, one section we'll have to wait for the other to finish running. We choose to use a single thread because it makes processes easier to control in our application and allows us to avoid race conditions more easily. Now, let's do a little bit of code refactoring inside the gooey dot services package. Let's create a class called import wallet service and add the service annotation to it. Let's create a method called import wallet. Will transfer the code from the created wallet import listener to the import wallet service. Let's also inject the required services into this class. And let's add the wallet as a parameter to the import wallet method. In the created wallet import listener. Let's remove all this code. Let's inject the import wallet service into it. Now in the non-application event method, let's just call the import wallet method from the injected service passing the event wallet as the parameter. The import wallet method contains the code that we want to run asynchronously. To make it asynchronous, we just have to annotate this method with the async annotation, passing the name of the bean of the executor service we've created. We also must return a value from this method, which will allow us to manage this async call from the method color. The returned value will be a future. A parameter type of void will return a new async result object passing null to its constructor. Now, let's test creating a wallet. But first, let's run our Bitcoin node. If it's not already running. We see that our wallet was immediately created, but when we check the node logs, it is still loading and importing the wallet addresses. Great. The node has finished the rescan. So our wallet load and import processes are asynchronous. Now let's do some fine tuning. Let's go to the created wallet import listener. In the non-application event method will record the return of the import wallet method and store it in the result variable. We'll make this variable a private field of this class. Now, we will add the following if statement. Before calling import wallet. If the result variable is not null, then we'll call the cancel method on it, passing true as its argument. This is necessary because if we try to create another wallet when one hasn't finished importing first, we'll need to cancel the import process of the first created wallet. Let's do another fine tuning in the GUI application class will override the stop method. Inside it, will add the following code. This code will ensure the thread created by our default ExecutorService gets closed after we close our application. Now, there's another issue with our application. When we create a wallet without our Bitcoin node running, the calls to create or load a wallet and importance addresses will fail. Let's see how that works in practice by closing our Bitcoin node and running our application. After creating a wallet, it seems our application is running normally, but that's because the exceptions and other threads aren't being reported. Our wallet couldn't have communicated with our node while our node was off. When it tried to do that, an exception was thrown by the thread and a thread finished running. Let's fix this. What we want our application to do when it creates a wallet is to indefinitely try to communicate with our note. If for some reason it couldn't do it after the first try, do it, we'll use a Spring Boot annotation called retrial. This annotation makes the annotated method execute again, if it throws an exception. To use it, we must add the following dependencies to our POM file. The first is spring retry, the second is spring aspects. Now in the import wallet method, let's add the retrial annotation will also pass some parameters to it. The first will be the exception expression, which will set as at sign-in port wallet service dot should retry open and close parenthesis. This will make the application called a should retry method before each retry and only retry if this method call returns true. We will also add the max attempts parameter, setting it to the max value integer constant. This setting will make this method to be retried indefinitely. Finally, let's add the backoff parameter, setting it to the backoff annotation, passing the delay parameter of 1,000. This will make the application waited 1,000 milliseconds or 1 s before executing the method at each try. Now let's create this should retry method. Its return type will be a Boolean. The method will return the negation of the result of that is interrupted method call from the current thread. This call will return true if the current thread is not interrupted or false otherwise. Therefore, if the application closes or if another wallet is created between each retry, this thread will be interrupted and the import wallet method won't be retried anymore. One more thing for the retrial annotation to work, we must add the enabled retry annotation in the async config class. Let's do it. Now. Let's run our application with our node closed and do some testing. Let's create a new wallet. Now, let's start our node. From the node logs, we see that the created wallet was loaded and the rescan has been completed. Now. Now let's create another wallet. We see from the node logs that it also has been successfully created, loaded, and imported. Great. 29. Listening for Transactions from the Node with ZeroMQ: In this video, we'll continue to integrate our wallet with our node. The next step in the integration is to listen to the messages are node sends when it receives a transaction to an imported address. For that, we'll create a class called node task, which will have a method that will run in an infinite loop in another thread after the application starts. This method will continuously listen for transactions that are node receives to any of our applications current loaded addresses. When it finds one, it will make our application handle it accordingly. So let's create a new package called node in the BYOD W package. Inside it will create a class called gooey started node listener. Let's add a component annotation to it. This class will be a listener triggered by the gooey started event published when the application starts. So it will implement the application listener with that event as its type parameter. Let's implement its method. Let's add the new node task service will create as a private field in this class. Let's create the new service. Now, let's inject it into the GUI started node listener. In the non-application event method will call the node task run method. Let's create this method in the node task. Let's add the service annotation to this class. Now, we'll add one dependency that the node task will need in the POM file. It'll be the hero MQ library. Let's click on the load Maven Changes button. This library manages the communication between the application and zero MQ. Zero MQ is a message broker that receives messages from the Bitcoin node. These messages will be sent to a local URL and collected by our application through zero MQ back to the node task. Let's add the async annotation to the run method. Let's pass the note executor service as its parameter. This will make this method to run asynchronously in another thread managed by the node executor service we're going to create in the async config class, let's create the node executor service. Like the default executor service, it will be managed by a new single thread executor. Now, let's inject the socket object from zero MQ into this class. This field will be called subscribers since it'll handle a subscription to the zero MQ message broker. In the run method, Let's set the subscriber receive timeout to 1,000. This will add a one-second delay each time our application queries zero and Q to search for messages. Let's call this subscribers subscribe method, passing the bytes of the string rod TX as the parameter. This will make our application only listen to messages related to rob Bitcoin transactions that are node sends to zero. Mq will also call the subscribers connect method, passing the variable z MQ URL to it. Let's inject this variable into this class. We'll add a value annotation to its constructor argument, passing this string as the parameter. Therefore, this variable value will be injected into this class through an application property named z and q dot URL will set now, the value of this variable has to match the same value we've set in our bitcoin.com file. So let's copy the value set for the z MQ pub rock TX bitcoin.com configuration and paste it here. Now, back to the node task run method will create our non stopping loop. Let's create a while loop. It will run while the current thread is not interrupted. Inside the loop, we'll call the subscribers wreck the STR method and store the result in the topic variable. The wreck of the STR method query zero MQ for any message and returns a string if it finds one. In our case, that string will contain the name of the topic, which will be equal to ra TX for raw transactions. Then we'll add an if loop checking the topic variable. If its content is different than Ratti x, then we will call continue making the loop run again from the beginning. If not, then we'll call the subscribers wreck V method and store the content in the contents variable. The wreck of the method is similar to the rec VNTR, but returns a byte array instead of a string. At this point, that byte array will contain the raw transaction or node sent to zero MQ. Now, we'll convert the byte array in the Bitcoin Java transaction object. To do that, we'll use the following code. We must add a throws IOException statement to this method signature. In the GUI started node listener. We also need to wrap the run call in a try-catch block like this. Back to the run method. Now we'll use an application event publishers service to publish an event. Let's inject this service into this class. First. We'll pass a new transaction received event to the publish event method. To the transaction received event instantiation will pass this and the transaction object before creating the new event class, let's add a missing piece for this method to work. Let's create a new class called node configuration. Let's move it to a new node dot config package. Let's add a configuration annotation to it. In this class, we'll add some beans for the node tasks injected Socket object to work. The first bean will be the Z context being. The second beam will be the zero MQ socket. It'll be named subscriber. And it'll take in its method the Z context created above. It will return the Z contexts to create socket method call passing the socket type sub constant as its parameter. Now back to the node task will create the transaction received event, will create it in the node dot events package. Will pass the node task to the super constructor and we'll inject the transaction into a private transaction field. Let's also create a getter method for the transaction. Now, let's create a listeners package in the node package. Inside it. Let's create a transaction received listener for this event. Let's add a component annotation to it. This listener will be responsible for filtering receive transactions by identifying if they have addresses belonging to a currently loaded wallet. It will implement an application listener with the transaction received event as its type parameter. Let's implement its method. In this method, let's get the event transaction and store it in the transaction variable. Now, the first thing we'll do is to identify the output addresses from the Received Transaction. To do it will create the addresses variable, which will be a list of strings. Then we'll assign the result of the following expression to it. Will map the transaction outputs passing an address parser parse method. Now, let's inject and create the address parser service. Let's create it in the node dot services package. Let's add the service annotation to it. Now, let's create the parse method. It will return a string and take a transaction output as its parameter. This method will be responsible for extracting the address from a transaction output back to the transaction received listener will convert the result into a list. Then for test purposes will print all the parsed addresses. Now let's implement the parse method. The first thing we'll do is to get the transaction script pub key and assign it to this variable. Don't worry, we'll explain what a script pub key is and other transaction details. In the next video, we'll return the result of the following switch statement. If the type of the script pub key is equal to the constant P2 WP k, h, which is the type of our current wallet addresses. Then we'll return the script pub key P2, WP k h address method call. Passing the address prefix factory Get method call as the parameter passing the Segway constant to it. The default case statement will be an empty string. Let's inject the address prefix factory into this class. Now, let's do some testing. My Bitcoin node is already running. Make sure yours is too. Let's go to the receive Bitcoin test class and run it. The test failed because we haven't modified our GUI test yet to consider the addresses table controller. Remember that our GUI started listener handles the issue of using this if condition. We could use the same if condition in our fixed, but let's do it in a neater way. Let's go to the GUI started event. Let's change the GUI application type to object. Will simply publish the gooey started event in our GUI test class, the same way we did it here in the GUI application class. In the GUI test class, let's remove all this code. Now, let's copy this line of the GUI application and paste it here. Let's remove all these unused imports and this unused private field. Now, let's run the receive Bitcoin test again. Our test failed, but we see here on the test logs that are application printed two addresses. This happened because we printed the addresses of the transaction our test made to one of our wallet addresses. One of these addresses is ours, the other is a change address of the sender. Great. We see that what we've done so far has worked. Let's do some refactoring in the GUI test class. Let's remove these unused imports. In the GUI application class. Let's include this code line which will make our note executor service thread stop running after we close our application. In the next video, we'll learn more about Bitcoin transactions to prepare us for what comes next. 30. Bitcoin Transactions: Inputs, Outputs, Scripts, and the UTXO Set: In this presentation, we will learn some concepts about Bitcoin transactions. There'll be useful to understand better the implementation of receiving Bitcoins in our application wallet. Let's recap what we've learned so far about Bitcoin transactions and gradually add complexity to our understanding of them. So a Bitcoin transaction is commonly used to transfer Bitcoins from person a to person B. A Bitcoin transaction can be composed of many inputs and many outputs. A transaction input indicates the previous Bitcoin owner or the sender of the transaction. A transaction output indicates the receiver of the coins or the owner of the coins after the transaction is published. In this image, we have a simple transaction with one input and two outputs. It says that one Bitcoin was transferred from John, who signed the input of this transaction. Output zero indicates that 0.9 Bitcoins were sent to marry. I'll put one indicates that 0.099 Bitcoins were sent back to John as the change. Bitcoin amounts cannot be divided in inputs. Since John wanted to send 0.9 Bitcoins to marry, but he only had one Bitcoin. He needed to create a change output back to Himself. But its amount is 0.099 Bitcoins, not 0.1 Bitcoins, as you could expect. The difference, which is 0.001 Bitcoins, is the transaction fee needed for the transaction to be included in the blockchain. So from this image, we take three lessons. The sum of bitcoins in inputs cannot be less than the sum of Bitcoins and outputs. The Bitcoin amount in inputs is fixed while it can be chosen at will and outputs given that it satisfies the previous rule. Finally, the transaction fee is the difference between the sum of Bitcoin amounts in inputs and the sum of Bitcoin amounts and outputs. Increasing the complexity. We also learned about the fields that are part of a transaction input and a transaction output. And input always refers to an output from a previous transaction. It does that by using the previous transaction ID and the output index of the previous transaction. It would be redundant for the input to have an amount field. These two fields are enough to identify any transaction output in the blockchain. Uh, transaction input also must contain a valid signature produced using the same private key used to derive the address from the output to which the input refers. Notice that a transaction input doesn't have a field indicating it's Bitcoin amount. That's because it's amount is automatically equal to the output amount to which it refers a transaction output has two fields. One is the address which is used to receive bitcoins. And address is an encoded string and by itself doesn't reveal the owner of the coins. That's why we consider Bitcoin pseudonymous. The other field is the quantity which indicates the Bitcoin amount locked by the address. Now, let's increase the complexity one more time explaining what exactly transaction inputs and outputs contain. The transaction input has the following fields. The previous transaction ID, which is a unique hexadecimal string, is obtained by hashing the previous serialized transaction. The previous transaction output index is an integer number. Since a transaction can have many outputs, a specific output can be unequivocally identified by its transaction ID and output index. The scriptSig or witness field. The input signature is added to the scriptSig field in non Segway transactions. In Segway transactions, the signature is added to the witness field, which does not count to the transaction size. The transaction output has the following fields. The script pub key. Script pub key contains the decoded address and the quantity field which determines the Bitcoin amount locked by the address. Now, let's see how to build a Bitcoin transaction through an example. Our objective in this example is to send 1.5 bitcoins to this address. Before starting, we have a confirmed transaction, which means that it's already stored in the blockchain. It has an output with two bitcoins, which I'm able to spend since I have a private key that was used to create its address, and that can be used to sign a transaction input for it in a new transaction. So let's build a new transaction, will add an input to it. The input we'll refer to our transaction through the previous transaction ID field. The previous transaction output index is zero, since it's the output index of our output. The scriptSig field is composed of a signature produced using the same private key used to produce the address of our output. And a public key, which is the same public key derived using our private key. The transaction will have two outputs. The outputs zero will contain a script pub key field comprised, among other things, of the hashed public key of the address. We want to send our bitcoins to. This hash is obtained by Beck 32 decoding the address. Back 32 is the algorithm used to encode the hash of a public key, producing a sec what address? Base 58 is another algorithm used to do the same for non segment addresses. Since we're sending bitcoins to a segment address, we must use Beck 32. The quantity field of this output will be equal to 1.5, which is the Bitcoin amount we want to send, will need a second output for the change. Its script pub key will contain a hashed public key obtained by Beck 32 decoding and address that belongs to us, that is derived from a private key we have control over. It's quantity will be 0.49 Bitcoins, which added to 1.5 of output zero is equal to 1.99. So we have a difference of 0.01 between the sum of Bitcoin amounts in inputs and outputs. That difference will be the transaction fee needed for the transaction to be included in the blockchain by a minor. We talked about scriptSig and script pub key, but didn't explain what those things really are yet. Bitcoin has a smart contract language called script. A smart contract is a fancy way to refer to a program written on a transaction and executed by the Bitcoin network. The scriptSig and the script pub key fields are made with script language code. This language is interpreted by combining the scriptSig of an input and the script pub key of an output and checking if the scriptSig satisfies the conditions encoded by the script pub key. You can consider this mechanism like a key and lock mechanism, where the scriptSig is the key to unlock the script pub key, which is the lock. If a scriptSig is valid for unlocking a script pub key, then you can spend the output funds locked by it. A scriptSig has this name because it usually contains a signature that satisfies a specific script pub key condition. Likewise, the script pub key has this name because it contained a public key in the first Bitcoin transactions. But in theory, any arbitrary script code can be included in both fields. The unique constraint for a script program to be valid is that it returns true at the end of its execution. There are many types of script programs, also known as script types. One of these is the pay to public key hash used in simple non sequitur transactions. Let's see how it's executed in this example, all Bitcoin scripts are executed similarly, what changes between them or the code being executed? So beginning with our confirmed transaction from the previous slide, here, we show only its output zero with its script pub key content in the gray box. In pay to public key hash transactions, the script pub key field is composed of opcodes and the public key hash. And opcode is a script language instruction. They're identified by the letters OP at their beginnings. Up underscore equal, e.g. compares two elements and returns true if they're equal. Every script pub key and pay to public key hash scripts has this code sequence only differing in their pub key hashes. Now we have our new transaction, which is the same as the previous slide. This time we show only its input here. It's scriptSig content is in the gray box. In pay to public key hash scripts. The scriptSig has only a signature followed by a public key. Now let's see how both fields are combined and executed. First, the scriptSig content of the input is concatenated with the script pub key content of the output referred by the input in this order. Then each element from the combined script is pushed into an execution stack from left to right. If the element is an opcode, it may act on other elements in the stack, processing them and adding other elements to the stack. So let's see how this script is executed. The signature is the first element from left to right. Therefore, it's pushed into the stack first. The next element is the public key, and it's also pushed into the stack. The next element is the up underscored up opcode. Up, underscored up encodes an instruction to duplicate the last element added to the stack and add the copy to the stack. The next element is the op underscore hash 160 opcode. It removes the last element added to the stack, applies the hash 160 function to it and adds the hashed result back to the stack. So we end up with the public key hash at the top of the execution stack. The next element to be added to the stack is the public key hash. Next, we have the op underscore equal verify opcode. This opcode removes two elements from the top of the execution stack and compares them if they are equal than the script continues executing. If not, it's execution fails and the transaction is invalidated. This step is important because it validates that the public key of the scriptSig is equal to the public key used to generate the address of the output it's spending from. The last element from the script is the op underscore check sig opcode. It removes two elements from the top of the execution stack and validates if the first element is a valid signature for the second element for this specific transaction, if it's a valid signature, a Boolean true is added to the stack. If it's invalid than a Boolean, false is added to the stack. Finally, after all the script elements were added to the execution stack, the transaction input would be considered valid if the last added element is true. Otherwise, the transaction input is invalid. This process must be repeated for every transaction input. For a transaction to be considered valid, all its inputs must be valid. There are many script types. The pay to public key script was the first Bitcoin script created, but today it's deprecated and rarely used. The first Bitcoin transactions contain the script type. Instead of using the hash of the public key, It's script pub key, use the public key directly. The pay to public key hash script was exemplified in the last slide. It was the most commonly used script type since the rise in relevance of Segway transactions in the last years. Today, it's still commonly used, so it's good to know about it. The pay to witness public key hash script is the currently most used script type in Bitcoin transactions. The reason for this is that it's advantageous to use it since transactions with it are smaller and thus have a smaller transaction fee. This script type has a smaller script pub key and it's scriptSig content is moved to the witness field, which does not contribute to the transaction size. For these reasons, we will implement this script type in our wallets first, the pay-to-script hash is another script used mostly for multi-signature transactions. Multi-signature transactions require more than one signature to spend an output. The pay to witness script hash is the witness version of the pay-to-script hash script. Its signature is moved to the witness field. So it has the same advantages that the pay to witness public key hash script has. The pay to witness public key hash wrapped in a pay-to-script hash script is also known as nested segment or rap segment. It's also commonly used and its main function is to make old wallets that are not native segment compatible, compatible with Segway transactions. We'll learn more about the script type later in the course. Finally, another script type is the pay to tap root script. It's the most recently created script type, adding more capabilities and privacy to Bitcoin transactions. Now, let's see a summary of how to build transaction inputs and outputs from the viewpoint of a wallet, starting with a mnemonic seed and a passphrase. Through a cryptographic algorithm, we combine both and obtain a root seed. Then through a series of transformations were master keys and extended keys are produced. We obtain many private keys. Here we show only one of these private keys. The same transformations can also produce public keys. A public key can also be produced from a specific private key, which we show here in our example. From a public key, we obtain an address using the hash 160 function and encoding the result through Beck 32 encoding in the case of segment addresses or base 58 encoding in the case of non segment addresses. To receive Bitcoins, you show your address to someone so that someone can send bitcoins to it. When a sender puts your address in his wallet and sends a Bitcoin amount to it, his wallet will decode the address back to a public key hash. Then it'll build a transaction with an output containing a script pub key equivalent to that address. The script pub key type will depend on the type of the address. In this case, the wallet identified that the address type is compatible with a pay to public key hash script. After receiving Bitcoins to that address, the receiver can spend them through a new transaction. The new transaction input fields contents will depend on the script pub key type that will be spent. In this case, the wallet will build a transaction with an input containing a scriptSig with a signature generated using the same private key that had originated the public key that originated the address that received Bitcoins previously. Details of signing a transaction we'll see in a future video. The public key cited previously will be added after the signature in the scriptSig field. Finally, the input will also reference the unspent transaction output using the previous transaction ID and the previous transaction output index fields as explained before. Now let's learn the important concept of the UTXO set. Remember that UTXO means unspent transaction output. Bitcoin has the important characteristic of not allowing double-spending. In other words, you can only spend Bitcoins from unspent transaction outputs. The UTXO set is the set of all currently existing UTXOs. This set is stored by nodes in a separate database which allows for fast retrieval by wallets. The UTXO set is being constantly updated with each new transaction adding and removing outputs to and from the set. Utxos are outputs that were never referenced in any input yet. Therefore, the UTXO set contains all coins available to be spent. The number of bitcoins in an address is equal to the sum of all Bitcoins from all UTXOs whose script pub keys referenced the decoded address. So the Bitcoin Core Node provides an API method called list unspent that returns all UTXOs that reference the addresses that you passed as parameters to it. By using the list unspent method, you can easily calculate the balance of an address and discovered transaction information such as the UTXO transaction ID and index, as well as its script pub key. So you can build transaction inputs to spend your Bitcoins from the UTXO. After you spend the UTXO, it's removed from the UTXO set. Now let's see a diagram explaining how our application will detect incoming transactions and will let us know about the bitcoins will receive. That will be the last slide of this presentation, which has introduced a lot of complex information. Don't worry if you didn't absorb it all at first. Along the course, we'll be reusing the information learned in dive deeper into it, so we'll have many opportunities to grasp it better. Now, back to the diagram. Here we have rectangles representing the application are Bitcoin node and the Bitcoin network. Transactions are created and broadcasted by nodes from the Bitcoin network. These transactions, when confirmed, are already stored in the blockchain. When not confirmed, they stay in the temple, a database containing all unconfirmed transactions. Every node has a copy of the mental transactions are eventually detected by our nodes which had already imported our application wallets and addresses. Through zero MQ notifications, the transactions are sent to our application. When our application has a wallet loaded, it will filter out all receive transactions not containing any of its addresses. Then it will send a list unspent call to the node, passing as parameters all addresses from the receive transactions that remained after the filtering. The node will return all UTXOs related to those addresses. Our wallet will then parse these UTXOs to calculate the Bitcoin balance for each of its addresses. Then we'll show the obtained information in the addresses table. 31. Obtaining UTXOs from the Node and Filtering Them: In this video, we will implement the list unspent client that will enable us to collect information about UTXOs after we receive transactions. So inside the node dot client package, Let's create the node list unspent client. Let's add a Service annotation to it. Let's also inject the node client into it. Now let's create the list unspent method. It'll return a list of UTXOs, which is a record we'll create. It'll take as parameters a list of addresses, and a wallet name. Let's create the UTXO record in the BYOD w dot domains package. The UTXO will contain the following fields. The TX ID, which is an acronym for transaction ID. The vout field, which represents the output index, the address, the label, which we won't use right now. The script pub key. The amount which represents the Bitcoin amount, the conformations which will contain the number of conformations that the UTXOs transaction has. The number of conformations of a transaction is the number of blocks that were added to the blockchain after the transaction was inserted in a block and this block was added to the blockchain. This number includes the block containing that transaction. So if a transaction has two confirmations, it means that it was already included in a block. That block was added to the blockchain and another block was added after that. Let's add two more fields. These fields won't be used for now, but they can be useful in other types of transactions that we'll see later in the course. They are the redeem script and the witness script. Now back to the node list, unspent client will call the node client make request method and store the result in the UTXOs array variable will pass the following parameters to the method. The last three parameters will be part of the poems list of the Bitcoin node API. The first is the minimum number of conformations that the return UTXOs must have. The second is the maximum. Since we want all UTXOs will set zero as the minimum and the max integer value as the maximum. The third parameter is the list of addresses. Now, we'll convert the resulting array into a list using this code and return it. Now back to the transaction received listener. Let's remove this line of code because it was just for testing. We'll test the node list unspent client. Let's get the UTXOs for these addresses. Let's inject the client into this class first, the list unspent method will pass the addresses variable. The second argument will be the wallet name from the receiving Bitcoin test. Let's copy it and use it as the second parameter. Now, let's add this line to print every UTXO obtained on the screen. Now, let's run our Bitcoin node if it's not already running. Now, let's go to the receive Bitcoin test and run it. In the test logs, we see that it printed a UTXO with all its data. Notice that its address is the same as the receiving address of our wallet. Rewind the video to check it. The amount is one, which is expected because it's the same Bitcoin amount sent and the test, it has zero conformations because no blocks remind after the node since the transaction. Now let's delete these lines because they were only for testing. Let's also remove the injected client from this class. Now, we'll add a filter to this stream. We want to process only transactions from the currently loaded wallet by the application. This filter will be responsible for that. The filter will check if the address is not empty. If the current wallet contains that address. So let's inject the current wallet into this class. Then we'll call the get addresses as strings method. Then we'll check if it contains the address. Oh, a letter S was missing here. Now let's create the get addresses as strings method. It'll return a list of strings. The returned value will result from calling the get addresses as strings method on the addresses field we'll create. So let's create this field. It'll have a new addresses class as its type. And we'll initialize it right here. Let's create it in the observables package. Let's also create its get addresses as strings method. First, we'll add a private addresses field. It'll be a map where the key type will be an address type and the type of the values will be another map. The second map will be a linked HashMap with strings as keys and address as the type of its values. We'll use this data structure to store the addresses. The reason to use this data structure is that it enables us to separate and query the wallet addresses by address type. The second map is a linked HashMap because this type of map maintains the insertion order. Finally, the second map allows us to query the list of address objects by their address string sequences. Now in the get addresses as strings method will return the following code. The flatMap function will be used to get all addresses in the second map key set and return a stream containing all of them. Then we'll convert the resulting string into a list. Ok, Now we can use the get addresses as strings method to get all addresses created for the current wallet. But one thing is missing. We also have to populate the addresses field from the addresses class. To do that, we'll add the following code in the update. Current wallet service will set the current wallet addresses, passing the wallet extended pub keys as the parameter. Now let's create the current wallet set addresses method. It'll call the set addresses method of the addresses field, passing the extended keys as the parameter. Then we'll create this method in the addresses class. Let's add the following code to it. We'll use the collect function to obtain a map from the extended pub keys. Inside it will add a to map method call. Its first argument will build an address type using the extended pub key type field. This argument defines the key of the resulting map. The second argument will define the value of the map and it'll contain the following code. Again, by combining the collect and to map functions will set it as a linked Hashmap. The keys will be the extended pub key addresses string sequences, and the values will be there corresponding address objects. Finally, the filter part of this stream is completed. In the next video, we'll use what we've built to continue building the receiving Bitcoins feature C, yeah. 32. Updating the Current Wallet Addresses: In this video, we'll get in process the UTXOs from transactions coming to our wallet. So in the non-application event method, in the transaction received listener, Let's add the following if statement. If the addresses list is not empty, then we'll call the update method in the update UTXOs service we'll create. This method will take the addresses, the current wallet name as parameters. Let's inject this service into this class. Now, let's create this service in the GUI dot services package. Let's add the service annotation to it. Back to the transaction received listener. Let's finish injecting the service. Now, let's create the update method in the update UTXOs service. We'll add an async annotation to this method and run it in the default executor service thread. The reason for running this method and another thread is that it'll call the list unspent node API method, which may be slow. So we'll run it asynchronously to avoid blocking the UI. In the update method will call the list unspent method from the node list unspent client. Let's inject the client into this class. We'll pass the addresses and the wallet name as parameters to the list. Unspent method will store the result of the method call in the UTXOs variable. Now, we'll inject a new update, current wallet addresses service into this class. Let's create it in the GUI dots services package. Let's finish injecting the service. Then we'll call the update method passing UTXOs as the parameter to it. Let's create this method. Let's add the services annotation to it. Now, we'll add the following code to create a map where the keys are addresses and the values are lists of UTXOs containing those addresses. To do that, we'll call the collect method on the UTXO stream, will pass the collectors grouping myMethod call to it. Passing the UTXO address method as its parameter. We'll store the returned value in the group UTXOs variable. Then for each group UTXO key value pair will set the corresponding address balance. It's confirmations and market is used. Let's implement the set balance method. Will return the sum of all UTXOs amounts using this code. Using the map to double method on the UTXO list stream, will obtain a stream with all UTXO amounts from the UTXO list. To obtain their sum will simply call the sum method on the result. Now, let's inject the current wallet into this class. Then we'll call the current wallet set address balanced method, which will create passing the address and the sum as its parameters. Let's create it. Inside it will call the addresses set address balanced method, passing the same parameters to it. Then we'll create this method. Inside it will call the get addresses as map method, which will create. Let's create it. It'll return a map where the keys are addresses, strings, and the values are addressed as objects. By using the following code will return a map containing all addresses. By calling the string method on the addresses values will obtain a stream containing all maps of the addresses private field. Then with this flatMap method call will convert the stream of maps into a stream of map entries. Finally, using the collect method on the resulting stream and the two map method with these parameters will obtain the desired map. On the result of the get addresses as map call will call the get method to get an address object by its address string. Then we'll set the address balance to the sum variable. Now, let's create the set balance method in the address record. Whoops, we can't add setters in a record, so we'll have to convert the address record into a class. Let's do it with a little help from our IDE. Let's remove these methods because we won't need them. Let's create the balance center now. And remove the final keyword here. In the address sequential generator. Let's add zero as the third parameter in the address instantiation here. Let's also change the getters name, making them start with get. Now in the update current wallet addresses service, let's create the set confirmations method. Confirmation. In this case, we'll refer to the address balance and it'll be defined as being equal to the number of conformations of the UTXO with fewer conformations for that address. E.g. let's say that an address has a balance of two Bitcoins, with each Bitcoin coming from a different transaction. One of these transactions has two confirmations, the other has just one. In this case, we'll consider that the addresses balance has one conformation. To accomplish that, we'll use the following code. We'll obtain a stream containing all confirmations of the UTXOs list passed. To obtain this stream, we'll call the map too long method on the UTXO list stream, passing the UTXO confirmations method reference as its parameter. Then by using the Min method and the good is long method will return the minimum number of confirmations in the stream and store it in the confirmations variable. Then we'll pass the confirmations and the address variables to the current wallet set address confirmations method call. Now let's create this method in the current wallet class. It'll call the addresses set address confirmations method, passing the same parameters that received. Let's create this method in the addresses class. We'll use the get addresses as map method to get the address and set its conformations. Now, let's create the set confirmations method in the address class. We'll use it to set the confirmations field we'll create. Let's create this field and add it to the constructor. Then let's add this parameter to the address sequential generator class in the address instantiation. Finally, let's create the mark is used method in the update current wallet addresses service. One of the objectives of our wallet and many others is to avoid reusing addresses when receiving Bitcoins. For privacy reasons. To do that, we must first market dresses that had transactions to it as used. The mark as used method will be used for that insight. It will call the current wallet market dress. As used method will create passing the address as its parameter. Let's create it. Inside it will call the mark is used method from the addresses class passing the address to it. Then we'll create this method. Inside it will use the get addresses as math method to get the address and market is used. Finally, let's create the mark is used method in the address class. Here will simply set the used fuel is true. Let's create this field in this class. 33. Showing Address Information in the Addresses Table: In this video, we'll finally connect everything we did in the last lessons to display our addresses information on the screen. So in the observables package will create the address row class. As the name suggests, this class will model a row in the address table. Let's create the following fields in this class, each for a column in the address table. The first field will be a string property named balance, will instantiate it here with a new simple string property. The next field will be a long property named confirmations, and it'll be instantiated with a new simple long property. The last field will be a string property named address. It'll be instantiated with a new simple string property. Now, with the help of the IDE, let's create getters for each property. Notice that when making getters for Java FX property fields, the IDE creates two getters, one for the property and the other for the content of the property. Now, let's create the following constructor for this class. Okay, Now that we've modeled the address row, will create code to populate it when updating our addresses. To do that, let's go to the update current wallet addresses service. In the update method, after marking the address as used, let's call the set address row method on the current wallet, passing the address as the parameter. Then let's create the set address row method. To implement this method will add the address rows field to this class. Let's create the address rows class in the observables package. Let's instantiate it here. Now we'll call the set address row method on the address rows property will pass an address object to it. This object will be obtained from the addresses field using the get addressed method we'll create passing the address string to it. To create this method will simply select this code snippet and extract a method from it using the ID. Let's substitute all code occurrences with this method, and we'll make the generated method public. Now back to the current wallet class. Let's create the set address row method in the address rows class. To do that, we'll create an address row variable calling the method on the address row class, passing the address object as its parameter. Let's create the form method in the address row class. It'll return a new address row, instantiating it with these parameters. Let's create the good confirmations method in the address class. And now we can use it here. Notice that here we're simply creating an address row object by converting the address field values to the address row field values. Back to the address rows class. We'll create the address road set field in this class. It'll be an observable set with the address row as its type parameter. Will instantiate it here with a new observable set wrapper, passing a new linked hash set to its constructor. This object will publish an event for each new address inserted or removed and will be necessary to update the addresses table as the current wallet receives new transactions. Now we'll call the address row set remove method, passing the address row as its parameter. Then we'll call the add method on it, passing the same address row as its parameter. You may wonder why we are removing and adding the same address row in the set. Well, this is a bit of a hack. If we don't remove the address row first and insert an address row that is already in the set. The observable set won't publish an event indicating that an address row was added to it. There's another thing we have to do for this to work. When we remove an address row from the set using the remove method, this method will use the equals method from the address row to define which address row it will remove from the set. We'll consider the two I dress rows are equal if they have the same address. Therefore, we must implement the equals method in the address row class. Let's do it. We'll add the equals and hash code methods using this IDE feature. Make sure this checkbox is checked to generate methods using getters. Now, we'll choose to only use the address field to generate the equals method. And the same field to generate the hashCode method and select the address field here to define it as non null. Okay, the IDE has generated the equals and hash code methods. Now let's go to the addresses table. Fxml will add FX IDs to each table column tag. The addresses. Table controller will need these FX IDs to bind and manipulate these columns later. First the column address, then the column balance, and finally the column conformations. Now let's go to the addresses table controller will add the following fields, each corresponding to one tag with an ethics ID in the addresses table, FXML. The names of these fields must be equal to the FX IDs of the tags. They're bound to. First the addresses table, then the column address, the column balance, and the column confirmations. Now we'll add the initialized method to this class. Remember that initialized methods in Java FX controllers are called When the framework is initializing these controllers. In this method, we'll add code that will bind the addresses table and their columns with our address role observables. To do that, we'll call the set items method on the addresses table as its argument will pass a new filtered list. This is necessary because we want to show only addresses with a balanced greater than zero in the addresses table. As the first filtered list parameter will pass the current wallet observable address rows. So let's inject the current wallet into this class. Then we'll call the get observable address rows method on it. Let's create this method. It'll return an observable list with address row as its type parameter. Then we'll return the good observable address rows method call on the address rows field. Let's create this method in the address rows class. Inside it will return the address row list field we'll create. Let's create it. This field will be instantiated here with a new observable list wrapper passing a linked list as its parameter. Now, we have to make the observable list respond to insertions and removals of address rows in the address row set. We'll do that in the class's constructor. First, we'll create a set change listener variable. We'll set it as this lambda function. The change parameter here represents an insertion or removal of an address row in the set. If the change was a removal, then we'll remove the removed element from the address row list. If the change was an insertion. Then we'll add the added element to the address role list. Finally, we'll add this listener to the address row set using this method. Now back to the addresses table controller. The second parameter of the filtered list is used as a filter condition to display rows. It will be a lambda function with an address rho parameter. The function body will be this code which will check if the address row balance is greater than zero. That way, we achieve our objective of only displaying addresses with a balanced greater than zero. Now, for each column field, we have to set a cell value factory that will be used to populate each cell of the addresses table. For that, we will use the following code. The property value factory will be used to get each address real property and bind its value to its corresponding cell. It knows what address real property we want to bind to the column by matching the name we're passing as its parameter to the name of the property. There's one more thing we must do for our receive Bitcoin feature to work properly. Let's go to the current wallet class in the set addresses method, which is called when a new wallet is created, we have to include this code to ensure that the address rose from a previously created wallet gets cleared. We'll call the address rows clear method, which will create. To do that, let's create it. Here. We'll simply call the clear method on the address row set and the address row list. Now let's test our feature. Make sure your Bitcoin core node is running. Let's go to the receive Bitcoin test and run it. Great, it worked. Notice that the first row of the addresses table was filled correctly with a balance of one Bitcoin as expected. Good job. In the next videos, we'll add more test cases to ensure our receive Bitcoin feature is working correctly in different scenarios. 34. More Test Scenarios For Receiving Bitcoins and Avoiding Address Reuse: In this video, we'll add more test cases to ensure our receive Bitcoin feature works correctly in different scenarios. The first additional scenario we'll test if the same address can receive Bitcoins from two transactions, one Bitcoin from each. We'll check address balance gets updated to two bitcoins. So let's copy the content of this method and paste it below. Let's modify the test name to should receive Bitcoins in two transactions to the same address. Now, let's select this code and extract a method from it with the help of the id. Let's name it, send Bitcoin and weight. We'll call this method two times since we want to send to transactions to this address. Let's modify the send Bitcoin in weight method including the following code. We'll check if the address in the first row of the table has a balanced equal to the expected total amount parameter. Let's add this parameter to the method signature. It'll have a default value of 1.0. In this method call, let's add 2.0 as the second parameter, since we expect that the address balance will be equal to two. Let's add two to the wallet name. There is a problem with our test environment. In reg test, it's only possible to mine 15,000 blocks with block rewards. Therefore, in this method, it's too much to mine 1,000 blocks when calling the generate to address method. Let's only call it if the test wallet balance is less than 50 and will generate only 150 blocks for each call. That way, we avoid the need to reset our reg test environment too often. Let's also substitute this code with the send Bitcoin and wait method. Now, let's make our tests a little more resilient to race conditions. I've noticed that sometimes these tests send bitcoins to our application wallets before they were fully loaded. Therefore, these transactions weren't captured by the application and the tests fail for that reason. So after creating a wallet and before sending Bitcoins to them, Let's call the sleep method with these parameters. The sleep method call will make the application wait for 10 s before sending Bitcoins enough time for the new wallet to get loaded completely. Depending on your computer, you may need to increase the timeout constant. Now, before running the tests, I'll reset my reg test environment. I need to do that because it already generated 15,000 blocks and the block generation isn't producing Bitcoins anymore. So I'll go to the folder where the blockchain is stored and remove the reg test folder inside it. In your case, you can find what folder it is located by checking the data DIR value in your bitcoin.com file. Now, let's run our Bitcoin node and run our receive Bitcoin tests. Great, the tests have passed. When we receive Bitcoins in our wallet, we want that the next receiving address gets changed. That way we avoid reusing addresses. It's important to use only one address for receiving transaction so that a third party can easily track how many Bitcoins you have and what addresses you transact with. To cover this scenario, Let's create the following test. Copy the last test and paste it below. Let's rename it to should receive Bitcoins in two transactions, two different addresses. Let's change the created wallet name to my test wallet three. Now before the second send Bitcoin and wait method call, let's add this code to query the receiving address field again and store its content in the next address variable. Now, change the first parameter of this method to the next address variable. And we expect that the total Bitcoin amount for this address will be equal to 1.0. Also, we expect that the table items size will be equal to 21 row for each address. So let's modify this method to accept the expected table size as a parameter. Let's add this parameter to it with a default value of one. Will substitute this value here to wait for the table number of rows to be equal to it. And we'll substitute the table dot items index for the expected total size minus one to wait for the last row in the table balance to be equal to the expected total amount for that row. Finally, let's parameterize the third argument of this method call to two. Let's run our tests. As expected. The third test failed because we haven't yet implemented the feature of changing the receiving address after using it. Let's do it now. So let's go to the update current wallet addresses service. Inside this for each block, let's call the update receiving address method we'll create. It'll take the address as its parameter. Let's create it. The first thing we'll do is to call the get addressed type method on the current wallet. Passing the address as its parameter will store the result of the method call in the address type variable. It's important to know the address type of the substituted address, since it has to be substituted by an address of the same type. So let's create this method on the current wallet class. It will simply call the addresses get addressed type method. We'll create passing the address as its parameter. Let's create it. Now. We'll call the get addressed method and return its address type. Let's create the get address type method in the address class. Inside it will return the address type field we'll Create. Let's create this field and add it to the constructor. Let's also fix the address sequential generator to add the last argument to the address instantiation. We'll add this address type as a parameter to this method. And we'll include the address type in this method call by calling the value of method on the address type class. Now back to the Update Current wallet addresses service will calculate the value of the next address index by calling the fine next address index method on the current wallet, passing the address type as its parameter will store the result of the method call in the next address index variable. Let's create this method. Here. We'll call the fine next address index on the addresses field, passing the address type as the parameter. Let's create this method in the addresses class with the following code, will get the last address used in store it in the address variable. Will get all that dress objects with the given address type and get a stream from it. Then we'll sort the obtains stream by using the sorted method with the following parameters. Will use the comparator dot comparing method, passing the address get indexed method as the first parameter and the reverse order comparator as the second. That way we'll obtain an address stream reverse ordered by their indexes. Now, we'll filter the stream to obtain a string containing only used addresses. To do that, let's create a getter for the used field in the address class. They used getter is called is used because that's how the IDE names Boolean getters back to the addresses class will pass the addresses used method as the prompt to the filter method call. Now we'll call the fine first method on the result. To obtain the first used address and the reversed ordered stream, which is equal to the last used to address. What if no used addresses found. In this case, we'll use the or else method to return null. We'll add the following if statement. If the obtained address is null, then we'll return zero as the next index. If not, we'll return the last address index plus one. Now back to the Update Current wallet addresses service will get the next address by calling the get address ID method on the current wallet. We'll pass the next address index and the address type as parameters. Let's create this method in the current wallet. Will return, they get address ID method call on the addresses field, passing the same received arguments as its parameters. Let's create this method in the addresses class. Will get all that dress objects with the given address type. Then we'll convert it to a list. Then we'll get the address by index. To do that, we need to change the address index type to a long object, not alone primitive type. And then we'll call the int value, passing it as the getMethod parameter. Now we'll return the address string from the obtained address. Now back to the Update Current wallet addresses service will simply set the current wallet receiving address as the obtained next address. Let's do one more thing before testing our code. Remember that the codon, this class will run in a new thread. In Java FX, it's good practice to run code that modifies the UI only in the main thread. To do that, Let's call the platform dot run later method passing a Lambda function to it. Let's move these two lines to the body of the lambda function since they cause changes that will affect the UI. Now, let's run our receiving Bitcoin tests again. Great. The receiving address field was updated after receiving funds and the tests have passed. In the next video, we'll continue improving our tests and add one more test scenario. C, yeah. 35. Improving Receiving Bitcoin Tests. Receiving More Transactions Than Addresses: In this video, we'll continue improving our tests and add one more important test scenario for the receiving Bitcoin feature. One thing is missing in our tests. We don't know yet if the right addresses are being generated and if they are respecting the derivation path index sequence. To check that, let's create the address is valid method. Then block of the first test called the address is valid method passing the address, the mnemonic seed and the expected address index, which in this case is zero as its parameters. Let's create this method. It'll return a Boolean. Let's set the correct parameter names. Here. We'll create a new mnemonic seed object and store it in the mnemonic seed variable. Let's rename the mnemonic seed parameter to the mnemonic seed string. Now we'll instantiate the mnemonic seed object passing the mnemonic seed string as the constructor parameter. Now, let's create the master key with the following code. Will call the two master key method on the mnemonic seed object, passing an empty string as the first parameter and the main net private prefix as the second. Now let's create the extended pub key string with the following code. We'll use the extended pub key service. So let's inject it into this class. Then we will call the create method on it, passing the master key as its first parameter. The second parameter will be a concatenation between part of the segment address derivation path and the index parameter. Let's change the index parameter type to the integer class, so we can call the toString method on it. The third parameter will be the address type Segway constant. Then we'll call the get key method on the result. Now, we'll obtain the extended pub key object from the Bitcoin Java library by using the extended pub key on serialized method, passing the extended pub key string as its parameter will obtain the expected address using the segment address generator. Let's inject it into this class. We'll then call the generate method on it, passing the extended pub key as its parameter. Finally, we'll return the result of comparing if the expected address is equal to the address parameter. Now let's add the address is valid method call to check the addresses in the other methods of this class. In this method, Let's add it two times. The second time we'll check if the next address is equal to the expected address with index one. Let's run our tests. Great, the tests have passed. Now we know that the addresses are being generated correctly. Now let's create another test. The next test will try to transfer more transactions than the number of generated addresses. Remember that we've set the initial number of generated addresses to 20. So we must check what happens when all initially generated addresses are used. But running a test with 20 transactions would take a lot of time. So we'll change the initial number of generated addresses in the test environment to three later to speed things up. So let's copy this method and paste it below. Change its name to should receive Bitcoin in seven transactions to different addresses with three addresses generated in our wallet and seven transactions in this test, our wallet would need to generate four more addresses than the initial number for this test to pass. Let's change the created wallet name to my test wallet. For now, we'll create a properties file for the test environment to change the initial number of generated addresses for our tests. So let's create a resources path inside the test package. Select the Resources option below. Inside it will create a file called application test dot properties. We'll copy the content of our application dot properties file and paste it here. Now let's set the initial number of generated addresses property to three. Now let's go to the address configuration class. The initial number of generated addresses method is currently returning 20 will inject this value into this class from the properties file using this value annotation and this private field. Now in this method will just return the created field. Now to use properties from the application test dot properties files in our tests. Let's go to the GUI test class. Add this annotation to it. Okay, Now every test file that extends the GUI test will get its properties from the application test dot properties file. Now back to our last test. Let's change the name of this variable to first address. This variable's name to second address. Now let's copy these lines and generate four more transactions to form more newly generated addresses, modifying their code accordingly. Let's change the expected table row size to seven. Let's copy these lines also to validate all addresses generated in the test. Let's change the methods parameters as required. Now, let's run our tests. As expected. The last test has failed after the third transaction that happened because the wallet couldn't find the fourth address since it generated only the first three addresses. In the next video, we'll fix that. Before finishing the video, let's add the initial number of generated addresses property to the application dot properties file. Let's set it to 20 so that the wallet will work as before in the non-test environment. 36. Generating More Addresses: In this video, we'll make our last created test pass. To do that, let's go to the update current wallet addresses service. In this method, let's add the following if statement. After calculating the next address index. Inside the if statement, we'll call them must import addresses method passing the next address index and the address type. Let's create this method. Will only import addresses if the next address index is equal to the total number of addresses in the current wallet with a given address type. If that's the case, it means that we ran out of addresses and thus cannot populate the next address for our wallet without creating more addresses. Inside this method will return the result of checking if the next address index is equal to the current wallet get addresses count method call will pass the address type to this method. And let's create this method. This method will return an int and it will return the addresses, get adresses count method call, passing the address type as its parameter. Let's create this method. Here we will simply get all addresses with the given address type in a list and return the list size back to the Update Current wallet addresses service. In the if block will first get the current wallets extended pub keys, and store them in a variable. Let's create this method. Here. We'll return the extended pub keys field. Let's create it. Let's also add a setter for this field. We'll call this set or in the update current wallet service update method. Passing the wallets extended pub keys to it. Now back to the Update Current wallet addresses service. We'll call the add addresses method on the ADD address service. Passing the previously obtained extended pub keys as its first parameter and the next address index as its second parameter. Let's inject this service into this class. Let's create this service and the API services package. Let's add the service annotation to it. Now, let's finish injecting this service into this class. And let's create this method in the ad addresses service. Let's change this parameter name to from index. What we plan to do now is to generate addresses for the extended pub keys that were passed as parameters. The number of generated addresses will be equal to the initial number of generated addresses injected field. And the first address generated derivation index will be determined by the firm index variable, e.g. suppose the initial number of generated addresses is equal to 20 and the from index variable is equal to 20. In that case, this method will generate a dresses with a derivation index of 20 to 39. To do that, for each extended pub key. We'll call the add addresses method, passing the key and the from index parameter. Let's remove this S letter. Now, let's create this private add addresses method. It will call the add addresses method on the extended pub key as its parameter. We will use the address sequential generator. So let's inject it into this class. We'll call the generate method on the address sequential generator, passing the extended pub key key, the extended pub key type, and the from index variable as its parameters. Let's go to the generate method implementation. Will change it to generate addresses with derivation indexes using the from index parameter. So let's add from index as its third parameter. Here in the range method call will add the from index variable as its first parameter. And the sum of the from index parameter and the initial number of generated addresses as the second. Now back to the ADD address service. Let's create the ad addresses method on the extended pub key class. Let's fix this parameter name. Here. We'll call the addresses add all method passing the addresses parameter to it. There's a problem with this code. The addresses field is of type list, which is immutable. That means that when we try to add items to it through the add all method, it'll throw an error. So let's change it to the ArrayList type, which is mutable. Let's also make it final and instantiated here. Let's also change the addresses getter and the addresses method to get and set an ArrayList. Let's also remove the set addresses method since we won't use it anymore. Back to the add addresses service. Let's wrap the generate method call result in a new ArrayList, since the ad addresses method now accepts only an ArrayList. Now let's run factors that create wallet service. Since we've made changes that affected. First, let's remove the address sequential generator service from this class. Let's also remove this method. Let's remove this code line. We'll use the add address service to add addresses to the extended pub keys. So let's inject it into this class. And let's call the add addresses method on it, passing the extended pub keys and zero as its parameters. Let's finish injecting it into this class. Now back to the Update Current wallet addresses service. We'll call the set addresses method on the current wallet, passing the extended pub keys as its parameter. Let's remove the address rows clear method call in the set addresses methods since we don't want to remove any addresses table rows after setting these addresses. Instead, let's create a method called clear address rows, which will do that. Then in the update method of the update current wallet service, we'll call this method to clear the address rows only after adding a new wallet. Now back to the Update Current wallet addresses service will get all the newly generated addresses in the current wallet and store them in this variable. To get the addresses will call the get addresses as strings method on the current wallet. Passing the next address index as its first parameter. And the sum of the next address index and the initial number of generated addresses field as the second parameter. Let's inject this field into this class. Let's add the qualifier annotation to use the bean defined in the address configuration class to inject the desired value into this parameter. Now, let's create this method. Let's change these parameter names to from index two index. This method will return the addresses, get addresses as strings method call passing the same parameters that received. Let's create this method in the addresses class. This method will return all its addresses with indexes between the parameters from index two index, but not including the ladder. To do that, it will return the following code. We'll use the flatMap method to convert all addresses into a stream of address objects. Then we'll filter the stream to only return addresses with index is greater than or equal to the firm index variable and smaller than the two index variable. Then we'll call a map on the result to return a stream of address strings. Finally, we'll convert the result to a list and return it. Now back to the Update Current wallet addresses service will use the node multi import address clients to import the newly generated addresses in our Bitcoin node. Remember that this is needed because it's required for the node to know about our addresses so it can send related transactions to our application wallet. So let's inject it into this class. Now we'll call the input addresses method on it, passing the current wallet name, the address strings, and a new date as its parameters. Great, our address rotation feature should work now, even after all initially generated addresses are used. But let's handle another issue here. We're setting the next address as the receiving address in our wallet. Even if it's addressed type is a change address. Let's fix that. Since we want only addresses with the Segway type, not the Segway change type being said as receiving addresses in our wallet. So we'll add this if statement. If the address type is equal to the main address constant, which will set it to segue. Now. Then we'll set the next address as the next receiving address in the current wallet. One more thing, let's remove this platform run later call will call the run later method only wrapping the code that will really change the UI. So let's use it to wrap only the current wallet set address roll-call. Let's also use it to wrap the current wallet set receiving address method call. That way, we avoid blocking the UI while communicating with our Bitcoin node in the import addresses method call. Now let's go to the addresses table controller. I've noticed that the TableView is sometimes not updated to reflect the actual state of its rows. To fix that, Let's add this code to this method. Will add a listener to the current wallet observable address rows. In the body of this lambda will simply call the refresh method on the addresses table. That way, for every update in our wallet addresses, we guaranteed that the table view, we'll refresh it state and we'll show the current information of our wallet addresses on the screen. Now, let's go to the address sequential generator test and add zero as the generate method third parameter so that this test continues working. Let's also fix the create wallet service test. In the setup method, Let's instantiate the ADD address service, passing the address sequential generator as its parameter. And let's substitute the third parameter of the create wallet service for the ADD address service. Now, in the last receiving Bitcoin test, Let's make a little change. After sending Bitcoin to the third address. Let's add asleep method call passing timeout and seconds as its arguments. Let's also add the same call after sending Bitcoins to the sixth address. The reason for these calls is that before sending Bitcoins to the fourth and seventh addresses, we have to generate them and import them to our nodes before accepting transactions to them. And the importing process takes some time. Let's finally run all our application tests. Great, all tests have passed. We finally finished the basics of the receiving Bitcoin feature of our wallet. Now, we'll start to implement the observation of new blocks that are added to the blockchain so we can update the number of conformations that are addresses have C, yeah. 37. Testing Confirmations: In this video, we will make tests to ensure that when a block is mined in the Blockchain, our wallet receives updated transactions with increasing conformations. So let's move the auxiliary methods in the receipt Bitcoin test class to the GUI test so that we can use these methods in other classes that extend it. Now, let's move all these properties to the GUI class also for the same reason. Now, Let's cut these two lines and paste them to the load wallet and add balanced method in the GUI test class. In the setup method in the received test class, we'll just call this method. Let's delete all these unused imports in this class. In the GUI test class, Let's make these methods and properties protected. Now in the GUI test package, Let's create the receiving block test class. It'll extend the GUI test class. Let's copy the setup method and the receive Bitcoin test and paste it here. Let's also copy the first test in the receive Bitcoin test and paste it into the receiving block test class. It'll be used as a blueprint for the next test we'll create. Let's change the created wallet name to my test wallet five. Let's change the name of the test tube should receive Bitcoin and add hashtag confirmations, confirmations to receive that dress. The hashtag conformations will be interpolated by the confirmations test variable we'll create. Now, after sending Bitcoins will call the mine blocks method, passing the confirmations variable as its parameter. Let's create this method. It'll take an int as its parameter. This method we'll use the node generate to address client to mine blocks. So let's paste some code into it. In the GUI test class, copy this code line and paste it here. Modify the address variable name to note address. Do the same with this other line. Change the generate method second parameter to blocks. So it will use this variable to define the number of blocks it'll mine and change this parameter to note address. Now, let's copy this weight for a method call and pasted here. Delete these code parts. This method will wait until the first address table row confirmation cell value is equal to the blocks variable. In the Venn block will check if the first table row confirmation cell value is equal to the confirmations variable. Let's include a where clause. Here. We'll set the confirmation is variable for some test values. We'll add a placeholder for the second column in the whereClause, because it apparently only works when it has two or more columns. Let's set the confirmations values to 12.3. Now, let's run our Bitcoin node, and let's run our new test. Great, the tests have passed. Now, let's make another test for the following scenario. We want to know what happens when an address receives two transactions. And the second transaction has fewer conformations than the first. In this case, we expect that the address number of conformations is equal to the number of conformations of the transaction with fewer conformations to that address. So let's duplicate the first test. Let's change its name to should receive Bitcoin and consider the transaction with fewer conformations as the address confirmations. Let's change the create wallet name to my test wallet six. Now, let's duplicate these code lines to send bitcoins and mine blocks again. In the second mine blocks call add minus one in its parameter to mine fewer blocks after the second transaction. In the block, we expect confirmations minus one as the number of confirmations in the first table row. Let's delete this line since we don't want this test case because it would try to mind zero blocks in the second mine blocks call, which would fail. Let's run our tests again. Great, the tests have passed. So we conclude that our wallet is already prepared to update the number of conformations of our addresses. That's because after each mine block, the node sends a message through zero MQ to our application containing the previously imported transactions, but with an updated number of confirmations. 38. The Transactions Table: In this video, we'll start to make the transactions table. This table will be similar to the addresses table, but instead of rows containing information about addresses, this table will contain information about every transaction our wallet sends or receives. So let's start creating a GUI test for this table. In the GUI package, create a class called receiving transaction test. Copy these methods from the receiving block test and paste them here. This class will extend the GUI test class. Change this test name to have should receive transaction. Let's format this method. Remove it's where block, change the create wallet name to my test while it's seven. Delete this line. Now, after calling the method sleep, let's make the test click on a component with an ethics ID of transactions tab. Now, let's add another optional parameter to the send Bitcoin and wait method. This parameter will be a string and it'll be called lookup component. Its default value will be hashtag addresses table. Let's substitute this parameter in the lookup method call for the lookup component variable. Now in the test, let's add these parameters to the send Bitcoin and wait method. The fourth parameter will be hashtag transactions table. That way after sending a transaction, this method call will wait for the transaction table to be populated with one row containing a balance of 1.0 Bitcoin. Now, let's change the lookup method parameter to hashtag transactions table, also. In the then block, Let's just leave the assertion of the table row size being equal to one for now. Now, let's design our table. Let's go to the playground dot FXML. Let's copy all this content between the tab tag and paste it below. Now change its text property to transactions and it's ethics ID to transactions tab. Also change the table view tag ethics ID to transactions table. Now let's change the text field of the first column to transaction ID. The table will also have a balanced column and a confirmations column. So we'll maintain these tags as they are. Let's duplicate the last tag, change its text to date. This column will contain the creation date of these transactions. Now let's click on the Scene Builder to see how our new tab and table looks. Okay, It's looking nice. Now, let's create a new FXML for this component. Let's call it transactions underscore table. Let's delete the boilerplate code. Let's copy this content from the playground dot FXML and paste it here. Let's import these tags. Change this tag to fx colon route. Delete this content as its type. Let's set the table view component path and set this URL as the XML NS field as the ethics ID property set transactions table. Now delete these tags, which we didn't need to copy. Now let's add these ethics IDs to these column tags. They will be useful later when we make the transactions table controller. Now in the main window dot FXML, let's duplicate the content between these tags. Let's change the tab text to transactions and it's FX ID to transactions tab. Now, change this tag to transactions table controller. Let's create this controller in the GUI dot controllers package. Let's imported into the main window dot FXML. Now let's add the component annotation to the transactions table controller. It'll extend the table view class parameterized with the transaction row class we'll create. Let's create the transaction real class in the observables package. Now, let's go to the Receive tab controller and copy its constructor and paste it here, making the appropriate modifications to it. Let's change its value annotation to point to the transactions underscore table dot FXML. Let's also inject the current wallet into this class. It will be useful later. Now, we need to include the transactions table controller in the list of custom components in the GUI started listener, we could simply add another or clause in the if statement in the initialize FXML method. But let's refactor this class by doing the following. Let's create a private static set of class objects called custom components here. Let's instantiate it here with the set class of method. Let's include these controller classes in the set. Now in the if statement will just check if the custom components set contains the given type. Now let's go to the receiving transaction test. Now, let's run the clean and compile lifecycle Maven goals. Sometimes this is necessary to include new FXML files in the compiled project. Now, let's run our Bitcoin core node if it's not already running. Finally, let's run the test. The test has failed because it haven't find a row containing the transaction information in the transactions table, will continue to implement this feature in the next video. See you. 39. Populating the Transactions Table: In this video, we'll finish the implementation of the transactions table and make this test pass. So let's go to the update UTXO service. If you remember, this update method is called after we receive a transaction from our node, the node task class monitors our node for transaction messages. Then our application publishes a transaction received event that is listened to by our transaction listener. The transaction listener parses and filters the message and calls the update UTXO service update method. So after retrieving UTXOs and updating the current wallet addresses, let's update the current wallet transactions using this service. Let's inject it into this class. Let's create it in the GUI dot services package. Let's add the service annotation to it. Now, let's finish injecting it into this class. Now, let's call the update method on this service, passing the UTXOs variable as its parameter. Let's create this method. This method will run asynchronously. So let's add the async annotation to it using the default executor service as its parameter. Let's do the same with the update method in the update current wallet addresses service. Now let's implement the update method and the update current Wallet transaction service will convert the list of UTXOs into a list of transaction rows and store the result in the transaction rows variable using the following code will filter the stream of UTXOs by maintaining in the stream only the UTXOs with addresses in the current wallet. So let's inject the current wallet into this class. Now, in the lambda body will get all addresses as strings and check if it contains the UTXO address. Now, we'll call the map method on the resulting stream, passing the transaction row from method as its parameter. Let's create this method. It'll be a static method and it will return a transaction row object. Similar to the address row class. The transaction row class will represent a row and the transaction table. So let's add the following properties to this class. Each property will represent a column in the transaction table. Let's delete the final keyword from each property because the IDE does it let automatically create setters for these properties if their final. Now using this ID feature, add getters and setters for each property. Now we can add the final keyword back to these properties. Now, let's create a constructor. The constructor will take each class property as its parameters. And we'll use the property setters to set the properties in the constructor body. Now, we can continue implementing the method. It'll return a new transaction row with the following parameters. Back to the Update Current Wallet transaction service. Now we'll convert the resulting string into a list. Now we'll add the obtained transaction rose to the current wallet using the add transaction rows method. Let's create this method. It'll use the transaction rows field. So let's create it now. It's type will be the transactions Rose Class. Let's create it in the observables package. Back to the current wallet. Let's make it final and instantiate it here. Let's also make the address rows field final. In the ED transaction rows method, let's call the add transaction rows method on the transaction rows field. Passing the given transaction rows as its parameter. Let's create this method. Just like the address rows class is responsible for managing the list of address rows shown in the addresses table. This class will do the same to the transaction rows and transaction table. So for each transaction row, we'll check if the transaction roadmap field already contains it. So let's create this field. It'll be an observable map where the key is a string and the value is a transaction row. Let's instantiate it here with an observable map wrapper, passing a new linked HashMap as its constructor. So if the transaction roadmap contains the transaction row ID in its keys, then we'll set the transaction rotate to the date of the transaction present in the transaction roadmap will do that to preserve the transaction creation date. Then after the if statement will remove the transaction row from the map by its ID and put the given transaction row again in the transaction roadmap using its ID as the key. Again, we're removing and adding the same transaction row to force the observable map to publish change events that will be listened to later. Now, let's create the observable list field that will be used to bind changes in the transaction roadmap to the table controller. Let's instantiate it here using an observable list wrapper instantiated with a new linked list. Now let's create the method get observable transaction row list. It will return the transaction role list. Now will bind the transaction roadmap with the transaction role list in the constructor, just like we did for the address row set and the address row list in the address rows class. So to speed things up, let's copy the address rows constructor and paste it here. Let's fix its name. Now, instead of calling methods on the address role list, we'll do it on the transaction role list. Instead of using a set change listener will use a map change listener parameterized with a string and a transaction row. Also, instead of using the get element removed here, we'll use the getValue removed. Here. We'll use the get value-added. And here we'll add a listener to the transaction roadmap. One more thing for this to work, we have to implement the equals method in the transaction row class. This is because the transaction row list, we'll use the method to decide what transaction row to remove from itself. So let's implement it using this IDE feature. Make sure to check the use getters checkbox in this window will use only the ID property to define equality in this class. Also, click on the ID checkbox here so that it can't be null. Okay, the IDE generated these methods as expected. Back to the transaction rows class. Let's create the clear method, which will be called when a new wallet is created. Inside it will call the clear method on the transaction roadmap and on the transaction role list. In the current wallet class, let's create the good observable transaction rows method. It'll return they get observable transaction row list method call on the transaction rows field. Let's also create the clear transactions method here. It'll call the transaction rows clear method we've just created. Now let's go to the update current wallet service. Here we'll call the current wallet clear transactions method. By doing so, we make sure we clear the transaction rows after creating a wallet. Now, let's go to the transactions table controller. Let's add the following fields. There'll be used in the initialized method later to bind the table and its columns to the transaction rows observable. Now let's create the initialized method. Here, we'll first set the transactions table items to the current wallet observable transaction rows. Now we'll add a listener to the current wallet observable transaction rows. We'll call the transactions table refresh method in the body so that every change that happens in the observable will trigger a redrawing of the table. Also will bind every column field to the transaction row field using the set cell value factory, just like we did in the addresses table controller. As the property value factory parameter, we have to use the same property names that we've used in the transaction real class to do the binding correctly. Let's duplicate this line three times and change the columns we're binding. Now let's go to the receiving transaction test class. Make sure you're running the Bitcoin Core Node and run the test. Boops, the test has failed. Let's see why. There's a problem with the column transaction balanced field in the transactions table controller. To fix that, Let's go to the transactions underscore table dot FXML. The problem is that we misnamed the balance, confirmations and date FX IDs. All three are missing the word transaction after column. So let's fix them and run the test again. Great, The test has passed. In the next video, we'll add more tests to make sure the transactions table is working as intended. C, yeah. 40. Improving Tests for the Transactions Table and Running Our Application on the Test Net: In this video, we'll add more tests to check if our transactions table works for other scenarios. So let's go to the receiving block test class. In each method will add code to test if the transactions table contains the expected information about the receiving transactions. So let's rename the table view in this test to address his table view, to clarify its meaning. Now, we'll call the click on method passing as its parameter, the string transactions. Now let's copy the line with the addresses table view variable and paste it below. Let's change this variable name to transactions table view. In the lookup method, let's substitute this parameter for hashtag transactions table. Now let's copy these two lines and paste them below and change them to call these methods on the transactions table view. Let's do the same to the other test method. But in this case, we expect the transactions table to contain two lines, one for each transaction. And for the second row, we expect the number of confirmations to be equal to the total confirmations variable, which will create the total confirmations value will be equal to the number of blocks mine so far, this number will be equal to confirmations plus confirmations minus one. Since we expect the second row to contain information about the first transaction, it'll be confirmed this number of times. Let's make a little fix in the mine blocks method. Sometimes this code line raises a NullPointerException due to the TableView having a null items property. To avoid that, Let's use the null safe operator before each property in the table view. Now, let's run our tests. First, make sure to run your Bitcoin node. Let's run the tests. The last two tests have failed. That happened because the transactions in the table, we're unordered, their order is seemingly random. Sometimes these tests may pass because they can be correctly ordered by chance. So let's fix that. We aim to sort the transactions by date with the newest transactions in the first rows. So let's go to the transaction row class. In the from method. Let's change how we pass the data to the transaction row instantiation. Instead of using a new date, let's use the instant now method. We're doing that because the instant class is more precise and easier to Parson sort. Now let's go to the transactions table controller. In the transactions table set items method call. Let's pass a new sorted list as its parameter. The current wallet observable transaction rows will be the first parameter instantiating the sorted list. The second parameter will be the comparator comparing method call. This method will pass a lambda as the first parameter or a transaction row will be the parameter in the lambda body. Let's call the instant parse method, passing the transaction rotate as its parameter. The parse method will generate an instance object from the date string. The second comparing method parameter will be the comparator reverse order method call. This way, we expect the transaction table to be sorted by the transaction date with the latest transactions first. Now let's run our tests again. This time only the ones that have failed. We'll do that by clicking on this button. Great, the tests have passed. Now let's add transactions table tests to the receive Bitcoin test class. We'll do the same as we did in the receiving block test class. For each method, we'll refactor the table view name, make the test click on the transaction tab and make assertions about the expected content in the transactions table. Let's do it. Okay, now, let's run these tests. Great, the tests have passed. Now we'll run our wallet on the test net environment for the first time. The test net environment is similar to the main net, but their coins are worthless. It's much easier to mind and their block time is shorter. It requires us to run and sink our Bitcoin node on this environment. We covered how to do that in the course setup guide. So let's modify our bitcoin.com to run our node in the test net environment. Just change this key from reg test to test net. Let's stop running our node on the reg test. And let's run our note again to start sinking our note on the test net. My note is almost sink, so it'll take a few minutes to catch up. But depending on the last time you ran it, it may take longer for us to sync because it'll take some time to download the latest blocks. Anyways, while it's sinking, Let's modify our projects so that we can run our application on the test net successfully. In the resources path, Let's create the file application test net dot properties. This file will contain the properties used in our project when we run the application on the test net environment. Let's copy the content from the application dot properties file and paste it here. Now, change the Bitcoin environment to test net. And the no dot RPC dot URI port 218332. This is the default port of our node when it runs on the test net environment. Now, let's make a little improvement. In our wallet, It would be nice to be able to copy the transaction ID is shown on the transactions table by simply right-clicking on them and clicking on Copy. Let's implement this feature. To do that, let's go to the transactions underscore table dot FXML. Now let's add the following code here. First, let's add these context menu tags inside it. Let's add the items tag. Then the menu items tag. In this tags text property add the string copy and hashtag coffee transaction ID as it's on action property. This tells the application to call the copy transaction ID method in the transactions table controller. After we click on the Copy Menu item in the context menu. The context menu is a menu that appears after we right-click on something on the screen. Now, let's go to the transactions table controller. Let's create the copy transaction ID method here. First, we'll get the transaction row that was right-clicked using this code. Now we'll simply call the copy method. We'll create passing the transaction row ID as its parameter. To create this method will create first a utils package inside the BYOD W package. Inside it, Let's create a class called Copy. Now, let's create the copy method here. As a static method. Will instantiate a clipboard content object, storing it in the content variable. Then we'll call the put string method on it, passing the variable text as its parameter. Let's add this variable as the copy method parameter. Finally, we'll call the get system clipboard method and set its content to the variable content in the transactions table controller. Let's import this method. One more thing. When running the Bitcoin node on the test net environment, our node may receive different types of transactions that the Bitcoin Java library cannot parse yet and they raise errors when trying to do it. Although not parsing these transactions will affect our wallets, the error is raised well. To avoid that, in the node task class, wrap the transaction method from byte stream in a try-catch block. In the catch block, let's use a logger to warn us about the error. In the one method call will pass a phrase indicating the error and a pair of curly braces at the end. These curly braces will be interpolated by the second argument, which will be the hex encoded content variable. The third parameter will be the exception object. So we can access the entire stack trace of the error in the logs. After logging, the error will go directly to the next iteration of the while loop by using the continue keyword. Let's create the logger field. It'll be a static property. Let's instantiate it here using the logger factory. Let's fix the logger class import. Actually, we have to import it from the 4D dot SELF for J package. Now let's run our application on the test net environment. First, let's check if our node is linked on the test net environment. Okay, it's already sink because it's progress is equal to 1.00. Now let's go to the BYOD W application class. Right-click on this symbol and click on modify Run Configurations. Now, click on modify options and make sure the ad VM options is selected. Now set it to minus d spring dot profiles dot active equals test net. Click on Okay, and click on the Run button. Now let's create a wallet. Notice that the receiving address starts with TB, indicating that it's a test net address. Now, let's copy this address. Will use a test net faucet to obtain test net Bitcoins. A Bitcoin faucet is a website or API that offers Bitcoins for free. They were very popular in the first years of Bitcoin, when one Bitcoin was very cheap. Nowadays, there are fast way to obtain test net coins. Let's go to the website on the screen. It's a test net faucet. Let's paste the copied address into this field. Choose an amount, and click on this button to send us Bitcoin. Let's wait a little. Okay, the alert says that it sends some Satoshi's to our wallet. Let's check if we've received it. Great. Our wallet identified our transaction and our transaction and address already have one conformation. There's one weird thing though. The balance is formatted in scientific notation. We'll fix that later. For now, let's copy our transaction ID by right-clicking on it and clicking on Copy. We'll check the transaction in a third-party blockchain explorer. A blockchain explorer is a website that shows information about Bitcoin addresses, blocks, and transactions in a nice and organized way. If your privacy concerned, searching for your red dresses and transactions on third-party blockchain explorer is not advisable since it allows them to link you with your wallet data. But since we're just using it for test purposes, that's okay. With that said, let's go to the website on the screen, which is a Bitcoin test net blockchain explorer, paste the copied transaction ID on the search field and click on the Search button. Here, we will obtain some information about our transaction. Notice that it already has two confirmations, but our wallet indicates that it has only one conformation. It turns out that on the test net environment, our Bitcoin node only sends transaction notifications through zero MQ when the transactions are sent and when they get one confirmation. After that, no matter how many more confirmations that gets, the node doesn't notify our application about it. We have to make our application start to listen for block notifications so that we can fix this problem. We'll start doing this in the next video. See you. 41. Listening for Blocks and Formatting Balances: In this video, we will make our application starts listening to block messages from the Bitcoin node. That way, we'll be able to update our transactions confirmations correctly in the test net environment. Also will modify the address and transaction balances formatting, since now they're not being displayed nicely on the tables. So let's go to the bitcoin.com file. Let's change this key to reg test. To start listening for block messages, let's add the Z MQ pub hash block property here. Its value will be the same URL in the property above. So let's paste it here. This configuration will make the nodes send the hash block to our application after it detects a new block, extending the blockchain. After that, the code will create, will send a list unspent request to the node containing all current wallet addresses. In response will receive a list of updated UTXOs that will parse and use to update our red dresses and transaction tables. Let's save the bitcoin.com file. Now, let's go to the node task class. Let's duplicate this line. Let's change the string to hash block. That way, we'll start to receive hash block messages from the node. Now, in this if statement, Let's add the following code. If the topic is equal null, or the list with these topics does not contain the received topic. Then we'll go to the next iteration of the while loop. Now, let's add a switch statement here. In case the topic variable is equal to ra t x. Then we execute the code to parse and process the received transaction. Let's move the line that publishes the transaction received event to this location. That way we can remove this redundant continue statement in case the topic variable is equal to hash block. Then we'll use the application event publisher to publish a new block received event. Let's create this event in the BYU w dot no doubt events package. Now let's create a listener for this event in the BYOD w dot, dot listeners package. Let's add a component annotation to it. Let's make it implement the application listener interface, passing the block received event as its type parameter. Let's implement its method. First. We'll get all current wallet addresses using this method and store them in the addresses variable. Let's inject the current wallet into this class. Then using an if statement will check if the addresses variable is empty. If it's not, then we'll use the update UTXOs service to update our addresses and transactions. Let's inject it into this class. We'll call the update method on it, passing the address is variable and the current wallet name as its parameters. Now let's go to the transaction received listener will optimize our code. Remember that after receiving one confirmation in the test net environment and all confirmations in the reg test environment, the node sends a transaction message to our application through zero MQ. Since from now on our block received listener will update all current wallet addresses when it receives confirmations, it doesn't make sense to update the addresses and transactions table in the transaction received listener class after we receive repeated transaction messages anymore. Therefore, we will modify this class to only process transactions if the current wallet doesn't contain them. So let's add this if statement. If the current Wallet transaction IDs contain the Received Transaction ID, then we simply return. Let's create this method. It'll return a list of strings, and it will return the transaction rows, get transaction IDs method. Let's create this method. Here. We'll return the following code from a stream of the transaction role list. We'll call the map method passing a reference to the transaction row getID method. Then we'll convert the result to a list and return it back to the transaction received listener. We have to wrap this code in a try catch block because the transaction ID method throws a checked exception in the catch block, will use a logger to print a warning message. Let's inject the logger into this class, just like we did in the node task class. Let's also add a return statement to the catch block. Now, let's fix the address row balanced formatting problem. Instead of using the double class two string method, we'll use the Bitcoin format or format method passing the address balance as its parameter. Let's create this class in the utils package. Now, let's create the format method. Here, we'll instantiate a new decimal format symbols object passing the locale route to its constructor. Then we'll set the dot as its decimal separator and the comma as it's grouping separator. Then we will instantiate a new decimal format object as its constructor parameter will pass this pattern. And the symbols variable. Then we'll set the format or grouping used as false. Then we'll set its minimum fraction digits to eight. And it's maximum fraction digits 282. Finally, we'll call the format method on the formatter, passing the received number as its parameter and return it. Using this method will format any number of pass to it with a decimal digits and without grouping separators. This type of formatting is useful since one bitcoin can have at most eight fraction digits. This formatting also facilitates the visualization of how many Satoshi is a balanced contains. Now let's go to the transaction row class. Let's use the Bitcoin formatter here to, to format the UTXO balance in the frame method. Now, let's adjust our tests to cover this new balance formatting. Let's go to the GUI test class in the send Bitcoin in weight method, let's change the second parameter type to double and adjust its default value accordingly. Let's also add this optional amount parameter with a default value of 1.0. Now, let's substitute this parameter for the amount variable. And here let's wrap the expected total amount variable in the Bitcoin format or format method. Now, let's go to the receive Bitcoin test. Let's modify this and Bitcoin and wait method call to send 0.00 001 Bitcoin. So we can test the new formatting when our wallet receives Bitcoin fractions. Now, let's check every usage of this method and modify their parametrization of the expected total amount parameter to pass a double instead of a string. Now, let's add these null checks to the table view properties in this method to avoid having null pointer exceptions. Now, let's run our node, and let's run all project tests. Great, the tests have passed. Now, let's run our application on the test net environment. To do that, let's adjust our bitcoin.com file. Now, let's restart our node. After some minutes, my note is fully sink. Now, let's run our application in the test net environment using our previously modified run configuration. Let's create a new wallet. Now, let's copy our address and use a test net faucet to receive Satoshi's, just like we did in a previous video. Okay, our wallets successfully identified the transaction and it's balanced is just as we expected. Now, let's eat a sandwich and leave our wallet running for awhile. After some minutes are addressed and transaction already got four confirmations. Great. 42. The Total Wallet’s Balance: In this video, we'll start to develop the total balance feature. Basically, it'll be a text above the transactions and addresses tab indicating the balance of the currently loaded wallet will show the confirmed balance, the unconfirmed balance, and the total balance. The confirmed balance will show the amount sum of all confirmed UTXOs. The unconfirmed balance is the sum of all unconfirmed UTXOs. The total balance will be the sum of unconfirmed and confirmed balances. So let's go to the playground dot FXML to sketch something. After the first closing tab pane. Let's add this label tag. Now, let's add this VBox dot margin tag. Inside it. Add this insets tag. We'll add some margin properties here. Let's set the bottom margin to 10.0, the left margin to 10.0, and the top margin to zero. Now, for testing purposes, let's set the text property of this label to this as a test. Let's see how it looks in the Scene Builder. Okay, we see that the balanced texts will be located here. Let's remove this text property. Let's create a new FXML file called total underscore balance. Let's remove this boilerplate. Now, let's copy all the content and the label tag we've just created in the playground. And paste it here. Let's also copy these import lines two and paste them into the total underscore balanced dot FXML. Now let's substitute the label tags for the FX colon root tag. It will have an FX id of total balance and a type of Java FX dot, dot control dot label. Let's also include this XML and S property. Now in the main window, let's add the total balance controller tag after the first closing tab pane. Now let's create this controller in the controllers package. And let's import it here back to the controller. Let's make it extend the label class and add the component annotation to it. Now, let's copy this constructor and paste it here, modifying it accordingly. The FXML resource value will be the location of the total underscore balanced dot FXML. Let's also inject the current wallet into this class. Now in the GUI started listener, Let's add the total balance controller class to the custom components set. In the total balance controller. Let's add the initialized method. We'll use the inherited setText method to set the label text dynamically. Let's set it to test for testing purposes for now. Now, let's create the total balance test in the GUI package. It'll extend the GUI test class. Let's copy these two methods and paste them into the new test. Let's rename this method two should calculate total balance. Now, let's make some adjustments to the body. The name of the created wallet will be my test validate. Let's remove this line since we won't need it. Let's also remove these lines. With this code, will get the text present in the total balance label and store it in the label text variable. Then block will check if the label text variable is equal to the following phrase. After receiving the transaction, we expect the label content to show that our total and unconfirmed balances are one Bitcoin. We expect the confirmed balance to be zero since our transaction won't be included in a block and mind during the test. Before running our node, let's make sure that our Bitcoin dot conf environment is set to reg test. Now, let's run our node. And let's run this test. It has failed as expected because the total balance label contains the string test instead of what we wanted. In the next video, we'll implement this feature and make this test pass. See you. 43. Calculating and Showing the Wallet’s Total Balance: In this video, we'll finish implementing the total balance feature. So let's go to the update UTXOs service. In the update method will add a new method call to update the wallet balance. For that, we'll call the update method on the update current wallet balance service will create. Let's inject this service into this class. Let's create this class in the GUI dot services package. And let's finish injecting it here. Now, let's create its update method. Here, we'll first calculate the unconfirmed balance and store it in the unconfirmed balance variable. For that, we'll need to inject the current wallet into this class. Then we'll get its observable transaction rows and convert them into a stream. Then we'll use the filter method on the result to exclude the transaction rows with confirmations different than zero. Then we'll use the map method to convert the obtained stream into a stream of transaction row balances. We'll use the parse double method to convert each balanced string into a double. Now we'll use the reduced method, passing the double sum method to it, to some every obtained balance in the stream. Finally, we'll use the or else method passing 0.0 to it. Therefore, in case the obtained stream is empty, the unconfirmed balanced variable will be set to zero. Now, let's duplicate this code block. Let's modify it to calculate the confirmed balance and store it in the confirmed balanced variable. We just have to change the equals sign and the filter method to this greater than sign. With this simple modification, we will obtain the sum of the balances of all transactions with at least one conformation. Finally, we'll call the set balances method on the current wallet, passing the unconfirmed balance and the confirmed balance as its parameters. Since this code will modify the UI, Let's wrap it in a platform run later method call. And let's create the set balances method in the current wallet class. To do that, let's add the balances field to this class. It's type will be the balances class we'll create. Let's create it in the observables package. And let's instantiate it here. Here we'll call this set balances method on the balances field, passing the unconfirmed, unconfirmed balances as its parameters. Let's create this method. First. Let's add some private fields to this class. We'll add the unconfirmed balanced field of type string property. Let's instantiate it here with a new simple string property. Let's duplicate this line two times. Let's change these field names to confirm the balance and total balance. Now in the set balances method will call the set method on the injected properties to set their values. Will use the Bitcoin format or format method to format the balances to the desired format. To the total balance will pass the sum of the unconfirmed and confirmed balances. Now, let's create getters for these fields. Let's also create the clear method. This method will set each property balance to zero. We'll call this method after we create a wallet to clear the values of the previously loaded wallet. Now in the current wallet, let's create the good balances method. It'll return the balances field. And let's create the clear balances method. It'll call the balances clear method. In the update current wallet service, which is called after a wallet is created, let's call the current wallet clear balances method here. Now, let's go to the total balance controller. Let's remove this line. We'll get the unconfirmed balanced property from the current wallet balances. We'll call the ad listener method on it. We'll pass a lambda as its parameter, where in the body we'll call the update text method. Let's create this method. Will call the setText method in it, and we'll pass a string format method call as its parameter. The first parameter of the format method will be this phrase. Each percent sign followed by the letter S will be interpolated by the following parameters of this method call. The next parameters will be the current wallet total balance. The current wallet confirmed balance. And finally, the current wallet unconfirmed balance. Now in the initialized method, Let's duplicate this line two times. We'll add the same listener to the confirmed balanced property and the total balance property. So let's modify these lines accordingly. Let's refactor this string, including it in a constant in this class. Let's call it balanced text and make it private. Now, let's make a little modification in the update UTXOs service. Notice that we already have an async annotation on the update method. So adding the same annotation in the method's called an it is redundant. Therefore, let's remove them. First in the update current wallet addresses service. Then in the update current Wallet transaction service. Another thing I've noticed is that we need to wrap the ad transaction rows method call and a platform learn later method call since it modifies elements in the UI. Now let's go to the total balance test. Let's make sure that our Bitcoin node is running. And let's run our test groups. The test has failed. Let's see why. Turns out that I forgot to add the services annotation to the update current wallet balance service. Let's fix that. And let's run our test again. Great, The test has passed. In the next video, we'll add more balanced tests in our other tests to make sure it's working as intended. 44. Adding More Tests for the Total Balance Feature: In this video, we'll implement more tests to ensure the balance feature is working properly. So let's copy this line and the total balance test, we'll first add some test assertions about the balance and the receiving block test. So let's paste the line here. Let's also copy this line and paste it into the then block of this test. In this test, we expect that the total balance will be equal to one Bitcoin. So let's adjust this phrase accordingly. We also expect that all the balance will be confirmed. Let's do the same for this other test. In this case, we expect that the total balance will be equal to two bitcoins, also confirmed. Now let's check if our node is running and run the test. The tests have passed. Now let's add some balance assertions to the receiving Bitcoin test class. In these tests will expect only unconfirmed balances. Let's run these tests. Great, the tests have passed. 45. The Send Bitcoin Tab: Okay, so far with our wallet, we can receive Bitcoins using generated addresses. We can also inspect the balance received by each address and check information about our transactions. Now, we'll start to implement the ability to spend those bitcoins by sending transactions to other addresses we want to. So let's start creating a test called send Bitcoin test in the GUI test package. It'll extend the GUI test class. We'll add the same setup method. We added two other tests, calling the load wallet and add balanced method. Let's create a test called should send Bitcoin. Now in the wind block, will create a new wallet and send one Bitcoin to its first address. The following code will be very similar to the code of the other tests. After sending one Bitcoin to our wallet address, we'll click on the Send tab. Then we'll click on the amount field to define how much we want to send. Let's send 0.5 Bitcoin, which is half of our balance at this point. Now, we'll click on the address to send field. In this test will send bitcoins to another address. So let's use the Node get new address client to get a new node address. Then we'll write the obtained address on the clicked input. Now, we'll click on the Send button. After that, we expect that a modal opens with information about the transaction and an Okay button to confirm and send the transaction. So let's call the click on method passing okay, as its parameter. Now we'll click on the transactions tab. And with the following code, we'll check if the transaction table has two rows, one for the receiving transaction and one for the transaction we've just sent. Now, let's go to the playground dot FXML to design our Send tab. Let's duplicate the code for the Receive tab. And let's change its text to send. Let's delete these lines so we begin with a fresh new tab to work on. Now, let's go to the Scene Builder. Let's click on the Send tab. Let's click on the body of the tab to select the grid pane component inside it. Let's set its pref height to 130, and it's pref width to 600. Now let's add a label control to the grid pane inside the Send tab. Let's set ten to its top, right and left margins. Let's change its name to address this end. Now, let's add a text field to this grid pane. Let's change its grid pane column index to one. It's not allowing us to do that. First, we have to add a column to the grid pane. Let's right-click here and add two rows and one column to the grid pane. Now we can change the TextField column index to one. Let's set ten to its top, right and left margins. Let's change its pref width to 350. Let's also change this Collins pref width to 600. Let's add another label to the grid pane. Let's change its row index to one, and let's set ten to its top, right and left margins. Let's also change its text to amount to send. Let's add another text field to the grid pane. And let's set its row index to one and its column index to one. Let's set its pref height to 26. And it's pref width to 100. Let's set ten to its top, right and left margins. Now we'll wrap the last inserted text field in an H box. So let's add an H box to the grid pane. And its row and column indexes to one. Let's move this text field to the H box. Let's also set ten to the eight bucks top, right and left margins. Now let's add a label to the H box. Let's also set these margins to ten and change its text to BTC. Actually, let's set these margins back to zero. We'll set five to these paddings instead. Now, let's add an OK button to the grid pane. And let's set its row index to two. Let's also set these margins to ten. And let's set its text to send. Now, let's copy all the Send tab content we've created in the playground dot FXML. Let's create the send underscore tab dot FXML in the FXML package. And let's paste the copied content into this file. Let's change the tab tag to the ethics colon root tag. Let's set its type to Java effects, dots seen, dot control, dot tab. Now let's import all the remaining tags. Whoops, we wrongly set the type property to label. Let's fix it. Now, let's set the FX id of these tags. First, let's set this fx ID to send tab. This fx ID to address, to send this fx ID to amount to send, this fx ID to send. Now let's go to the main underscore window dot FXML. Let's duplicate this line and let's change this tag to send tab controller. Let's create this controller in the controllers package. And let's import it here. It'll extend the tab class and let's add the component annotation to it. Let's copy the Receive tab constructor and let's paste it here, adjusting it accordingly. Let's inject the current wallet into this class. Now let's add the Send tab controller class to the set of custom components in the GUI started listener. And let's change the value of this parameter to send underscore tab dot FXML. Now let's make sure our Bitcoin node is running. And let's run our send Bitcoin test. As expected, the test has failed. In the next videos, we'll continue implementing this feature. C, yeah. 46. Transaction Fees and Sizes: In this video, we will learn more about Bitcoin transactions. More specifically, we'll learn more about transaction size and transaction fees. This knowledge will be necessary later when we start building transactions to transfer Bitcoins from our wallets to other addresses. From the previous presentation, we learned that the transaction fee is equal to the sum of Bitcoin in inputs minus the sum of Bitcoins and outputs of a transaction. Remember that the transaction fee is the price you pay for a minor to pick your transaction from the mental included in a block and mine it. The higher the transaction fee, the faster the transaction will be included in a block. With a small transaction fee, your transaction will stay in the mental for more time. So it's important to choose the right fee to ensure that your transaction gets confirmed in a reasonable time without overpaying it. The transaction fee varies a lot with time. It's value follows the logic of supply and demand. The greater the number of transactions being sent, the greater tends to be the transaction fee. And the greater the number of miners, the smaller tends to be the transaction fee. This graphic shows the average transaction fee in dollars in the last two years. Notice that in this period, the transaction fee varied from a couple of dollars to more than $60 per transaction. So how do we calculate the transaction fee? Considering the transaction blocks have limited space but unlimited demand, it makes sense that fees are calculated by transaction size. There are different ways to obtain the recommended transaction fee rate. E.g. you can use websites such as Bitcoin Fees, earned.com. Here we can see how many transactions have per fee rate in the last 24 h. In the right column, we see an estimate of how long it would take to confirm a transaction with these fees in blocks and minutes. If you scroll down, it gives a recommended fee rate to use. That almost guarantees that your transaction will be confirmed in the next block. Men pull dot space is another site that along with cool graphics, showing the average fee rate for each block, also shows the recommended fee rate to use for low, medium, and high priority transactions. The higher their priority, the faster the transaction is expected to be confirmed. We can also use our Bitcoin Core Note RPC estimate smart fee method. According to its documentation, it takes as a parameter, a confirmation target, which is the number of blocks that we expect to transaction with the return fee rate will take to be confirmed. It also takes an optional parameter to define the estimate mode, which can be unset, economical, or conservative. The fee rate is returned in Bitcoin per kilo virtual byte or KV byte. These examples show that recommended fee rates can vary a lot between different tools. For simplicity, in our wallet will use the Bitcoin Core estimates smartphone RPC call, since it won't require us to query external tools with a fee rate. And hence, we can calculate the transaction fee by multiplying the transaction size in v bytes by the fee rate in Satoshi is privy bite. But wait, what is a virtual byte? To calculate the transaction fees, there are two important concepts to understand first, virtual size and virtual byte. Virtual size, or V size, is the transaction size in virtual bites or v bytes. They are concepts invented to account for the smaller size of Segway transactions. The V size is calculated in a backward compatible way so that preset what transaction sizes are equal to preset what transaction V sizes. For Segway transactions, the V size is equal to the non witness part size of a transaction plus its witness size divided by four. The witness is a field present only in Segway transactions. It contains the fields that in pre segment transactions were located in the scriptSig field of each input. This different way of calculating transaction sizes results in smaller transaction V sizes for Segway transactions compared to legacy transactions. E.g. for transactions with one input and one output, Segway transactions are 110 v bytes in size, while legacy transactions are 192 v bytes in size. For transactions with one input and two outputs, Segway transactions are 141 v bytes in size, while legacy transactions are 226 v bytes in size. Finally, for transactions with two inputs into outputs, Segway transactions are 209 v bytes in size, while legacy transactions are 374 bytes in size. So let's say we want to calculate the fee for a segue transaction with one input and two outputs with a fee rate of 19. Satoshi is privy byte. To do that, we would multiply its transaction v size, which is 141 v bytes, by the fee rate, which is 19 Satoshi's per v bytes. That would give 2,679 Satoshi's in fees for that transaction. So in summary, to construct a transaction, we would need to build the following items. For one output, we would need an address and an amount to send to that address. If there's a need for a change and most transactions do, then we would need to build a second output containing a change address and an amount. We would also need a variable number of inputs whose Bitcoin amount sum must be greater than the amount to send plus the transaction fee. Remember that an input will refer to an unspent output of a previous transaction sent to one of your addresses. A change will be needed if the sum of input amounts is greater than the amount to send plus the transaction fee. If by luck or by design, the sum of input amounts is equal to the amount to send plus the transaction fee than the transaction won't have a change output. And the sender will benefit from paying less in transaction fee for a transaction with only one output. Again, to calculate the transaction fee will need the fee rate in Satoshi's per v bytes. We'll get this value by using the estimate smartphone gRPC API from Bitcoin Core and convert the result in Satoshi's per V bite will also need the transaction size in v bytes. In the next video, we'll implement the note estimates smart Fee, client and a service to calculate the transaction size. Later, we'll combine both to calculate transaction fees. See, yeah. 47. Creating the Transaction Size Calculator and The Node Estimate Smart Fee Client: In this video, we'll create a transaction size calculator and build the node client for the estimate smart feed Bitcoin node RPC method. In the api dot services package, Let's create the transaction size calculator class. This class will be responsible for calculating transaction sizes according to their types and numbers of inputs and outputs. These sizes will be used later to calculate the fee amount we have to include in our transactions. Let's add a services annotation to it. First, we'll define some constants in this class. These constants will contain the sizes of each part of a transaction. Since we're working only with Segway transactions for now, these constants will refer only to parts of Segway transactions. So let's begin defining the size of the transaction overhead. The overhead is the part of the transaction whose size doesn't change with the number of inputs or outputs. The first constant will be called inversion, which is part of the overhead. It encodes which version the transaction has. It has four bytes in size. Then we have the input count, which as the name suggests, specifies the number of inputs in the transaction. It has a variable number of bytes, but for up to 252 inputs, it's size is one byte. Then we have the output count field, which has the same size and rules as the input count. As its name suggests, it specifies the number of outputs in the transaction. Then we have the N lot time field, which has four bytes. This field is sometimes used to encode the time after which the transaction can be spent. Then we have the Segway marker and flag, which is present only for Segway transactions. It has two bytes in size. Now let's set the input field sizes, starting with the outpoint, which has 36 bytes in size. The point is the combination of the previous transaction ID and the output index. It indicates the UTXO used for that input. Then we have the scriptSig length field, which we're up to 252 bytes, has one byte. It indicates the scriptSig size for the input. Then we have the scriptSig field. For Segway transactions. It's size is zero. Remember that for segment inputs, the scriptSig content is moved to the witness field. Now let's add the end sequence field. It has four bytes in size and it's used to set if the transaction is replaceable in case the sender wants to change its fee. Next, let's add the witness count field for up to 250 to witness items. It has one byte in size. Then we have the witness items field, which has a size of 107 bytes for P2, WP k, h inputs. This field is comprised of the signature, which can have 71 or 72 bytes in size, and the public key, which is 33 bytes in size, 72 bytes, is chosen as the size for the signatures, since we prefer to overestimate a bit the transaction size. So the calculated F0 is guaranteed to be enough for the transaction. The two remaining bytes which encode the size of the signature and the public key. Explain the witness items constant value of 107. Now let's set the constants with the output sizes. The n value is the amount of bitcoin being sent in that output. It has eight bytes in size. Then we have the script pub key length, which has one byte in size for up to 252 bytes in script pub key length. Next, we have the script pub key, which has 22 bytes in size for a sec, what addresses? Now, before continuing implementing the transaction size calculation, let's create the transaction size calculator test in the API test package. It'll extend the specification class. Let's add a transaction size calculator field in this class. And let's use a setup method to instantiate it. Now, let's create a test name should calculate transaction size for P2, WP k, h transaction outputs and inputs. In the one-block, we'll call the calculate method on the transaction size calculator service and store the return in the result variable. As parameters will pass the inputs and outputs, which we'll define in the where block. In the block will check if the result is equal to the expected size variable. In the where block will add the following test cases. For the inputs and outputs variables will set lists with a variable number of addresses. Since for now, we don't care about the type of addresses, will simply add a letter representing each address. The expected size values here were previously calculated for each combination of inputs and outputs and validated using the Bitcoin Core CLI. Now, let's create the calculate method in the transaction size calculator class. It'll return a big integer and it will receive as parameters a list of input addresses and a list of output addresses. Now, let's first calculate the overhead size. It's equal to the sum of these constants. Remember that the value we want to calculate here is the V size. So the elements from Segway transactions, such as the Segway, marker and flag, must be divided by four. As such, Let's divide this constant by four. Now, let's calculate the input size. It'll be the sum of these constants. Now, let's calculate the size of all inputs by multiplying the input variable by the number of input addresses. Now, let's calculate the witness size by adding the witness count and witness items constants. As segue what elements? Let's divide their sum by four. The total witness size is equal to the witness variable multiplied by the input addresses size. Now, let's calculate the output size. It will be equal to the sum of these constants. The all outputs variable will be equal to the output size times the number of outputs. Finally, the transaction size result will be equal to the BigDecimal some of the previously calculated values. Let's also set the scale of the result to zero with the rounding mode half up. This will make the result have zero decimal places rounding to the nearest integer. If the result decimal value is five, then it'll round to the integer above. Now, we return the result converted to big integer. Now, let's run the transaction size calculator test. Great, The test has passed. Now let's create the node estimate smart Fee client in the node dot client package. Let's inject the node client into it. And let's create the estimates smart fee method. It'll return a new node FI object will create, and it'll take an integer as its parameter. Now let's return to make request method call on the node client. The method name will be estimates smart fee. It's second parameter will be a new parameterized type reference object. It's third will be an empty string and its last parameter, the blocks variable. Now let's create the node V record in the domains dot node package. It's fields will be a double fee rate and a list of errors. Now in the api dot services package, Let's create an interface called estimate fee service. Let's add the estimate method to it. It'll return a big decimal. Now, let's create an implementation of this interface. Names note estimate fee service in the same package. Let's implement its method. This class will be used later to estimate the fee using the node estimates smart Fee client. If we want to change the fee estimation method or add more options to do this later, we just create another implementation of the estimate fee service interface. First, we'll call the estimate smartphone method from the previously created client and stored in the node V variable. Let's inject this client into this class will pass to this method so that we try to get a fee rate that will make our transaction to be confirmed in the next block. If for some reason the returned fee rate happens to be equal to null, we'll return the fallback fee rate. Let's inject this variable into this class. Will inject it from the properties files. So let's add this value annotation before it. After the if statement will return the big decimal value of the fee rate. Now let's add the bitcoin dot fallback fee rate property to all property files of the project. Let's make it equal to 0.0 002. 48. Coin Selection and Dust: In this presentation, we'll continue explaining important concepts to understand Bitcoin transactions and to continue building our sin transaction feature. So let's talk about coin selection. Coin selection is the process of selecting UTXOs to build a transaction. The general rule for this selection is that the UTXOs Bitcoin amounts sum must be greater than the amount of sand plus the transaction fee plus the change if needed. There are many different coins selection methods. Each one has advantages and disadvantages. The algorithm we'll choose for our wallet is called single random draw. It's probably the simplest coin selection algorithm and good enough for our purposes. This algorithm was first presented in a master thesis titled and evaluation of coin selection strategies by Mark Earhart. I recommend reading this thesis if you want to know more about coin selection strategies. This coin selection method was added to Bitcoin Core in September 2021 as a fallback coin selection strategy. It consists of shuffling the spend or UTXOs, then selecting UTXOs one-by-one until the sum of the selected UTXOs amounts is greater than or equal to the amount to send plus the transaction fee plus the change if needed. If the change amount is smaller than the dust limit, the change output is removed from the transaction and its amount is added to the transaction fee. But wait a moment, what is dust? A dust output is an output whose Bitcoin amount is smaller than the cost to spend it. The following example shows how dust outputs are uneconomical to spend. Let's say you have a UTXO containing 50 Satoshi's and you want to send these 50 Satoshi's to a friend. When building the transaction, you discover that the transaction fee required to send it as equal to 100 Satoshi's. Therefore, it does not make sense for you to spend the UTXO with 50 Satoshi's since you will pay more in fees than the amount sent. Also, your friend will not benefit either from receiving a UTXO with 50 Satoshi's since he would have the same problem as you're spending it. This example shows that it is detrimental to the Bitcoin network to create dust outputs, since no one in the network benefits from it. Therefore, most Bitcoin nodes don't relate transactions containing dust. This helps to protect the network from dust attacks. Dust attack is the process of maliciously sending dust to wallet addresses to track their transactions. This attack is shown in this example. Suppose the government agency sends dust to address X that belongs to person. Why? When e-wallet naively builds a transaction, it includes the dust output and five others as inputs. Now, the government agency knows why five previous addresses and all their previous transactions. Also, the government now knows the change address of that transaction and contract further transactions with it. But what is the criteria to consider an output as dust? The dust limit is used for that. Every output whose Bitcoin amount is lower than the dust limit is considered dust. Bitcoin core uses the following formula to calculate the dust limit. The dust limit in Satoshi's of a transaction output is equal to the transaction output size plus the input size necessary to spend it both in v bytes multiplied by the industry leafy in Satoshi's per KV bytes divided by 1,000. The result represents the transaction output cost that a transaction output Bitcoin amount must be equal to or surpass to not be considered dust. The dust relay fee is a configuration property from the Bitcoin node. It's the transaction fee used when calculating the dust limit. The default dust relay fee is set to 3,000 Satoshi's per KV bytes or three Satoshi's per V bite. This makes the default dust limit for segue outputs equal to 294. Satoshi's. The default dust limit for non segue what outputs to be equal to 546 Satoshi's. For more details about calculating the dust limit, this link from the Bitcoin Core code has a comment explaining how the dust limit is calculated. Now let's summarize the general steps of the single random draw algorithm. It's first step is to shuffle all wallet UTXOs in a list. Then for each available UTXO from the shuffled list, add that UTXO to a list of selected UTXOs. Calculate the adjusted target, which is equal to the amount of sand plus the transaction fee plus the change if needed. If the total Bitcoin amount in the selected UTXOs list is greater than or equal to the adjusted target. Stop. Finally, use the selected UTXOs as inputs of the desired transaction. Some points of attention about this algorithm, adjusted targets with and without the change output must be calculated for better precision since transaction fees differ between transactions with 1.2 outputs, if the generated change is between zero and the dust limit, we stop the iteration since we won't include a change to the transaction and thus do not need more UTXOs. This is necessary to not generate a dust output for the change by accident. The drawback of single random draw algorithm appears in some pathological cases, e.g. when you have one single big UTXO and a lot of small UTXOs. A transaction with a lot of inputs and a high transaction fee may be created instead of using the big UTXO to avoid needing many inputs. When that is the case, a different approach is recommended to construct a transaction. E.g. manually choose the UTXOs that will be part of some specific transactions. In the next video, we'll implement a dust calculator and the single random draw algorithm, C, yeah. 49. Implementing the Dust Calculator and Other Utilities: In this video, we'll start to implement a dust calculator and the single random draw algorithm. But first, let's refactor the UTXO record. Since we'll do a lot of calculations with the UTXO amount field. And calculations are better done with big decimals instead of doubles will change the amount type two big decimal. Now, we have to refactor all usages of the amount field in the project. So let's do it. Let's change the Bitcoin format or format parameter to BigDecimal and adjust this parameter accordingly. Let's do the same to all methods that the IDE flagged as errors in the project. Here we'll add big decimals using the add method. And let's pass the big decimal zero value instead of the zero primitive to these method calls. Now, we have to change the type of this balanced field and all its usages. Let's refactor this method to make the sum using big decimal values. Let's also adjust this code to do the same thing, but with big decimal values. Okay, the refactoring is done. Now in the api dot services package. Let's create the dust calculator class. Let's add the service annotation to it. Let's create these dust method in it. As its name suggests, it will return true if an amount is considered dust false, otherwise, it will return a Boolean and take a big integer as its parameter representing the amount in Satoshi's. This method will evaluate if the amount in Satoshi's of an output is smaller than the cost to spend it. The cost of spending is equal to the V size of the output plus the v size of the input necessary to spend it, which will store in this constant times the dust relay feet in Satoshi's per kilo v bytes divided by 1,000. Since we will work only with sigmoid outputs for now, we'll worry only about the dust limit for segue outputs. So let's create this constant which will be equal to 98. This value is taken directly from the Bitcoin Core policy dot cpp file mentioned in the last presentation. Let's also inject the dust relay fee into this class. It will be along and its value will be injected from the properties file. Let's add the following value annotation before it. Now let's add this value to all properties files. Let's set it to 3,000, the same default value used in the Bitcoin Core Node. Now in the api dot services package, Let's create the coin selector interface. Will create this interface so that it enables more flexibility. If we want to create more coin selector implementations later. Let's add the select method to it. It'll return a list of selected UTXOs. And it'll take us parameters, a list of UTXOs, a big integer for the amount to send, a big decimal for the fee rate, and address to send, and a change address. Now in the same package, Let's create the single random draw coin selector, which will implement this interface. Let's implement its method and add a Service annotation to it. Let's inject the transaction size calculator into this class. And let's inject the dust calculator into it. Before continuing to implement the select method, let's create the single random draw a coin selector test class. In the API test class. It'll extend the specification class. Let's inject the single random draw into this class. And let's use the setup method to instantiate it. Let's pass the transaction size calculator and the dust calculator with a dust relay fee of 3,000 as its parameters. Now, let's create a test Tidal should select expected n inputs, coins for transaction with expected and outputs outputs. Now let's create a utility class that will help us to test and implement the single random draw coin selector. Let's call it Satoshi and created in the utils package. Now, let's create the two Satoshi's method. It'll take a big decimal as a parameter and returns a big integer. This method will convert an amount in Bitcoin to the same amount in Satoshi's. To do that, we simply return the amount in Bitcoin multiplied by 100 million and convert the result to a big integer. Let's also create a method to do the inverse operation, which is to convert Satoshi's to Bitcoin. For that, we'll just return the amount wrapped in a new big decimal divided by 100 million. In the divide method will pass eight as the second parameter to make the result have eight decimal places. We'll also pass the rounding mode unnecessary as the third parameter. Now, let's create a method to convert a fee rate in Bitcoins per KV bike to Satoshi's per V byte. It'll be named BTC per KB to Satoshi's per byte. It'll return a big integer and take as its parameter a big decimal. First, we will multiply the fee rate by 100 million. Then we'll divide the result by 1024 with two decimal places and a floor rounding mode. Then let's convert the result to a big integer and store it in the right variable. If the result is less than one, then we make it equal to one. Finally, we return the converted rate. In the next video, we'll finish testing and implementing the single random draw coin selector C. Yeah. 50. Implementing the Single Random Draw Coin Selector: In this video, we'll finish implementing the single random draw algorithm. In the single random draw coin selector test in a given block, we'll first create UTXOs using this method and store the result in the UTXOs variable. These will be the available UTXOs that will pass as the first parameter to the tested method. So let's create this method. It will take a list of big integer as its parameter, which will define the amount of each UTXO. So for each element in the list, we'll call the create UTXO method to create a single UTXO. Let's create this method. Let's instantiate a UTXO with these parameters. You can copy these values from this lesson's resources. Now, let's create an additional UTXO and add it to the list of UTXOs using this code. The reason to add an extra UTXO to the list is that we want to allow the select method to wrongly add it to the selected UTXOs list. If that's the case, we'll know that the tested method is not working as expected. Let's define these two addresses. One to be the address to send and the other to be the change address. You can copy them from the Project and Resources page. Let's set the fee rate to 0.0 002. In the wind block, we'll call the single random draw select method with these parameters. In the then block will check if the selected UTXOs size is equal to the expected number of inputs variable in the where block. Let's add these test cases. You can find them on the Project and Resources page. These test cases covered transactions with 12.3 inputs and with 1.2 outputs. The input amounts for transactions with one output are expected to not generate change or to generate change with dust whose value is added to the fee. The input amounts for transactions with two outputs are expected to generate non does change, which returns to the sender via a second output. Let's run the test. It has failed as expected. Now, let's implement the single random draw select method. First, we'll filter all received UTXOs to create a list with only UTXOs that have one or more conformations. So let's create this method. To do that. We'll call the filter method on the UTXOs stream, returning a list with only confirmed UTXOs. Now, let's create this variable to store the fee rate in Satoshi's per V byte. For that, we'll use the BTC per KB to Satoshi per bike method from the Satoshi class. Now, let's store the shuffled UTXOs in this variable, assigning the return of this method call to it. Let's create this method. First, we'll instantiate a new ArrayList containing the UTXOs list content. Then we'll call the collection shuffle method, passing the new list as its parameter. Then we'll return the shuffled coins list. Now let's instantiate an ArrayList that will store the selected UTXOs. And let's create this variable to store the total input balance. Now for each UTXO from the shuffled coins list, we'll add the UTXO to the selected UTXOs list. And we'll add its amount in Satoshi's to the total input balanced variable. If the total input balance is less than the amount ascend, we continue the execution from the next loop iteration. After the if statement, when the total input balance exceeds the amount to send will instantiate an ArrayList with the output addresses and add the address to send to that list. And we'll create a list with the addresses of the selected inputs using this stream mapping. Now, let's calculate the total fee in Satoshi's and stored in this variable. For that, Let's call the total fee method, passing the fee rate in Satoshi's per V bite the input addresses and the output addresses as its parameters. Let's create this method. Inside it will return the transaction size calculator calculate method call passing the input addresses and output addresses as its parameters. Then we'll multiply the result with the fee rate in Satoshi's per V bite. Now we'll create the adjusted target variable, which will be equal to the sum of the amount to send and the total fee. Now let's add the change address to the output addresses list. We'll calculate the total fee with change, calling the total fee method, passing these parameters. And we'll calculate the adjusted target with change, which will be equal to the sum of the amount of sand and the total fee with change. Now, if the result of the input balanced fulfilled transaction method with these parameters is true, we will exit the loop using the break keyword. Let's create this method. It'll return the result of the following statement. If the total input balance is equal to or greater than the adjusted target and the generated changes dust, then it means that the selected UTXOs are enough to fulfill this transaction. Another condition for the selected UTXOs to fulfill the transaction is that they're amounts sum is equal to or greater than the adjusted target with change. Let's create the change is dust method will return the dust calculator is dust method call passing the big integer difference between the total input balance and the adjusted target as its parameter. Finally, we'll simply return the selected UTXOs from this method. Now, let's go to the single random draw coin selector test and run this test. Grade. The tests have passed. 51. How Segwit Transactions are Built and Validated: In this presentation, we'll see more details on how to create a transaction. So let's say we already used the coin selector to select some UTXOs to spend as inputs in a transaction. In our wallet, we also have the ability to derive the private keys necessary to spend these UTXOs. These private keys will be necessary to sign the transaction later. We've already chosen an address to send some Bitcoins. And we have the change address where the change will be sent to. After defining these things, it's time to construct our transaction. Let's see the fields that are part of a Bitcoin transaction. First, the version field. It's used to define the rules that the transaction follows. Currently, version one, which we will use is for common transactions. Version two is for transactions following the BIP 68, which implements rules to validate a transaction only after a certain time. The lifetime field is used for a similar purpose. Its value can represent a certain time to add a transaction to a block or zero to ignore this rule, then we have the seg would flag and marker. It's only present in Segway transactions. If its value is 0001, then it marks this transaction as having said what inputs, each transaction has one or more transaction inputs. Each transaction input has a transaction ID which defines a previous transaction from which the current input is spending Bitcoins. The output index indicates which output from the previous transaction. The current input is spending Bitcoins from. Together the transaction ID and the output index are called the out point. You can view the outpoint as a coordinate to identify which UTXO and input refers to. Next, for each input, we have the scriptSig field. In segment inputs. This field is empty and its content is moved to the witness field. In non segment transactions, its content is needed to unlock the spending of the UTXO. The input is referring to. The n sequence field defines when the input is valid to spend. When this field value is equal to the maximum hexadecimal value for its size, this field is ignored. A transaction also has one or more outputs. Each output contains a script pub key, which has script code defining the rules to spend that output in a future transaction. Each output also contains an amount field which defines the number of Satoshi locked in that output. Finally, transactions also contain a witness field. For non Segway transactions, this field is empty. For Segway transactions, the witness contains all the content that in non sequitur transactions is in the scriptSig of each input. Now let's talk about how to build transaction inputs and the witness field for segment inputs. For every selected UTXO, we have to build one transaction input. The transaction ID field of the transaction input will be equal to the UTXO transaction ID. The output index field will be equal to the UTXO output index, also known as Vout in the Bitcoin Core RPC API documentation. The scriptSig will be empty and the end sequence will be equal to this hexadecimal value, which is the maximum value allowed for that field. We also have to build one witness for each input, the witness field will contain a signature obtained using the private key used to derive the UTXO address. And a public key which was derived using the previous private key and which can also generate the same UTXO address mentioned. We'll see more details about the signing process in a future presentation. Notice the dummy signatures and bupkis, which values can be a bunch of zeros, can be used as placeholders to create and sign transactions. This trick facilitates transaction v size calculation before signing transactions. Now let's talk about how to create segue what outputs. First. On a side note, it's possible to create a transaction with different types of inputs and outputs, e.g. in the same transaction, you can have segment and non segment inputs and outputs. Back to the main subject. Generally, we want to create one output for the address to which we want to send bitcoins and one output for the change address. If the transaction needs a change. Each transaction output has a script pub key field. Each segment script pub key, also known as pay to witness pub key hash or P2, WP k H has a witness version of zero. The witness version is one for taproot scripts. New versions can be added for future scripts if needed. The second script pub key item for sigmoid outputs is a public key hash, which is obtained by Beck 32 decoding the address for that output. The transaction output also has an amount field in Satoshi's representing the amount sent to that output address. Now, let's finish this presentation by talking about the segment script execution and validation. When a node receives a transaction, it starts to validate it. For each input in a transaction, the node combines the witness from an input with the script pub key of the UTXO referred by the outpoint and net input executes the combined script and validates it. Let's see how that's done. Here is the script pub key of a UTXO and the witness field that wants to spend that UTXO both generate the following combined script. You may be asking where the opcodes from the combined script came from. It turns out that when a node identifies the zero version on the segment script pub key, it triggers a special rule that generates part of the combined code below. Next, the combined script is executed just like non-sequiturs scripts. From the combined script, the signature and public keys are added to an execution stack. Then the OPT up opcode duplicates the pub key in the execution stack. Up hash 160 hashes, the last pub key added to the stack. Then from the combined script, the pub key hash is added to the stack. Up equal verify opcode removes the last two elements from the execution stack and compares them. If they're equal, the script continues to execute. Finally, the object sig opcode checks if the signature is valid for the pub key remaining in the stack. If it's valid, it returns true to the execution stack. After all the script elements were added to the execution stack, the transaction input would be considered valid if the last added element is true. This process must be repeated for every transaction input. For a transaction to be considered valid, all its inputs must be valid. Just as a visual reminder, let's review from where each element in the script pub key and witness came during transaction construction. The pub key hash present in the script pub key came from back 30 to decoding the address of the UTXO that is being spent. The signature in the witness came by applying the ECDSA algorithm, which needs a valid private key. The public key and the witness came from the public key derived from the mentioned private key. The same public key was used in the past to generate the address of the UTXO being spent by sequentially applying the hash 160 algorithm and back 32 encoding. 52. Implementing the Transaction Creator: In this video, we'll create a transaction creator service. At first, this service will only deal with segment inputs and outputs, but later in the course, we'll improve it. So in the api dot services package, Let's create the transaction creators service. Let's add the service annotation to it. Let's also inject the dust calculator into it. Now in the API test package, Let's create the transaction creators service test class. It'll extend the specification class. Let's inject the transaction creators service into it, and let's instantiate it in the setup method. Will need to instantiate it with a new dust calculator passing 3,000 as it's dust relay fee parameter. Before making this test, Let's go to the single random draw coin selector test to make a little refactoring. Let's cut these two methods from this class and paste them into the new utils class we'll create in the BYOD W test package. Let's make these two methods static. Now, let's fix the single random drug coin. Select your test to use these methods from this class. Now, let's go to the transaction creators service test. Let's create a test called should create transaction with hashtag n inputs, inputs and hashtag expected n outputs, outputs. In the given body. Let's first create this UTXOs variable and assign the utils dot create UTXOs method call returned to it, passing the input amounts variable as its parameter. Now, let's create this address to send variable. Its content will be equal to the variable with the same name in the single random draw coin selector test. Let's also create the change address variable, which will be equal to the variable with the same name in the single random draw a coin, select your test. Let's create the fee rate variable, which will be equal to 0.000 to. Let's also define the expected total fee variable, which will be equal to the expected size variable times the fee rate in Satoshi's per V bite. Now, let's create the variable total input amount. Its value will be equal to the result of this expression, which will return the sum of every UTXO amount in Satoshi's. The amount to send variable will be equal to 100 million Satoshi's. Let's also calculate the expected change amount. It will be equal to the input amount minus the amount of sand minus the expected total fee. In the one-block, we'll call the transaction creator create method will pass the following parameters to this method. The result will be stored in the transaction variable. In the then block will check if the transaction v size is equal to the expected size variable. But first, let's update the Bitcoin Java version to 0.4, 0.2 to make the get v size method available. Now, we'll check if the number of transaction outputs is equal to the expected and outputs variable. We'll also check if the first output amount is equal to the amount to send variable. Now, if the expected number of outputs is greater than one, will check if the change amount is equal to the second output amount in the transaction. In the where block. Let's add the following test cases. You can copy them from the Project and Resources page. These test cases covers scenarios with and without change outputs and with input amounts that generate does changes or not. They also covered transactions with 12.3 inputs. Now let's create the transaction creators service create method. Let's rename these parameters. Before implementing this method, Let's create the fee class in the utils package. Here we'll create a method to calculate the transactions total fee in Satoshi's, let's call it total calculated fee. It will receive a transaction in the fee rate in Bitcoin per KV bite will create the following code inside a try catch block. First, we'll convert the fee rate from Bitcoins per KV bike to Satoshi is privy byte. Then we'll return the result by multiplication the transaction v size by the fee rate in Satoshi's per V bite will catch an IOException which can be thrown by the good V size method and rapid in a new runtime exception. Back to the transaction creators service. In this method will first build the transaction inputs using this method, passing the received UTXOs as its parameter. Let's create this method. We'll return the result of the following UTXOs stream transformation will not the stream into a new transaction input will pass the received UTXO ID as its first parameter. The big integer value of the UTXO vowed as its second parameter. These two parameters define the transaction input outpoint. Next, we'll pass a new script instantiated with an empty list. This parameter is the transaction input scriptSig, which is empty for segment inputs. Next, we'll pass a big integer instantiated with these parameters, which defines the input in sequence. This value is the maximum value allowed for this field, making the nodes ignore it. Now, for each transaction input in the stream will use the peak method to set the witness, will instantiate the witness with a list containing constants for a dummy signature and a dummy pub key. Now let's create these constants. The dummy signature will be equal to the hexadecimal string zero repeated 144 times, which size in bytes is equal to 72. The dummy pub key will be equal to the hexadecimal string zero repeated 66 times which size in bytes is equal to 33 will set these dummy values because they will be necessary to correctly do the transaction v size calculation, which will make in the create method, the signing process will be done separately later when the real values, we'll substitute the dummy ones. Finally, we'll convert the stream into an ArrayList and return it. Now, we'll build the transaction output for the address to send using the buildup PUT method, passing the address to send and the amount to send as its parameters. Let's create this method. First, we'll parse the address prefix using the parse prefix method, which will create. This method will check if the address starts with one of the valid segment prefixes, and it will return the address prefix or an empty string if a valid prefix was not found. Now we'll build a script object using the script class P2, WP k h script method. As its parameter will pass the result of the back 30 to decode method call, passing the prefix and the address to the latter. The return of the back 30 to decode method is an object array where the second element is the pub key hash, which will pass to the P2 WP k h script method. This method will return the equivalent of the script pub key, where the first parameter is zero and the second parameter is the pub key hash, as we explained in the last presentation. Finally, we'll return a new transaction output instantiated with the amount and the created script. Now, we'll create an ArrayList to store the transaction outputs, will instantiate it, adding to it the address to send output we've just created. Next, we'll create the transaction will pass as its parameters, the big integer one, which is the transaction version. The transaction inputs, the transaction outputs. The big integer zero is the lock time which will be ignored. And the boolean true to define this transaction as a segue transaction. This parameter will make the transaction have the Segway marker and flag. Now, let's calculate the total transaction fee using the total calculated F0 method which we've created previously in the FI class. We'll pass the transaction and the fee rate as its parameters. Let's also calculate the input zone for that will map the UTXO stream into a stream of UTXOs amounts. Then we'll use the reduced method to sum them. Finally, we'll convert the result is a ptosis or zero if the UTXOs don't exist. Next, we'll calculate the change which will be equal to the input sum minus the amount of sand minus the total fee. Next, we'll add the following if statement. Using the dust calculator will check if the change is dust. If it is, then we'll return the transaction as is. If it's not, we'll add another output to the transaction using the build output method, passing the change address and the big integer one as its parameters will pass one to the output amount just as a placeholder value, since we'll have to recalculate the transaction fee for the transaction that now has two outputs which demands a higher fee. So let's recalculate the total fee using the total calculated F0 method. Again, Let's recalculate the change which will be equal to the input sum minus the amount to send minus the new calculated total fee. Now, let's remove the last added transaction output from the transaction outputs ArrayList. Let's check again if the new calculated change is dust. If it is, then it will return the transaction without change. If it's not, we'll add a new output to the transaction using the build output method. This time, we'll pass the real change value for the transaction with two outputs to this method. Finally, we'll return the transaction. Now let's go to the transaction creators service test and run this test. Great, the tests have passed since we've previously changed the single random draw coin selector test. Let's also run it again to ensure we haven't broken anything. They're great. It's working as usual. 53. The Send Transaction Dialog Window : In this video, we'll start to create the window that will pop up when we click on the Send button. That window will contain information about the transaction. We're sending a password field and an Okay button to confirm the transaction broadcast. So in the FXML package, Let's create the send underscore transaction underscore dialog dot FXML file. Let's erase the generated boilerplate. Now, let's create a dialogue pain tag. Now, let's change the view to the Scene Builder. Let's set the dialogue pain pref height to 300. And it's pref width to 650. And let's make the min-height min-width to use the press size. Now, let's add a grid pane to the dialog content. Let's add four more rows to this grid pane. Now let's add a label to the first row. Let's change its text to send transaction question mark. Let's increase its font size to 16 pixels. For the next rows, the idea here is to add labels and data for the sending transaction. Let's add a label to the second row and change its text to amount to send colon. In the second column of the same row. Let's add another label. This time it's text will be empty and we'll add an Fx ID to it so that we can change its content dynamically later. Let's add another label in the third row, this time with the text total fees in the cell at the right. Let's add an empty label with another FX ID. In the row below. Let's add another pair of labels for the total field. In the next row. Let's add these labels for the fee rate. Now, let's do the same for the address to send. In the last row. Let's add a label for the wallet password. In the cell at the left. Let's add a password field. It'll have an FX id of wallet password. Sudden labels are missing a colon at the end. Let's fix them. Now. Let's go to the dialogue pain setup and add an OK button here. Let's also add a cancel button. The Cancel button text is in my native language. If that's also your case, you can change it by doing the following. Let's go to the editor view. First, let's add an Fx idea of okay to the Okay button. And let's add an Fx idea of cancel to the cancel button tag. Now, let's remove this property. Let's set the button data property to this value, and let's set its text to cancel. Now, in the Scene Builder, we can see that the change took effect. Now, let's go to the Send tab FXML. In the Send button, Let's set the action property to hashtag send so that when we click on this button, the send method of the Send tab controller will be called. So let's create this method. Before implementing it, Let's create a transaction DTL record in the domains package. Ttl stands for data transfer object, and it's a common design pattern to use for objects whose main purpose is to transfer data between classes and methods. As such, the transaction DTO will be used to transfer transaction data between our services. Let's add the following fields to it. At this point, you may be asking what's the difference between the total actual fee and the total calculated v? We'll get to that shortly. Now, let's go to the Send tab controller. Let's add the following fields to it. These fields will bind to the corresponding tags in the Send tab FXML file. Now let's implement the send method. First. We'll convert the amount to send text into a big decimal amount. Now, we'll create a transaction DTO object using the create transaction service will create. Let's inject this service into this class. Let's create it in the GUI dots services package. Now, let's finish injecting it into this class. Here we'll call the create method on it, passing the address to send text and the amount variable. Let's create this method. Now, we'll use this method to open the dialog window, passing the transaction DTO as its parameter. Let's create it. After opening the dialogue window, we'll call the clear method on the address to send and the amount to send variables to erase the content in these inputs. Now, let's go to the create transaction service. Let's add the service annotation to it. We'll implement the create method. Now, the idea here is to use many of the services we've built in the past videos to create a transaction and some additional data for the transaction DTO. For that, the first thing we'll do is to use the estimate fee service to get the fee rate and store it in the fee rate variable. So let's inject this service into this class. And let's call the estimate method on it. Now, we'll get the currently loaded wallet addresses using the current wallet object. So let's inject it into this class. Then we'll call the get addresses as strings method on it. Next, we'll get all our wallet UTXOs. For that, we'll use the node list unspent client. So let's inject it into this class. We'll call the list unspent method on it, passing the addresses and the current wallet name as its parameters. Now, we'll use the coin selector to select the UTXOs that will be used as inputs in our transaction. So let's inject the coin selector into this class. Now, we'll call the select method on it, passing the UTXOs, the amount converted in Satoshi's the fee rate, the address to send, and the current wallet change address, calling the current wallet get change address method, which will create. So let's create this method. It will simply return the change address property. Let's create this property as a string. Let's move it to here. Let's also create a setter for it. We'll use it later. Now, let's use the transaction creators service to create a transaction. So let's inject this service into this class. Let's call the create method on it, passing the following parameters to it. Now that we have our transaction will build additional data to include in the transaction DTL. Next. First, let's use the total actual fee method from the FI class to get the total actual fee will pass the transaction and the selected UTXOs as its parameters. Let's create this method. The difference between the total calculated feet and the total actual fee is that for the latter, we use the difference between the inputs and outputs amounts to calculate it. While for the former, we estimated using the transaction size and the fee rate. In theory, it's expected that both values be the same, but let's default to using the total actual feet when possible, to guarantee that we're showing the user the actual transaction fee and to let the user spot possible buggy three values. So here we'll calculate the input amounts, some in Bitcoin using the following stream transformation. We'll map the selected UTXOs stream to produce a stream of UTXOs amounts. Then use the reduced method to sum all values in the stream. And use the or else method to return zero if the string is empty. Now, let's calculate the output amongst some in Satoshi's will do the same transformation we've done for the inputs, but with the transaction outputs this time. Now we'll return the input some in BTC is converted to Satoshi's minus the output some. Back to the Create transaction service. Now, let's create the total calculated F0 variable and assign the result of the total calculated F0 method call to it. This time, we'll pass the transaction and the fee rate as its parameters. Now, let's calculate the total spent, which as the name suggests, is the total amount in Satoshi's that the sender spent on this transaction. For that, let's use the total spent method passing the transaction, the total actual fee and the address as its parameters. Let's create this method. With this if statement. Let's check if the address to send belongs to our wallet. If not, then we'll return the total actual fee plus the first transaction output amount. If our wallet contains it, that means we are transferring bitcoins to ourselves, and thus we're spending only the transaction fee. Finally, we'll return a new transaction DTO object instantiated with these parameters, will continue to implement the dialog window feature in the next video. See you. 54. Showing Transaction Data in the Send Bitcoin Dialog Window: In this video, we'll finish implementing the transaction dialog window. So let's go to the Send tab controller. In the open dialogue method, Let's instantiate a new dialogue object like this. Then let's call the unit owner method on it, passing the window object as its parameter, like this. Let's set the dialogue title to send transaction. Now with the following code, we'll define that when we click on the Close button of the dialog window, the dialog window will close. Next, we'll create an FXML loader object inside a try catch block. To instantiate it will need to inject the dialogue FXML resource into this class. Let's do it. Let's add a value annotation to this field indicating the path of the sin transaction dialogue FXML. Here we'll call the get URL method on it. Then we'll use null in these parameters. And the context get beam method reference here. First, let's make the context object of field in this class and assign it here. Now, we'll set the content of the dialogue pain to the result of the FXML loader load method call. Now with the following code, will get the syn transaction dialogue controller from the FXML loader. Let's create this controller in the controllers class. Finally, we'll pass the transaction DTO object to the sin transaction dialogue controller using the set transaction method. Let's create this method. Here, we'll catch an IOException that the FXML loader can throw and wrap it in a new runtime exception. Then we'll show the dialogue using this method. Now, before implementing the second transaction dialogue controller, Let's go to the update current wallet service. When we update the current wallet, we must set its change address, which will be used when we send a transaction. So let's do it. We'll do it by getting the second extended public key from the created wallet. Remember that this extended key was derived to generate change addresses. Then we'll get its first address and set it as the current wallet change address. Now, let's go to the second transaction dialogue controller. Let's set the Component annotation to it. Now, let's go to the second transaction dialogue FXML. Let's set the dialogue pain FX ID. And let's set the FX controller property to the recently created controller path here. Now we'll set every tag with an ethics ID in this file, this fields in the second transaction dialogue controller by using this cool IDE feature. Now let's set every field here is private. Let's add the FXML annotation above all of them. Before implementing the Set Transaction method, let's create the transaction dialogue domain in the domains package. Will need this record soon. It'll model the fields will show in the transaction dialogue. So let's create these fields. Let's also create this from method. It'll create a new transaction dialogue from a transaction DTO. We'll use the Bitcoin format or format method to correctly parse the amount to send the total actual fee and the total spent will also pass the fee rate and the address from the transaction DTO to the transaction dialogue instantiation. Back to the second transaction dialogue controller. In the set transaction method, Let's set the transaction D TO field to the Received Transaction DTO. Let's create this field in this class. Now, let's create the transaction dialogue object using it's from method passing the transaction DTO as its parameter. Then we'll set the amount to send text to the transaction dialogue amount to send will set the total fees field text to the transaction dialogue, total fee. The total field text to the transaction dialogue total the fee rate field text to the transaction dialogue. Fee rate concatenated with the string BTC slash KV. Bite. Let's set the address to send field texts to the transaction dialogue address to send. Now let's create the initialized method in this class. Here will bind the cancel button to an action that will close the dialog window. To do that, Let's call the Lookup Button method on the dialogue pain passing the cancel field to it. Then we'll call this method to add an event handler to the cancel button. The handler will receive an action event and an event as its parameters. And the handler body will use this statement to close the dialog window. Now, let's go to the send Bitcoin test. Something is missing in this test. After calling the send Bitcoin and wait method, we have to instruct the node to mine a block so our UTXO gets confirmed and can be used to create a transaction. To handle that, Let's call the generate to address method on the node generate to address client passing these parameters to it. And let's move this code line to here. Now, let's run our node. And let's run this test. As expected, the test has failed, but the transaction dialogue opened and was populated with transaction data. Now, let's improve this test. Will check if the values in the transaction dialogue are correct. But first, let's make this test more resilient. After clicking on the send button will add code to make sure we wait for the transaction dialogue to appear before acting on the dialog window. So let's create the weight for dialogue method. Here, we'll call the weight for method. Passing these parameters to wait timeout seconds in the lambda body will get the dialogue pain and return only after it is not null. Now, let's get the value for each label in the transaction dialogue and store them in the following variables. Let's add the transaction row type here. And let's change the table view name to transactions table. In the then block, let's add the following assertions to check if the labels in the transaction dialogue are correct. Now, in the where block, Let's add a test case to populate the variables we've just referenced in the then block. It's missing an equal, equal sign here. Let's fix it. Let's add another test case. Now, let's remove these lines. Will adapt the code to create previous transactions according to the previous UTXOs number variable. So for each UTXO defined in that variable will look up for the receiving address. Then we'll call the send Bitcoin and wait method with these parameters. Now, let's substitute the parameter in the right method call for the amount to send variable. Now, we have to make sure that the fee rate is equal to 0.0 002 for the test to work. To do that, we'll inject the node estimate fee service into this class and add the mock Bean annotation to it. Then in the setup method, let's add the following code. It'll make sure that when the estimate method of the service gets called, then it will return the fee rate value we want. This lookup method perimeter is missing the letter S at the end. It's total fees. Now, let's run the test. It is failed, but for the wrong reason, notice that the amount to send label is empty. That's because there's another label with the same FX ID in the Send tab controller. There is also an address to send field with the same FX ID. Let's go to the second transaction dialogue controller to fix that. Let's rename this field to amount to send dialogue. And let's rename the address to send field to address to send dialogue. Let's go to the send transaction dialogue FXML to change the labels FX IDs. Okay, We don't have to, because the IDE did that job for us. Back to the send Bitcoin test. Let's update these parameters to look up for the correct labels. Now, let's run our test. Okay, the tests have failed, but only because the transaction table doesn't contain the expected number of transactions. That means the transaction dialogue labels are correct. Great. 55. How Transaction Signatures Work: In this presentation, we'll show how transaction signatures work. First, let's review the fields of a transaction input. Transaction inputs have a transaction ID field whose content indicates from which transaction the UTXO being spent in that input came. The output index field indicates which UTXO from the previous transaction the input is spending. Together, both fields make an out point which unequivocally indicates which UTXO, the input is spending. The scriptSig field is empty for segue transaction inputs contains an unlocking scripts for non segue transaction inputs. That unlocking scripts is a signature and a public key for common transactions. Finally, the transaction input contains the end sequence field. The end sequence field defines when the input is valid to spend. This field is ignored when its value is equal to the maximum hexadecimal value for its size. For segue transaction inputs, the content which for non Segway transactions is in the scriptSig is moved to the witness field. The signature in that field is an ECDSA signature obtained using the private key used to derive the address of the UTXO. The input is spending. The other field in the witness is the public key, which is derived from the private key we've just referred to. But wait, what is an ECDSA signature? Ecdsa stands for Elliptic Curve digital signature algorithm. It's a signing algorithm that combines a private key and a message to produce a signature. And ECDSA signature has a property that allows verifying if it's valid, that is, verifying if a given signature was produced by a given private key and a message by using the public key derived from that private key, the message and the signature. That way, we can verify if a signature is valid without revealing the private key used to generate it. You can use the ECDSA to sign any message you want. In the case of a transaction signature, the message being signed is a modified version of the serialized transaction. So let's see how Bitcoin transactions are signed. To sign a transaction, you have to sign each transaction input separately. For each transaction input starting with an insane transaction, which is a transaction where its inputs have empty script, CIGS and witnesses. You create a signature hash, which is the hash of a modified version of the serialized transaction. To do that, you use a signature hash algorithm, which we'll explain in the next slide. The signature hash will be the message to be signed with a private key valid for that input and the signature hash use the ECDSA to generate the signature. Remember that the valid private key for an input is the same private key used to generate the address from the UTXO that input is spending. If the input is a segment input, add the signature and the public key derived from the referred private key to the witness. Otherwise, add these elements to the input scriptSig field. When nodes receive a transaction, they verify if the transaction signatures are valid. To do that, they use the signature verification algorithm cited in the previous slide. They do that during the script execution as explained in the last presentation. Now, let's see how the signature hash is generated. There are different signature hash algorithms for segue, non segment and tap root transaction inputs. However, the three algorithms modify the transaction in some way and produce a hash, which is the message that will be signed. Let's see the signature hash algorithm for a segment inputs. To create a signature hash for a given transaction input, start with an empty string, then add the transaction version to the string, concatenate all out points from the transaction inputs. Hash the results using the hash 256 algorithm append the resulting hash to the string, then concatenate all inputs and sequences. Hash 256 the result, and append the hash to the string. Now add the outpoint of the input being signed to the string. Add the script pub key of the UTXOs spent by the input being signed to the string. Add the amount of the UTXOs spent by the input being signed to the string. Add the end sequence of the input being signed to the string, concatenate all transaction outputs. Hash 256, the result, append the resulting hash to the string, add the transaction lock time to the string. Add the hash type, which is sig hash all for common transactions to the string. There are other hash types, but they are rarely used. They define the inputs and outputs. The input being signed can go within a transaction. Sig hash. All means that the signature produced is valid only in a transaction with all the inputs and outputs of the given transaction. Finally, hash 256, the obtained string. The result is the signature hash for the input being signed. A signature hash must be obtained for each transaction input being signed. The process is replicated by nodes when they verify the transaction signatures. 56. How Our Wallet and Node Will Handle Sent Transactions: This presentation will explain what happens when we send a transaction to a Bitcoin node. Then we'll see how our wallet currently handles receiving transactions and how we plan to change it to correctly calculate the transactions addresses and total wallet balances after sending a transaction. So let's see how a Bitcoin node handles transactions sent by our wallet. Our wallet will send transactions to our node through the note RPC method called send raw transaction. Our application will send the sign transaction in a hexadecimal format to our node. After receiving the transaction, the node validates it. If the validation pass, the node broadcasts the transaction to other nodes in the Bitcoin network. The other nodes do the same until all nodes in the network acknowledged the transaction. The transaction remains in the mental for awhile, waiting for a minor to include it in a block and mined the block with it. Eventually, a minor broadcasts the mind block with the transaction to other nodes in the network. As the nodes receive the mind block with the transaction, the transaction is excluded from the mental and is considered confirmed. Each block added after the block with the transaction adds a confirmation to the transaction. It is recommended to wait for six conformations for a transaction to be considered irreversible. Now, let's see a naive model of how our wallet can handle send transactions. After our wallet sends a transaction to our node, the node will send back through zero MQ, the same transaction to our application. Our node task service will detect the transaction and send it to our transaction received listener. As most transactions will have a change output, the transaction received listener will usually verified that the change address is from our wallet. And we'll use the update UTXOs service to update our wallet addresses, transactions and balances, but relying only on the transaction received listener as it currently is to update our wallet will raise some problems. First, the balance calculation of the update UTXOs service does not consider the input balances. So we will have to modify how our wallet calculates a dress and transaction balances to discount the input amounts from the change amounts. But we'll have to deal with a bigger problem with this model. What about transactions without change? In this case, the transaction received listener won't consider the receipt transaction is ours since it verifies only the output addresses and the scent output won't be from our wallet. Thus, our application wouldn't update. It's balanced for these cases, will adopt the following strategy to overcome these problems when updating our wallet after sending transactions. After sending the transaction to our node, will publish a transaction sent event which will be captured by a transaction sent listener. Then the transaction send listener will use the update UTXOs service to update the wallet with the transaction to eliminate the issue of not updating transactions without change, both the transaction received listener and the block receive listener will use a node list transactions client to search for all transactions related to our wallet in the node, this client will send a list transactions RPC call to our node, which will return all relevant transactions to the client. Then using the return transactions, the update UTXOs service will update all transactions in our wallet and their balances correctly. 57. Signing and Sending Segwit Transactions: In this video, we'll build some classes and services that will allow us to sign and send transactions. So first, let's create a class called transactions signer service in the api dot services package. Let's add the service annotation here. Now let's create the sign method here. It'll take a transaction object on mnemonic seed, a password, and a list of UTXO DTLs a class will create. So let's create it in the domains package. Now, we'll use the stream range method to loop over each UTXO DTO. For each UTXO DTO, we'll call the sign method passing the parameter a, which is the index of the input to be signed, the UTXO DTO, which will get using the i parameter, the transaction, the mnemonic seed, and the wallet password. Let's create this method. Let's change this parameter name to mnemonic seed string to sign a transaction input. First we have to derive the valid private key to unlock the UTXO that input is spending. If you want to remember how that's done in greater detail, re-watch the HD wallets and Bitcoin addresses presentation. So first, we'll instantiate a mnemonic seed object here, passing the mnemonic seed string and the instantiation. Now we'll derive a master key using the mnemonic seed to master key method as its parameters will pass the password. And this prefix. For our use case, it's okay to pass the main net private prefix even if we use it in another environment because it affects only the master key serialization, not the derivation process. In the process of deriving the master key that to master key method first derives the root seed, which is mentioned in the previously referred presentation. Now, we'll derive the extended private key using the master key CKD method as its first parameter will pass the UTXO DTO derivation path. First, let's create this field in the UTXO DTO. And let's take the opportunity to add the amount field which will need next. The next parameter will be true, which indicates we want to derive an extended private key, an extended public key. The last parameter will be the main net private prefix. Again, no problem using the main net prefix here. Notice that the way we derived the extended private key here is similar to how we derive the extended public key and the extended public key service. We use the same derivation path we've used to create the extended public key to derive the UTXO address for our wallet. Now, we'll obtain the desired private key by simply extracting it from the extended private key through the two private key method. This method is available in the next Bitcoin Java version. So let's go to the POM file to update it. Now inside a try catch block, we can finally use the sign method from the transaction ECDSA signer class from Bitcoin Java. This method will take the transaction, the private key, the input index, the UTXO DTO amount converted to Satoshi's. And the boolean true, which indicates that this input is segmented. The same method will obtain a signature hash with the private key. We'll use the ECDSA to obtain a signature for that input. Then it will insert the signature and the public key derived from the past private key in the transaction witness. The UTXO amount is needed for the signature hash, and the last true parameter is needed for the correct signature hash generation and to correctly add the signature and the public key to the witness instead of in the scriptSig, which is the case for non segment inputs. Finally, we catch a possible IOException that the sign method can throw and wrap it in a new runtime exception. Now, let's create the node send raw transaction client in the node dot client package. This service will be necessary to send our transactions to our Bitcoin node. Let's add the service annotation to it. Let's inject the node client into this class. And let's create the send method. It'll accept a transaction hexadecimal string as its parameter. Here we'll call the node client make request method. We'll use it to call the send raw transaction Bitcoin node RPC method. As usual, let's pass a new parameterized type reference object. Here. The URL is empty, and we'll pass the transaction hex parameter as the last parameter. Now in the GUI dots services package, Let's create the second transaction service. This service will be responsible for signing and sending the creative transaction. After we click on the Send button in the transaction dialogue, let's add the service annotation to this class. And let's create the sign and send method. It'll return a future of type void. And it'll take the transaction DTO and the wallet password as its parameters. Now, first we will create a list of UTXOs, CTOs, by converting the selected UTXOs from the transaction DTO. We'll call the method map on the selected UTXOs stream and use the UTXO DTO builder to build the UTXO d t goes from each UTXO object. So let's inject the UTXO DTO builder into this class. Let's create it in the GUI dot services package. Now, let's create this build method. It'll return a UTXO DTO back to the center transaction service. Here will return the list method called on the resulting stream. Let's refactor here to use the method reference instead of a lambda. Now, let's implement this method. First. Let's add the service annotation to this class. Here we'll get the current wallet address object corresponding to the received UTXO address. So let's inject the current wallet into this class first. Now we'll call the get address method on it, passing the UTXO address as its parameter. Let's create this method. It'll return an address object. Here will return the result of calling the get addressed method on the addresses field, passing the received address as its parameter. Finally, we'll get the current wallet address index and store it in the address index variable. Now, we'll get the same address from the current wallet and get its address type, storing it in the address type variable. Now, we'll obtain the UTXO derivation path by calling the build derivation path method with the address type and the Address index. Let's create this method. Here. We'll use the address configs object to obtain part of the derivation path. So let's inject it into this class. Actually, it'll be a list of address configs. Let's fix it. Now from the stream of address configs, we'll use the filter method to select the address config valid for the address type. Then we'll use the find first method and get to obtain the address config we want. Finally, we'll get the derivation path from the address config and concatenate it with the following string. We'll add a forward slash and then add the address index. Here will return a new UTXO DTO passing the derivation path and the UTXO amount. Back to the send transaction service. Here, we'll need the transaction signer service. So let's inject it into this class. Now, we will call the same method on it as its parameters will pass the transaction DTO transaction, the current wallet mnemonic seed. So let's inject the current wallet into this class. Let's create this method in the current wallet. It'll return a string. Here, will return the mnemonic seed field. Let's create this field. And let's add a setter for this field. The third parameter of this method is the wallet password. The next parameter is the UTXO CTOs. Now, in a try-catch block will use the node send raw transaction client to send a signed transaction to our node. So let's inject it into this class. We'll call the send method on it, passing the transaction DTLs serialized transaction using the serialized method will catch an IOException and wrap it in a new runtime exception. Now we'll use the application Event Publisher. So let's inject it into this class. We'll use it to publish a new transactions sent event passing this and the transaction DTO as its parameters. So let's create the transaction sent event in the GUI dot events package. Let's change the constructor signature first parameter to accept an object. And let's pass this object to the super constructor. And let's set the transaction DTO field to the Received Transaction DTO. Let's add this field to this class. And let's create a getter for it. We'll use this event later. Back to the sign and send method will return a new async result here, passing null as its parameter. Let's add the async annotation to this method passing the default executor service as its parameter. Remember that we're doing that to run this method asynchronously, which is our policy when communicating with our node. Okay, we've created the mnemonic seed field in the current wallet class, but now we have to set it after we create a new wallet. So let's go to the wallet record and add the mnemonic seed field to it. Now let's go to the create wallet service and add the mnemonic seed string here as the last parameter in the wallet instantiation. Now in the update current wallet service, let's set the current wallet mnemonic seed to the wallet mnemonic seed. Now let's go to the second transaction dialogue controller. In the initialized method, let's call the Lookup Button method on the dialogue pain passing the Okay button to it. Now let's add an event handler to this button. The first parameter is an action event, which defines the click on the Okay button as the action. The second parameter is a Lambda method that takes an event object and calls the sign and send transaction method. So let's create this method. Here. We'll need the second transaction service. So let's inject it into this class. Now, we'll call the sign and send method on it, passing the transaction DTO and the wallet password text as its parameters. Finally, we'll close the dialog pain using the hide method on the dialogue pane window. Let's run our node. And let's finally test what we've done by running the send Bitcoin test. Great, the tests have passed. The wallet, detected our transaction and added it to the transactions table. But wait, there's something strange. I'll rewind the video and pause it in the addresses table view to check something. This is the addresses table after our wallet sent our transaction in the first test case, notice that the wallet detected that one of our change addresses in the second row received Bitcoins. Good. But since the address in the first row has its UTXO in the input of the transaction we've just sent, its current balance should be zero because its output was spent. And since our addresses table only shows that dresses with balances greater than zero, this table should only show one row with the change address. Now, let's check the transactions table for the same test case. Boops, the balance of the transaction we've just sent is wrong. It should be equal to -0.5 bitcoin minus the transaction fee. The minus sign would indicate that we've sent a transaction from our wallet. The total balance text is also wrong. It should be equal to 0.5 minus the transaction fee. In the following video, we'll fix those issues. 58. Fixing Transaction and Addresses Tables and Balances: In this video, we'll fix some issues we had in the last video. One of those issues is that the addresses table shows outdated balances for addresses whose output was spent. Since the spent address after being used has a zero balance, it shouldn't appear in the addresses table. So let's adjust this test to verify if the addresses table has only one row and if that row has a balanced equal to the expected change in Mount. Here, we'll get the addresses table by using the lookup method. And in the then block will check if the addresses table has one row. Let's also check if the first row balance is equal to this variable, which we'll define in the web block. Next, let's define the change amount in the wear black cases. Another problem we've seen in the last video is that the balance of the transaction is wrong in the transactions table. That is happening because when our application receives a transaction from our node, it's considering only the change balance as the transaction balance to ensure the test detects this error, let's add the following line and then block will check if the first row in the transactions table has a balanced equal to minus the total spent variable. Balance is also wrong since it's equal to the sum of all transaction balances. So let's make our test detects this problem. Here. We'll check if the total balance text is correct. First, let's define this variable. It'll be equal to the text present in the total balance label of the window after we send a transaction. Let's check if this variable is equal to the following text. And here let's define the funds variable and updated in the end stream lambda. Now, let's run our node. And let's run this test. Okay, The test has failed because the addresses table has two rows. Let's fix those issues. To do that, let's create the transactions sent listener. But first, let's fix something totally unrelated. The block received listener is in the node dot events package instead of the node dot listeners package. Let's fix that. With that out of the way, let's create a transaction send listener in the GUI dot listeners package. As its name suggests, this listener will handle the transaction sent event which the transaction service will publish after it sends a transaction. Let's add the component annotation to it. It will implement the application listener with the transactions sent event type. Let's implement its method. Here will lead the update UTXOs service. So let's inject it into this class. Now, let's call the update method passing the event transaction DTO. Now let's create this method. Here we will obtain a list of UTXOs from the transaction DTO selected UTXOs. We'll use a map on the selected UTXOs stream and instantiate a new UTXO for each received UTXO will pass every received UTXO field in the UTXO instantiation, except the amount which will be zero since we've just spent it. Now to update our wallet addresses, we'll call the update current wallet addresses service update method, passing the UTXOs to it. And to update the wallet transactions, let's call the update method on the Update Current Wallet transaction service will pass the result of calling the transaction row from method to it with the transaction DTO as its parameter. Finally, let's call the update current wallet balanced service update method to update the current wallet balance. Let's create this from method in the transaction row class. Here will return a new transaction row in a try-catch block. We'll instantiate it with the transaction DTO transaction ID. The formatted transaction DTO total spent negated using the negate method. It will make the value negative since we're spending it. It'll have zero confirmations. And its date will be the current date. Finally, we'll catch an IOException which can be thrown by the transaction ID method and rapid in a new runtime exception. Back to the Update UTXOs service. Now let's create the update method which will receive a transaction row in the update current Wallet transaction service will use the platform run later method since the following code will modify the wallet interface. Here we'll pass a lambda that will call the add transaction row method on the current wallet will pass the transaction road to this method. Now, let's create this method. Let's move this method to this location close to the add transaction rows method. Here we'll call the add transaction row method on the transaction rows field, passing the transaction row as its parameter. Let's create this method in the transaction rows class. Here, we'll put the transaction wrote in the transaction roadmap using the transaction row ID as the key. Okay, with these modifications, we expect that at least the addresses table be updated. Let's rerun the send Bitcoin test to verify that. Okay, The addresses tabled now is correct, but the test failed due to the transactions table. The send transactions still is with an outdated balance. That happened because although our sin transaction listener is updating the transaction correctly, when our wallet receives the same transaction from our node, it detects an update is only the change address UTXO. It does not discount the fee and the input we've spent. We must change how we update our current wallet transactions to fix that. In the update UTXOs service update method, which is called after our application receives a transaction, will call the node RPC list of transactions method. This method will return all our wallet transactions, including those we send it smart enough to return transactions with negative balances if they are sent from our wallet. With these transactions in hand, we can update them correctly in our application. So let's use the node list of transactions client to obtain all transactions of our wallet and store them in the node transactions variable. Let's inject this service into this class. And let's create it in the api dot services dot no dot client package. Let's finish injecting it into this class. Now, let's make the node transaction record, which will model the return of the list transactions method, will create it in the domain and start node package. Here we'll call the list transactions method, passing the current wallet name. Let's build this method. And let's add the service annotation here. Let's inject the node client into this class. Here we'll obtain an array of type node transaction by calling the node client make request method with the following parameters. The list transaction string, which is the name of the node RPC method, a new parameterized type reference. The wallet URL concatenated with the wallet name. And asterisk string, which indicates that we want all transactions from that wallet. The max integer value, which means that we want the maximum number of transactions in the response zero, which tells the method that we don't want to skip any transactions. And true, which indicates that we want to watch only transactions included in the response. Watch only transactions are transactions. The node doesn't have the private key to spend. This option makes sense because our wallet doesn't pass any private key to our node. Finally, we returned the transactions array converted into a list. Now let's create the node transaction record fields will add only the fields will use. They are the T XID, the confirmations, the amount, the address, which is the address that the sender intends to send bitcoins to, not the change address. And the time, which is the timestamp of the transaction creation. Back to the Update UTXOs service. We'll call the update node transactions method on the Update Current Wallet transaction service. As its parameter will pass the node transactions. Let's create this method. Here, we will obtain a list of transaction rows from the no transactions. We'll call the filter method on the node transaction stream. As it's parameter will pass a lambda that will take a node transaction and check if the current wallet contains the node transaction address. Then we add an or operator and check if the current wallet contains a transaction with the no transaction ID. This filter will result in a stream of transactions that contains only transactions who is addressed to send is one of our own, which covers receiving transactions. The condition after the or operator will make the transaction stream also includes transactions that our application already has. That means transactions that were previously added by the transaction send listener will have their balanced correctly updated with negative balances. Now, we'll not the resulting stream using the transaction row from method. Let's create this method and move it to here. Here will return a new transaction row instantiated with the node transaction ID. The formatted node transaction amount, the node transaction confirmations, and the node transaction time converted to a string. Now we convert the transaction stream into a list. Finally, we use the platform run later method and using a lambda, we call the Add transaction rows on the current wallet passing the transaction rows to it. Let's remove this method since we won't need it anymore. Let's also remove this method in the transaction row for the same reason. One more thing here in the ad transaction rows method in the transaction rows class, we have to update the transaction row balance before our changes take effect. So let's include the following code to do that. Now, let's go to the send Bitcoin test. Before running it, let's include asleep call after the test clicks on the OK button in the second transaction dialogue. With that, we avoid the test failing due to racing conditions. Now, let's run our test. Great, the tests have passed. Let's run all application tests to ensure we haven't broken anything in our wallets. I'll speed up the video now, since these tests will take some minutes to run in reality. Great. All the tests have passed. 59. Changing Change Addresses. Adding Error Alert for Wrong Passwords: In this video, we'll add more tests to verify if our wallet works as expected when sending transactions in different scenarios. Let's see if our wallet can send two transactions, one after the other. To do that, Let's duplicate this test in the send Bitcoin test class. Let's change its name to. It should send Bitcoin to times. Let's fix its formatting. Let's change the wallet name to my test while at ten. Now let's extract this code section to a method. We'll call it send Bitcoin. Let's add the amount to send as its second parameter. After creating a transaction, will click on the Okay button to send it. Then we'll use this code line to make our node mine a block. With this, we expect our second transaction to be confirmed, allowing us to use the change UTXO generated by that transaction as an input in the next transaction. Now we'll click on the Send tab. And we'll call the sleep method with these parameters to wait for our transaction to be confirmed. After sending the first transaction, we expect our first change address to be shown in the addresses table. We expect a different change address to be used in the second transaction because it's important not to reuse addresses when receiving Bitcoins for privacy reasons. So we'll compare the change address in both transactions and check if they're not equal. To do that, let's look up the addresses table with this code line. Let's change the TableView type to address row for correctness sake. Let's remove the declaration here, and let's take the opportunity to fix the same issue in the previous test method. Will store the first change address in this variable, getting it from the addresses table. Then we'll call the send Bitcoin method again to send the second transaction. After the second transaction will look up the addresses table again. Hopefully the first row in the table will contain the second change address. So let's query it again and store the first row address and the second change address variable. In the then block will add the following assertion to check if the first change address isn't equal to the second. Here, we will expect the transaction table size to be equal to the previous UTXOs number plus two. And let's change this part of the total balance text. We expect the confirmed balance to be equal to the funds minus the total spent. Let's remove this test case, will only have one case for this test. Let's change the amount to send a 0.25. Let's update the total spent accordingly. And let's change the last four digits of the change amount. This change amount is the sum of the change amounts of the two transactions. Now, let's run our node. Let's add the ignore annotation to the first test, since we want to run only the last test. And let's run it. The test has failed because the first change address is equal to the second change address. Let's fix this. Let's go to the update current wallet addresses service will move this code line to this location. Here we'll add an if statement to check if the address being updated is a change address. Let's add this constant to this class. It'll be equal to address type seg would change. In the body of the if statement, will set the current wallet change address to the next address. Let's also add a return statement to this if statement body. Let's rerun the test. Great, The test has passed. Now, we'll start to implement some error handling for situations where things don't go well when we try to send transactions, e.g. what should happen when we use the wrong wallet password when attempting to send a transaction. When our wallet sends a transaction with the incorrect password, this causes the transaction to be constructed with invalid signatures. When our node receives it, it tries to validate that transaction. Since it's signatures are wrong, it will return an error message and won't relay the transaction to other nodes. Currently, our wallet is not handling the returned error and will fail silently. Let's create a solution for this situation. Our node returns an error after receiving our transaction, will show the user an error alert saying the wallet couldn't send the transaction. And y. First, let's create a test for this scenario. In the send Bitcoin test class. Let's duplicate the first method. Let's rename it to should not send Bitcoin with Wrong password. And let's adjust its formatting. Let's also change the wallet name to my test wallet 11. Here we'll click on the password field. Let's define a variable for this password. Let's set it to my test password and write it in the password field. After receiving Bitcoins, let's store the formatted balance in the formatted funds variable. Since we won't be successful in sending a transaction, we expect that the final balance of our wallet doesn't change and continues to be equal to this variable. Now, let's substitute this code section with a send Bitcoin method call. After the transaction dialogue appears, we'll click on the wallet password field. And we'll write the wrong password. After clicking on the Okay button, we expect an error message to appear. Let's define this error message and store it in this variable. Then, with this code, will try to store the node with this message in the node query variable. The error alert will have an Okay button which will try to click. In the then block, will check if the node query texts is equal to the error message. Will also check if the address in the addresses table has a balanced equal to the formatted funds variable. We expect the transaction table size to be equal to one, since we won't show the failed transaction in the table. Let's also change the expected transaction balance here to be equal to the formatted funds. We also expect the total balance and the confirmed balance to be equal to the formatted funds variable. The expected unconfirmed balance must be equal to zero with eight decimal places. Let's remove the second test case in the where block. Now let's implement the error alert feature. In the second transaction service. Let's add a catch statement here to catch an internal server error. This is the error type that the node will return if something goes wrong when we try to send a transaction to it. Now, we'll use the logger to log this error. So let's add the logger to this class as a static field. Will instantiate it using the logger factory get logger method, passing this class as its parameter. Then we'll call the error method on it, passing the error get response body as string method call. Then we'll return the node error handler handle error method call passing the error to it. Let's inject the node error handler into this class. Let's create this class in the GUI dots services package. Let's finish injecting it into this class. Let's create this method in it. It will return a future of type error. Going back to the location which will call it, we see that the ID indicates a type error. To fix that, Let's change the return type of the sign and send method to future of type error. But first, let's create the error record in the domains dot node package. Let's copy this line and paste it here. We'll change it to import this error class we've just created. If we don't do that, Java will use its built-in error class. Now, let's change this type parameter to error. Let's pass the import line to this class too. Let's add a Service annotation to it. Now, before we continue to implement the feature, let's run the last test to check the format of the error message the node returns in the logs. First, let's add the ignore annotation to this test. So we only run the last test. Here, we see that the node returned to JSON message. The important part says that the script failed and 0 p equal verify operation. That means the node failed due to an incorrect signature when executing the combined script to validate the transaction. Now that we know what the node returns to the application when the wallet password is wrong, Let's map this response to the incorrect password response we want the user to see. In the node error handler. Let's add a try-catch block will convert the received error into a node error wrapper object. So let's create this record in the domains dot node package. Following the node error adjacent response as the specification will add an error field of type node error here. So let's create the node error record in the domains dot node package. It'll have a code field and a message field. Back to the node error handler will need the object mapper. So let's inject it into this class. Now, we'll call the read value method on the object mapper as its parameters will pass the error get response body as string method call. And the node error wrapper class. This code will convert the received error into a node error wrapper object. Finally, we'll return a new async result object instantiated with an error object. To instantiate the error object, we'll use the error from method passing the node error wrapper error as its parameter. Let's create the front method. It'll return an error object. Let's add the message field to this record. The front method will return a new error object instantiated with an error message. To create the error message, let's add the error messages field in this class. This field will be responsible for mapping the node error messages to the messages we want to display. It'll be a map of string keys and string values. Let's use the map of method to create it. It's first key will be the error message returned by the node, which we saw in the application logs previously. The value will be the error message we want to display. For this, we'll use the constant wrong password from the error messages class we will create. So let's create this class in the domains dot node package. And let's add this constant to it with the message we want to display. Now, we'll call the Get or default method on the error messages field in the form method, its first parameter will be the error message. It's second parameter will be a default message, which we'll define in this constant. So if the node returns an error message that we haven't mapped yet, the error message displayed will be an error occurred. Back to the node error handler. Let's add a catch statement here to catch adjacent processing exception that the object mapper can throw. Then we wrap it in a runtime exception and throw it. Now let's go to the second transaction dialogue controller. Here, we'll get the result from the sign and send method and store it in a variable. Just make sure to import the correct error class. Now, we will need the alert error service. So let's inject it into this class. This service will be responsible for showing an alert with an error message. Let's create it in the GUI dots services package. And let's finish injecting it into this class. Now, let's call the handle error method on the alert error or service object passing the result to it. Let's create this method. First. Let's add the service annotation to this class. Here we'll declare an error object. Then in a try-catch block will set the error variable to the result dot get method call. Then we'll catch an exception that the result can throw and wrap it in a new runtime exception. Now, in this if statement will check if the error is not equal null. If it's not, then we'll call the alert error method, passing the error message to it. Let's create this method. Here. We'll create a new alert object with an alert type error. Then we'll set the alert title to error. And we'll set the alert header text to error or two. Let's set the alert content text to the message variable. Finally, let's call the show method on the alert object. Now, let's rerun the test. Great, The test has passed. 60. More Error Messages and Tests for the Send Bitcoin Feature: In this video, we will continue adding more validations and alerts to notify the user of failed transfer attempts. First, we'll create some test cases for those scenarios. So let's duplicate this test will add a test for the scenario where the user wants to send a transaction with more bitcoins than their funds. Let's rename it to should not send Bitcoin without funds greater than amount plus v. Let's reformat it. And let's change the wallet name to my test while at 12. Let's delete these lines. Here. We'll set an error message variable to the content we want the user to see for the error, the message will be could not send transaction, not enough funds. Then with this code, will try to store the UI element with this message in the node query variable. And we'll try to click on the Okay button in the alert dialog. In the then block will check if the node query text is equal to the message we defined previously. Let's delete these variables in the where block since we won't need them. And let's create the previous amount variable here with the following value. Let's duplicate this line to create a second test case. This amount value will be one Satoshi lower than the necessary to send 0.5 bitcoin. Now, let's delete this line. Let's replace these values with the previous amount variable. Now, we'll create a similar test scenario, but this time using a wallet with no funds. So let's duplicate this test. Let's change its name to should not send Bitcoin without any funds. Let's change the wallet name to my test while at 13. Let's remove these lines since we won't receive any funds. And let's leave only the amount to send variable and the where block. Now let's implement the feature in the create transaction service class. Let's store the transaction DTO in a variable here. And let's return this variable. Now. Before returning, it will call the validate funds method, passing the transaction DTO as its parameter. Let's create this method. Will use this method to validate if the transaction input amounts sum is greater than the transaction output amongst some. So let's create this variable to store the input amount. Some will assign the result of calling the transaction DTO, get input amounts of method to it. Let's create this method. Here. We'll use a map on the selected UTXOs stream to create a stream of UTXO amounts. Then we'll use the reduced method to sum each obtained amount. Finally, we'll use the or else method to return the sum or zero if no UTXOs are available. Now, let's create the get output amounts of method here. We'll use a similar strategy to some of the output amounts. But instead of using the selected UTXOs, will use a map on the transaction output stream. The map method will return the output amounts converted to Bitcoin. And we'll use the reduce and a Rails method the same way we did for the previous method. Back to the validate funds method. Here, we'll create the output some variable to store the result of calling the get output amounts. Some method we've just created. Now we'll add an if statement to check if the input sum is smaller than the output sum plus the total calculated F0. If it is, we throw a new create transaction exception with the not enough funds message. Let's create this constant in the error messages class. Let's make both constants final. And let's create the create transaction exception class in the GUI dot exceptions package. It'll extend the runtime exception and will pass its message to the super constructor. Let's take the opportunity to add another validation here. What if we try to send a transaction without a loaded wallet? To handle this case, let's use this if statement to check if the current wallet has any addresses. If it doesn't, we throw a create transaction exception with a wallet not loaded message. Let's create this constant to store this message. Now, let's go to the Send tab controller. Let's wrap the transaction DTL creation in a try-catch block. The open dialogue method call to. Here, we'll catch it. Create transaction exception. We'll use the alert error or service and the catch body. So let's inject it into this class. Then we'll call the alert error method, passing the exception message as its parameter. Let's make this method public. Let's go to the send Bitcoin test. Let's add the ignore annotation to the test we made in the last video. Let's run our node. Before running the test, let's adjust some details. Let's add a point at the end of the error messages. In the send Bitcoin method. Let's add this parameter. It'll default to true and will only call the wafer dialogue method if it's true. Now, let's set it to false and these calls, because the transaction dialogue won't appear in these tests. Finally, let's run the tests. Grade the tests have passed. Let's remove all the ignore annotations from this class. Now, we'll add a bunch of new tests in a new class called send Bitcoin additional test in this package. But don't worry, this time we'll just copy the content of this class from the Project and Resources page. All of these tests must pass. Hopefully, we won't have to change anything in our code for it. But they'll help to ensure our wallet will send transactions correctly and detect possible code breaks will make in the future. Let's reformat all of them. The first test we'll verify if a wallet with a password sends transactions correctly. The next test will generate transactions without the need for change and check if their parameters are correct. This test will try to send a transaction to an address of our own wallet and check if the wallet correctly calculates its amounts and balances. Finally, the last test will have a lot of different test cases with different numbers of previous UTXOs and amounts. For these tests to work, Let's move the weight for dialogue method in the send Bitcoin test to the GUI test class. Let's make it protected. Let's remove these imports in the send Bitcoin test. One more thing in the send Bitcoin method, in the send Bitcoin test, let's add the super keyword here to ensure we will call the correct weight for dialogue method, not the parameter with the same name. We'll do another test in this class. This time, we'll check what happens when we try to send a transaction with a dust amount. So let's duplicate this test. Let's change its name to it should not send dust Bitcoin. Let's fix its formatting. Let's change its wallet name to my test while at 18. Now, let's copy this code and add it to our method to fund our wallet. Let's change the error message to could not send transaction amount to send is dust. Let's change the where block, adding the following variables to it. We'll choose an amount to send equal to 293 Satoshi's, which we know our node cannot accept since it'll be considered dust. For the previous amount will choose 0.1 bitcoin. Since we will trust our note to detect this kind of error, will wait for the transaction dialogue to appear after we click on the Send button. And let's add the click on the Okay button method call to confirm the transaction of the dialogue. Now, let's go to the error class. Let's add the following entry to the error messages map will map the dust message error received from our node to the message present in the dust constant in the error messages class. Let's create this constant. It will be equal to the message we've just defined in the test. Let's add the ignore annotation to the other tests in this class and run our new test. Great, The test has passed. Let's delete all the ignore annotations we added previously. At this point, I recommend running all the application tests. I did so and they all passed. I won't show it in this video because it would take several minutes. I'll leave this as an exercise for the student. 61. A Necessary Refactor: In this video, we'll start to refactor our application to prepare it, to add support for more address types. It'll be a relatively big refactor, but we'll see later that it will allow us to add support for other address types, such as the nested seg would address. The idea of this ref actor is to centralize everything specific to an address type in an address config object. By doing so, we'll be able to add more addressed types to our wallets by adding new address config objects to the project. After doing this refactor, we'll add a new address type called nested segment, whose importance we will explain in a few videos. So let's go to the address config record to add some fields. We'll add the address generator field. We'll use it to define the service used to generate addresses for different address types. A map with an environment enum key and a string value. We'll use this field to register the address prefixes for each environment. So let's create this enough. In the BYU w dot domains package. It'll have the main net, test net and reg test constants. Let's add the extended ki prefix field here. As the name suggests, it will define the prefix of the extended key that will generate the addresses. The next field will be a predicate string as the type parameter. It will receive a lambda function with an address as its parameter and an expression that will return true if the address matches the address config type and false. Otherwise, we'll add a script pub key type field so we can identify which address config to use by using the script pub key type. Then we'll add it by function with these type parameters will use this field to define a function to parse an address from a given script, pub key, and a prefix. Now let's delete the address conflict bean for the Segway change address. In this refactoring will use only one address config bean for both the segment and the segment change addresses. Let's change the Bean annotation to reflect this change. Now, let's change this address config instantiation to include each resource related to this address type will change the derivation path field to a map where the key will be an address type and the value will be its corresponding derivation path. Here we'll add two entries, one for the segment address type and its initial derivation path, and the other for the Segway change and its initial derivation path. Now, as it's addressed, generator will add a new segment address generator. For the address prefixes field will add the following map will add one entry for each environment and they're P2, WP k h address prefixes. The extended ki prefix field will be the main net segue prefix constant. As the address matcher will use the address matcher is segue with Lambda function. So let's create this class and the utils package. And let's create this function. It will be a function that will take an address and return true if the address starts with one of these three prefixes present in segment addresses. The next field will be equal to the script P2 WP k h constant. Finally, the address parser will be a reference to the script P2 WP k h address method. Let's go back to the address config to substitute the type of the derivation path. It'll be a map with address types as keys and strings as values. Now, let's create the address config finder class in the api dot services package will use this service as a way to retrieve the right address can fake and other services we'll refactor next. So let's add the services annotation to it. And let's inject a list of address configs here. Now, let's create this method which will allow us to find an address config by address. Its return type will be an optional of type address config. Then we'll filter a stream of address configs and use the address matcher of the config in the filter lambda. Then we'll return the optional address config corresponding to the received address using the first method. Now let's create another method which will return an optional of type address config. This time, it will find an address config by its script type. It'll be similar to the previous method, but we will use the filter to verify if the script pub key past matches the one from the address config. We'll also use defined first method in this case. Now we'll create a method to find an address config by address type. Again, we'll use a filter on a stream of address configs. This time, the filter will contain a lambda that will check if the address config address type is equal to the past address type, or if it's equal to the corresponding change address type. This time, we'll return the address can fake without the optional object using the orals throw method. This method will throw an exception if it doesn't find the appropriate address config. Now we're ready to start refactoring other services to use our new address config and address config Finder. Let's begin with the create wallet service. Let's delete these two lines. Here. We'll use a flatMap on the address config list. Then we'll pass a lambda method as its parameter returning in the lambda body the following transformation will get the derivation paths of the received address config. It's missing a final S letter. So let's rename this field to derivation paths. Now, we'll get the entry set of the derivation paths. Then we'll call the map method on the stream of derivation path entries will return an extended pub key for each entry using the extended pub key service create method. As its parameters will pass the master key. The entry value, which will be the derivation path, the entry key, which will be the address type, and the Address config extended ki prefix. Finally, we convert the result to a list. Now let's go to the extended pub key service. Let's delete these lines. Let's add a fourth parameter to this method. It will be an extended ki prefix. Here, we'll substitute this argument for the extended ki prefix, public prefix. Now let's go to the segment address generator. Here, we'll add the prefix as a second argument, and we'll use it as a parameter here. Now, let's remove the address prefix factory from this class. And let's add the second argument to this interface, generate method two. Now let's go to the address sequential generator. In the generate method call, we will use the address prefix factory. So let's inject it into this class. Now let's call the get method on it, passing the received address type as its parameter. Now we'll refactor the address generator factory. Let's delete all of these lines. Let's inject the address config Finder into this class. Here we'll call the find by address type on the address config finder, passing the address type as its parameter. Then we'll return the phone address config address generator. Now, let's refactor the address prefix factory. Let's remove all of these lines. Then let's inject the address can think Finder into this class. Again, we'll find the address config by addressed type using this method. Then we'll get the address prefixes from the found address config. Finally, we'll return the address prefix corresponding to the current Bitcoin environment like this. Let's fix the tests for the classes we've just refactored, starting with the address sequential generator test. Let's add the address config finder as a field in this class. And let's assign it to a mock of this class here. Now, let's instantiate a new address configuration, setting it to this variable. Then let's use the one method to define a returned object when we call the find by address type method on the address config finder. In this case, will return the Segway config. So let's make this method public in the address configuration class. Now let's change this address prefix factory parameter to the main net string. And let's pass the address config finder to the instantiation of the address generator factory. Let's run this test. Whoops, the compilation failed due to an error in the UTXO DTO builder. Let's fix it. Here. We'll get the address config using the address config Finder. So let's inject it into this class. Let's delete the address config list from this class. Now, we'll find the address config by address type here. Then we'll get the derivation path using the received address type. Finally, we'll concatenate the string slash and the address index to the result. Let's run the test again. Great, The test has passed. Now let's fix the create wallet service test. Let's delete these lines. Will instantiate the address configuration here. Then we'll create the address config list here. Adding the seg would config to it. Let's remove all of these lines. Now, we'll instantiate the necessary objects like this. Let's run this test. Grade. The test has passed. Now let's fix the extended pub key service test. We'll add the main net seg would prefix as the last parameter of the create method. And let's run this test. Great, it has passed. Finally, let's fix the segment address generator test. We'll remove the address prefix factory from this class. And we'll pass the main net P2 WP k h address prefix as the second parameter to this method. Let's run this test. Grade. The test has passed. In the following video, we'll continue to refactor our application. 62. A Necessary Refactor Part II: In this video, we'll continue to refactor our application. So let's start with the address parser class. Let's inject the address config Finder into this class. Let's remove this code. Now, we'll use the address config Finder to find an address config by script pub key type, passing the script pub key type to this method. Then we'll map the result and apply the address config address parser, passing the script pub key and the proper prefix as its parameters. Now, we'll use the URL method to return an empty string if an address can't be parsed. Let's return this transformation. Now, let's go to the current wallet class. Let's remove the receiving address and change address from this class. Instead of using one field for each receiving and change address will use one receiving addresses field to model the different addresses will use to receive Bitcoins in our wallet. So let's add the receiving addresses field to this class. It'll be an observable map with address types as keys and strings as values. Will instantiate it here with an observable HashMap from the FX collections class. Let's delete the methods that use the removed fields. Now let's create the set receiving addresses method. We'll put an entry in the receiving addresses map for each extended pub key. The key of each entry will be an address type obtained using the value of method passing the extended pub key type as its parameter. The value will be the first address of the extended pub key. Now, let's create the set receiving address method. We'll use this method to update the current receiving address for a specific address type. It'll accept an address index and an address type as parameters. First, we'll get the next address using the get address ID method passing these parameters. Then we'll put the obtained address in the receiving addresses using the address type as the key. Let's create the get receiving address method. It'll take an address type and return the current receiving address for that type will get it from the receiving addresses using the address type as the key for the retrieval. Now, let's create a getter for the receiving addresses. Let's rename it to get observable receiving addresses. Now, let's go to the update current wallet addresses service. Let's remove all of these lines inside a platform run later call. Let's add a Lambda function that will use the current wallet set receiving address to set the next address. Let's remove these fields since we won't need them. Now, let's refactor the update current wallet service. Let's remove these two lines. Then let's add a call to the set receiving addresses method we've just created in the current wallet. Now, let's go to the Receive tab controller. Let's remove this code. Here. We'll get the observable receiving addresses from the current wallet and add a listener to it. The listener will be the following lambda function. With this if statement will check if the receiving address that was changed was a segue what address? If so, we'll set the text of the receiving address field to the newly added address. Now we'll refactor how the change address is used in the project. So let's create a class called a change address type Finder. This class will be responsible for finding the appropriate change address type for a given address output. Although we can use different address types as outputs in one transaction, it's recommended to use the same type to complicate third parties in discovering which output was used as the change. This service will allow us to address this concern. Let's add the service annotation to this class. Let's inject the address config Finder into it. Now let's create the find method. This method will return an address type and take an address as the parameter. Here we'll call the find by address method on the address config finder. Then we'll map the obtained value to the equivalent change address type using the following code. Finally, we use the or else method to return the seg would change address type. If the address type wasn't found. We'll use the Segway change address for this case. Although we'll allow our application to send transactions to most address types, we need to provide this fall back because we won't implement all the address types as receiving addresses in our wallet. Now, let's go to the create transaction service. We must refactor how the change address is obtained in this class. Let's add the change address variable here. Its value will be equal to the result of the fine change address method call with the address as its parameter. So let's create this method. Let's first substitute these good change address method calls for the new change address variable. Here we'll get the address type by using the change address type Finder. So let's inject it into this class. Now, we'll call the find method on the change address type finder, passing the address as its parameter. Then we'll return a call to the get receiving address method, passing the obtained address type as its parameter. Now, let's go to the address config class. We'll add fields related to the transaction creation. Now. The first will be the transaction input builder with this new class as its type. Let's create this class in the API services package. It'll be an interface. It's method will be called Build, return a transaction input and take a UTXO as its parameter. Back to the address config. We'll add the input plus output size field here. We'll use it later in the dust calculator class. Let's also add the scriptSig size field here. It'll be used in the transaction size calculator. Now, let's also add the transaction signer field. Let's create this class in the api dot services package. It'll be an interface. It will have a sign method which will have the following parameters. It will also throw an IOException. Now in the address configuration class, let's define the new fields in the segment address config. We'll add a new segment input builder as the transaction input builder. Let's create this class in the api dot services package. It will implement the transaction input Builder interface, and it will implement the build method. To implement it, let's copy the following code inside the build inputs method in the transaction creator class and paste it here. Let's change this parameter to a new ArrayList. We'll store this transaction input in this variable. Then we'll call the set witness method, passing a new witness with the same arguments we've used in the transaction creators service. Finally, we returned the transaction input. Let's copy these constants and paste them to the segue what input builder. And let's add the service annotation here. Back to the address configuration. We'll add 98 as the input plus output size, zero as the scriptSig size, and a new Segway transactions signer. Let's create this class in the api dot services package. Let's implement the transaction signer method. Let's add the service annotation here. Let's go to the transaction signer service. We'll copy this line and paste it here. Let's substitute this parameter for the index variable. And let's substitute the UTXO amount for the amount variable here. Our address config is finally ready. Now let's go to the transaction size calculator. Let's use the cleanup code IDE command to add the final keyword to every field in this class. Let's inject the address config Finder into this class. Let's delete this code. Let's redefine the all inputs variable will map the stream of input addresses passing a reference to the input size method. Let's create this method. It'll return a double and take an address as its parameter. Here will return a code similar to the previous one that define the input size. But the scriptSig size parameter will be taken by finding the proper address config. Using the address config finder will throw an exception if we don't find the address config. If we find it, we'll take the scriptSig size from it. Then we'll add the sequence to it. Finally, we'll sum the input size results using the double sum method. If we don't find any input, will return zero as the sum. Now, let's delete these lines. Like the input size. We'll call the map method on the stream of output addresses will use the output size method to return each output size. Here we'll return the sum of the n value, the script pub key length, and the result of the script pub key size method passing the address as its parameter. Using an if statement will check if the address is a seg would address by using the Segway method. If it is, then we return the script pub key constant. If it's not, we'll throw the following exception. Remember that we won't use the address config to calculate the output size because the address config refers only to the addresses we can accept in our wallets. Since we plan to support more output addresses, then we will take as inputs, will have to handle the output construction without using the address config. Finally, we use the reduced method to calculate the sum of outputs sizes. And the or else method to return zero with no outputs exist. Let's delete this constant. Now. Let's go to the dust calculator. Let's inject the address config Finder into this class. Let's add the address as a second parameter to this dust method. Let's remove this line, will create the input plus output size variable. We'll use the address config Finder to find the address config by address. If an address config is not found. We'll throw an exception. If it is, then we get its input plus output size property and store it in a variable. Finally, we return the formula to calculate if an output is dust using the variable we've just defined. Let's remove this constant from this class. Now, let's refactor the single random draw coin selector will add the change address parameter to these methods. And we pass the change address to the dust method call. Let's refactor the transaction creators service. Now, let's delete these constants. Let's inject a list of script pub key builders into this class. Let's create this class in the api dot services path. It'll be an interface. It'll have a match method which will return a Boolean and take as its parameter and address. And it'll have a build method which will return a script and take an address as its parameter. Let's finish injecting this field into this class. Let's also inject the address config Finder into this class. Let's add the change address to these method calls. Let's remove this code from this method, will create the script variable and assign the result of the following stream transformation to it. Will filter the script pub key builders stream to find the one that matches the address variable. If we don't find any, we throw an exception. Then we call the build method on the script pub key builder found passing the address as its parameter. Finally, we return the transaction output containing the amount and the script variable. Now let's remove this and used method from this class. In the build inputs method, Let's remove this code. Now, we'll call the map method on the stream of UTXOs. Inside it will pass the following lambda, will find the address config using the UTXO address. If we don't find it, we throw an exception. Then we get the transaction input builder from the address config and call it spilled method, passing the UTXO to it. Finally, we use the collect method to convert the resulting stream into an ArrayList. Let's create the P2 WP k h script builder class in the api dot services package. It will implement the script pub key Builder interface. Let's implement the interface methods. Let's inject the address prefix factory into this class. In the match method will return the result of calling the address matcher is Segway test method. In the build method, we'll first set the prefix variable to the address prefix factory Get method call result will pass the Segway constant as its parameter. Then we return the result of the P2 WP k h script method call as the parameter to this method will pass the result of calling the back 30 to decode to hex method. First, let's go to the POM file to update the Bitcoin Java library to the 0.4, 0.4 version, which has the best 32 method we need. We'll pass the prefix and the address to this method. Now, let's go to the transaction signer class for more refactoring. Let's inject the address config Finder into this class. Let's delete this line. In its place, will call the same method passing these parameters to it. Let's create this method will create the transaction signer variable. We'll assign the result of the following transformation to it. We'll use the address config Finder to find an address config by addressed type will pass the UTXO DTO address type to this method. But first, let's add the address type field to the UTXO DTO record. And let's add the address type to the UTXO DTO instantiation in the UTXO DTO builder. Back to the transaction signers service will get the address config transaction signer from the phone address config. Finally, let's call the transaction signers sign method, passing these parameters to it. Let's add a throws clause to this method to indicate that this method can throw an IOException. The refactoring is done. Now let's fix some tests, starting with the single random draw coin selector test. Let's add the address configuration to the setup method. Then let's add the address configs list variable with the segment Config inside it. Now let's instantiate a new address config finder, passing the address configs to it. Now let's run this test. Great, it has passed. Now, let's fix the transaction creators service test. Like the previous test. Let's instantiate an address configuration and create an address configs variable and an address config finder variable. Let's also instantiate an address prefix passing the reg test string and the address config finder to it. Now let's create the script pub key builders variable will assign a list to it with a new P2 WP k h script builder inside it. Let's run this test. Great, it has passed. Now, let's fix the transaction size calculator test. Like the previous tests, let's instantiate an address configuration and create an address configs variable and an address config finder variable. Let's change these case tests. We'll paste the test cases you can find on the Project and Resources page. Let's import the end copies method. These test cases or equal to the previous, but they have real addresses this time, since they are now important to the transaction size calculator logic. Let's run this test. Great, it has passed. Now, let's go to the GUI test class. Let's add the main net segment prefix constant to this method call. And let's add the reg test P2 WP k h address prefix constant as a parameter to this method call. Now I recommend that you run all the application tests. They all must pass. 63. Nested Segwit Addresses: In this presentation, we'll talk about nested segment addresses. So what is a nested segue? What address? Nested segment addresses are also known as rap segment P2, SSH dash p2, WPA, and WPA2. And P2 SSH addresses. The latter name describes best what they are and address that encodes a pay to witness pub key hash script. Inside a pay-to-script hash script. Most modern wallets support these addresses. Their main advantage is that they allow older wallets, which usually support pay-to-script hash addresses, but don't support native segment addresses to send bitcoins to them. Therefore, owners of nested segment addresses can benefit from some advantages of Segway transactions, such as cheaper transaction fees and receiving funds from old wallets. So why the need for segue native addresses? You may ask. The reason is that segue native addresses make transactions even smaller than nested segment addresses. Nested segment addresses became available in 2017 after the seg would update, the rules to generate nested segment addresses were defined in BIP 141. We've chosen nested segment addresses as our wallets secondary receiving addresses to allow receiving Bitcoins from old wallets. So to understand nested segment addresses, let's first understand P2 SSH addresses. P2 SSH is an acronym for pay-to-script hash. P2 SSH addresses are exactly that. They encode a hash generated from a Bitcoin script. Let's see the process to generate a P2 SH headdress. We begin with an hexadecimal serialized redeem script. I'll redeem script is usually a multi-signature Bitcoin script, but it can be any other Bitcoin script. We use the hash 160 algorithm to generate a script hash from the serialized redeem script. Then we combine the script hash with a prefix and apply the base 58 encoding algorithm to produce a P2 SH address through base 58 decoding, we can obtain the script hash back from a P2 SSH address, a nested segue. What address is simply a base 58 encoded P2 SSH script was redeem script is a segment script. Now let's learn how to build a P2 SH script pub key. Remember that a script pub key is part of a transaction output and is how the receiving address is present in a transaction. So starting with a P2 SSH address, we first base 58 decoded to obtain a script hash. Then we build a script consisting of an OP hash 160 opcode, the script hash and an OP equal opcode. This is the P2 SH script pub key. To send funds to a P2 SSH address, you should put this script in the transaction output along with the amount any wallet, but can send bitcoins to a P2 SSH address, can send bitcoins to a nested segue. What address? Now, let's see how to build a nested segue transaction input, starting with the valid pub key for a UTXO address. We then apply the hash 160 algorithm to obtain a pub key hash. Combining the hash with a zero prefix, we obtain a segment script. This is the redeem script, will add it to the transaction input later. Now will sign a transaction. To do that, we first produce a signature hash from an insider transaction using the same signature hash algorithm we use to sign a segue transaction. Then we combine the signature hash with a valid private key to generate the signature using the ECDSA. Next, we show the sign transaction input, the transaction ID output index, and then sequence fields work the same way as other transaction types. We add the redeem script in the scriptSig field, and we add the signature and the pub key to the witness field. Notice that unlike native seg would inputs, the scriptSig is not empty. In this case. The witness field of nested segment inputs has the same elements as native segment inputs. Now let's see how a nested segment script is executed during transaction validation by the nodes. Nested segment validation requires the validation of two combined scripts. Given a P2 SSH script pub key from some UTXO and the corresponding scriptSig from a transaction input. Both scripts are combined, forming the first combined script. The redeem script, is passed to the combined script as a single serialized element. In this first validation, from left to right, each element in the combined script is evaluated, starting with the redeem script, which is added to the execution stack. Then the OP hash 160, apply the hash 160 and the redeem script, transforming it into a script hash. Then the script hash and the combined script is added to the execution stack. Finally, the OP equal opcode compares both Script Hashes and returns true if they're equal. If they're not equal, the transaction is deemed invalid. Next, a second script is formed by combining the witness and the scriptSig. This time, the redeem script in the scriptSig is evaluated in its entirety just as it is in segue native script evaluations. And like segue native script evaluation, the initial zero digit in the scriptSig triggers a special rule that converts it to the script present in the combined script. From now on, the combined script gets executed just like the combined script from segment native transactions. From the combined script, the signature and pub keys are added to an execution stack. Then the OPT up opcode duplicates the pub key in the execution stack. Up hash 160 hashes, the last pub key added to the stack. Then from the combined script, the pub key hash is added to the stack. Up equal verify opcode removes the last two elements from the execution stack and compares them. If they're equal, the script continues to execute. Finally, the object sig opcode checks if the signature is valid for the pub key remaining in the stack. If it's valid, it returns true to the execution stack. After all the script elements were added to the execution stack, the transaction input is considered valid if the last added element is true, this process must be repeated for every transaction input, all its inputs must be valid for a transaction to be considered valid. Just as a visual reminder, let's review from where each element in the script pub key, scriptSig and witness came during transaction construction. The script hash present in the script pub key came from base 58, decoding the address of the UTXO that is being spent. The pub key hash and the scriptSig came from the hash 160s of a valid public key. The same public key is present in the witness. The witness is signature came by applying the ECDSA algorithm, which needs a valid private key. The public key and the witness came from the public key derived from the mentioned private key. Now, let's see some parameters important to derive nested segment addresses. On the Bitcoin main net, the prefix needed to derive P2 SSH addresses is C4. After base 58 encoding a dresses with that prefix start with the digit three on the Bitcoin test net and the reg test, the prefix needed to derive P2 SSH addresses is 05. After base 58 encoding addresses with that prefix start with the digit to. The derivation path used to derive nested segment addresses begins with the 49 hardened path for wallets, following the BIP 49 guidelines. 64. Receiving Bitcoin in Nested Segwit Addresses: In this video, we'll implement the nested seg would address in our wallet, will add it as another option to receive Bitcoins in our wallet. Let's first prepare our application to add some tests related to the new address type. So let's go to the Node, get new address client. We need to make our application able to call our node to generate P2 SSH addresses. So we can create tests to send Bitcoin to these addresses. So let's use the change signature IDE option to add a new parameter to this method. The new parameter will be a string, its name will be addressed type, and its default value will be the string back 32. Let's add an empty string to this method call. This parameter is used if we want to add a label to our new address, since we won't need it, we'll set it to an empty string. And let's add the address type as its last parameter. Okay, now we can ask our node to create P2 SH addresses if the IDE refactor worked. Now the current calls to this method will have the string back 32 as they're less parameters. Now, let's go to the send Bitcoin test. Let's move this method to the GUI test class. Let's make it protected. Instead of using the super keyword here, let's use this. Now, let's go to the receive Bitcoin test class. Let's copy all the code in this class. In the GUI test package. Let's create a new test class called receive Bitcoin nested segue test. And let's paste the content to this class. Let's make some adjustments to this class. Let's change the class name to receive Bitcoin nested segue test. Now let's change the test method names. Let's add in a nested segment address here. Let's do the same to all other test methods indicating in their names that will receive Bitcoins in nested segue what addresses? Now, let's adjust this first test. We'll adjust its wallet name. Then let's modify the lookup parameter here. So the address variable gets assigned to the value of the field where the nested segment addresses. Here, instead of using the address is valid method, we'll use the nested segment address is valid method we'll create. Let's fix this code formatting. Now, let's create the nested segue what address is valid method in the GUI test class, we'll use the addresses valid method as its base. So let's duplicate it. Let's fix its name. Now. Let's change the address type here to the nested segwayed constant. And let's change the derivation path here to start with 49. Let's create this constant in the address type enum. Let's also create the nested segue to change constant here. Here, let's change the prefix of the generated address to the test net P2 SH address prefix. And instead of using the segment address generator, will use the nested segment address generator. Let's add this field to this class. We'll use the auto wired annotation to inject it into this class. Let's create this class in the api dot services package. Will implement it later. Back to the receive Bitcoin nested segue test class. Let's make the same adjustments to the other test methods. Now let's go to the address configuration class. Let's duplicate this bean will use it as the base to create the nested segwayed Config. Lets change these parameters to nested segment and nested segue change. Let's change this method name two nested segment config. Now let's change the address config parameters. The first parameter will be the nested seg would address type. In the second argument, let's change the map keys to nested segment and nested segment change. And both derivation paths. We'll start with 49. We'll use the nested segment address generator as the address generator. Let's make it implement the address generator interface. Let's add the interface method. Now, let's set each environment address prefix. The main net environment. We'll use the main net P2 SSH address prefix constant. The test net and reg test environments. We'll use the test net P2 SH address prefix constant. Let's change the extended ki prefix to the main net nested segment prefix constant. The address matcher will be the as nested segue predicate. Let's create this field in the address matcher. It will be similar to the segment predicate above. But the matcher will return true if the address starts with three or two instead. Now, let's import it here. Let's use the P2 SSH constant here. Let's use the script nested segment address method as the script parser. Will use the nested segment input builder as the transaction input builder. Let's create this class in the api dot services package. Let's add the interface method. As the input plus output size. We'll set 180 as the scriptSig size 23. And as the transaction signer will use the nested Segway transactions signer. Let's create this class in the api dot services package. And let's add the interface method. Our nested segue config is ready. Now we need to implement the nested segment address generator, input builder, and transaction signer. Let's start with the nested seg would address generator. First, let's add a test for this service in the api dot services test package. It'll extend the specification class. Let's add the following setup method. Let's add the security ad provider method call. Let's add the nested segment address generator as a field in this class. And let's instantiate it here. Now, let's go to the segment address generator test. Let's copy this test and paste it here. We'll use it as a base for our new test. Instead of using the segment address generator, will use the nested seg would address generator here. Let's change the prefix to this constant. Let's remove these test cases and let's paste the ones valid for nested segment addresses. They're available on the Project and Resources page. Back to the nested segment address generator. I mistakenly created this class as a groovy class. Let's use this IDE feature to convert this class to Java. Lets remove this code. Let's add the service annotation to this class. Here we'll convert the extended child key to a public key. Then we'll return the nested segment address from compressed public key method call on the obtain object passing the prefix variable to it. Let's rename this parameter to extended key. Now let's run this test. Great, it has passed. Now let's implement the nested segue what input builder. Let's add the service annotation to this class. Let's copy the build method in the segment input builder and use it as a base for our new build method. Let's also paste these two constants to the nested segue input builder class. Now let's add the dummy scriptSig nested segwayed constant in the script ArrayList. Let's create this constant. It will be equal to the string zero repeated 44 times. Here, we must pass this constant inside a list of method actually. Now, let's implement the nested Segway transactions signer. Let's add the service annotation here. Let's copy the sign method in the Segway transactions signer and use it as a base for our new sign method. Here, instead of using the transaction ECDSA signers sign method, we'll use the sine nested segue method from the P2 SH transaction ECDSA signer. Let's add the redeem script as the fourth argument in this method. Let's remove this last argument. Let's create the redeem script variable. This variable will be equal to the P2 WP k h script method call. As its parameter will pass the hash 160 of the corresponding compressed public key of the received private key. The sign nested segue method will take care of adding the redeem script to the witness field and the public key and signature to the scriptSig field. Okay, the nested segue config is finally ready. Now let's add the new nested segment field to the Receive tab FXML. First, let's change the receive address and the label text for segment address. Now, let's duplicate all this code and let's change this label text to nested seg would address. Let's also change this ethics ID two nested segue receiving address. Let's move this field to the second row of its container. To do that, let's add the grid pane row index attribute to this field, and let's set it to one. Let's do the same with this label. Now, let's go to the Receive tab controller. Let's duplicate this if block in this if statement will check if the change to address is a nested segment address. If so, then we'll set the nested segue receiving address TextField content to the change to address. So let's add this field to this class. And let's add an FXML annotation to it. Let's also add a return statement here. Now, let's do some testing. Let's run our Bitcoin node. And let's run this test. Great, the tests have passed. In the next video, we'll finish adding the nested segments support for our wallet. See, yeah. 65. Sending Bitcoin to Nested Segwit Addresses and Testing our Wallet on the Test Net: In this video, we will implement the ability to send Bitcoin to nested segue what addresses. We'll start by creating tests for that feature. So in the GUI test package, Let's create the send Bitcoin nested segue test class. It'll extend the GUI test class. Let's copy some tests from the send Bitcoin test. They'll serve as a base for our new tests. Let's copy this code and paste it here. Now, we'll copy this first test, then paste it into our new class. Let's do the same with this test. Let's do the same with the dusk test. Now, let's adjust the new tests. Let's change this test name to send Bitcoin with nested segment inputs and nested segue what outputs. Let's change the wallet name to my test while at 23. And let's change this lookup method call parameter two nested segment receiving address. Here, let's change this parameter to P2 SSH hyphen segment. This parameter will make the node return a nested segment address for us so we can send Bitcoin to it. Now, let's adjust the test cases. I have previously calculated the expected total fees for these cases. They differ from transaction fees with segue native inputs and outputs because their transaction sizes differ. Let's make similar adjustments for the next test. Now, let's create the P2 SH script builder. It will implement the script pub key Builder interface. Let's implement its methods. In the match method will return these nested segue test method call passing the address as its parameter. We'll return the P2 SH script method call in the build method as its parameter will pass the base 58 decoded address like this. Let's add the service annotation to this class. Now, let's go to the transaction size calculator test. Let's duplicate this method. We'll use it as a base to create a test to verify the size calculation of transactions using nested segment inputs and outputs. So let's change the method name to reflect that. Let's remove these test cases and let's paste the test cases available on the Project and Resources page. Now, in the setup method, let's add the nested seg would config in the address config list. Now let's go to the transaction size calculator in the script pub key size method. Let's add the following if statement will test if the received address is a nested segue. What address? If so, will return the script pub key nested segwayed constant. Let's create this constant. Its value will be 23. Now let's run this test. Great, it has passed. Now let's run our node. And let's run the send Bitcoin nested segue test. Great, the tests have passed. Now, let's play a little with our wallet in the test net environment. To do that, Let's change this variable in the bitcoin.com file to test net. And let's restart our node. Let's wait for it to synchronize. Depending on how up-to-date your note is. It may take minutes to hours. Okay, I weighted sum hours. And finally, my notice sync. Let's run our application. Let's create a wallet. First. Let's receive some Bitcoins in our nested segment address. To do that, let's use this faucet. Okay, the transaction appeared in my wallet. Let's wait for a little for it to confirm. Okay. Now the transaction has one conformation. Now, let's send some funds to the faucet address. Interestingly, this transaction didn't need change and we ended up with no funds since we've spent our only input. Let's check the last transaction in the block explorer. Let's wait for a little for it to confirm. I waited some minutes, and now it has three conformations. The Block Explorer shows the same. Great. Everything is working as expected. Let's do one more test. Let's receive more Satoshi's first in our segment address, then in our nested seg would address. Okay, now that both transactions confirmed, let's send some funds to a nested segment address from this page. Now the transaction generated change. Since we've sent it to a nested segment address, the generated change was also sent to a nested segue. What address? After awhile, the transaction was confirmed. Great. 66. Sending Bitcoin to Legacy Addresses: In this video, we will implement in our wallet the ability to send bitcoins to P2 pKa H addresses, also known as legacy addresses. P2, pk h was the most used to dress type before the rise in popularity of segment addresses in the last years. Nowadays, it's still very popular. So it's important for our wallet to have the ability to send bitcoins to those addresses. Let's start by refactoring how our wallet build script pub keys so that it gets easier to add support for sending bitcoin to other address types in the future. For that, Let's create the script config record in the domains package. Similar to the address config, this class will contain parameters important to building transactions to specifics script pub key types. So let's add the following fields to it. The script pub key builder, the script pub key size, and the address matcher predicate, which will help to identify the script config type by address. Now let's create the script configuration class in the api dot config package. Again, similar to the address configuration class. This class will be responsible for instantiating and defining all script pub key is our wallet can send Bitcoin to. Let's add the Configuration annotation to it. Now, let's create the following Bean annotated method. It'll return a script config and define the P2 WP config. It's script pub key builder will be the P2 WP k h script builder. It Script size will be equal to 22 and its address matcher will be the segment Lambda. Let's go to the P2 WP k h script builder. To make it easier to instantiate, it will remove the address prefix factory from the service. Will build the prefix variable by parsing the prefix from the address variable using the parse prefix method. Let's create this method. We'll first verify if the address starts with the test net P2 WP k h address prefix constant. If so, we'll return that constant. Then we'll make the same statement, but using the reg test P2 WP k-th address prefix constant instead. Finally, we'll return the main net P2 WP k h address prefix constant if the code gets executed to this point. Now let's create the bean for the P2 SH script config. It'll use the P2 SH script builder. Its size will be 23 and its address matcher will be the nested segment lambda. Now let's create the script config find her class in the api dot services package. As its name suggests, this service will be responsible for finding the appropriate script config for other services. Let's add the service annotation to it. Now, let's inject the list of script configs into this class. Spring Boot magic will inject all script config beans into this list after the application starts. Now, let's create the find by addressed method. It'll return a script config and take an address as its parameter, will return the following stream transformation here will filter the script can think stream using the address matcher of each script config. We'll use to find first method to get the first script config filtered. If we don't find any, will use the URLs throw method to throw an exception. Now, let's go to the transaction creators service will use the script config finder to refactor this class. First, let's remove the list of script pub key builders from this class since we won't use it. And let's inject the script can think Finder into this class. Now in the build output method, Let's remove this code. Will create this script variable using the script config finder, find by addressed method. Then we'll call the script pub key builder build method on the result. Now, let's refactor the transaction size calculator. Let's inject the script config Finder into this class. Now, let's remove the code in the script pub key size method, in its place will use the script config Finder to find a script config by address and return its script pub key size. Let's remove these imports and constants since we won't use them. Now, let's go to the script pub key Builder interface. Let's remove the match method from it and from all its implementations, since we won't use it anymore. The refactoring is done. Now before adding the P2 pKa H Script Config lets create the send Bitcoin legacy test in the GUI test package. It'll extend the GUI test class. We'll use this class to verify if our wallet is correctly sending a transaction to a legacy address. Let's copy the following code from the send Bitcoin test and paste it here. We'll use it as a base for our new test. Let's change its name to should send Bitcoin with segment inputs, legacy output and seg would change. Notice that although we'll be able to send funds to a legacy address, we won't be able to receive them to a legacy address belonging to our wallet. Therefore, will use segue native addresses to receive change in these transactions. And this test name reflects that. Let's change the wallet name to my test while at 26. Let's change this parameter to legacy so that we can create a legacy address that we'll use to send bitcoins to. Let's also change the test cases using the following previously calculated values. These values differ from other transactions because P2, pKa, H script pub keys are a little bigger than segue native script pub keys which impact the transaction size and phi. Now let's go to the script configuration class. Let's add the public keyword here. Let's create the P2 pKa H config bean as its script pub key builder will set a new p2 pk H Script builder, which will create later. It's script pub key size will be 25 and it's addressed. Matcher will be these legacy Lambda we'll create later. Let's create the P2 pKa H Script builder in the api dot services package. Let's implement the interface method. In the build method will return the script P to P k h script method call as its parameter will pass the base 58 hex decoded address using the base 58 decode with checksum to hex method. Now, let's go to the address metric class. Let's duplicate this field. We'll use it as a base for these legacy lambda. Here will change these parameters to one, M and N. One is the prefix of legacy that dresses in the main net. M and n are the prefixes valid for the other environments. Let's import these legacy lambda here. Okay, now our wallet can send Bitcoin to legacy addresses. Now, let's adjust some tests. Let's go to the transaction size calculator test. In the setup method, Let's instantiate the script config finder. We'll pass a list of script configs to it. Will take the script configs from the script configuration class. So let's instantiate it here. Now, let's add the script can figs here. Now, let's duplicate this test. Let's rename it to should calculate transaction size for P2 WP k-th transaction inputs and p2 pk each transaction outputs. This test name describes well the scenario will test. Let's remove these test cases. Will paste these test cases here which are available on the Project and Resources page. Let's fix the formatting of these test cases. Let's run this test. Grade. The tests have passed. Now, let's fix the transaction creators service test. Let's copy this code and paste it here. Let's remove the address prefix factory and the script pub key builders. And let's fix the service instantiation here. Let's run this test. Great, it has passed. Now let's fix the single random draw coin selector test will need this piece of code again. So let's copy it and paste it here. Make sure the single random draw coin selector is instantiated correctly. In my case, the ID already did that. Let's run this test. Grade. The test has passed. Now, let's run our node. Before that, make sure the bitcoin.com file has the reg test environment set. Now let's run the send Bitcoin legacy test. Great, The test has passed. 67. Saving and Encrypting our Wallet: In the past videos, we implemented a fully functional application that you can already use to create wallets and send and receive Bitcoins. But if we close the application, we lose every information about the wallets we create in this video and the next, we'll start to implement the ability to save and load wallets in our application. To store our application's data, we'll use the H SQL database. Sql is a SQL database implemented in Java. We've chosen H SQL for the following reasons. First, it's a lightweight database. Secondly, it's compatible and easy to use with the Spring Boot Data JPA library. Finally, it can be easily encrypted as we'll show in this video. Let's go to the poem dot XML file to add the Spring Boot Data JPA and the H SQL DB dependencies. Click on this button to load the new dependencies. Now let's go to the application dot properties file. We'll set some configurations necessary for the database. This configuration determines that each modification we do in our entity classes, we'll update our database accordingly. In Spring Boot, entity annotated classes defined table structures, as we'll see soon. Let's duplicate this line to use as a base for the other configurations. We have to set the driver class named config to the following class. The username and the password. You can set us whatever you want. Since I'm using it only for testing, I'll set these fields to be Y0 W for now. But remember to change these values to more secure strings before using this wallet on the main net. Now, let's define the URL of the database. Since we'll use a file based database, will have to set this config to JDBC colon H SQL DB colon file colon, the path we want the database files to reside. In my case, the path we'll start with the BYOD W folder located in the seat dr. Root. Inside this folder, I want to create specific folders for each Bitcoin network environment. To do that, I'll refer to the Bitcoin environment variable in this application dot properties file, putting it between curly braces and after $1 sign like this. Finally, I'll use the data sub folder inside this folder and name the DB files as my DB. And we finished the line with a semicolon. Now inside the BYOD W package, Let's create the database package. Inside this package, Let's create the entities package. And let's create the wallet entity class inside it. This class, we'll model registers in the wallet database table. To do that, let's add the entity annotation to it. And the table annotation with its name parameter equal to Wallet. Now, let's add some fields to this class. Each field in this class, we'll model a column from the wallet table. We aim to save only the necessary fields for obtaining the same wallet data after loading it. So let's add the ID field. Will add this field to follow the good practice of always adding an auto-increment identifier to a relational database table. To do that, let's add two annotations to this field. The first is the ID Annotation, the second is the generated value annotation with the following parameter. Let's also add a column annotation with ID as its name parameter. The column annotation will determine the corresponding name of the column bound to this field in the wallet table. We'll follow the snake case style for the column name parameters where all the letters or lowercase and underscore separate the words. Now let's create the name field. Let's also add the column annotation to this field. Besides the name parameter, let's also add the unique equals true parameter and the nullable equal to false parameter. These parameters will add the unique and non nullable constraints in the table for this column. Therefore, the application will raise an error if you try to create a register without a name in the wallet table. Let's also create the mnemonic seed field with the following annotation. The length parameter will limit the max length of this field to 500 characters. Let's also add the nullable equal false parameter to this annotation. Now, let's add the number of generated addresses field with the column annotation following the snake case style. The last field will be the created at. Let's add the created date annotation to indicate that this field will use the current date to register its values. Now, let's create some constructors. First, an empty constructor, which is necessary for Spring Boot to instantiate this class correctly. Next, let's create a constructor with all this class's fields except the id. Let's create getters for the same fields. Our wallet entity is done. Now inside the database package, Let's create the repositories package. And let's create the wallet repository interface inside it. The wallet repository interface will be responsible for interacting with the database by retrieving data from and saving data to the wallet table. To achieve that, it'll extend the JPA repository interface will add type parameters to this extension. The first test to be the entity that this repository we'll manage. In this case, it'll be the wallet entity class. The second has to be the ID type of the entity. Therefore, it will be the long class. With this simple interface, we already have access to common database operations for the wallet table, such as inserting registers and finding them by ID. All this is automagically brought to you by the Spring Boot Data JPA library. Now let's create the services package in the database package. Inside it, let's create the save wallet service class. This class will be responsible for saving the wallet after its creation. Let's add the service annotation to it. Let's inject the wallet repository into this class. Let's do the same with the initial number of generated addresses field. Now, let's create the save wallet method. It'll take a wallet object as its parameter. To implement. It will first instantiate a new wallet entity object with the following parameters from the wallet. Then we'll call the wallet repository save method, passing the wallet entity as its parameter. *****. I mixed the order of parameters here. Let's fix it. And let's add the qualifier annotation for the correct injection of this field here. That's it. With this simple code, we managed to save the wallet information to the SQL database easily. Now let's create the listeners package in the database package. And let's create a class called save wallet listener. Inside it. This class will serve as a listener for the created wallet event. So that after the application creates a wallet, It will be responsible for calling the save wallet service to save the wallet. So let's add the component annotation to it. It will implement the application listener with the created wallet event as its type parameter. Let's implement its method. Here, we'll call the save wallet method, passing the event wallet as its parameter. Let's create this method. We'll use the save wallet service here. So let's inject it into this class. Then we'll call the save wallet method here, passing the wallet as its parameter. Now, if everything works correctly, our application will save wallets in the database after their creation. So let's run our application to test this feature will test first in the reg test environment. Make sure the VM option in the BYOD W application run configuration is empty. For this specific test, we won't need to run our node. Let's run it. Let's create a wallet. Okay, if everything worked correctly, the wallet was saved. Let's close our application. Now. Let's see if the database files were created in the specified folder. Great, the application created the reg test folder and the DB files expected in it. Let's open them. Idb dot log file. Here we can see all our applications database operations in SQL written in plain text. We can see that it has an insert command containing wallet data, including its mnemonic seed. Good. But this is unsaved since anyone who obtains this file can know all our wallets, mnemonic seeds. We'll fix that soon by encrypting these files. For now, let's see the Saved wallet data in a more readable format. To do that, let's go to this website to download the H SQL DB. Click on the download link to download the latest version. After downloading it, extract its content to a folder. Let's open the bin folder located inside the extracted folder. Now let's execute the run managers swing dot that file. Let's go to the application dot properties in our application to copy the URL of the database. Now, let's paste its content into this field. And let's substitute this variable for reg test. Let's add here the same username and password we defined in our application dot properties file. Let's click. Okay, great. We've managed to connect to our database. Now, right-click on the public dot wallet folder here and click on the SQL select statement. Let's run this command by clicking on this button. Great. Here is our wallet data in a table format. We can see that our application successfully saved the wallet data. Let's close this application. Now, as I said before, it's important that we encrypt our database files. To do that, let's add the following suffix to the database URL in the application dot properties file. Here we'll define a crypto key and encrypt type. The crib type will be AES, which is a symmetrical cryptography that the application will use to encrypt data before saving it in the database and decrypt data when retrieving it. The crypt key will be the key necessary for both operations. Let's use the SQL DB manager again to generate a valid crypt key. Click on the Okay button here. Let's execute the following SQL command. Let's copy the generated key into a text editor, then copy it again to the crypt key value in the application dot properties. Now let's add the same database configuration to the other property files in the project. Let's remove the reg test folder, create a distorts the database files. And let's run our application again. Let's create a new wallet. Now, let's open the reg test folder and the generated my db dot log file. Its content is entirely unintelligible now, that means it was successfully encrypted. Let's copy the database URL again, including the encryption suffix and open it using the H SQL DB manager. Great, We can see the Saved wallet data again using the new URL in this application. 68. The Load Wallet Menu: In this video, we'll start to implement the ability to load previously saved wallets in our application. First, let's make some necessary refactoring. Let's go to the create wallet service. We want to be able to create wallets with different dates and numbers of generated addresses. So let's add these as parameters in this method. Now, let's substitute this date instantiation for the created at variable. And let's add the number of generated addresses variable as the last parameter of this method. Now, let's go to the create wallet dialogue controller to add these parameters to the create method call. Let's inject the initial number of generated addresses into this class. Now, let's change the signature of the ADA addresses method to include the last parameter we've just added to this call. In the ADD address service, let's add the number of generated addresses variable to this method call and signature. Let's also pass it as the last parameter of the address sequential generator generate method. Let's change the signature of this method to include this parameter. Now, let's delete the initial number of generated addresses field from this class. And let's substitute it here for the number of generated addresses variable. Now let's go to the update current wallet addresses service will set the initial number of generated addresses field as the last parameter of this method call. Now let's create the load wallet test class in the GUI test package. It'll extend the GUI test class. Let's go to the send Bitcoin test to copy this code part, since we'll need it for our new test. And let's paste it here. Now, let's go to the receiving Bitcoin test class. Let's copy this first test and use it as a base for our new test. Let's rename it to should load wallet and receive Bitcoin. Let's format this test. Let's add a given block to this test. Here, Let's define a wallet name and password variables. Let's also define a mnemonic seed variable. We'll use the mnemonic seed service create method to generate it. Let's inject the mnemonic seed service into the GUI test class. Now, let's call the create wallet method here, passing the wallet name, the password, and the mnemonic seed as its parameters. Let's create this method in the GUI test class. Here, we'll create a Wallet using the create wallet service. So let's inject it into this class. Now, let's call the create method passing these parameters to it. Now we'll use the save wallet service. So let's inject it into this class. And let's call it save wallet method, passing the wallet as its parameter. Finally, let's return the wallet here. Back to the load wallet test. Now that we've created and saved a wallet will try to load it. So let's remove this code. Let's call the load wallet method, passing the wallet name as its parameter. Let's create this method in the GUI test class. It will also take an optional password parameter with an empty string as its default value. First, we'll try to click on a component with the texts load. This component will be the load menu button, which will be next to the New button in the menu on the top of the main window. Then we'll move the mouse to a component with the text wallet. After that, we will expect a sub menu containing all the loaded wallet names to appear. Then we'll click on the one with the text equal to the wallet named variable. Next, we will expect a dialog window to appear with a password input field and an Okay button. So we'll click on this field which has the load wallet password ethics ID. Now we'll type the password in that field. Then we'll click on the Okay button. Finally, let's call the sleep method to wait for the wallet to load. Okay, the rest of the test will be just like the receiving wallet tests that we've used as a base for this test will send Bitcoin to the loaded wallet and expect the addresses and transaction tables to be filled with appropriate values. Now, let's go to the playground dot FXML file to design the load menu. Let's add a menu control to the menu bar. Let's change its text to load. Now, let's add a menu control to the load menu. Let's delete this menu item that was added automatically. Let's change this menu texts to wallet. And let's delete this menu item. Now in the text editor view, let's add an Fx ID to this menu tag. Let's set it to load menu FXML. Let's add it to the main window controller. Will add an FXML annotation and change it to a private field. Now, let's add the load menu class in the observables package. This class will be responsible for managing the menu items that will be added for each wallet we create in our application. Let's add a component annotation to it. Let's create the menu items field here. It'll be an observable set of type wallet entity. We'll instantiate it using a new observable set wrapper, passing a new LinkedHashSet to it. Now let's create the good observable menu items method here. It will return the menu items. Now let's create the load menu listener in the GUI dot listeners package. This listener will be triggered by the gooey started event published after the application starts. We'll use it to load all wallet saved in the database and add them to the load menu. Let's add a component annotation to it. It will implement the application listener class with the GUI started event as its type parameter. Let's implement its method. We'll use the wallet repository here. So let's inject it into this class. Let's also inject the load menu into this class. Then we'll call the final method to load all wallets from the database. For each wallet will call the add wallet method. Let's create this method wrapped in the platform run later call, let's call the load menu add method, passing the wallet entity as its parameter. Let's create this method and the load menu class. Here will simply call the menu items add method passing the wallet entity as its parameter. Now let's copy this line. Let's go to the Save wallet service class. We'll paste it here. Let's inject the load menu into this class. With this code, will make our newly saved wallet be added to the load menu. Now, let's go to the playground dot FXML. Let's copy these lines and paste them into the main window FXML. Now, let's go to the main window controller. In the initialized method will bind all changes in the load menu observable to the load menu. Fxml component will need the load menu here. So let's inject it into this class. Now, let's call the get observable menu items method on it. And let's call the ad listener method on the result as its parameter. We'll pass the following Lambda. The Lambda body will get the element added and store it in the wallet variable like this. Then we'll use an if statement to check if the menu contains the wallet like this. Let's create this method. Using the following stream transformation will check if the load menu FXML contains a menu item with the same name as the wallet entity variable. Here, if the load menu FXML does not contain the wallet, will proceed to add it to it. Will instantiate a menu item object passing as its parameter, the wallet name. Then we'll add the menu item to the load menu FXML, like this. Now, let's go to the GUI test class in the start method before each test will clean the database so that wallets, wood duplicated names won't be persisted. That way, we avoid test crashes due to the unique name constraint in the wallet table. We'll need the wallet repository here. So let's inject it into this class. Then we'll call the delete all method on it. Now, let's run our node. And let's run the load wallet test. Okay, the test ran until the expected part and failed. We could see that our load menu was created and populated with the created wallet name. Good. In the next video, we'll continue to implement this feature, C. Yeah. 69. Loading a Wallet: In this video, we'll continue to implement the load wallet feature. To start, we'll build a dialog window that will appear after we click on the name of the wallet we want to load and the load menu as a base to build it, we'll use the create wallet dialogue. So let's go to the create wallet dialogue FXML. Let's copy all this content. Let's create the load wallet dialogue FXML file in the FXML package. And let's pay The copied content here. Let's change the dialogue header text to the following phrase. Let's change the pref height attribute to 300. Let's also remove these lines. Let's go to the Scene Builder to see how it's looking. Let's change this label text to wallet password. In the text editor view, let's change this fx ID to load wallet password. And let's change the FX controller of the dialogue pain tag to load wallet dialogue controller. Let's create this controller. Let's add the component annotation to it. And let's add all these FXML fields to the controller. Now, let's go to the main window controller here before adding the menu item to the load menu FXML, we'll call the set on action method on it, passing the following Lambda to it. This will make the application execute the open load wallet dialogue method, passing the wallet as its parameter after we click on this menu item. So let's create this method. Let's copy the content of the open create wallet dialogue method and use it as a base for our new method. Let's set the dialogue title to load wallet. Let's change the FXML loader instantiation first parameter to the load wallet dialogue field. Let's inject this field into this class. Let's add this value annotation here and change its parameter to the load wallet FXML file. Now, we have to pass the wallet to the load wallet dialogue controller. To do that, let's first get the controller from the FXML loader. Then let's call this set wallet method on it, passing the wallet to it. Let's create this method. Here. We will simply set the wallet entity field to the wallet variable. Let's create this field. Now, let's create the initialized method which will be executed after the dialog appear. Let's copy this code and the create wallet dialogue controller and pasted here. This will set the action of closing the dialog window to the cancel button. Let's also copy and paste this code to the new initialized method. It will set the Okay button action. But instead of calling the create wallet method, it'll call the load wallet method. Let's create it. First. We'll recover a fresh wallet entity from the database and set it as the wallet entity field. To do that, we'll need the wallet repository. So let's inject it into this class. Then we'll call the method find by name on it, passing the wallet entity name to it. Let's create this method. The method will be just like this. Spring Boot Data JPA magic will automatically translate this method name into a SQL query and recover the wallet entity with the name passed as the parameter from the database. Now, we will create a wallet object. To do that, we'll need to create wallet service. So let's inject it into this class. We'll call the create method passing the following parameters. All these parameters except the wallet password, will be taken from the wallet entity found in the database. The password will be taken from the dialogue password field. Let's inject the context object into this class. Now, using the context will publish a loaded wallet event passing this and the created wallet to it. Finally, we'll call the hide method to close the dialog window like this. Let's create the loaded wallet event class. Will pass the load wallet dialogue controller parameter to the super constructor. And we'll set the wallet field to the wallet constructor parameter. Let's create a getter for the wallet field. Now, let's do some refactoring in the created wallet import listener. We want to make it to listen for loaded wallet events. But the way it is now, it can only listen for the created wallet event. To change that, Let's delete this implement statement and this Override annotation. Let's change this method's name to import wallet and its parameter to a wallet object. Let's change the import wallet method parameter to Wallet. Now let's create a method annotated with the event listener annotation. It'll be called on created wallet event, and it will receive a created wallet event as its parameter. Here we'll call the import wallet method, passing the event wallet as its parameter. This refactoring will continue to make things work as before. But now, if we want to listen for another event, we can just create another event listener annotated method passing the event we want as its parameter. That's exactly what we'll do now using the load wallet event will also call the import wallet method here, passing the event wallet as its parameter. That will make the Bitcoin node import the wallet, just like when we create a new wallet. Now, let's create the loaded wallet listener class in the listeners package. Let's add the component annotation to it. Let's create an event listener annotated method called unloaded wallet event. It'll take a loaded wallet event as its parameter. Here we'll call the load wallet method passing the event wallet as its parameter. Let's create this method. Here. We'll need the update current wallet service. So let's inject it into this class. And we'll call the update method on it. Passing the wallet as its parameter will also need the update UTXOs service. So let's inject it into this class. Then we'll call the update method on it, passing the wallet addresses and name as its parameters. With these two code lines, we expect that the current wallet will be changed to the loaded wallet and its addresses, transactions and balances to be updated accordingly. Now let's fix some tests. We broken the previous videos in the address sequential generator test. Let's delete this first parameter in the address sequential generator instantiation. And let's set 20 as the last parameter of this method. Let's run this test. Great, it's working as expected. Let's do the same with the create wallet service test. Okay, It's working. Now. Let's run our node. Let's clean and compile the project using this Maven IDE feature. And let's run the load wallet test. It failed. The problem is in the main window controller. Here we have to call the FXML loader get controller method instead of the load method. Let's run the test again. Great, It has passed. 70. Plausible Deniability, Refactoring and More Tests for the Load Wallet Feature: In this video, we'll add more tests and make some optimizations to the load wallet feature. One of the characteristics that our wallet will have is plausible deniability. Plausible deniability in this context is a security feature that will make you able to hide your wallet addresses by entering a different password to load your wallet. That means our wallet won't have wrong passwords. Each entered password will give access to a different set of addresses, but observing third parties won't be able to tell if the loaded wallet addresses have the bulk of your funds. Let's create a test for this scenario. Let's duplicate this test and use it as a base for our new test. Let's rename it to should load wallet with different password and receive Bitcoin. Let's reformat it. Let's increase the wallet named number. Now let's define this different password variable and pass it to the load wallet method as its second argument. Let's also pass it as the last parameter of the addresses valid method. Let's set the password parameter as an optional parameter to this method, setting its default value to an empty string. Let's substitute the empty string and the two master key method for the password variable. Let's run our node. Let's comment this method and run our new test. Great, it has passed. This test shows that our application already supports any password for loading a wallet and that each password will generate a separate set of addresses. Let's uncomment this test. Given our way of viewing a wallet as having multiple sets of addresses according to their passwords. We have to fix an issue in our application. When we make calls to our Bitcoin node through our application, we use our wallet name. This is a problem since for operations such as retrieving our wallet transactions and UTXOs from our node will collect the same information for different sets of addresses generated by different passwords. To optimize our note RPC calls and collect only information for the generated addresses with a given password, will use the first generated receiving address as the name of the wallet important to our node. To do that, let's go to the wallet record. Let's create the good first address method here. It'll use the get addresses method to return the first address of the wallet. Now, we have to substitute every call to the wallet name field that was made to communicate with our node for a good first address method call, let's use our ID to identify the usages of the name field and do the refactoring. Now, let's go to the update current wallet service and set the first address of the current wallet. Let's create this method. Here. We'll set the first address field to the received parameter. Let's create this field. And let's create a getter for it. Now, let's substitute the relevant current wallet getName method calls for current wallet get first address method calls. Now let's go to the load wallet test, comment the first test, and run the remaining test. Great things continue to work as before. Let's uncomment this test. Now, let's go to the address configuration class. Since we're now using the first wallet address to interact with our node, the first address must always be the same for a combination of mnemonic seed and password. Therefore, we have to guarantee that the list of address configs and their addresses always be in the same order. To do that, let's use the order annotation in both beans. Let's add the order annotation with zero as its argument in this first Bean. This will make Spring inject this bean in address config lists as the first element. Let's also change the second argument of the address config object to a linked Hashmap. Contrary to maps generated by the map of method, the linked Hashmap maintains the insertion order, will achieve this using the following code. Now let's do the same refactor to the other red dress config bean. And let's add the order annotation here using one as its parameter, guaranteeing that it'll be injected after the first bean enlists of address configs. Now, let's do another optimization. Importing addresses to our node is sometimes slow. To avoid unnecessarily importing addresses to our node will check if they're already imported. To do it, Let's create the node received by address client in the node dot client package. This client will retrieve all the current loaded addresses by our node. Let's add the service annotation to it. And let's inject the node client into it. Now, let's create the list addresses method here. It'll return a list of node address objects as its parameters. It will take a wallet name. Amen conf, which will define the minimum number of conformations of the addresses returned. The include empty parameter, which will define if the call will return addresses without funds. And the include watch only parameter which will tell the node if we want to retrieve addresses which the node doesn't know their corresponding private keys. Let's create the node address record in the domains dot node package. It will have only an address field. Using the node client. Let's make the RPC call here. It'll return a node address array. The first parameter to the make request method will be the list received by address string. Then we'll pass a new parameterized type reference object. Next, the wallet URL. Finally, the listed dress method parameters we described previously. Now will return a conversion of the node address array into a node address list like this. Now, let's go to the import wallet service. Here we'll add an if statement to check if the wallet addresses were not imported like this. Let's create this method. Inside the if body will use the import addresses method to import the addresses only if they weren't imported before. Let's implement the address important method. We'll get the imported addresses using the node received by address client. So let's inject it into this class. Then we'll call the list addresses method. Passing the following parameters will convert the result into a stream and use the map method to extract all node address addresses. Then we'll convert the result into a set of addresses using the collect method. Next, we'll convert the wallet addresses into a set like this. Now, by using the removal method on the wallet addresses, will remove all imported addresses from it. Finally, we'll return the wallet addresses is empty method call. If the result is true, all wallet addresses were already imported. Oh, we forgot to delete this line. Let's do it. Now. Let's go to the send Bitcoin test. From now on, we'll add some assertions regarding the load wallet feature to some tests. Then if we find any bugs in the process, will correct them. Let's start with the first send Bitcoin test. Let's delete this line in its place. Let's add a weight load wallet method call. Using this method will try to make this test run faster. Let's create it in the GUI test class. Here, let's call the wafer method. Passing these parameters. At each iteration of this callback will use the sleep method to wait for 1 s. Then we'll check if the current wallet first address is set. So let's inject the current wallet into this class. Using the node list wallets client will check if the node loaded the address with the current wallet first address. So let's inject this service into this class. With this code will wait until the node loads the wallet. Now, let's fix an issue that may cause test failures sometimes. Here, the expected total size parameter is equal to the sum of the current iteration index plus one. Now let's create the last receiving address variable will set its value to the receiving address present in the window. Now, let's set some other variables that will help us compare the values in the wallet before and after we load it. First, the transaction table size. Then the first row transaction table balance. Now let's call the load wallet method, passing the wallet name as its parameter. Let's set this variable here. Now, we'll set the transactions table after load variable. We'll get it using the lookup method just as before loading it. Then we'll click on the addresses tab and set the addresses table after load variable in the same way. Next, we'll click on the Receive tab and set the last receiving address, afterload variable and the label text after load variable. Now in the then block, Let's delete these two lines. And let's compare the last receiving address variables before and after loading the wallet. Then let's set the addresses table size and first row addresses table balanced variables here. And let's add these two comparisons which are equal to the ones we've just deleted. Now, let's compare the addresses table sizes before and after loading the wallet. And let's do the same to the addresses table first row balance. Now let's delete these two lines, substituting them for the following lines, which make the same comparisons but use the re-factored variables. And let's add the following comparisons of the variables before and after loading the wallet. Let's comment all other tests in this file. And let's run the remaining test. The test failed because the last receiving address before and after loading the wallet are different. In the next video, we'll fix that. 71. Fixing Addresses, Transactions and Balances: In this video, we'll fix the error of having different receiving addresses before and after we load a wallet. It happens because we're using the UTXOs to update the current receiving address index. After loading the wallet and retrieving the wallet UTXOs, the old outputs used to update the receiving address aren't part of the UTXO set anymore because they were already spent. Thus, the receiving address ends up not being updated. We'll fix that by transferring the code responsible for updating the receiving addresses from the update current wallet addresses service to a new class. The New Class we'll use the retrieved transactions from the node containing all the wallets used addresses to update the current receiving addresses. So let's create this class which will be called update current wallet receiving address his service in the GUI dot services package. Let's add the service annotation here. Now, let's copy and paste some code from the update current wallet addresses service to this class. Let's add this qualifier annotation. Now let's create the update method here. It'll take a list of node transactions. Using the map method will get a stream of addresses from the stream of node transactions. Then we'll filter the stream to make it contain only addresses in the current wallet. Then we'll call the mark is used method on each address. Let's take this method from the update current wallet addresses service. Now we'll call the current wallet get addressed types method. Let's create this method. It'll return the result of calling the addresses get addressed types method. It'll return a set of address types. Let's create this method in the addresses class. Here will simply return the key set of the addresses field. Now for each address type, we'll call the update receiving address method. To do that will change the type of this method parameter to address type. And we'll delete this line since we will no longer needed. Now, let's go to the update current wallet addresses service to delete the same code we pasted to our new class and their usages. Now, let's go to the update UTXOs service. Let's inject the update current wallet receiving addresses service into this class. And let's call the update method from the injected service passing the node transactions as its parameter. Now let's go to the send Bitcoin test. Let's add the sleep method call here to avoid a new race condition that may happen sometimes makes sure your node is running. And let's run this test. The receiving address issue was fixed, but the test failed due to another bug. The transaction balance after loading a wallet is not the incorrectly calculated. Let's fix this. To solve this bug, we have to understand better how the Bitcoin Core list transactions API works. Here is the documentation of the list transactions bitcoin Core API. Notice that for each transaction, the API returns only one address field. The amount refers only to the Bitcoin amount sent to that address being negative if it does not belong to our wallet and positive otherwise. If the transaction has a change output, the API returns more than one register for each transaction. Each register with an address field of the transaction output. Let's see an example of the result of this API for a transaction sent from our wallet with one input and two outputs. For the same transaction, the API returned three registers. We can see that they refer to the same transaction by looking at their transaction IDs. Notice that the first two registers have the same address. These registers refer to the change output. The first has a positive amount indicating that it's an address belonging to our wallet. That is the change amount. The second register has the same amount, but as negative. That means our wallets sent an amount to that address. It also has a negative fee, which is the transaction fee that we paid in the transaction. If we sum the amount of the first two registers, we end up with zero, which is exactly the balance we paid ourselves in the transaction. Finally, the third register contains a negative amount indicating that we send Bitcoin to that address. It also has a fee equal to the fee in the second register. Considering how this API works, the correct way to calculate the transaction balance is to sum the register amounts returned for the same transaction and the fee of one of those registers, the transaction balanced before loading a wallet is correct because we're calculating it in a way that takes the second transaction built before we send it to our node into consideration. After we load our wallet, we lose the transaction information that is not considering it to calculate the transaction balance. So let's go to the Update Current Wallet transaction service to fix the issue. Our new solution won't need this filter anymore. So let's delete this line in its place. Let's add a call to the collect method as its parameter. We'll call the collectors grouping by method, passing a reference to the node transaction TX ID with this code will obtain a map where the keys will be transaction IDs and the values will be lists of node transactions with the same transaction ID. Let's call the values method on the result than the stream method to obtain a stream of lists of node transactions with the same T XID. The rest of this method stays as is. Let's create the transaction from method. It will take a list of node transactions and return a transaction row. Let's move this method here. Let's first get the transaction fee. Will take it from a stream of no transaction fees. Let's create the fee field in the node transaction. Then we'll filter the stream for nominal fees. Then we'll call the fine first to get the first few returned and use the URLs method to return zero if no fee is found. Now, let's calculate the amount. Using the map method will get a stream containing all node transaction amounts from the node transaction stream. Then we'll use the reduced method, passing the big decimal add method reference to some all amounts. Finally, we'll use the or else method to return zero with no transactions are found. Now let's copy and paste this line here. We'll use the first node transaction TX id as the first parameter of the transaction row instantiation. Next, we'll add the obtained transaction fee to the amount and pass the amount as a parameter here. Finally, we'll pass the first node transaction confirmation in time as the last transaction row instantiation parameters. Let's delete this method since we won't need it anymore. Let's run this send Bitcoin test again. The first test passed, but the second failed due to a race condition. Let's quickly fix it with the sleep method call here. We'll do a better fix for this error in the next video. For now, let's comment this line to run only the failed test grade. The test has passed. Let's uncomment the rest of the test. 72. Updating the Number of Generated Addresses and Optimizing Tests: In this video, we'll add more test assertions to check if we can correctly load a wallet with more addresses generated than the initial number of generated addresses config. But first, let's optimize a test method to avoid some race conditions in some tests. In the send Bitcoin test class. Let's delete these two sleep method calls since our fixed will better handle race conditions after we send bitcoins. Let's go to the GUI test class. Let's add this optional parameter in the send Bitcoin and wait method with the default value equal to hashtag receiving address. Then let's add the following and condition to this return value. With this code will only stop waiting if the receiving address field is different than the address variable. Therefore, we avoid the error of sending Bitcoins to the same address two times sequentially. Now, let's go to the receive Bitcoin test. In the last test of this class, we'll add some assertions to test if we can correctly load a wallet with more addresses generated than the initial number of generated addresses config. So let's set the wallet named variable and substitute the parameter in the right method for this variable. Now let's call the weight load wallet method here and delete the sleep method calls of this test. Now, after receiving Bitcoins seven times, let's set the last receiving address variable to the value present in the receiving address field. Now, let's copy this line in the sand Bitcoin test and paste it here. Let's change this variable to address his table view. Let's do the same with this other line. Now, let's copy and paste all these lines from the send Bitcoin test to our test. Let's also copy and paste this line to our new test to compare the last receiving address before and after loading the wallet. Let's add this line to compare the transaction table size before and after loading the wallet. This line, we'll do the same with the addresses table size. And this other line will compare the label text before and after loading the wallet. Let's run our node. Let's comment the other tests in this class and run our new test. The test has failed due to the difference between the last receiving address before and after loading the wallet. Also, if you noticed the number of addresses in the addresses table after loading, it is only three when the correct would be seven. This is because we're not saving the number of generated addresses after we generate them. Let's fix this. Let's go to the update current wallet receiving addresses service will need the wallet repository here. So let's inject it into this class. Now, we'll call the increment number of generated addresses method on the wallet repository. As its parameters will pass the initial number of generated addresses and the current wallet name. Let's create this method. Let's change this type parameter to the integer class and this parameter name to increment. As its name suggests, this method will increment the number of generated addresses field in our wallet. To do that. Let's add the transactional annotation to it. This annotation is a requirement of the JPA library because it'll do the SQL operation in two steps. Let's also add the modifying annotation. This annotation is needed by repository methods that modify registers and tables, which is the case. Finally, let's add the query annotation to this method. This annotation will indicate the SQL operation we want to make as its parameter. Let's add the following string. This SQL-like statement will add to the number of generated addresses, the increment value passed as the first argument to the annotated method. The where clause will make this operation occur only in the wallet with the name equal to the name parameter. To bind the method parameters to the SQL variables. Let's add these two poem annotations to these parameters. Now let's run our test again. Great, it has passed. Our load wallet feature is done. Now, it's important to run all our application tests to check if a bug appeared. But first, we'll fix an optimize some of our tests to use the weight load wallet method and delete some sleep method calls that aren't needed anymore. Let's first uncommon these tests. And let's make the mentioned optimizations. In the nested segment tests, such as the ones from this class, we must add some parameters to send Bitcoin and wait method call. So let's do it. The last parameter of these calls must be the string hashtag nested segment receiving address. In some methods such as this, we also need to set the ID plus one is the third argument of the send Bitcoin and wait method call. Now, we can run all our application tests. They all must pass in my machine. They're taking half an hour. So I left this as an exercise for the student. 73. Importing a Wallet with the Mnemonic Seed: In this video, we'll implement the ability to import a wallet with the mnemonic seed. It's important to have this option to recover your wallet and cases where you lose, destroy, or don't have access to the hardware or files containing the application or database with your wallet data. In these cases, you would simply enter your backed up seed and optionally your passphrase in the import feature of the application to get access back to your wallet. One more thing, you won't be restricted to recover your wallet. Using this application, you'll be able to use mnemonic seeds generated by this application to recover your wallet and other BIP 39 compatible wallets. Also, you'll be able to recover access to your Bitcoin wallet addresses by importing your BIP 39 mnemonic seed generated by other wallets into this application. Just make sure both applications support the derivation pads of the addresses you want to import. So let's start by creating the import wallet test. It'll extend the GUI test class. Let's copy this code from the send Bitcoin test and paste it here. Now let's create a test called should import wallet and receive Bitcoin. In the one-block, let's set the wallet named variable. And let's create a mnemonic seed using the mnemonic seed service create method. Now let's call the import wallet method, passing the wallet name and mnemonic seed as its parameters. Let's create this method. Let's also add a password as a third optional parameter to this method. Here we'll click on a menu with the Text Import. Then we'll click on the Menu item with the text wallet. Now, we'll click on the component with an FX id of wallet name. This component will be an input field where we'll enter the name of the imported wallet. Next, we'll call the write method passing the name variable as its parameter to type the name in that field. Next, we'll click on the password field, which will have an FX id of wallet password. Then we'll write the password in that field. Next, we'll click on the mnemonic seed field and write the mnemonic seed variable in that field. Finally, we'll click on the Okay button. Let's also add asleep method call to wait for the wallet to load. Back to the import wallet test using the lookup method, let's retrieve the address value present in the receiving address field. Using the send Bitcoin and wait method, Let's send 1,000 Satoshi's to the retrieved address. Now we'll click on the addresses tab. Then using the lookup method, we'll get the addresses table and store it in a variable. We'll click on the transactions tab, get the transactions table and store it in a variable. Also, let's do the same with the total balance labeled text. Now, let's set two variables to store the addresses table size and the transactions table size. Let's add the following assertions in that then block to check if the previously set variables have the expected values. Now let's duplicate this test. Let's rename it to should import used wallet and received block. In this test will create a wallet and receive Bitcoins in it before we import the wallet, then we'll import the wallet, generate a block in our note and check if the application correctly loads and updates the imported wallet. So let's create a given block here where we will create a wallet and send one Bitcoin to it. Now, let's delete this line. Let's change this variable name to import wallet name and increase its wallet named number. We'll use this variable to name the imported wallet, since we can't create two wallets with the same name. Let's pass the password variable to this method call. After importing the wallet, let's generate a block. To do that, let's first generate a note address using the node get new address client. Then we call the generate to address method, passing the node address as its parameter to generate a block. Now, let's call the sleep method to wait for the block to be mined. Finally, let's change the expected total balance. Will expect a balance of one confirmed Bitcoin and zero unconfirmed Bitcoin. The rest of the test stays as is. Now. Let's go to the playground dot FXML to design the import feature menu. Let's duplicate the load menu tag and its contents. Let's change this text attribute to import. This fx ID to import menu FXML. Let's also add the action attribute here with its value referring to the method open-end port wallet dialogue will create this method later to respond to a click on this menu item by opening a dialogue window. Let's go to the Scene Builder to see how it looks. Okay, the Import menu was added next to the load menu. Now let's copy and paste this code to the main window FXML. Let's create this method in the main window controller. It's code will be very similar to the open create wallet dialogue method. So let's copy it and paste it here. Let's change the dialogue title to import wallet. And let's substitute the load wallet dialogue field for the import wallet dialogue field here. Let's create this field and let's inject it into this class. The value annotation here will point to the import wallet dialogue FXML. Now let's create the input while a dialogue FXML in the FXML package. Let's use the content of the create wallet dialogue FXML as the base to build it. Now let's change the dialogue header text. Instead of click on Create, let's ask the user to enter a valid mnemonic seed. Next, let's change the FX controller to import wallet dialogue controller. Now, let's go to the Scene Builder. Let's delete the Create button. Let's put a label here and change its text to creation date. Let's add a date picker control to the cell. Let's click on the mnemonic seed text area and make it editable. Back to the text editor. Let's change this Fxi de toilette name and this fx ID to wallet password. Let's set the date picker FX ID to creation date. Now let's create the import wallet dialogue controller in the controllers package. Let's add the component annotation to it. Let's add all these FXML fields to the controller. Let's make all these fields private. And let's add the FXML annotation to them. Let's copy and paste the initialized method from the create wallet dialogue controller to our new controller. And let's do the same with the all required inputs are fulfilled. Let's change this name variable to wallet name. Let's also copy and paste this method to our new class. In the Okay button event handler we'll call the import wallet method. This method will simply create a Wallet using the data type by the user. So let's use the create wallet method from the create wallet dialogue controller as a base to build it. Let's inject the create wallet service into this class. Let's change these variables to the ones in this Controller. And let's inject the initial number of generated addresses into this class. Let's do the same with this context field. Now, instead of using a new date as the parameter to this method, will call the bill date method. Let's create this method. We'll use the following logic here. If the user does not choose a date, we'll use the date when Bitcoin began to work. If he chooses, then we'll use the chosen date. The date parameter will define how far in the past the node we'll go to find information about the imported wallet addresses. The older the state is, the longer the node will take to import the wallet. So let's use the default date method to define the default date. Here we'll use the simple date format object with the following parameter. Then we'll try to return the simple date format parse method call passing the default date constant as its parameter. We'll use the catch block to wrap the parse exception in a runtime exception. Let's define this constant, which is the date when Bitcoin began to work. Here. If the creation date is not null, then we redefine the date variable to the following value. Finally, we return the date. After creating the wallet will publish the imported wallet event. Let's create it in the GUI dot events package. Here, we'll pass this parameter to the super constructor, and we'll set the wallet field to the wallet parameter. Let's create a getter for this field. Now, let's go to the Save wallet listener. This listener will respond to imported wallet events to save imported wallets. Let's refactor it so it can listen to more than one event. To do that, let's remove this implements statement. Let's change this method named to uncreated wallet event. Let's add the event listener annotation to it. Now let's create the unimportant wallet event method, passing in imported wallet event as its parameter. Let's copy and paste this line here. And let's add the event listener annotation to this method. Setting an order annotation to event listener annotated methods will make the order of execution of these listeners predictable. The smaller the order annotation parameter is, the higher the priority for this listener to run compared to other listeners of the same event. So let's add this annotation to this method. Let's pass zero as its parameter to make this listener the first of its kind to run, Let's add the same annotation to the uncreated wallet event method. We prioritize saving the wallet first after its creation to guarantee that if later listeners fail, at least we save its DataFirst. Now let's go to the created wallet import listener. We want this listener to import the imported wallet into the Bitcoin node. So let's duplicate the unloaded wallet event method. Let's change its name to unimportant wallet event and make it except the appropriate event. Now let's add the order annotation to these methods. The imported and created wallet event listeners will receive one as its parameters and the loaded wallet event listener zero. This way, we guaranteed that when the wallet tries to fetch data from the node, it will already be imported by the node. Now, let's go to the loaded wallet listener and add a listener method for the imported wallet event, as we just did in the previous class. Now let's add an order annotation to both methods, passing to as the parameter for the unimportant wallet event method and one for the unloaded wallet event method to make these listeners run after all others for their events. Now, let's run our node. And let's run this test. The first test passed, but the second failed. Let's see why. Okay, a constraint violation exception occurred because we tried to save a wallet with the same name two times. We forgot to change the wallet name variable in the import wallet method call for the import wallet name variable. Let's fix this and let's run the faulty test again. Great, It has passed. 74. Validating Addresses: In this video, we'll implement some validations before we create an import wallets and try to send transactions. The first validation will prevent the wallet creation from continuing if the wallet name is equal to a previously created one. So let's go to the create wallet test to create a test for this condition. It'll be called should not create wallet with repeated name. Let's create a wallet in the given block, creating the necessary variables and using them in the create wallet method. In the one-block, let's add some code to create a wallet with the same name as the one created in the given block, but now using the GUI. After trying to create the wallet, let's add asleep method call here, we expect the application to show an alert dialog window containing a message saying the wallet name already exists. So let's define a variable containing the message. Now, we'll use the lookup method to get a component with that message and store it in the node query variable. Finally, we'll click on the Okay button to close the dialog window. In the then block. Let's add the following comparison to check if the message in the alert dialog window is equal to the error message variable. Now, let's go to the create wallet dialogue controller. In the create wallet method, we'll use an if statement with a validate wallet service to check if the wallet name is valid. So let's inject this service into this class. Let's create this service and the database dot services package. And let's finish injecting it into this class. In the if statement, let's call the wallet exists method on it, passing the name text as its parameter. Let's create this method. We'll use the alert error service and the if body. So let's inject it into this class. Now, we'll call the alert error method on it as its parameter. Let's pass this constant. Let's create this constant in the error messages class. It'll have the same text we defined in the test. Let's import this constant here and call the return statement. Now, let's go to the validate wallet service. In the wallet exists method will lead the wallet repository. So let's inject it into this class. Now, we'll return the exists by name method call on it, passing the wallet name as its parameter. Let's create this method just by this method signature Spring Data JPA magic already knows how to query the desired information from the database. Let's go to the create wallet test. Let's comment these tests. Run our node and run our new test. Great, The test has passed. Let's uncomment these tests. Now, let's add the same wallet name validation in the import wallet feature. So let's copy this test and paste it here in the import wallet test. Let's change its name to should not import wallet with repeated name. Let's make some adaptations to this test. First, let's increase the wallet named number. Then let's modify it to import a wallet here instead of creating it. And let's change the parameters of these method calls. Now, let's go to the create wallet dialogue controller and copy this if block here. And let's paste it here in the wallet dialogue controller. Let's inject the necessary services into this class. Let's change this variable to wallet name. Now, let's comment these tests and run our new test. Grade. The test has passed. Let's uncomment these tests. Now, let's add an address validation. When trying to send transactions. Currently, we can type anything in the address to send field. If we try to send a transaction to an invalid address and error occurs and his silently ignored by the application without the user noticing, will implement a validation that will make an alert dialog appear on the screen if the address to send is invalid. First, let's go to the send Bitcoin test to create a test for this scenario. Let's name it should not send Bitcoin to invalid address. Let's add code to create a Wallet using the GUI and the wind block. Let's wait for the wallet creation. Now, let's copy and paste this code here to send funds to the wallet. Let's create this previous amount variable here and set its value to 0.1. Let's set one to the second range method called parameter. Now let's create a node address and generate a block for it. Let's click on the Send tab and call the send Bitcoin method to try to send 0.01 Bitcoin to the address to send variable. Since the address to send variable will contain invalid addresses, we expect an alert dialog window to appear containing a message saying the address to send is invalid. So let's create an error message variable with the following message. Now, we'll use the lookup method to get a component with that message and stored in the node query variable. Finally, we'll click on the Okay button to close the dialog window. Then block, let's add the following comparison to check if the message in the alert dialog window is equal to the error message variable. Let's define the address to send variable with some test cases in the where block. Here, Let's pass these test cases available on the Project and Resources page. Each test case has an error. The different parts of the code will detect. The first test case is a string with a non-existent prefix. The second case has a correct reg test prefix, but a remaining invalid address. The next three addresses would be valid reg test addresses, but their last characters were changed. During address construction. Part of the address uses the rest of the address to be built. That part is the address checksum and its function is to detect address alterations. During address decoding, the checksum is verified and we would expect an error to occur if this verification fails. The last three addresses are valid, but they're not from the reg test environment, so they must be considered invalid. Let's go to the script config finder. In the URLs throw method call, let's pass a lambda whose body will return a new create transaction exception with an invalid address constant from the error messages class. The create transaction exception is already caught later in the code and its message is already shown in an alert dialog window. Let's create this constant in the error messages class. It'll have the same text we defined in the test. With this modification, we expect the validation to cover addresses with invalid prefixes. Now, let's go to the transaction creators service. Let's wrap the code in the build output method in a try-catch block. In the catch block will throw the create transaction exception passing the invalid address constant. With this modification, we expect the validation to cover errors from decoding addresses who's checksum verification fails. Let's go to the send Bitcoin test. Now, let's comment these tests and run our new test. The last three test cases failed. Our wallet succeeded in sending funds to these addresses. This happened because the address decoding discards the address prefixes. Of course, the transactions were sent only in the reg test environment. Therefore, making these addresses invalid is important to avoid situations where you think you're running your wallet in one environment, but it's actually running in another. Let's fix this. Let's go to the address matcher class. Let's create these segment method. It'll return a predicate of string. And it'll take an environment enough as its parameter. Now, we'll create a map object with environments as keys and predicates of strings as values. We'll use the map of method to create this map. For each environment will set a Lambda to validate if the address parameter has the expected prefix for that environment. For segue main net addresses, we expect that they don't start with BCR and start with BC test net addresses. We'll start with TB and reg test ones. We'll start with BCR t. Then we'll return the map.get method call passing the environment as its parameter. Now, let's duplicate this method and change its name to his nested segment. In this case, may net addresses. We'll start with three tests, net and reg test addresses. We'll start with two. Let's duplicate this method and change its name to his legacy main net addresses. We'll start with one. Test net and reg test addresses. We'll start with M or N. Now, let's remove these Lambdas from this class. Now let's go to the address configuration class. Let's add this Bitcoin environment field. Let's add a value annotation here to inject the value of this field using the Bitcoin environment application dot properties setting. Now let's change the segment parameter here to call it as a method and pass the Bitcoin environment field as its parameter. Let's do the same to these nested segment parameter here. Now, let's go to the script configuration class. We'll do the same modification we just did in the address configuration class. Let's inject the Bitcoin environment into this class and modify the script config beans to call the proper address matcher methods. Now, before running our new test again, let's fix some tests. In the address sequential generator test, we must set the Bitcoin environment in the address configuration instantiation like this. Let's run this test. Great, It's still passing. Now, let's do the same to the create wallet service test. Okay, It's still passing. Let's do the same to the single random draw a coin selector test. This time, we have to set the Bitcoin environment in the script configuration to. Let's run it. Great, It's still passing. Now, let's fix the transaction creators service test. Okay, it's still working. Finally, let's do the same fixed in the transaction size calculator test. But this time we have to set the Bitcoin environments to test net. Since we use test net addresses in this test, grade, the tests have passed. Now let's go to the send Bitcoin test. Let's comment these test cases to run only the last three. Let's run it. Great, the tests have passed. Let's uncomment these tests. And let's fix this test named letter. It send, not sent. 75. Creating a Progress Bar: In this video, we'll add a footer section to our application's main window. The footer will contain a progress bar and a text label. The progress bar will be active when our wallet communicates with our node, which can sometimes take awhile. The text label will show a brief description of the activity our wallet is doing during that communication. So let's design that section in the playground dot FXML. Let's go to the Scene Builder. First. Let's add an H box to the bottom of the main window. Let's change the pref width of the H box to 600 and the pref height to 19. Now let's add a progress bar to the H box. Let's also add a label to it. We'll set the label left margin to ten, and its text to an empty string. Now in the text editor, let's copy this code here and paste it into the main window dot FXML. Now let's encapsulate the progress bar and labeled components into FXML files. First, let's create the progress bar FXML. Let's delete this content. Let's create an ethics root tag with a type pointing to the progress bar Java FX class. Now let's copy the attributes from the tag and the main window dot FXML and paste them to our new FXML. Let's set this XML NSF X tag in the main window, FXML. Let's delete this progress bar in its place. Let's add the progress bar controller tag, which will create later. Now, let's create a footer dot FXML file to encapsulate the label tag. Let's delete this code. Let's copy and paste the label tag code from the main window FXML to the new FXML. Let's change the label tag to an ethics root tag with a type pointing to the Java FX labeled class. Let's add this XML NSF x attribute to the new tag. Now let's add the missing imports to this file. Back to the main window. Let's substitute the copied label tag for the footer controller tag. Now let's create the progress bar controller and imported here. Let's do the same with the footer controller. Now, let's go to the progress bar controller. Let's add the component annotation to it. Let's use the Receive tab controller constructor as a base to build the progress bar controller constructor. Let's fix its name and value annotation to point to the correct ones. And let's delete the current wallet since we won't need it. Now, let's copy this constructor and paste it into the footer controller. Let's fix the constructor's name, and let's add the component annotation to this class. Let's make the value annotation point to the right FXML. Now let's make this class extend the label class. And the progress bar controller class will extend the progress bar class. Let's go to the GUI listener class and add both controllers to the set so they get configured as custom components. Now, let's create an observable that will model the progress state. It will be the async progress class created in the observables package. Let's add a component annotation to it. To define the progress bar state will create a double property field called progress. Let's instantiate it here with a new simple double property object using zero as its parameter. Later, the parameter zero, which sets the progress bar state to inactive, will be passed to the progress bar. Now let's create the task description field. It'll be a string property and we'll define the footer label text. Let's instantiate it using a new simple string property. Let's create getters for both properties. The IDE created two getters for each field, one for the property and the other for the value of the property will need only the getters for the properties. So let's delete the other getters. Now, let's create the start method here. We'll use it to set the progress value to the indeterminate progress constant. The value of this constant will make the progress bar show a bar moving to the left and right, indicating that some task is running in the background. Let's also define the stop method, which will set the progress value back to zero. So the progress bar will be inactive, indicating that no task is running in the background. Finally, let's create the set task description method. It'll take a string as its parameter. And it will set the description parameter to the task description field. Now to control when the progress bar and footer label change, we'll use an aspect. Let's create the progress aspect class in the GUI dot services package. In Spring Boot. And aspect is a method modifier. We'll use an aspect to define that every method annotated with a specific annotation will start the progress bar to find the text and the footer label, execute the code in the method and revert the state of the progress bar and label. To do that, let's add the aspect and component annotations to this class. Let's inject the async progress observable into this class. Now let's create the activate progress bar method. It'll return an object. Let's add the around annotation to this method as its parameter will pass a string with the text at annotation, open parenthesis, activate progress bar, close parenthesis. This annotation defines that the aspect will execute code before and after it's modified methods. The activate progress bar parameter, we'll define that the aspect will modify methods annotated with an annotation with that name. Now, let's add two parameters to this method. The first will be the preceding joint point, which will be a handle for the annotated method. The second will be the activate progress bar, which will give access to the annotation parameters. So let's create this annotation, will create it in a new GUI annotations package. To make it an annotation, we must modify this keyword to an interface. Let's add the target annotation to this file as its parameter will pass the method constant. This will make the annotation valid only in methods, not classes or fields. Let's also add the retention annotation passing the runtime constant as its parameter. This will make this annotation active at runtime. Finally, let's add the string value field to this annotation. This field will be populated by the parameter passed to this annotation call. Back to the progress aspect class. Here inside a platform run later method call will pass a lambda whose body will call the async progress set task description method, passing the activate progress bar value as its parameter will also call the async progress start method here. Now we'll call the preceding join point proceed method and storage returned object in the result variable. The proceed method will make the annotated method run and return its result. Now wrapped in a platform run later method will change the states of the async progress fields again. But this time we'll set the task description to an empty string and call the stop method on the async progress. Finally, we'll return the result variable containing the annotated method returned object. Now let's go to the progress bar controller. Let's inject the async progress observable into this class. Will bind the async progresses progress field to this controllers progress property in the initialized method. Let's go to the footer controller. Let's inject the async progress observable into this class. In the initialized method will bind the async progress task description field to this controllers text property. Now, for the progress bar to work, we have to annotate the methods we want to track the progress with the activate progress bar annotation. Let's do it in the import wallet service first. Let's pass the string with the texts loading wallet as its parameter. Let's copy this annotation and paste it here in the sign and send method of the sin transaction service. Let's change its parameter to sending transaction. Let's also add this annotation to the update UTXOs service classes update method as its parameter. Let's pass the phrase updating UTXOs. Now, let's run our node. And let's run the send Bitcoin legacy test to check the progress bar in action. As we've seen, the progress bar and footer label are working as intended. Great. 76. Updating Dependencies: In this video, we'll update the dependencies of our project. Maintaining a project's dependencies up-to-date is a good practice. By doing so, we benefit from bugs and security vulnerability fixes applied to our dependencies, maintaining our application more secure. So let's go to the palm dot xml file will increase the version of our obsolete dependencies. Depending on when you're updating them, newer versions may be available. Let's increase the Spring Boot starter parent version. For me, the newest version is 2.7. 0.5 will increase the Java version to 19. Let's remove this groovy version now, since it's not necessary anymore, it's version will be set automatically. Let's go to the project structure settings. Let's update the projects Java version. If you're needed, Java version isn't available. You can click on add SDK to download it. Let's set the project language level to the latest available. Now, let's increase the Java FX controls version. Let's do the same with the JavaFX FXML. Now, let's update the Java FX Maven plugin and the G Maven plugin for correctness. Let's update the Bitcoin Java version to 0.4, 0.4 in the Maven dependency plug-in configuration. Now let's click on the load Maven Changes button. Now let's update the Bitcoin Core Node version to 23. Let's download it from the Bitcoin core.org website. Let's download version 23 and install it in the same folder as the previous version. I already did that, so I'll skip this part. Now. Make sure to set the reg test environment flag in the bitcoin.com file. Before running our node, let's delete the reg test folders inside the Bitcoin no data folder and our application's database folder. We'll do that just to clean our test environment. Now, let's run our node by looking at the console. Notice that our node is running version 23. Good. Now, we must do a small modification for our wallet to work correctly with the new Bitcoin Core Node version. Let's go to the create wallet RPC method documentation to understand it better. In Bitcoin Core version 23, the descriptors argument of the create wallet RPC method defaults to true, while in the previous version it was set to false. That makes our application wallet unable to call some RPC methods we use to fix it, will manually set it to false so that the change won't affect us anymore. So let's go to the node create wallet client. Let's add the following parameters here. Let's add them to the create wallet method's signature. Also, the disabled private keys parameter will be a Boolean and define whether the created node wallet will generate private keys. When set to true, the blank parameter creates a node wallet without seeds and keys. The passphrase sets and optional passphrase to encrypt the NerdWallet. As the name suggests, the avoid reuse parameter defines a policy to avoid address reuse. Finally, the descriptors parameter defines whether the created node wallet is a descriptor wallet. A descriptor wallet is a new type of wallet in the Bitcoin Core Node we won't use. Now, let's go to the node load or create wallet service. Let's add these variables to this method call. Now let's copy this code and the node create wallet client and paste it here. Now let's go to the wallet service. Let's add the following values to this method call. Here, we'll set the disabled private keys and blank parameters to true. Since our application, while it won't require the node to create private keys and seeds for us. The passphrase will be an empty string. We'll set the avoid reuse parameter to false, since our node will generate addresses for us and the descriptors parameter will be false. Now, let's go to the GUI test class. In this method call, Let's pass the following values. Unlike the previous case, this time, we want to generate private keys and seeds because we'll use the node wallet to send bitcoins in our tests. Therefore, the first two parameters will be false. The third will be an empty string. The avoid reuse parameter will be set to true. So the node will avoid reusing addresses for our test wallet and the descriptors argument will be false. Now let's do one more modification for some reason after updating our dependencies when there are two okay buttons on the screen during some tests, test FX ends up clicking on the wrong one. To fix that, Let's go to the alert error or service. Will add an Fx ID to the alert OK button programmatically. To do it, Let's create the ok. variable here. We'll use the lookup method to obtain the button reference and assign it to the ok. variable like this. Then we'll set the ID to alert. Okay. Now let's go to the create wallet test. In this test, instead of calling the click on method with the okay parameter, let's pass a reference to the alert dialog Okay button using its ID. Now, this test will unequivocally click on the right okay button. Let's do the same with every other test with the same problem in the project. Let's fix the one in the import wallet test. Now, let's do it in the send Bitcoin nested segue test. Finally, let's fix the tests and the send Bitcoin test. Now, as an exercise, I'll leave it to the student to run all application tests. 77. Running our Wallet on the Main Net Environment: In this video, we'll install and run our application on the main net environment. Since we'll deal with real money, it's highly recommended that you guarantee that all the application tests are passing. Also, it's advisable to start playing with small Bitcoin amounts. First, let's update the Bitcoin Java library to version 0.4, 0.5 in the POM file. This version fixes an issue when importing the word list file when running the application after installing it. Let's go to the mnemonic seed service and remove this throws statements since we no longer need it. Let's do the same to this create mnemonic seed method in the create wallet dialogue controller. Now, let's run our node on the main net environment. To do it, Let's go to our bitcoin.com file and remove the reg test configuration line, save the file and run the Bitcoin node. Okay, now our node is running on the main net environment. Here comes the sad part. It may take days or weeks to sync our note on the main net environment since, for the time being, it has 436 gb in size. In my case, the console indicates that the blockchain download progress is about 52%. Later in this video, I'll show you the application running on my other machine, which has already sync to completely. For now, let's modify our application to run it on the main net environment. In the application dot properties file, let's modify the Bitcoin environment setting two main net. We'll assign the port 83 32 to the note RPC URI config. This is the default port the Bitcoin node uses to expose its RPC API on the main net. Next, let's set the crypt key in the spring data source URL config to this environment variable that requires us to set this environment variable in our operating system before we compile our code. By doing so, we increase the security of our application, avoiding exposing the database variables in our code. Let's do the same with the values of the spring Data Source username and password configs. Now let's generate secure values for these configs. To do that, let's use the SQL DB manager will achieve that by calling the crypt key function like this. Let's generate three values and copy and paste them into a text file. It's important that you keep these values in a safe place since any change in these values before compiling the application again will result in losing access to the database. If that happens, you'll still have access to your wallet. If you keep your wallets, mnemonic seed and password, but you'll have to delete the database files and compile the application again. Now, I'll paste these environment variable values directly into the application dot properties can fix. I'm doing that because at least in my Windows machine, the application does not interpolate these values with the system environment. One's, the same problem doesn't happen in Linux. So I think it's some kind of strange bug during compilation. Tell me in the comments section if you experienced the same problem. So we can find a solution for this problem together. For now, we can move on with the application dot properties is, is in the Maven tab. Let's right-click on the Install button. Click on modify run configuration. In the runner tab. Let's activate the skip tests checkbox so that the Maven install command won't run the application tests before installing the application. If you're using newer IntelliJ AID versions, this option may be available in the configuration icon in this window. Click on the Okay button. Now, double-click on the customized install option inside the Run Configuration section. Great, the application was successfully installed inside the indicated folder in the console. Before running it, make sure to install the Java SDK with the same version as the application. I'll go to the Oracle website to download and install it. After installing it, close and open the terminal. Now, copy the path where your application installed the application JAR file. You can use the command java space double hyphen version to ensure your terminal runs the correct Java version. Now run the command java space, hyphen jar space, the path you just copied. Great, the application started successfully on the main net environment. Let's try creating a new wallet. It successfully created a new wallet, but since our node is still sinking, the loading progress bar would stay active for a long time before we could test it. Now, I'll show the wallet working on the main net environment in my Linux machine where the node is 100% synchronized. So I've just installed the application the same way we did for Windows. This shows a great Java advantage, which is the smooth cross-platform compatibility. Let's run the application. From now on, I'll hide some data you'll see on the screen for privacy reasons. First, I load a wallet. I've already created it correctly loaded as expected. Now, I'll create a new wallet. I'll annotate the mnemonic seed using pen and paper before clicking on the Okay button. Now, I'll copy the address and paste it into a text editor. Now, I'll load the previous wallet, which has some funds in it. Now let's send some Satoshi's to the address we copied from the addresses table. We can see that a new change address received some funds. Great. In the transactions table, we see that a new transaction with zero confirmation was created. Now let's open the wallet that received funds. We can see that both the addresses table and the transactions table have a new register indicating we've successfully received some Satoshi's. Great, everything is working correctly. 78. Extra class - Bitcoin Core v26: Welcome to our first extra class on updating our application to communicate with Bitcoin core version 26. We'll see that there are very good reasons for staying up to date with the newest Bitcoin core version. First, let's visit this website to download Bitcoin core version 26. Click on the appropriate version for your operating system. Since I'm using Windows, I'll download the file. Essentially, we'll be overwriting the current version of Bitcoin core that we have. Make sure to choose the same installation path as our current one. In my case, I won't proceed with the installation since I already have it. But for you, it should be as simple as clicking the next button multiple times before running the newly installed version. Let's explore the immediate benefits it offers, starting with Bitcoin core version 25. We can see from its release notes that it implements a new index that significantly speeds up wallet Re scans. To opt in for this new filter, we simply add the block filter equals one setting to our Bitcoin config file. Upon restarting the node, it will begin building this new index. It may take a few hours to complete, but afterward we'll notice that loading a wallet after some time without running our node becomes much faster. Now let's discuss some changes introduced in version 26 release notes. We find that to use non descriptor wallets, we need to set a deprecated RPC setting in our Bitcoin config file. Subsequently, non descriptor wallets will be deprecated in future core releases. Don't worry. We'll demonstrate how to migrate our application to descriptor wallets in the next extra class. For now, to ensure that our current wallets will function with Bitcoin core version 26, let's add this setting to our Bitcoin config file. While at it, let's also add the block filter equals one setting that we discussed previously. Now let's run our Bitcoin core node in the reg test environment. We're almost done, as always, with any significant change we make in our application, we must run all our tests to ensure everything is working correctly. I've already done that on my end and found that one test stopped working when running against the new Bitcoin core version. It turns out that the should not send Bitcoin with the wrong password test from the send Bitcoin test class failed. However, not because the transaction was successfully sent, but because the actual returned error differed from the expected one. I debugged it and discovered that the error response Bitcoin core sends in the new version now contains a different message, which is this one. We simply remove the non from the beginning and add failed at the end. Now the mapping between this error response from core and our application should be accurate. That's it. Now if you run our tests, they should all pass. In the next extra class, we'll delve into what a descriptor wallet is and how to adapt our application to create this type of wallet. See you then.