Asterisk
Greenfield build of peer to peer securities lending platform
Overview
Asterisk Networks is the first fintech platform for peer-to-peer global securities lending and repo transaction negotiation.
I joined Asterisk to lead the front end design and build, architecting a robust and modular system in response to stakeholder requirements, over the course of around a year.
Implementation
Tech stack
The site is a Vue JS (opens new window) SPA, served by a .Net REST API, and hosted on the Azure (opens new window) Cloud. Authorisation is handled by Auth0 (opens new window) and live updates are handled by Signal R (opens new window).
The application is written in TypeScript (opens new window) and is built using WebPack (opens new window), compiling to 4 environments with programatic CSP (opens new window)s for each. We use a variety of components and libraries including Element UI (opens new window), Vee Validate (opens new window), Vuex (opens new window), Vuex Pathify, Alias HQ and Handsontable (opens new window).
Core UX / UI
The essence of the platform is to connect lenders and borrowers to negotiate securities:
Borrowers generally begin negotiations by requesting lists of securities from lenders, to which lenders respond with what they have on their books. Both parties can edit the same spreadsheet (with slightly different columns and rules) with sophisticated formatting and controls to ensure each is kept updated (live!) with any changes from the other.
Negotiations have many additional constraints on them, such as user preferences, availability, “special” securities, updates from 3rd parties, even exchange closing times. Complex validation and rules designed to prevent parties making a mistake or putting the system into an unstable state are managed at both the front and back end.
Parties take it in turns to counter, accept or reject each other’s offers until an agreement is reached; think email with the message content an ever-evolving spreadsheet, and you’re pretty much there.
As the day passes, negotiations are moved across a kanban board from “Locate Lists” through “Requested”, “Negotiating” and “Completed” columns. Cards are updated with colour-coded tags and other information including value, state and any “special” properties such as who replied last.
Once the day is complete, all negotiated items are generally cleared overnight by an external clearing house, and are then stored in the system as loans, which in turn can be queried, returned, recalled or rerated… which trigger new sub-negotiations pertaining to those tasks.
Highlights
In an application of this size, there are many other systems, such as authentication, user management, state management, async data, error handling, dynamic routing, notifications, security, component design, build system, etc etc, but here are a few interesting highlights.
Handsontable
The star of the show of this app is our Handontable implementation.
We use a system of column factories to generate the column definitions, in conjunction with various custom cell renders, cell editors:
The data that goes into through the table is managed by a bespoke Handsontable wrapper that ensures one-way data flow, keeps track of changes, and marshals validation and errors.
All these states, editors and renderers have sophisticated formatting and styling constraints that need to work with one another, and clearly indicate to the user what state any negotiation item is in:
Additional tools such as right click menus allow us to provide tools to our users to make the process of negotiating securities intuitive and less prone to mistakes:
Additionally, all cells and controls were tweaked to match our overall application formatting, which is designed around our Element UI component set:
Vee Validate
We used Vee Validate to validate every single human input that goes into our tables.
This allows us to pair validation rules with column definitions, and pass in complex rules which can in turn be tracked and called by the table class:
Working with data in this way led to deep understanding of the Vee Validate library, resulting in several pull requests, including one to provide an intuitive new way (opens new window) to do cross-field validation (opens new window):
const values = { value: 20, maxValue: 15 };
const names = { value: 'Value', maxValue: 'Max Value' };
const rules = 'between:0,@maxValue';
Modular build
A modular build powered by a custom WebPack setup and AliasHQ allows domain-specific functionality to be developed in isolation and stitched together at build time:
+- src
+- app
+- areas
+- core
+- modules
+- ...
+- negotiations
| +- ...
|
+- notifications
| +- components
| +- enums
| +- models
| +- pages
| +- routing
| +- services
| +- state
| +- index.ts <- exports local services, etc
| +- main.ts <- sets up routes, store, etc
|
+- organisations
| +- ...
+- reports
| +- ...
+- ...
This made working on any particular unit simple:
- aliases prevent brittle paths
- the
main
file allows individual modules to be instantiated - the
index
exports members so modules may borrow functionality from each other