We have been so focused on building the UTRUST platform, that we haven’t had much of a chance to show you the cool stuff we’re working on. Hopefully, this article will give some insight on how we are building and architecting UTRUST from a technical standpoint. If you are interested in learning more about our process and the specific features we are building we’ve got you covered with our Product Updates.
Before we go any further I would like to leave a brief note on the programming language we are using for most of the backend code. Both our platform and the mobile wallet are built on Elixir. The point of this article is not to showcase Elixir, but if you have never heard of it, it’s worth checking out.
Elixir has been a great ally in providing us with confidence that we will be able to scale pretty well, as well as a good transition to a more functional world since most of the team came from Ruby. Its concurrency story is top notch, as we learn more about the OTP and supervision trees, we feel we can create a robust system within this ecosystem.
No language is perfect though, as if there is one thing we all would like Elixir to have is a strong type system that would provide stronger guarantees at compile time. That being said, dialyzer does help a bit with both the checks and generally as a guide to other developers on how to use certain APIs.
Event Sourcing and CQRS
Another set of software concepts we are using and that seems to be very en vogue these days (at least in our little corner of the universe), is Event Sourcing and Command Query Responsibility Segregation (CQRS).
Conceptually, this is pretty simple. Write in one place, read from another. Communication flows one way through sending events. However, there’s a lot of technical stuff that goes into this, in order to make it work well.
Thankfully, we’ve been using a library called Commanded which has been very helpful in handling a lot of the grunt work. This allows us to (mostly) focus on the interactions and flows. As you might imagine, these are pretty tricky in their own right.
As an example let’s look at how placing an order and subsequently show the buyer the different exchange rates works within UTRUST:
- We get all the order info from the merchant’s store, either by using our API directly or via one of the many e-commerce plugins we support.
- The request is handled by a controller (we’re using Phoenix for the web layer), which in turn calls down to our core platform application
- A command has now been sent to the appropriate context (see Bounded Context), which knows how to send it to the correct Aggregate. In this example, the command is PlaceOrder.
- The Aggregate will do any business logic validations that are required. In the case of everything being ok, it will emit an event, meaning that something has happened, it’s a fact. In this example, that event is OrderPlaced.
- Via Commanded the event will be propagated to any event handler that wishes to know about it. These can range from an event handler that will schedule the sending of an email, to what we call projectors, a specific type of handler that manages a database table or tables. These tables represent reality as far as it is aware of it (eventual consistency comes into play here). We call them projections or query models.
- The payments context will also be listening for this event in order to start the process of assigning exchange rates, which are based on multiple parameters. Eventually, it’ll emit its own event, ExchangeRatesAssigned.
- In the meantime, as a buyer, you have already been redirected to a page with our payment widget, which will be in a loading state until it can read payment data from these projections.
- Once all this information has been propagated through the system, it will be shown to the buyer as prompt to select whatever crypto currency they wish to pay in.
There is some work involved in building a system like this, as opposed to CRUD, but we believe that will help us in growing at a steady reliable pace.
JSON:API and GraphQL
Our external APIs are RESTful APIs that follow the JSON:API conventions, that’s what you’ll be interacting with as a merchant. However, all our internal APIs are using GraphQL, which we have been experimenting with and really enjoying so far, so expect some more developments in this front.
We are currently live with a mobile wallet for both Android and iOS (with a few selected beta users only), which has been written in React Native. We decided on this technology rather than writing natives apps directly because we felt we would be able to launch something that meets our high standards. At the same time, it lets us move quickly and efficiently with the team we’ve built.
Blockchain and Exchange Integration
We are a payments company however, we are largely invested in the blockchain community and cryptocurrencies are a big part of what we care about here at UTRUST. Therefore we integrate with different blockchains and exchanges.
Integrating with the blockchains directly allows us to have better control over how we generate addresses, detect and confirm payments, for instance.
Exchange integration was another must have for us since we need to be able to present both the buyer and the merchant with multiple exchange rate pairs. This happens in payments (as we’ve just seen in the above), but also in the case of a refund, for example.
Here, we’ve gone into some detail about how the UTRUST platform works and what technology it is built upon. If you have any questions about our tech stack, just drop us a comment and we’ll answer it to the best of our ability.
Building this product and being in this community has been extremely fun. We can’t wait to release it into the world so that all of you can help us become as good as we want to be!