 Before I start, so my clicker doesn't work, so I'll try to make it anyway. Before I start, how many of you are using Redux or using Redux in the past? Okay, just probably, I see yes and no's. Okay, we'll try and see what. Maybe we can try a quick one. Is it going to install it? Oh, okay. Let me just see what I can do. We're closing. It doesn't seem to be working. Oh, it's working. Okay, so that's, okay, cool. It is working and that's great. I've got a clicker as well. So, good. So, I don't normally, I spend most of my time nowadays talking about other technologies other than JavaScript. So, I usually spend my time doing Kubernetes, so it's really good to be back and doing a little bit of JavaScript for a change. I'm really excited about it. So, today, I wanted to talk a little bit about our story. So, and this story started two years ago and I had a friend, a close friend, we were both in London and this friend runs a small investment fund and he was moving to New Zealand. Okay, and then usually, when you move to a new country, or you have family in other countries, you might need to move some of your money from where you are right now to somewhere else, right? And, while doing so, you might experience different things such as the exchange rate, the need to find a reliable service and it has to be quick and the government doesn't have to ask questions and so on and so forth. Okay, but there is something strange. I was talking to my friend and he basically said, have you ever noticed that there is something, something going on with these services? Okay, there is something weird. So, he said, go to transfer wise. Are you familiar with transfer wise? Most of you are. So, if you're not familiar with transfer wise, it's just a way to transfer money from one currency to the other. So, in this particular case, I've got the transfer wise website and what we're looking at is the two currencies. We've got euros and we've got British pounds and what we're interested in though is not just the two currency, but the exchange rate. So, in this particular case, my friend said, have a look at the exchange rate and jot down the value, okay? The number that you see. In this particular case, I'm looking at 88 cents as an exchange rate from euro to pounds. And then said, go back, just refresh the page and start from scratch, but this time, just swap the two currencies, right? So, we used to go from euros to British pounds, we go to British pounds to euros and he said, again, do the same thing, just look at the exchange rate and write that down, okay? So, I did that and just look at the exchange rate, write that down and these are the two exchanges for the two pairs of currencies that we are interested in. And then he said, imagine you're sending money to your mom, okay? Let's imagine we are sending 1,000 pounds to your mom, right? We've got British pounds and we send euros. So, for each British pound, then we're gonna get 1.14 something, something euros. So, at the end of what we get, let them out. Okay, you're good. What if we send the money back now? Just, you know, we change our mind, we convert all the euros we've got back to British pound. Well, easy enough, we can do that. We've got the exchange rate that we saved earlier on and we just do the multiplication and this is what we get. Oh, oh, where are these three cents coming from? Looks interesting. Okay, but surely, right? It's gonna be like some sort of bugs. We transfer wise, surely it's, you know, something that they do wrong, probably not. So, this is, I don't know if you're familiar with this artist app, it's called Revolut. Again, based in London, I did it with similar things. There'll be more than just transferring money between currencies. They're also sort of a bank. They're applying for a license. So, it's very exciting space. But we're not interested about anything more than exchanging rates. So, if you look at the numbers here and you look at exchange rates, so we've got 88, it's in the middle, it's quite small, about 88 cents and 1.13 on the other side. So, we can do the same sort of math that we've done earlier on, right? And if we do, if we buy these 1,136 pounds and 12 pence and we convert them back 88 cents or 0.2, this is what we get back. I've got a cent. Okay, but why? I mean, I'm creating money out of nothing. Right, well, where is the cash? To explain how it works, let's take a step back, right? Let's imagine that instead of going to transfer the Ys or Revolut, you just go to your bank and you say, I want to transfer some money. Now, there are two cases. You are in the same country, so you are in Singapore and you want to transfer money in Singapore, then you don't incur any transaction. At least, I think I don't incur any transaction. I hope I don't. But anyway, you don't incur it, they're definitely not in England. And you get the money, but if you do, if you transfer the money with your bank from your account to someone else's account, which is not in the same country, then what happens is the bank is gonna take a hefty fee from the money you're transferring. Okay, so that's a little bit of a problem. And then companies such as Transferwise and Revolut came up with a really, really interesting solution. And this is how it works. Instead of having like just two people wanting to exchange money, they actually had a pair of people wanting to exchange money. You can see that the person at the top want to transfer a thousand pounds. The person at the bottom want to transfer 1,200 euros, which are similar, right? So the clever people at Transferwise said, what if I convince the guy at the top to give the money to the guy at the bottom, and I take the money at the bottom from the right side and give it to the first one? If I do that, right, we never, ever move the money outside of a country. We adjust the middleman that moves the money from one side to the other. Okay, so, and that's exactly what they did, right? They basically found a really clever way to transfer the money inside the same country instead of moving that money outside of a country. Now, to do that, of course, they charge a small fee, but it's in comparison to what a bank would charge, that's just like tiny. Now, this is what works for the pounds and this is what works for the euros. You can see that at the end, I get the same result. And this is great, but it is not great when I start having a lot of different currencies, right? I need to find more people wanted to do this match, right? In this particular case, we had, in the previous case, we had euros and British pounds, but as soon as we had one more currency into the mix, then we need double the people to just match everyone else's demand, okay? So that's why services such as Transferwise and Revolute, they offer you really, really good deal when you join because they need to have a massive user base to be able to transfer this money around, which also takes us to liquidity. So, market like Transferwise and Revolute, they are most of the time just not very liquid, which basically means that sometimes your money can wait a little bit longer to be transferred on the other side because we need for someone else in that country to move the same amount of money out of the country. At that point, we can do the match and then we can do the transfer. So all of this was saying, okay, good. We know how to make free pens, maybe one. I mean, it's more than nothing, but it was still like it's tiny. What can you do with it? It turns out that not all the platform works in the same way. So, what I was looking for, for platforms that do transfer money between different countries, I came across these other websites called currency fair. And then, as I was interested in exploring the space, I built a small dashboard in D3 and that dashboard basically would track the exchange rate for each pair and would tell me what happens. The interesting thing about currency fair, you can see currency fair here, is that had really, really good sort of exchange rates which basically meant that if I were to multiply and just assume that I could transfer a thousand pounds worth of money from British pounds to Euro and from euros to British pounds back, I would get four pounds. Great. So if I have two transactions per day, 20 days in a month, this is the best side project I had in a while. The first side project will actually makes money. It was like a dream come true, right? So, and that's what I did. I said, okay, I can build this stuff, okay? It shouldn't take long, so I'm gonna build it. So when I started, I had three sort of goals. I want to, it's a side project, right? So usually the goals are I want to play with toys. I want to play a lot of toys and need to be shiny. So I had three wishes when I started and the wishes were, well, the first wish was, I definitely need something that can listen to changes, right? The thing is, I showed you the happy path when things go okay and the two exchange rates are actually good and you make money, but sometimes they're actually not making money at all. Now, if I have two orders and the exchange rate is not profitable, I want to cancel my order, otherwise I'm gonna lose money. So I want my tools, I want my system to be reactive to changes, right? I want to listen to pride changes. I want to say listen to order changes so if an order is matched or partially matched, I want a notification from that. And I also want to know if there is any money coming in, when it's coming in, if it is going out so I can basically decide if that, I should place an order or not, right? So this is the kind of events I was looking into. And the other interesting things I wanted to play with was time traveling, okay? Who wouldn't want to play with time traveling, right? I mean, it's not that kind of time traveling when you go back to the future, but it's a kind of time traveling that we do all days if you're using React and Redux, okay? So this is a simple to do app and all we're doing is adding and removing items from a to-do list, but if you use Redux and Redux tools, you can basically replay the session as it happens, so you can basically go back in time. And why would you do that? Well, I thought if I could record all the actions coming into my system, so price changes, order coming in, order being matched, then I could actually replay them and just make sure that my algorithm is doing the right thing. So doing time traveling would be quite interesting to explore a new possibility for my algorithm and also to inspect what's really going on. The third sort of goals I had was to make sure that my system is bulletproof. So I know this might sound a little bit, you know, crazy. Well, not crazy, but just weird, but at the time when I was working on it, then this news came out of someone accidentally publishing some test data on NASDAQ, you know, on the NASDAQ Exchange and taking down the entire stock for Amazon. And I mean, I'm not making things up. You can read the press release and someone basically just, you know, mistype and publish the test data and that crushed the stock. I don't want that to happen to my bot. I'd rather not lose the money if I can. And on a similar subject, I also tried the same algorithm on the stock market and you can see this stock is quite expensive. It's $100,000 per stock. And one day I was testing stuff and for some reason, well, I forgot a break close in my loop and it just kept, you know, buying everything. But I was lucky if there was another bug that actually prevented the order to be submitted. So the double bug saved me. But I learned a lesson that time. I said, well, better be safe. Oops. So this is what I built. The first MVP I had was basically a combination of a small message broker like ActiveNQ and then I had a database where I could save all the prices and the orders. And this is what it looked like. So you can see I had like my Node.js application which was in charge of making the decisions. And then the RabbitNQ is basically just a place where I could place the messages and consume them. And then there's a series of worker that could just basically consume and publish messages into the queue. And it was great. It works. So I could basically grab price information from the exchanges and ingest them in my application and then save them back to the database. It was great until it wasn't. It was a little bit over-engineered so it took me like ages to get it running. But I think the most big problem that it had was actually the state. And now I'm gonna explain why because this is perhaps something a little bit more interesting than me over-engineering a side project. But we have currency fare on one side and your application on the other. And then usually what happens is all the orders are stored in currency fare, so the exchange. And then what you would do with the application, you would say, hey, please send me the order. I'm gonna store them locally. Okay, that's what you do. And then you say, I want to know the price so I can make a decision if I should place an order or not. And then you get an order back. You get a price back. But if in that time frame, one of the order changes, there is nothing notifying you because you're not subscribing to it. At least I couldn't subscribe to the exchange. For in this example, the order two goes completed. So it's not available anymore. Now I just show you that I received the price information. I ingested the price information and actually what I realized is that I'm losing money. So what I want to do is to update the order. But if I update the order, the API is gonna say, well, that order is gone, game over. Okay, so that was a real problem for me. So I basically decided to scratch all of that and then go back and think about a better way to do it. And a better way to do it for me at the time was had a look at these new programming language. I don't know if you heard of Helm. But I think the easiest way to think about it is just look at Redux. Helm is basically a much better version of it. And then the way it works is very, very simple. All of your state is in one single place. If you want to change the state, you need to send a message. And what happens is you have a function that takes the two and gives back a state. So this is what it looks like. This could be a message, right? So just the plain object and then the state. So it's basically again a plain object. So what you would do, you basically take a function that takes the message in the state, crunches them together and returns the state. Okay, that's what all Redux is. And I thought, well, this is great, right? I can have all of my states, all of my prices, all of my orders inside the state. And I can be clever about it and just, you know, this time maybe keep it simple, just get it running first. And I did. And it was kind of great. It had Redux, it had level DB, so it embedded database. And I packaged it as a docket container as well. I was really excited about it. I had one challenge though. And then if you're using Redux, you probably find this every day. When you're building an application with Redux, so this way to send a message in the state, then usually what happens is you've been told by every guide on the internet, every sort of tutorial or material you read is that you cannot have side effects inside your Redux state. And side effects are like HTTP calls or doing a console log or the set interval. And usually what you should do is you should refact to your code in such a way that side effects are outside of your store. And that's usually what's recommended. So if you use Redux in the past, you're probably familiar with these actions. And then basically here what we're doing is just refactoring these actions and making sure that they are outside of the state. And then what we end up with is just another type of event and then we create a state with the extra events and suddenly we refactor all the state and it's pure and everyone is happy. And if you read a story on the internet, you can tick all the boxes. All good. The challenge with that is that your state and your flow are separated. And with that, I mean, you need to do something on one side in the action and then you need to go on the other side and make sure that it's actually in sync with everything else. Which I thought it's just madness. And there are a bunch of projects actually trying to address that. So you might have heard of Redux Saga, Redux Sunk, Mobex is doing something similar, but I thought it was like really something that I couldn't live with. I want to have my actions next to my state. I don't want the two things to be separated. So I went on and then put aside version three. So version three has a slightly modified Redux version and what it had basically, I have the same state, same message, and instead of returning just a state, I will return a state and a series of commands. You can think of the commands with side effects I will pass to someone else. And this is what it looked like. I will basically, I used to have the update order inside the action, now it's inside my state. And what will happen is basically, the update order will basically just be a description of what it will look like, what the action looks like. And this is what happens. So I send a message to the update, I get back a state and a command, a series of commands. These commands are just description of what I want the action to be. And then I will use something like an interpreter. So just like a JavaScript object that takes commands and then executes them. And that could be like an HTTP call, a console log, a set of might, also all the things that are impure that produce side effects will be encapsulated in my interpreter. So that's interpretive pattern. And this is what I look like, right? I would return a fetch and that is just like a description of what I want to do. And then I would have an interpreter that will go for each command and actually execute that action. So no side effects. It was good. I thought it was really clever because I like to play with toys. But the reason why I thought it was really good is because I can make a request and I can say I want to fetch an order and it goes to fetch an order. But because it's an interpreter, right? I could change the execution of the interpreter. We've actually changed the logic of my application that I could implement things such as web sockets without anyone noticing it because it was inside interpreter and not inside the application itself. So it allowed me to do things such as that or even better, I could basically change the interpreter altogether and just use mocked version of my services. So that was quite cool. If you're interested in the kind of space, I would suggest look at sort of these three tools. And, but at the end of the day, it was quite interesting. So I had the state and logic together. I loved that. It was a very, very easy test and interpreter, I could just mock things out so it was really good. But it was a little bit complicated. I went down a really hard path of doing something weird so I basically decided to quickly refactor that. So in the end, I settled on this design which was basically actors. So instead of sending something special, I would basically have messages going around and being posted on small queues inside the application and then going back. That's basically what it is. So it ended up, you know, I started with a really over-engineered system with queues and MySQL. I ended up with a really, really small application that was just 200 lines of code for the frame or to send messages and making sure that I could react to them. Now, before I jump into some of the results, I'll just quickly mention what I find really interesting. So the testing side, I think what I found really interesting is that you want to test, I showed you why you want to test. You don't really want to spend millions on the stock market just because of a bank. But one of the things I noticed is that I will find myself writing this code which is testing something where, and then I would come up with test cases and then I will come up with test, negative test cases and then it will look like this which is really, really long when in reality what I was doing, I was just changing the values inside this object, right? The function at the bottom was the same. I would just, just tweak those two numbers. So I found this really interesting library which I regularly recommend which I'm not able to pronounce but it's basically just a way to refactor your tests in such a way that they are data driven. So in this particular case, you see the function I want to update is at the top and then I'm just changing the values in the given and that allowed me to basically write way more tests than I usually do and that brought up the confidence level I had about my application. The other one, good one, and I think this is just a general recommendation. I think TypeScript is really, really good and the reason why I find it good is because most of the times you have things like this, right? You have an order and you start developing your application and then most of the time you realize that you forgot and you need an extra flag, like active for example, is the order active or not? Then you add the extra flag in. If you don't have TypeScript, then you need to go back and retrofit that flag to every other object you've got in your code base. Now, if you're doing a small project that's probably doable, but if you have like a legacy code base that's not doable at all. Things like TypeScript in this particular case just for an error and help you refactor that object so you have the confidence that everything is the same across the board. The last one is about integration. So we talked about unit tests. I think I'd really like this gift when it comes to integration tests and unit tests. Okay, so if you have a lot of unit tests, doesn't mean that this is gonna work. And that was the very same thing for me as well but usually end-to-end test, integration tests are quite hard to maintain, right? But the interesting thing was because I went down the, well, because I went down the rabbit hole and ended up with a different version of Redux. One of the things I could do was to basically record the market as a series of event and then replay them and making sure that the results of my code would be the same. Now, I know this is probably very, very small but this is like a Bitcoin market and I'm just recording the sessions with all the coming in, prices coming in, all the coming in and out. And then you can see that they're always written down as events. So I recorded the session and now I can just replay the session whenever I want and just make sure that the result of the state is the same as I progress through my test or my development. But I know what you're all waiting for, right? Did it work? Was all this testing worth it? Yeah. Really optimist. Well, it did work. You can see, so this is a graph showing the number of orders I would do during a day. So you can see that some days I was really, really lucky so that peak that had up there is about 24 order, 24 order placed in a day. And you can see the other days I would basically be a little bit unlucky. It could be because I was testing or the market wasn't particularly good. And this is over three months. And then you can see this is the revenue that I had during three months and it's kind of going up. So I think it's a side project was okay for me. Can you guess why that happened? Crash? Anyone else? Bug. Bug? Actually that was my wife. She realized that it was working so she gave me more money. Yeah. Okay. So in the end I made like twice the investment which was really, really good I thought. I mean it's not a lot of money but you know playing with this kind of toys I wouldn't expect any sort of money it was whoever actually worked. And I made almost a thousand transactions when I got this email. And let me read some of the lines of this email because I think when I read the email I was pretty sad. I hope this finds you well. No, it didn't find me well. We had just completed some routine checks on your account and then wanted to contact you regarding how account is being used. Uh-huh. It would see you're predominantly using it as a trading platform. Maybe. So currency fair wasn't happy that I was making a lot of transactions on their platform because this is against their terms of service. Lessons learned. Lessons learned. So read the terms and condition of the services that you're using. It was my lesson learned. But I think I want to focus on a couple of things here. And the first one is it's a trading bot in JavaScript. Only five years ago I was playing with script kiddies on jQuery on a browser and now I'm doing an algo trading bot with no JS. I think the JS community has gone a long way from being just a couple of guys collaring stuff on a browser to being a fully programmed, fully grown up programming language that can do a lot of stuff. So I'm really excited about things such as TypeScript. I'm really excited about things such as Babel, show transpilers, Redux, which introducing backend sort of paradigms such as CQRS to the front end. I mean, we don't even know this stuff when we're using it. It's so powerful. So I'm really excited about it. The other things I'm really excited about is actually trading. When I started, I didn't know anything about trading. I didn't know how it worked and I spent a lot of time just understanding. And one of the things I was looking at is just, you go online and everyone is saying, oh, why are you using JavaScript for trading? You should be using C++ or R or Python or something else. So you should have an MBA or you should need a special hardware. It needs to be really fast. That just doesn't work that way. Just a bunch of bullshit, really. What really made the difference for me is that trading at the end of the day is just basically calling APIs. You can do it with JavaScript. You can do it with Bash. You can do it with any technology that can call APIs. So there doesn't need to be any sort of special skill. It's not something that's relegated to people who have studied Binance. You can do it. I think that was the big message for me. And then the other one was, yes, I've been caught by currency fair. But, but what if I replay the same stuff on another markets? Is the Bitcoin markets suffering from the same sort of inefficiencies? Can I play into different exchanges and move the money? Are there actually stocks that behave in the same way? Is the forex market manipulated in times of the day or year where I could actually pray my algorithm? So if you're interested in this talk and this kind of stuff, so for me was a big lessons in side effects and how to test things properly. But if you're interested in the kind of stuff, I think I'm gonna post the slides. You can visit all of these links and they contain more information about sort of building this sort of side effects free applications. That was everything I wanted to show you today. Is there any question? I wanted to ask too. Okay, so first I want to know if this project was open source. So the short answer is no. I'm asking this because I was doing like by triangular advocate on Binance for the cryptocurrency. And somehow it works for a while. So what I was doing was only the background. I used like a bad backend and I used like an online service to provide the board. But I really want to make my own post. So if this one was open source, it can be very useful for me. The reason why it's not open source. Well, first of all, it doesn't work anymore. No, because the currency fair is gonna get you. But actually what happened after they sent me an email, I showed you a, let's see if I can quickly go. I showed you a diagram, a D3 diagram earlier on. Yeah, I've got a few slides. I don't remember anymore actually. I was a little bit more. There we go. So you can see in this diagram and this is perhaps the best way to learn about this stuff is that the two lines are going this way. But you don't make money when they are on the other side. Okay, the spread becomes less than one, you lose money. Yeah, yeah, yeah. So what happened is after I received an email from currency fair, I noticed that the line will always be reversed, which made me think that probably currency fair is manipulating the market and making a profit out of it. So I could open source the code. But it wouldn't work. Yeah, and what I'm interested in is not the strategy. I'm interested in your project like the... Okay, so you're really interested by my really dodgy code. Yeah, yeah, yeah. No, I mean, because I want to implement the system on my own, but if there is already the one you tested, like the structure of the whole project, I can only like alter the API I call the, a different exchange. Okay, I can send me your email, I can never look. Yeah, I think there are some links in the presentation of projects that are much better than mine. But I don't think there is a project which works in the same way. And I mean, my project doesn't have documentation. It doesn't have a lot of things. So it's not like, you know, you can grab it and just, oh great, you know, this is how I do it. It's just like a guy, you know, sitting in his bedroom just playing with stuff and documentation is not something that you could find. Sorry? Yeah, but some of the projects, I do actually that. So my suggestion would be rather than looking at my code, I think it would be really beneficial if you spend a little bit more time and see what's going on behind of it. Yeah, yeah. Okay, is there any other question? Do you go through all the currencies or coins to check which are the most inefficient one before you did it? Or you just chose meaningful currencies to you like pounds? So at the beginning, I didn't know how to move really because I didn't have experience with currency exchanges. I didn't have experience in sort of trading. And I think one of the first thing I did was like writing a very small argument where basically just map all of the currencies available and find a way to transfer all of them and get money in the end. And it works in theory, but doesn't work in practice because of a number of reasons. Which algo do you use to run through them at the same time? I don't remember the name of it. It's not such a problem. So I think it's a very well-known argument. You can see it online and there are plenty of options. But I think what I did was at the beginning I looked at all these currencies. But I think that like you said, there are some that are more efficient than others. So when they are efficient, then you don't make money. And there are some which are really, really inefficient. So for example, at the time, I think it was Japan yen was very inefficient. And you could make like between 20 and 30 British pounds which is like, we're talking about 60, more than $60. So $60, $70, Singaporean dollars, every transaction. Which is a lot of money, but at the same time, the market is so inefficient that there is no one making the exchange. So your order will stay pending for days. So you have the options. Do I get one time $60 or 20 times $20? And then it's a way of just optimizing for what you're interested in. At the same time, having more orders is actually reducing the risks that one is going to stay pending for a long time. So you need to find a good balance. At the end, we were just basically trying and seeing which currencies were more liquid on the market because we currency fairs and transfer wise. If they don't have enough people, your order will stay pending for a long time. Any other questions? On your redox advancement. So like I learned in school at a long time back that there are such things as state machines and we did them in rational rows on IBM software from back in the days with Java and all that stupid thing. I'm old, sorry. Sounds good. Like they're called like state entry functions or state transition function or state exit functions that you would normally define with statically defined states. Now we don't do that in JavaScript. We only call functions in reduces sometimes. I don't know if you use redox a lot. Any plans to put your version on the open source train as well to see how that compares? I mean, there are things like Saga that you might have heard of that are similar. But it's always nice to see different takes on it. So like I said, I think I wasn't the first to come up with a solution such as that. So redox Saga is one of the options. The other one is called, I think redox loop and it's basically very, very close to what I had. I think it goes back to the question you had, or can you, I think I could. I mean, it's, I'm not using it at the moment and maybe someone else is gonna find it interesting. But there are a lot of details that I didn't explain today. So things, for example, because it's a toy project for me, I tend to use more functional paradigm like such as, you know, monads and stuff like that, which adds a lot of complexity just for the sake of adding complexity so I can learn stuff. So I can open source a code, but it's sometimes could be really, really hard to understand what's going on just because it's reaching for myself and not for public consumption. But the project that I listed there, that they actually do the right thing with proper documentation and you can do 90% of what I've done. Oh really? Basically open source a code. Is that the only question? You mentioned Elm and TypeScript. Using a combination of the two and which did you, which was better for doing some things or better for doing other? So I had a look, so you said Elm and the other one is Elm and TypeScript. So basically everything I've written since there is in TypeScript. And the reason is it's much, much easier once you get the feeling for TypeScript to actually write really, really large application or just really safe applications in JavaScript. I would recommend it. If you haven't tried it, just spend, I know it's gonna be painful and just really be prepared for that, but spend half an hour and try and it's really worth it. So everything you saw here is actually written in TypeScript which is probably another reason why it's not super easy to get started. So Elm is basically was driving a lot of a decision I was making about this Redux state with side effects. So if you had a look at Elm in the past or if you plan to have a look at it, you probably realize that it's a side effect free sort of language. And a lot of the idea from Redux are actually, as far as I know, are coming from Elm. So that's why I was keeping always a reference on what Elm is doing and then mapping that back and see how I could fit the two things together. Okay, uh... I didn't hear anything about middlewares. Do you actually use them? Redux middlewares. Redux middlewares. I, and in this project I didn't use them. I think when I started using the effects, then all my middlewares actually went away and I just used the effects as part of the state. So I ended up having more, the logic all in one place, which is also the same structure you will see if you look at Elm. So it was much easier to understand and I didn't have anything like middlewares. I had only actions and then there is a slightly different thing. So you have a distinction between actions. One is events, the other one is commands. But it was, at least for me, it was easier way to look at a system. It was like one way. You couldn't, it's like basically, it's like Redux, right? There is no way to go back or, so it's a linear thing. Time for one last question before we, because we're done. Are we all good? Okay, cool. Thank you very much.