 And we write software mostly in our entire stacks, and Haskell or PureScript were like sub-functional programmers, and we wrote a lot of libraries that you probably don't use in Haskell and PureScript for dealing with Ethereum specifically. Now we work on a different project also for Haskell bindings to basically Haskell. Yeah, can you hear me in the back? No. I'm literally shouting, so. Close the door, maybe. Close the door. Now we're working on a different project, basically like Haskell bindings to like a, you know, the tenor in ABCI, sockets for a call, and at Haskell SDK for the Cosmos Network that's also part of our work, which is my work. So that's what we do more or less in this talk, trying to finish on time. But it's up to some point you can't hear us in the back, but try to keep the door closed. That's what's going to do most of the work in the end. Well, all right, so, as Martin said, this is the presentation through the blog. We have a workshop tomorrow. If you're interested in what we're talking about, you'll get the chance to use libraries and ask people for that specific purpose and bring people forward. To talk about what do we mean by functional programmers. Functionals are more of those things around the log. So, for us, we basically focus on purely functional languages with strong static typing. What does that mean? Purity is a concept much like referential transparency. It means that your computations actually don't have any side effects. So think about your computations as equations like x equals five plus three, whatever, you're not actually performing any operating real work. You can manage effects to different kinds of concepts. In Pascal and Pierceberg, you should talk about monads. So it's sort of a pure way to talk about impure programs. Then the type system, which maybe in your typical programming languages deals with different types of data, strings, integers, proteins, and so on. The type system in the programming languages that we want to talk about actually are able to reason about these effects as well. So it prevents you from doing things that deals with the real world when you're writing something that is almost computer valid. Usually what happens when you have type systems like that is that the compiler needs to get really sophisticated. So we try to use that to our benefit. So you have really advanced metaprogramming capabilities in the libraries that we're using. And a lot of the libraries that we've been developing utilize that to a large extent. Yeah, so it's the key. Basically the kinds of things that we're contrasting against your widely popular programming languages like JavaScript or Go, they're kind of like languages that everybody uses in this space. People seem to be very productive in those things, so that's your DM and that's cool. But basically you can't really make an argument that either is a particularly future thinking or innovative programming language. Especially if people like Go, and it seems like lots of programs are suggested written in Go, but for languages like Tobias in 2005 or whatever it was, and knowing everything that we know now, they've basically just created a Java server like 1998. So it's like you can do things in those, that's cool, but there's like a lot of research in programming language theory that enables kinds of reasons about programming, reasoning about programming that we can do now in 2019 that would not possible in 1998. That's like we're trying to work on these. So because like neither one of these offers much in terms of like safety so the ability to statically analyze for behavior or performance or possible whatever, you know, people focus especially on things like security threats in this space and all those things are really difficult in these languages. Oh, and so... Yeah, basically these are the libraries that we're talking about right today or like tomorrow with this other workshop where some of them are written in a language well-pure script, which we'll talk about later. Basically like the ones of, you know, whatever, there's a web-free API similar to whatever, you know, JS, web-free or Java, web-free or whatever. It has lots of features that those things don't, but that's some kind of functionality that it covers. And then Chantrel is like a tool that we have made and has come to kind of like maturity at this point that is a smart, contract-employed management and testing tool similar to Truffle but without all the, you know, nonsense. So, and I should also mention that like, okay, then there's also the Haskell libraries which are maintained for this. We don't maintain this, but we're, I'm like the largest contributor to that probably at this point. And we run a fork because we go through that one. It's also worth mentioning that we proposed this talk through last year's thing and we were denied because it was considered like French or like Nietzsche or whatever. So I don't know if the standard's got lower or the stakes got higher. Like none of these things are new. They've been around for over a year. And just now we got invited to talk, we actually got invited to talk about it instead of denied. And yeah, so the ones that are in gold or whatever, those are things that we actually own. The ones that are purple are more important for it. This is not super interesting but just to highlight the point that we actually did all this stuff last year. So this isn't like your new like JS framework of a week or whatever that's going to, next week is going to get replaced. All I have to say is that these libraries are mature and you can use them and illustrate that in this workshop tomorrow. But this is not like some new thing that doesn't work or whatever. All I wanted, we can just skip this in the interest of time but basically all of this work really started in 2017 and more or less like, except for the case of Truffle which happens, whatever this Truffle decision were to replace it. It was kind of all happening contemporaneously like with our growth as a company. Like maybe you haven't heard of home as a Ethereum company but we started writing software in 2017 and basically the reason why all this software exists is that we try to use the off-the-shelf stuff and people figure out how to use it and we're like reasonably smart people. So all of this started to be developed in order to produce our own products and write our own applications which today run on the main Ethereum. It might, I think, quite successfully give it to other people that we actually are working with. And in fact, if we don't have a lot of users and not a lot of complainers, so I think it works. Yeah, I'm just skipping this. Yeah. So just before we dive in to sort of like more technical details of how these libraries work I just wanted to get a little bit of motivation for why we think it's important. So Martin showed that we started working on these libraries in 2017 when FOM was new and we started developing what's now called our map. Back then we called the Spatial Index and we were faced with, we had a little bit of Haskell blockchain experience and we were faced with having to write a full stack application that's now fairly sophisticated. Imagine kind of like Google Maps.com or whatever, running on Ethereum. And so we've had a couple of years and we back then decided that it's worth doing the upfront investment to develop these libraries for the front-end side as well as the backend instead of using established technologies. And I guess the reason for why we're still happy with that and we'd like to admire you to use these tools as well is that we're basically now a small operation where like four or five developers working mostly on other things at this point. And we have the basically type safe deployment. So when we're generating code from, you know, the solidity code generates all kinds of bindings for both the backend and the front-end because we're using these strongly typed languages these bindings also have types, right? So that means that the compiler will tell us if we've changed something on one end of the stack and the rest of the stack that depends on it hasn't made the reflective changes. And because it's not just like matching word by word or counting number organs, it's actually very able to encode a lot of the actual behavior of those functions, we get a lot of safety when deployed. And so this, you know, we're not on the camper we're saying don't write tests anymore but the types for the compiler and type checking are integration that effectively eliminates a whole set of tests. And so this has served us really well when we're generating an application. Another point that I don't think we'll get to it to show it here, but one of the really beautiful aspects of the classical part of this is that our whole API is a type. So that means that the compiler, the compiler understands the type, you can reason about it. And so it effectively generates all, well I should say most of our bindings, the compiler does that for us. So that means that we do get, so we expose our production API in terms of this swagger definition which is like a standard for exposing API. We didn't write that. That's generated by the compiler every time we deploy. We use that internally, but other companies use the same swagger definition to integrate with us. So they have the same level of, you know, guarantees that we have ourselves. And so recently, we've had a couple of sort of great integration happening completely without our help. So no, like, telegram, you know, health channels or even both of those really. We're just exposing this API and the generated docs. And so we've had recently an Android application that's paired with knows the safe and uses phone for locating points. So you need five different points physically to like recover your wallet. They want some hackathon. There's an upcoming chain integration that uses cross-chains, both mainnet and proven. And we have sort of written global cloud output from our API. And actually part of our host, we don't have the ability to write applications for every use case. So we actually have a user community that builds applications for us to serve our users. And again, a bit very little support. So that's kind of why this tool is a little, they have a large learning threshold. They really pay off once you have it. We can probably skip this or whatever, but I will say that like, oh yeah, this is kind of relevant for some of the work. So yeah, people, you know, there's like a, you know, a solidity by the assembly. There are various states of development on those things. You know, like, or even like in the area of like applications-specific blockchains, people are looking at, you know, not even having to worry about this entirely. You know, it's like, it's a Cosmos tournament where you can write your applications in what you want. And now that you're given, like, a variety of choices, it's kind of like, well, don't make the same mistake twice basically. So that's all this is really about. Also there's like, probably some confusion because pure script is not really a popular language. But if you've heard of Haskell, which a lot of people have heard of it, Haskell is kind of like more of this big point means like a family of languages than it does even one specific thing. So there are, like, people talk about a K Haskell. It just means like a language which has a similar type system up to a certain point, and very similar syntax. So basically like pure script is an opinionated dialect of Haskell. It was created, the first compiler that was written in 2013. So like to compare with other things that people know about like typescript or null or sort of the same like family of functional programming languages but are not typescript but null but are comparatively much weaker. They're roughly the same age. This is also not sort of like the new fad JavaScript framework for this week. And basically like, the language itself simplifies and distills a lot of concepts from Haskell that were learned and separate from the kinds of backwards compatibility problems that Haskell has because it's a very old language. So lots of things are like re-done and done right the first time. And it's actually not even really a language itself. It's more like a language specification that supports like multiple backends or run times. So like the pure script language itself is just a language specification. It doesn't specify the run time behavior which means that you can technically write bindings to like the pure script or DOM or whatever in any language that you want. And the most popular one is JavaScript because it needs to run in the browser. And the reason why is that most of the pure script core developers were coming from the user interface design and they wanted to write frameworks to write web applications in this language. So that's why it's the most sophisticated but there are others. There's an Erlang one which somehow it's the most advanced of them but there's also the C++ and there's some experimental work on someone for Go as well. Like if you have like a large Go application in the, well not now but in the future but today you've had like a C++ application and you wanted to start off loading some of the core parts of the application to a more time-heavy language you can write certain parts of this thing in pure script and have it compiled and linked to C++ to like get a later big phase of the tool chain. Yeah, I'm actually not sure however in this, oh I see it because we're at the bottom of this. I see how. We're like somewhere in like a three-dimensional slide show right now. Yeah, so basically like the present day situation is that like I said all of these things are mature for working with the standard stack of an Ethereum blockchain for the Ethereum blockchain and solidity or something that produces an AMI of the standard type of what we're used to. Chantrel itself is kind of like married to solidity at this point because it integrates salt as part of this pipeline build pipeline but you know there's other things you can go in directions there that are kind of more they're newer, they're kind of stabilizing but they're not really stable enough for us to really integrate with like this Ethereum support kind of like that's kind of other shortlets of things to do but then there's other things like language, other language support like my birth or whatever it is this morning like formality or whatever the case of anything that generates an AMI though is very fair to you. And then here's like a comparative stack diagram in case none of that makes any sense to you so basically on the left hand side you have like your kind of traditional stack that you kind of like comes from a lot of like the working consensus to the beginning and now it's kind of like off-shoot shoots to other companies but you have things like test RPC or like Gnash or maybe the same product as a point or Truffle, the main involvement is assumed by like one project sitting sorry, those kinds of like fake Ethereum layers or maybe a real Ethereum layer you have a solidity compiler with 3JS Truffle and then you build all of your applications on top of that and what we're advocating for is more on the right hand side so there's like Ethereum and clickbait just like our version of some kind of test RPC it's effectively like a simplified Docker container that runs a real Ethereum node but in a timeline that you can expect to run unit tests and stuff like that. Here's for web3, solidity compiler, chan-trail as well as all of your app development so you can use slides for your publishing. So like that's part of the talk of what this stuff looks like and you know here is like, for us it's like yes, it's a firelight for some definition of the word simplified because there's like a pretty steep learning curve starting to know how to do these things but at some point your life gets exponentially simpler it's just, I don't know how long it's gonna take for you individually but you kind of like well basically like I just want to talk for a second, this is kind of like more in-depth of what we were talking about earlier, some of these more concepts of functional programming are illustrated through these libraries so again like there's this notion of purity, it means there's a separation of the time system between what's called like effectual computation or stuff that has side effects or might throw exceptions or whatever it's a list of something to codex like coming to and from bytes or byte strings whatever has the possibility for decoding errors and what happens when you have those how far did they bubble up and how much do you handle them that's the kind of side effect that's like more pure in the sense that it didn't happen because of like a network failure it's something that just you're programmed through an exception in some way at some point you have to deal with it throwing other kinds of runtime exceptions or indicating errors that happen unrecoverable errors such as like database failures or API call failures but also basically like improperly formatted data exceptions etc also like invoking a web3 or another network call these are all things that we need by like side effects because you've in that sense you've communicated somehow a real world which means you've actually created some side effects such that if you made the same call again you would get different results depending on what you just did examples of pure functions are like more kind of like you know they're everywhere but they're like somehow difficult to come up with like interesting examples because they're kind of situation specific but like data transformations that can't fail there's sorting a list for example is a pure computation because there's really nothing what are you going to why do you need to ask you know the internet how to sort the you just like write a sort of algorithm and it works there's no unless you ask stack over basically there's no way that you're going to there's no way that I can throw an exception there's no way that I can call call as a network failure there's no way that needs to read or write from a disk the sorting algorithm itself is a pure data transformation from a list to a list that's an example of like a pure function or other like mathematical functions or operations that just basically stuff that can't possibly fail unless it's implemented wrong but like there's no like random reason why it might fail so like here's you know basically like starting to get into some of the surplus like this is like a you know ground like a common framework here like we can talk about you know private public and private keys in Ethereum they use a certain signature schema called ECDSA on this particular curve people look forward to low enough levels and probably come across this a private key uniquely determines a public key this framework and address like the typical Ethereum address that we all talk about all the time is basically just like the last one of the bytes that happens in public keys so like this is just a common framework to say that like these are the things that you can actually talk about in these like these are probably a difficult to see from the back so I try to try to get in here but like anybody you know this is basically like kind of like parts where you know by the types by using the types in this way you're best in building a universal things you can talk about so like there's private keys or public keys and their addresses or whatever one of these things at a low level they're like byte strings of course everything at some point is a byte string but the point is to like basically build up abstractions like you do in every other language so that you know you can't confuse things like private keys even though they both prefer to byte strings you're basically trying to like abstract your way like the low level things you can talk about the high level things and then address it to whatever it's a hash result so it could be like a hex it's usually a hex string or whatever it's a sort of kind of coded byte string but it could also be whatever so like the example of purity for example here like these are kind of boring functions or whatever but these are examples of your functions so these will be the highlighting points like basically a way to like unwrap things so are to you know basically to take a public key and increase the hex string there's pretty much no way that because you're taking a hash result it's not a computation that fails you can basically you can ask for like how to get the you know how to make a private sorry a whatever how to how to make a public key from a private key that's something that again based on the description that we just gave in the last slide it's a combination of like actually taking slices or whatever because you know that hash is a certain size you know that the slice won't fail because pure computations these are kind of boring right these are the ones that are in some sense right because like is every hex string or this every byte string or hex string whatever correspond to a public key probably not if it's not 20 bytes long it doesn't so there's like a potential to fail here which is encapsulated in something public maybe or an option type or more familiar with these from like Rust or TypeScript or whatever can you put anything can any hex string become a private key possibly I mean basically the number again so but there are cases where this can fail can any add can any hex string correspond to an address no it has to be a certain number of bytes long here's an example of like you know whatever encoding you know what I say like encodings are not these are like effectful or not pure it's because basically like if you look at this like yeah okay ABI encodings there's a specification somewhere if you read the docs how do you talk how do you encode data that can be read by an Ethereum smart contract it's through an A it's through a codec schema called ABI or something it has even a name at all but you know basically for any data type that you should be able to communicate across a contract boundary line there should be a way to turn it into some like byte string or some hex string and similarly like if you want to decode like a two-pool of a salivary if you want to decode like a two-pool of EVM types you need some way to parse hex strings into those things so this is like basically like this is a language specific idea that like there's some for some types out there we can encode them and for some types we can decode ideally they're the same right if you can encode it you should be able to decode but then like here's this idea you know like okay we have like a hex string we want to parse it into something that has a particular type and we're making a constraint on this particular type that somewhere you define codecs for this thing this still might fail because like it doesn't matter that the thing has the decode instance the problem is is that the thing that you have at hand this raw byte string might be coming from somewhere else where it's not long enough or it doesn't correspond in some way to the thing that you're trying to decode because you made a mistake somewhere so in this sense like this is an impure computation because it might produce the value that you're looking for it might also produce a parse error instead that should tell you basically this is just basically saying what I just said which probably usually what we say is like this last computation or whatever it takes the hex string and runs it into either something of a type parse error or that you're looking for it's like basically you can think about this to like resolve the effects at some point like all the effects have to come out at the end of the day the program has a type which is IO if you get every program has this type in history of mankind and at the end of the day all of your effects have to resolve to some basic thing that the program can run and as your program evolves as your program is like coming down the way you're basically constantly resolving effects kind of like simpler and simpler things at the end of the day with the one type that programs all of these effect systems like whether it be like an error effect system or a network effect system they all have to resolve at the end of the day and this is part of like programming this style it's choosing where you want to resolve so how so basically like you know it's a it's a specific example like yeah it's a specific example of like a place where this can get interesting is like okay I'm like address is it address in EVM type you can decode this if you have if you have a by string of a certain length you can decode it so basically like throw away the first 12 bytes or whatever or take the last 20 bytes and try to basically just figure out if you have the right sorry if you can make an address from these last 20 bytes then it should be good otherwise it should fail I think this last one is I don't know I did use my hands there's no way this can fail basically this is basically saying you're like take the first take the first 12 bytes take the remaining 20 bytes and call it an address and the only way this can fail is if this take fails or this take fails and what that means is the thing you had so it wasn't long enough that's all this is saying okay cool so you can decode addresses from types or whatever that's pretty cool but like what if you you know to do something that's a little more complicated for example like in the EVM you also have this notion of like size to raise so like you have a precise array let's say it's like a tuple of addresses right like and then types also correspond like this in some way like for example everybody's favorite event is probably the transfer event that results in your address getting more money or whatever and that's effectively like a free tuple right of like well there's two addresses in there and then there's like a uint in there somewhere but in this sense like there's like a notion of like it also makes sense to speak about like a vector of addresses which is like a list of addresses of a predefined length and like okay so if you can somehow communicate the predefined length to the program that you're writing you can basically reason about it and say like okay like the only way that this thing can fail in parsing or whatever is if so if you're looking at like a vector of a predefined length which is this in here of certain type A you can decode into this thing basically what you're telling once you can successfully decode into this what you're telling this program is like no matter what at this point I know that this thing here is it's a vector of a certain length you don't ever have to worry again about like checking the size of this thing like you pass it off to a different function that function also will know the length of this vector because it's encoded in the types so if you can build that into like the codex or whatever basically what it means is that after you're able to decode information from the EVF you have enough information about this in this particular case this vector so that you'll never get an array out of bounds because you try to access like its third argument because you know that in order to even try to access the third argument this vector has to have a size of this I will show you an example of this you will get a compile time error if you try to access something which is not there so rather than like trying to check for this everywhere trying to throw some exception in case it didn't happen what's in end up happening is that like every part of your program will now be on instinct it will know that this vector has to be there it seems like a stupid thing but then it is a stupid thing but then once you realize how to do this you can do this more and more and more about it this is a particular example of what I'm talking about so like you know statically size factors if you do enough low level stuff with solidity you know how these things are encoded or whatever the first word is like the length of the thing that you're looking at and then it's followed by just the concatenation of all the arguments so I can have this you know you can't read this in the back probably but this is just the number 2 followed by 2 addresses and you like to parse this into a vector of length 2 this is like some type level language that's very specific to like the library that we use but basically what this is going to do is try to turn this texturing into either a parser or a vector of length 2 of type address and after that and after that forever like you can't for example you can't fail in this last case when you try to take the first coordinate this array you can never fail so maybe the intuition here is a little bit like so when you're typically in like an imperative language or languages less sophisticated type language every kind of operation you end up doing on something important you'll have like a lot of it statement and they kind of like all end up at the same place because you're doing something you can't find on whatever was kind of before carry the certainty of that information at that point in your code whereas like typically by composing a lot of interactions in which the guarantees of the data is encoded in a type this way you basically don't see any of these if statements or assertions in your code itself they're all packed into the type and then there's sort of the corresponding parser or whatever it is so when you're looking at an actual application code you don't see any of these like oh let me just make sure right here that I didn't like mess up the whole golf and it's in this sort of like places instead so that's kind of maybe the intuition yeah totally and then you know for going back to the effectual system for like network computations so we've previously covered just things that are like basically handling errors or exceptions or whatever what you know if you're able to encapsulate like network also particularly in context of a theory or whatever inside of this effect system what it kind of guarantees is that like you can't take for granted that if you run you know a commutation in one place then you would get the same result as if you tried to run it in another place so what it's saying is that like where you call where you make effectful calls can change the code that comes after it and so you can't just like make them where you want you need to have those sequences in a certain way if you don't you will get a type error your program will never run because it can't be applied so for example like whatever there's like a Web3 effect which is in this library which manages all of the effectful computations that run against an inferior node and there is a really really big difference between a value of type A and a value of type Web3 of A and basically like understanding this difference or at least getting used to it is kind of the basis for everything that happens here so I can't tell you how to understand it but I can tell you that if you understand the difference between having a value of type address and having a value of type Web3 of address these are very very different things I can't explain it to you all I can do to show you examples this is an example which unfortunately is going to be really hard to read for those in the back but here's an example from a test suite or whatever so here I have in highlighted so here I have highlighted all of the pure computations here which are effectively a series of Web files so basically like variable bindings and making size integers and things these are the things which I'm saying are not effectual and then actually for example this is a setup for context this is a setup to basically an ERC-20 token here is like the effectual computations are highlighted here basically it's a transfer so when you want to transfer tokens that is an effect when you do that whether it succeeds or fails the world is forever changed because you've caused some other thing outside of your program to react and then basically what I'm saying here is that like in order to run the effects or in order to give the thing that you're looking for which is effectively like at the end of this computation is like the result of causing this transfer event to happen is usually produced in terms of like events or whatever this is here is another effect like these things this has to happen before this can happen so here we're telling the compiler that this transfer action lives in Web 3 we don't know what that's going to look like because it lives in the other world the only way we can sort of look into it is to run a third Web 3 this is sort of like a run it's how you like resolve the effects to something low level so like I'm happy to talk to anybody who are asking questions about this but it's like there are certain places where you're allowed to you know find a variable to the result of an effect and it can't be just like in a simple assertion statement like here where I bind like the recipient of this token is going to be the null address that's cool I can do that because there's no effect here but at some point if I wanted to like take the result of this transfer like the data from an account and bind that to a variable to use for later computation inside of some of the effects but when you were saying that the assert Web 3 actually caused it to happen is that strict over there or is it still is it will it still be like lazy there and it will be there's something down the line will force the computation so in this language the peer script is strict which means that like all these things will happen immediately but in Haskell this would look identical to syntax and everything all of the things look exactly the same but yeah in that case actually you have some notions instead of the type of functional programming world there are some notions about when competitions run as part of runtime is built for the language itself and that can you're still guaranteed that they're going to happen in order but yeah like at what time will it take it depends on the thing so basically like yeah this you can go through these slides you know and ask yourself these questions like which you know continues to this previous slide like which part of this computation is pure which are effectful which parts can be thrown in exception which parts can be thrown in no pointer exceptions there are none because they don't exist in these languages but which parts can fail which parts can't fail these become basically like self-evident from the code itself and so rather than like skimming through line by line it's starting a bunch of print statements for things to figure out like when something's going to fail I can look at this program I can look at this program in advance and tell that this line could fail because it has it has an effectful computation this might be tricked up by a network error this is a variable binding that could cause that basically whose result is an effectual computation you could run later there's nothing being run here it's just setting it up so there's nothing that can fail here there's nothing that can fail it in these led lines so if this test fails because of an effectual reason there's no place in this line there's no possible way that it can do anything else so it just I don't know in that sense how you start to look at projects large bodies of code where many things are happening it's very important to be able to look at looking at only this particular block I can tell that the only way that this can fail is this one this one part here so what you gain the analogy here is that whatever like the the code is to the program it's like the type starts in the metaphor which is to say that the compiler is taking in the types that you're giving to the program that you're writing whether you like it or not is typed you don't have to always write it yourself but you don't always have to annotate it and say that this thing has typed whatever the compiler is able to figure out a lot of that for you but by typing the language itself the compiler is able to operate on your on your types and to produce certain guarantees for certain things in the same way that your program can operate on values so in the same way that your program manipulates values the compiler here is basically reading in types and reasoning about those things in the same way that you were reasoning about Boolean logic or whatever it is that your program does and the more accurate and expressive that your types are the more work that the compiler can do for you for free the more accurate that your types are for saying when things can throw exceptions and if they can't, when they might fail and when they might not the compiler is able to basically tell you more and more about the possible places where your program is being correctly written or where it might fail on the downside of this is that this kind of program is really hard but it's different than being really hard to get right it's really hard to learn but once you learn how to do it there is not really it's very difficult to implement a program improperly in these languages like you have these people who talk about Askelol especially like oh the first time I went to Askelol program by the time I figured out how to get it to your pile like a few months later it just worked the first time there was no unit test it just worked it's because like it's actually while it's somewhat difficult to express programmers in these languages it's difficult to get a program to compile it doesn't do the thing you think it's doing or something actually it's interesting because it's somehow done in some sense like it's supposed to be impossible so the interesting parts of this library which I would tout or whatever whatever the way that it does parsing in ABI basically dealing with writing coding and decoding stuff is pretty cool it's easy to prove it all so I didn't spend six months writing testing stuff and then it just kind of like works and it's not really the way that it's implemented is not really cool the thing which I would say is like the most interesting thing is probably the way that it does so there's like a meme here I think I would say here is probably the most interesting feature that this has that does not exist in your vanilla.3.js library or whatever is something that's just called like the multi-filtering or something which is like basically a way to use Ethereum logs in a particular order that you want to specify and I just built up with the remaining time before we have a few questions or whatever I would just specify like what that means so Ethereum logs if you don't know are basically the way that it's a mechanism for applications to create updates to contract states so like when contracts change you don't always know unless there's an event that gets fired that would tell you to go back and basically look at it or possibly just consume the log itself to get all the information you want to know and these are consumed by some kind of like something called a filter like a Web3 filter it's a diagram about how this works it took me forever to make and so like the problem statement for like this multi-filtering thing for example is like you want to listen to multiple events each one of them coming from one of several different contracts this is very common because you have multiple you know to separate concerns you write multiple different contracts you don't have just one giant contract each one of these things submitting different kinds of events from different addresses and you want to define specific handlers that run against each submit type this is you know most common in some cases when you're just trying to store them in some kind of cash layer but it also might you know whatever it might update a UI or something like this and every time that you want to write each handler over its event in the event that in the event that the events were logged you know so like in chronological order so like contracts if I have one contract in this event before its return statement makes a call somewhere in its body which causes another event to fire then like I want to resolve these things in the order that they came out basically like a block and so the use case for this which we have which probably lots of other people have is that you're building a cash for contract state which is updated or revalidated whenever a certain event is fired because you want to use as your back end you want to use like a relational database but you know you don't want to use like the EVM as your back end so you might want to fill out some cash for your application there are dependencies in your events for example like an empty market contract like a token listed for sale event that indicates like oh there's a new token I can buy but that token itself refers to a token ID and that token ID is you would only know that that token existed the event that like meant new token event from the NFT contract itself and fired in some case so like there's kind of like a result resolving of actions that spawn things to happen but in order to make sense of one action I might have to know that oh this token was meant in a different location and the reason why is that you know in a relational database for example you have things like 4 and 2 constraints that say that like this token for sale this token for sale is a row in some database and that row has a column called token ID is pointing to a token table somewhere else and if that token is not in that token table then this schema has now been invalidated because I can't talk about a token for sale unless I know about the token so basically like you have created a situation in which you have you know 4 and 2 constraints in a relational database that you cannot maintain unless things are processed in order to keep those 4 and 2 relations sound and so this is particularly useful to not run against like a full archive node where so like if you want to run a full yeah that's not a big problem if you if you have a full archive node cool you can do whatever contract lookups at whatever point in time you want for example if I have like two different event processors one catching all the tokens that were ever minted one catching all of the tokens that were listed for sale if I don't have a full archive node whenever I get this token listed for sale and this like token minted event or else I can look up stuff that things are going to resolve we're out of time or I would talk more about this because it's an interesting problem that kind of all kinds of things that will come up in this talk here in tomorrow but that's how I'll do it for now and the last case is you know we're going to have time to talk about this but if you want to talk about Cosmos then ask me what you're talking about that's it