Every week, we run a meetup for the Investec Programmable Banking community. Developers demo cool projects they’ve been working on and everyone has the chance to ask questions. If you’ve been wondering where programmable banking is at, here’s your sneak peek!
In this demo, Marcin Jekot shares how he approached exploring functional languages to create a GraphQL for RESTful APIs. In this presentation, he goes into more detail on how he did an F# implementation.
Click here to download Marcin’s presentation slide deck.
Check out the repo here.
Transcript of the demo
Hello, everybody. Thanks for joining in. My name is Marcin, and I run a small software consulting company. It’s called Got.Codes. I’m a big fan of functional programming, and I also believe that exploring different languages or learning different programming languages makes your brain work in different ways and makes you approach problems differently. I think it’s a good mind-expanding exercise.
Today, this demo is about looking at the Investec banking API through a GraphQL lens. Sorry, Ben, I didn’t get to send you the questions, but what I wanted to ask is who (and I don’t know if we can raise hands) but who has used GraphQL in this meetup, or played around with it?
Stop me if anything is not making sense, feel free to stop me to ask questions. The de-facto nowadays is to open something up through a RESTful API. That’s what has become the de-facto standard. So why would we want to do GraphQL?
It does have many benefits over RESTful API, which we’ll try to explore in a little detail today. The tech stack that we’re using is F#, and .NET Core. I’m also new to this whole Microsoft .NET space, but it has been quite a fun experience looking into it.
I like to remind myself to zoom out, take a look at the bigger picture, and you take a step back and look at everything from the side. It seems that software grows in complexity and can get crazy and out of hand at times. What I like to do is question if there’s a different way of doing things.
Today, we will introduce two different concepts, two separate concepts that are off the beaten track, as it were, and depending on where you’re sitting, of course, because you could be way deeper into this already on this journey. To start with is the concept of GraphQL – GraphQL is this API endpoint where the types and documentation are bundled together in one, and there is no way to supply an out of sync definition of your API. There’s no way to say, Hey, you know, here’s my documentation, but I forgot to update it. I just added this field yesterday. While I update the docs, we have an OpenAPI, which was called Swagger in the REST world, and we can auto-generate documentation, but there are no guarantees that it’s correct and it’s out of the band.
With GraphQL, it keeps you honest – everything is kind of all packaged together. It’s a specification, and implementation all bundled in one and I hope that comes out in the little demo later when we do some requests against the API.
With REST, it’s become a tradition to create a wrapper CLI API for your language of choice. Well, not necessarily CLI but let’s say you’re using Investec API and we’ve already seen some clients emerging, I think in Go, Python, C# and Java, and there are probably others like Dino, which I have used. I have to mention in the acknowledgements that the Dino client helped me a lot with this, but the point is that we create this wrapper for each API that we use, and each language that we use, we create this big matrix of wrappers, and it just becomes this obliteration or explosion of lots of different wrappers.
With GraphQL, you just need a single client to interact with all GraphQL endpoints and any GraphQL endpoint out there. You use a GraphQL client, just like you would use an HTTP client in your language of choice, so you don’t need to create this wrapper specifically for the actual API – be it Investec or SendGrid API or Trello, whatever you’re using.
With GraphQL, we also create a single request, and we get the data that we need, in the shape that we need. So for example, with REST, we have to make multiple requests to get the login, get the accounts, get the balances, get the transactions, and as I will show later with GraphQL, we can do that all with a single request. It’s a lot less network latency, so it’s one request-response cycle, and it comes to you a lot quicker.
The other concept that we are exploring here, that’s off the beaten track is functional programming. In this instance, it is F#, which is functional programming, with static typing. I also wanted to evaluate a sample for solving business problems and seeing if it’s a good language that it’s not just a toy language, but a good language to use in real-world scenarios or creating fake and complex apps.
It has a thing called type interference. I’m not a user of C#, so I think this is in C# as well as a small subset of it, but it’s kind of saying if we have x = 2 let us have the strong guarantees of strong typing, but we do not have to be explicit about it.
So if we say x is equal to two, the compiler knows that two is an integer, and we don’t have to say, integer x is equal to two – the compiler is just going to be cool, I know x is an integer. The type guarantees or holds your hand while you’re busy coding and also, they get it out of your way because you don’t need to explicitly type things the whole time. It is less overhead and also less code.
It’s not just the typing that you don’t have to provide, it does seem that the code is much more concise, has less verbosity, and it’s very expressive, and you’re able to say many things in a fewer number of lines and you get this property, which is kind of weird. It’s often laughed at, but you will hear a lot of people say this about statically typed functional programs, that once your code compiles, it usually works on the first run.
It’s a weird thing for newcomers because they spend all this time fighting the compiler, and eventually your program type checks and it’s okay, I’m exhausted, let’s run this, and it just works, and you’re oh, wow, that was cool. It just gives you this very cool iterative feedback loop, and we get fewer bugs with it.
It doesn’t mean that we eliminate all bugs, but certain types of bugs, which we would need to check for, with dynamic languages just go away, but it’s not just that with static languages, we still get null pointer exceptions, and in F#, no pointer exceptions are not expressible; you have to explicitly deal with so-called optional type, which doesn’t let you shoot yourself in the foot and get an all point exception in your card. F# has also proved to be a good fit for working with GraphQL, REST and JSON. That’s just what we’re doing here.
Let’s run the demo of what this looks like. Let’s change the screen here and start the app up. I’m using the bare minimum number of tools, and I’m not using Visual Studio, I’m using just Visual Studio coded and a basic CLI interface. It’s a dotnet project that some of you might be familiar with. We just run it. On the other end, we get for free this GraphQL playground, which I’ll show you now. This is it. This is some stuff from an earlier session.
Okay, cool. This GraphQL playground I didn’t have to write this. This is looking from both the client developers, or from the consumer’s point of view, and me as the back-end developer. We get this cool, postman style interface for free, which we just bundle with our app, but it’s not coded we have to write.
There’s a couple of variants out there with different flavours of these, but you choose the one you like, and you include this as your static files in your project. It gives you this Explorer, where you can click to see what’s available in the API.
We have this Doc’s view, which is clickable. You can see that all accounts – it returns a list of accounts, and the account has these different fields. All of these are scalar fields, these are just IDs, and scalar fields, describing the account.
Then we get these more complex objects, like a balance, which itself contains available and current balances for the account. Then we get another list of transactions, that has all of these fields, now, all of this stuff is available in REST, the difference being that this is the way you would interact with any GraphQL endpoint, not just this Investec one.
Any developer would be familiar with interacting with a GraphQL endpoint like this, once they’ve worked with one, all the others just, provide a different domain, but the way you interact with them is the same. We also get the schema view over here, which is the same thing, but as a single file, it’s just as good as an SDL Schema Definition Language, which GraphQL spec defines, and you can just browse it, you can check that into your, source code repository.
From the back-end developer’s point of view, we can quickly make some test calls against our API that we’ve just created. What I’m doing here is I’m just using the editor window with Ctrl-Space and auto-completion, because it gives you that for free as an ID would. To query all accounts, we choose exactly which fields we want to bring back.
You don’t automatically get everything back, and you choose exactly what you want if there was a really large object and you just wanted 2 fields, you wouldn’t be wasting all your bandwidth, and you wouldn’t have to explicitly receive all of these details that you didn’t want.
Let’s just make a call against it and let’s get the account number back. I just wanted to get an overview like you would on the website. We get all accounts, and for each account, we want the number, the product name, and the reference name. Let’s fire that off. As a front-end developer, obviously you would choose this query according to what you were displaying on your front end.
Let’s say you had a page that was showing just an account overview, and you’d only bring back the fields that you were interested in and not the whole lot. This is taking a while, as I think my code isn’t optimised. It’s not using all the synchronicities tricks, as it could be in a slow demo shape.
I think I managed to set up a poll. I will launch the poll to keep people busy again.
Okay, cool. We got a response back.
Okay, so you can see how the response came back with all of the accounts. I’ve just blanked out a couple of the digits here, but basically, this is my five accounts that I have with Investec with the details exactly as you would in the RESTful endpoint. So there’s no real magic happening yet but what we can do now is, we can change that to just get the main account, which is the current account, and still get all the details as we did before, but now choose, we want the balance, the current and available balance and then let’s just bring that back.
Let’s say we wanted to display those things about, the main account, the parent account. I told Ben earlier that I just faked the balances, but it does get the balances in the background, but for the sake of this demo, I have blanked those out.
If we were to do this for all accounts, we could run that we could say, all accounts, maybe a boring query, but you’ll see that we go off and we just make one request to the server and resolve that. The GraphQL resolves what we’ve written on the back end and they are the ones that take the responsibility of creating a request for each of the accounts. For the sake of the demo, this is boring, but every one of my balances is the fake point, the one that I have faked.
You can see that we’ve now gone and created this balance query for every single account and we didn’t have to write that code in the front end, we just declaratively said in our query exactly what we wanted in the response. Let’s explore that a little bit further with transactions. Let’s say we go back to the main account and we want to get the transactions – what are the fields of the transactions, and you can sort of browse there, we can see there’s a posting date, let’s get the description and the amount. That’s all we want. Cool. Okay, so it’s quite a spread. Thanks, everyone.
You inspired a bunch of people to look into it.
With this transaction resolver what we can demo here, is it’s got an optional argument here if we just add brackets, we can see this and that so we could just explore this transaction element in the docs explorer here. If we look at transactions here, we can see that it’s an optional end – everything without an exclamation mark at the end is optional.
We could just ask it for the last five transactions just so it doesn’t spam us with massive results. If we want just an overview of what happened recently in our account, we can provide that parameter there and with the GraphQL endpoint designer, you decide what you want – we could have put a date range in here, or a filter to say, give me all your transactions above a certain amount. You create almost a domain-specific language for the domain, for your accounts and your information about your money.
I’m just waiting for this response to come back. This is still the old one – here we go with the main account the same details as before, but now we have the last five transactions. Yeah. We’ve got exactly the fields we asked for, which is just the date that it was posted, the description should be transaction date, which will be more interesting and the description amount.
It’s great as an exploration of what data is available to me because it’s super interactive. The point is that it’s all part of the tooling and GraphQL keeps all this integration very tight together. We discussed before – I just refreshed this with the transaction date there in case – the documentation is basically always honest. For example, call this “names” instead of a “name”, it tells us we’ve got an error there.
Unfortunately, my error reporting on my server, I’m still taming the F# implementation, and I haven’t got it to respond with the right HTTP status code. It does give the error back, but it gives the wrong code. I have not figured out all the integration points, but you can see that it’s unhappy about this reference “names”.
It says, cannot query field reference names on the top account. Did you mean referenced name and I didn’t put any of that, I didn’t write any of this code, I’ll show you that. We can do a quick dive into the code, but it’s the tooling that does this for you.
GraphQL does this whole implementation. That’s 300 lines of code that I had to write, the rest is all the ecosystem that sort of holds your hand and does the heavy lifting for you.
I’m just going to jump in from a coding point of view, and maybe I should make this a little bit larger. This page that you are looking at here from login, all the way down to get transactions, is just over a page now that I’ve made the text a bit bigger, but that’s essentially these 50 lines of code are wrapping those all the RESTful API calls that we were doing, that we made against Investec and F#. It is really helpful giving us things called type providers.
We don’t write the types for the responses. I just downloaded a response on how the API responds to getting a token. All I did was download a real response and included that as part of our project, in a mocks folder, and F# goes, the compiler does the hard work for you by generating type JSON  or a coder and encoder.
You get to use these tops in your code without having to write nothing more than this line. This line is all it takes, and the JSON mocks that I have to feed into it, which is great – so for 50 lines of code, we’ve got the API wrapper.
As I said, we’ve got all these client wrappers, we had to write a client wrapper for Investec, but here, we just wrote it in one language and our language of choice. We didn’t have to provide all of the different kinds – we just provided a GraphQL endpoint for everybody to consume. That’s the idea.
On the server-side, sorry, on the GraphQL– basically, schema resolver and an HTTP server it’s not the neatest code, but I made some, tweaks and changes, and I’ve just gone over the 300 line marker, that will be like, 325 lines for all this functionality and I think that’s pretty, sweet and pretty good bang for our buck for what we achieved,
F# gets a thumbs up. I think it’s a delightful language with great qualities. It is ready for primetime, GraphQL already used it. I just think here is another proof that it does create a better user experience as a client developer, and it can improve on REST in many ways.
If there is any Investec, developers, any Investec team, or API people on the call, then I’d like to request that you add actual times to the transactions rather than just the dates, actual timestamps would be awesome.
From my side, from my use case, the original currency and amount, if it weren’t in ZAR, that would also be great coming back in the RESTful endpoint.
If we could add all of that as a basic supported GraphQL endpoint in the near future, I think that would be super cool. And yeah, I’ve decided to split this up into different phases and in the next couple of weeks, I’d like to evaluate a different language. I’m using an Ocaml, which is also very similar to F# but it has a whole different ecosystem, and a whole bunch of different properties but I’d like to play around with that.
Then also to extend on the client-side, look at the user experience of developing the client-side application, once the GraphQL endpoint is available, for doing front-end and real-time live query subscriptions, where you can get updates to your queries as things happen.
I also want to experiment with putting more banks under one endpoint so that if you have more than one bank account, you can query all of that from one GraphQL endpoint. If you also find any of this interesting, I’d love to hear from you so please get in touch don’t hesitate. This is just some of the social coding and media handles, and I will be open-sourcing it soon, and I’m sure Ben will post it on the Slack and the GitLab project page.
Thank you for joining and spending time watching this. If you’ve got any questions – Ben, do we have time for questions? Yeah.
I think we do have time. I know folks asked one question, but firstly, thanks Marcin, that was super awesome. Nice run through of the functionality of GraphQL on top of Investec.
Willem is not around tonight, and he’s the API developer, but I will get your questions to him and get responses. Just to be clear, your two questions were can we get timestamps on the API transactions? I am semi answering that one. It will be hard because those transactions sit in a centralised place in the bank because it comes in debit orders, deposits, cash deposits, all the different types of things and then they clear it, and then it gets added to, at that time, so I don’t know if they come along with timestamps originally but interesting question. Willem is working with the other divisions in the bank to get more and more data accessible through the API.
Then the second question was, what are the chances of getting a GraphQL endpoint from Investec?
It was, yeah. It was one of them. And the third one was, if it’s not a ZAR transaction – if it’s a Euro or USD or a different foreign transaction – if we get that detail as well, the amount and the currency that it was originally made for?
Yeah. Ernie is on the call. He’s working with the programmable card. Ernie, do you have any idea if we can get access to that original amount in the data if you can.
I know on card transactions we do have that data. It should be on all transactions, but I will have to find out.
From my point of view, it’s only the card that has that, as I don’t do multi-currency accounts or anything. I just have a ZAR account. It’s just if the card came through with the original currency and the original amount that would be helpful.
Okay, and I will double-check with Willem on the currency on the OpenAPI side. I do know that we are adding it to the programmable banking side. So yeah, it would be nice to have that on both.
Because it’s not currently on the programmable card side right, Ernst?
No, it’s currently giving you the ZAR amount, but we are adding the base currency and base currency amounts.
Huggs had a question I guess – based on your question for Investec, would you agree that it would be better suited to implement this on the Investec side as that would allow filtering out a source instead of pulling all the data and filtering based on the query?
It would make it a lot more efficient and faster and I guess we wouldn’t have to talk to a RESTful endpoint, we would just be using the same business logic that the actual REST point and implementation are using so it would be a lot quicker, and the code would be much tighter integrated. It would be a better experience all around, I think, but you know, it is an added burden on the team.
I understand we kind of expect to maintain this extra bit of functionality but I am hopefully throwing ideas around with the hope that there will be enough excitement about this and that enough people will see, oh wow, well, maybe there is something about this, maybe we can support both.
Maybe if we implemented our whole domain as a GraphQL endpoint, there are libraries out there that can expose that for you as a RESTful endpoint, and so all you do is you provide the GraphQL implementation, you make that really tight and integrated, and your RESTful layer is automatically taken care for you. That’s all auto-generated stuff that you don’t need to worry about.
There are tons of benefits for the Investec side because they don’t have to provide specific querying parameters and querying abilities. You can make it all available and go, okay, cool – here are the GraphQL endpoints. You can query via GraphQL, and query however you want to and filter however you want.
Yeah, Ernst, have you got any idea if that would be possible, or something that would be considered?
From my side, I haven’t looked at GraphQL yet. I know we had a team in the bank that was looking at it last year, but I don’t know as it’s quite a process for us to add new tech, so I would need to also find out for you on that one where that project ran. I know there was a POC done to investigate the technology, but I don’t know where it led to from there. I would need to find out for you.
There’s a survey that’s just going out with a whole bunch of feedback. I’m going to be sending out a survey now to the community so I can add in “Who wants GraphQL” to that, because I know the Investec team – they’d be wanting to know what the priority is.
Yeah, exactly. You don’t want to just clog the backlog and then get nowhere.
It sounds like it’s going to be popular. Yeah. Does anyone else in the audience have questions about GraphQL, F#, or any of this? Awesome stuff.
Okay, it doesn’t sound like it. Thanks, Marcin, that was super awesome. As I mentioned, thanks for the cool presentation as well. I like that you made it nice to follow and spent a bit of time on the presentation. So really appreciate it as I know you put quite a bit of time into all this. So thanks a lot.
Marcin is a huge functional programming fan and believes that different languages make you think differently. He’s currently running a small software consulting company called Got.Codes.
Get involved in the Programmable Banking Community
For those of you in the community, check out our GitLab to see more of the awesome projects members of our community are working on. You can also sign up for challenges, where you can help find solutions for real life problems.
For more information, get in touch!