Less noise, more data. Get the biggest data report on software developer careers in South Africa.

Dev Report mobile

Programmable Banking Community: Adrian's Open Banking CLI

16 October 2020 , by Ben Blaine

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, Adrian Hope-Bailie shares the CLI that he built for working with his bank account and learning more about Deno. It’s a simple tool that makes use of one Typescript file, Read Eval Print Loop (REPL) and basic state held-in memory that is shown in prompt. It also keeps you logged in to a selected account in privacy mode. Check it out here!

Click here to download Adrian’s presentation slide deck.

Find the repo and installation instructions here.

Transcript of the demo

Ben [25:19]

And then next up would be Adrian.

Adrian [25:58]

What I built is not as impressive as what Imraan just showed us. It's a very simple kind of REPL or CLI that interfaces with open banking APIs. My main goal here was to teach myself a new technology. I've been looking for a project, where I could try out Deno. There's a hot debate as to exactly how you pronounce it.

Adrian [26:29]

I decided this would be a good one. I work for a company called Coil. We're based out of San Francisco, and we have four of us here in Cape Town in our little office in Newlands. Long term plans for this are, really this was just a learning project for me, but I have a few ideas about things we can do next.

Adrian [26:58]

How does it work? It's very simple. It's a single TypeScript file. It's a REPL, so it's just a loop that takes in commands, executes them, prints output, waits for the next command. It keeps a little bit of state. When you start-up, you're not logged in and it will auto log you in if it can, so it looks in environment variables for your credentials. If you try and execute a command that needs you to be logged in, it'll try to log you in silently.

Adrian [27:27]

Once you pick an account, then all the operations you perform are against that account. And then I added a privacy mode yesterday, which does a bit of masking of sensitive data because I wanted to show you guys something and the only accounts I have to show are my accounts but I will show you that as well.

Adrian [27:54]

A little bit about Deno and the motivation for doing this. It's a pretty cool project. It was started by the guy who started Node.js, Ryan Dahl, and this is his attempt at a better version of what he did the first time. It's a runtime for JavaScript and TypeScript.

Adrian [28:08]

What's quite cool is that it interprets TypeScript natively, so you don't have to transfer your TypeScript into JavaScript first. It also uses V8, the same engine as Chrome and Node, but it's been built in Rust. What's nice about it, and what I like about it, and you'll see this when I demo just now, is that it doesn't give processes access to the file system, to the network, to the environment – unless you explicitly enable them. You'll see when I install my CLI, I explicitly only give it access to the Investec APIs so it cannot make any other network calls or do anything else.

Adrian [28:48]

That's cool because it means that you can pull a script from somewhere and you can lock it down. In this case, it's not taking my time credentials and sending them to somebody else. It can't access or disconnect any other network calls. Another thing that I like, which some people might not like, is that a lot of the stuff that we have used third-party tools for in the Node world are built into it.

Adrian [29:15]

Things like, dependency management, dependency inspector – and linting, and formatting are built-in. If you're someone, like me, who uses things like standard JS, and you don't want to buy shared linting rules, and you're just happy to live with the ones that someone else prescribed then, Deno is definitely for you.

Adrian [29:38]

The one bummer is that all the third-party modules and so on that exist in npm need to be ported over to work with Deno. And the way Deno does module imports is via URLs. If you want to import a module, you point to the URL of another JavaScript or TypeScript file, and that's how it works. It caches everything locally, and you can do some clever stuff to make sure you sort of shrink-wrap your application, always using the same versions and stuff but that's how it works.

Adrian [30:13]

With that, let me give you a little screencast of a demo that I recorded earlier. I had to be careful not to make mistakes and reveal all my banking details. Instead of giving you a live demo, I'm going to quickly show you a little video. Here you go. On the left, that's the repo. Feel free to send me requests, and point out the bad mistakes that I've made in my code.

Adrian [30:50]

As you can see, it's simple. It's got a license file, readme file and an Investec file, and if you look at the installation instructions, they are using a command built into Deno, where you replace Deno run with Deno install and what it does is it sets up a nice little installer for you of that code. You can see in that case, I'm telling the installer that it should allow network access, only to open API.Investec.com and allow environment access. That is to allow it to read environment variables and get my credentials.

Adrian [31:23]

What I'm going to do now is show you what happens once Deno is installed. That's what you'll have – that’s step number one. Step number two – pretty simple copy and paste that little line in and you'll see, it's downloading all of its dependencies from the web because they're all referenced by a URL. And then the next thing I'm going to do is print out the commands that are available.

Adrian [31:58]

There's one undocumented command, which I'll show you at the end, but that's an Easter egg that's waiting to be unveiled. The first thing that I'm going to do is list accounts. You'll see that when I list accounts, it logs me in, in the background, and then gets a set of accounts. You pick one, and then you can see that the prompt changes the state. The state is now changed to a selected account, and you'll also see the little icon changes to show that I'm logged in. There was an open lock, and now there's a locked lock.

Adrian [32:39]

If we carry on a little bit, the next thing we're going to do is list some transactions on that account. We want to unselect accounts, call accounts again, and just hit enter. Now you'll see there's no longer a selected account, but we are still logged in. So instead, let's get a list of transactions and select an account, all as part of the same command.

Adrian [33:02]

You see, I requested transactions but because there was no account, it prompted me to pick an account. You can see there I picked the private business account, it listed those four transactions that we have. None of them are transactions so I'm going to switch accounts quickly because I don't mind revealing the account number of the cash management account.

Adrian [33:37]

If I toggle between private mode and the prompt shows. If you do the commands with private, you also see the full account numbers and amounts. There's the hidden command that is part of my “coming soon” feature that I want to do. Let's get back to that and finish up.

Adrian [34:15]

The things that I bumped into were that Deno was a bit of a learning curve. It's not the same even though you are building for the server, not for the browser. It uses all the browser’s API. Node has a bunch of its API beyond the standard ECMAScript stuff.

Adrian [34:29]

Deno tries to replicate all the browser APIs and their behaviour so you don't have some of the stuff you might be familiar with, like the buffer. For example, when you're reading from the command line, and so on you’re using [raw code(?)]. It takes a bit of getting used to, but if you've used other languages that work similarly, like Java, or those kinds of languages, it's not too much of an issue.

Adrian [34:57]

It has a much smaller choice of third-party libraries. At this stage, this is positive in some respects because a lot of the third-party libraries are good ones, there's not as much rubbish. For example, yargs is a great library for building these kinds of applications but I couldn't use that. I had to implement a lot of that myself.

Adrian [35:19]

I would like to expand beyond just showing information and being able to start some stuff. Read-only APIs are the one challenge and then finally, the lack of a sandbox. It would be nice to give a slightly richer demo revealing a bit more of what I'm doing there without having to run it in private mode.

Adrian [35:45]

Next steps. I want to make some minor tweaks, and there are to-dos documented in the readme, that I must get to and then, I want to implement the pay command. I want to have a stab at using something like Puppeteer, to see if I can implement that and host my instance of a pay API endpoint and play around with what the shape of that would look like.

Adrian [36:07]

I was advised by someone once – he was one of the founders of Marquette – that if you don't move real money, it's not worth experimenting. That's what I am going to see if I can do so I will let you know if my account gets drained and if I am broke after that.

Adrian [36:38]

The long-term plan here is to see if I can build on the work that I've been doing with REPL and then, more recently with Coil, around open payment protocols, like intelligent open payments where I use the Investec OpenAPIs as a way to settle payments between people that might run Node on inter ledger networks. I don't want to get into all that detail now, but the idea is that it's a payment clearing network, a way for people whose entities connect to make payments, but they can settle anyway.

Adrian [37:04]

I want to use bank EFTs, as a way of settling between participants and automating that through the API. That's my long-term goal here even though the start is just a learning project.

Adrian [37:17]

If anyone's interested, please feel free to get hold of me. Email is adrian@coil.com and I'm on Slack. And that's it. I tried to get through everything before we ran out of time, so I hope that wasn't too quick.

Audience member [37:46]

Adrian, this is a really nice tool. I quickly ran the code on my machine, and it looks dope. There's just one thing I would like to see added to this as you are already playing in the environment variables and with auth secrets. What would be nice is, instead of having to open Investec first, and then go and run your balance and stuff, for me it would be cool if you could run Investec [].

Adrian [38:30]

One of the other things, I originally had in there, and I think there might still be remnants of it in the code, was to keep a record of your selected account, so keep your account reference as an environment variable, so you could by default startup with an account selected and immediately start transacting on that account. But I like that, that's a nice idea.

Wayne [38:58]

We are looking at opening payments. It's just being a bank, and it's quite hard to do. But it's happening slowly. We will get there, and then you can show us what you can do with API for payments.

Audience member [39:15]

It's our job to push you.

Ben [39:19]

Did you mention somewhere finding a way or workaround to do payments?

Adrian [39:25]

Yeah, I've been playing around with Puppeteer, which is a headless browser orchestration, and seeing if you can use that too the hood go and log in, and do a payment through the online banking. The advantage there is instead of giving your online banking credentials to some third-party like play, you run that service yourself.

Adrian [39:50]

And it's running locally, and you're not sharing credentials anywhere. It would be a kind of proof of concept, to get that working and then expose that to the API and then that helps inform what the API shape needs to be for that API. That's my goal, there.

Wayne [40:20]

Thanks, you could clean script into the website. That's the workaround.

Adrian [40:24]

Yeah, Puppeteer is not raw HTTP, you're not just using HTTP requests. It spins up an instance of Chrome, which is headless, and you have a Chrome process running.

Adrian [40:41]

Chrome allows you to control that remotely through the dev, the dev tools API and Puppeteer is a nice, JavaScript library that exposes all of that through an SDK.

Adrian [40:53]

You can talk to this Chrome instance and say, navigate to this page, find this element on the page, put in this value. Again, hit okay, wait for the push notification to my app, authorise and wait for the page to go through.

Adrian [41:12]

That's kind of as far as I've thought through on, how it would work but, it's something. It doesn't scale as well as schemes for screen scraping, because technically, you need to run an instance of Chrome for every user session.

Adrian [41:25]

Someone like a [] wouldn't do it this way because they would have to be running a Chrome instance for every user that they're emulating.

Adrian [41:34]

But it works nicely for what you want to do. Personally, its main goal is for testing, but I think we can leverage it for this.

Audience member [41:49]

If it was just, adding to Puppeteer, then I've done exactly that before not on Investec. Puppeteer is very easily containerised. I had Azure functions that spin up, did it, and then it died and they could query it.

Speaker 2 [42:11]

It's very achievable and there's also a service, and I can't remember what it's called but I think it's called browser.io, which is Puppeteer as a service.

Adrian [42:24]

The one thing I don't want to do is start passing my banking credentials to anything outside of my control. That's what I quite like about the Puppeteer. I would run it locally, give it the credentials, and everything's local. It's as if the browser is running on my machine and I just automate.

Audience member [42:45]

I didn’t take it much further but there's also a bunch of pretty good documentation out there on getting your Puppeteer farm up and running – kind of like what browser.io does. Then, if you throw a task or Puppeteer script over into this farm it will spin up an instance, kill the instance and give you a result. It is a very cool idea, and it's very doable.

Adrian [43:11]

So, you can build your botnet.

Audience member [43:13]


Ben [43:17]

Cool, I like the way that Wayne is frowning.

Ben [43:37]

Yeah, I'd like to see some workarounds for payments. That'll be awesome if we can reuse that.

Ben [43:46]

I had another question. Does anyone else have questions or anything to add? Or Adrian, do you have questions for people in the audience?

Adrian [43:57]

No, good feedback so far. I think it is quite a nice feature to add. This is not a day job, but I'll hack away at this as we go. It's a super simple code. If anyone wants an example of how it differs from the normal Node or TypeScript projects, it's a useful example. Don't judge the code itself, but if you want to see the differences, in terms of, importing modules from URLs versus from NPM, there's no package .JSON file, for example.

Adrian [44:27]

To run it, you say, Deno run and point it to the Typescript file. Then, there are examples of reading and writing from the command line and stuff that I think is a useful reference for that as a simple starting point. If someone's using it for that, feel free to start sending some pull requests with new features as well.


Adrian heads up Interledger and Services at Coil. He lives in Cape Town with his three kids, a staffie, and his magnificent wife. He loves the Web and digital payments but thinks both can serve people better than they currently do. He's passionate about open standards and open source software, and the power of both to build sustainable ecosystems that benefit users and businesses alike.

Get involved in the Programmable Banking Community

If you’re not part of our community yet, sign up and join the fun. You can also see more of the demos from our meetups on our YouTube channel here.

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!

Recent posts

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.