Leveraging Corda’s Token & Account SDK in Financial Institutions: Use case by VALK

October 09, 2020

Asset Manager ABC is a mid-sized investment bank in London. According to our conducted research, up to 50% of their investment teams’ man hours are wasted on back office and manual tasks, therefore, preventing them from focusing on analysis, negotiation, deal sourcing, and execution. In their expansion plan, ABC had two choices, either to increase their resources to drive more sales or to automate the tasks they do manually today. Having decided to go for the second option they met VALK.

VALK’s technology is an end to end digital transaction tool for private markets that makes investment, trading and management of unlisted assets effortless. Their white labelled platform centralizes and automates tasks and processes that today are still performed manually. By using their software the client digitizes their investment and asset management workflow. The user-friendly interface improves clients’ deal execution experiences, resulting in an increase of customers and trading volumes of unlisted assets.

VALK white labeled software is directly integrated into the customers’ existing systems. Therefore, instead of using multi-channeled manual tools for trading, they benefit from one unified tool in order to transact in a safe and controlled environment, like those used for online banking.

Company ABC was convinced of the benefits that the VALK solution can bring to them but they had a concern about the technology that is being used underneath the application part. VALK is entirely running on Corda and company ABC didn’t want to manage a network and several Corda nodes due to the small size of their IT resources. Luckily, VALK has thought about these challenges and has built a system that allows their customers to take part in their shared private network without the need of any integration.

How did they do that? Thanks to Corda.

On September 29th 2019, R3 released the latest version of Corda V4.2 that includes an essential feature for Corda node usage efficiency: Accounts SDK.

The Accounts SDK allows us to split the vault into multiple “logical” sub-vaults and provides the possibility to create multiple identities inside one Corda node. This feature leads to significant economy of the resources and optimization of the node usage.

The most interesting combination for the financial world is pairing Accounts and Tokens SDK together. Such tandem represents the concept of the banking system inside a single node. Of course, one node is not the limit and Accounts from different nodes may easily perform transactions and exchange digital tokens or fiat currency between themselves as well as doing such actions in frames of a single node. In order to issue or redeem fiat to the Account, a bridge should be built between the real banking system and the Corda node. For this purpose, R3 created a tool which is called cash-issuer — https://github.com/corda/cash-issuer.

Cash issuer handles the connection to the Bank Account via Open Banking API and observes bank transactions representing a digital copy of the funds on the Corda node. Let’s dive into the details of the money tokenization miracle and figure out how to use machine code as a magic stick to perform this.

First of all, we need a Corda Network with two nodes (excluding Notary) — Issuer and Users node. This architecture can easily be scaled to any number of nodes depending on the participating organizations in the Network.

Let’s create two accounts on the Users node for Elie and Antoine. We create an account by performing a simple flow:

val elieAccount = Users.rpc.startFlow(::CreateAccount, “Users — Elie”).returnValue
val antoineAccount = Users.rpc.startFlow(::CreateAccount, “Users — Antoine”).returnValue

Then, we need to share information about the created accounts with the Issuer node.

Users.rpc.startFlow(::ShareAccountInfo, elieAccount, listOf(Issuer.legalIdentity())).returnValue.getOrThrow()
Users.rpc.startFlow(::ShareAccountInfo, antoineAccount, listOf(Issuer.legalIdentity())).returnValue.getOrThrow()

Once the Issuer Node is aware about the newly created accounts, the Users should provide their bank account details to provide payments recognition to the cash-issuer. As each Account by itself is a Linear State which is represented by AccountInfo Class, we can include its Unique Identifier to BankAccount Class of the cash-issuer, so that the structure appears as follows:

data class BankAccount(
val accountId: UniqueIdentifier,
val accountName: String,
val accountNumber: AccountNumber,
val currency: FiatCurrency,
val type: BankAccountType = BankAccountType.COLLATERAL
)

Creating Bank Accounts for each user Account:

Users.rpc.startFlow(::AddBankAccount,
BankAccount(elieAccount.linearId, elieAccount.name, AccountNumber(12345678909876), GBP), Issuer).returnValue.
getOrThrow()

Once cash-issuer recognizes the bank transaction with account number: 12345678909876, the procedure of fiat tokenization starts. As we are dealing with the Accounts SDK at final stage after transaction is verified, Anonymous Party should be generated and Amount of FiatCurrency issued to Elie Account on Users Node. To implement this IssueCash Class of cash-issuer should be extended with the following code:

// get bank account number from the nostro transaction
val toBankAccount = nostroTransactionState.amountTransfer.destination
// get bank account state by bank account number
val bankAccountState = getBankAccountStateByAccountNumber(toBankAccount, serviceHub)!!.state.data
// get AccountInfo of user
val elieAccount = Users.rpc.startFlow(:: AccountInfoByUUID, bankAccountState.accountId).returnValue.getOrThrow()
// create Anonymous Party by generating a key pair for Elie Account
val elieAnonymousParty = I.rpc.startFlow(::RequestKeyForAccount, elieAccount.state.data).returnValue.getOrThrow()
// determine Amount of issuing tokens
val quantity = nodeTransactionState.amountTransfer.quantityDelta
val tokenType = nodeTransactionState.amountTransfer.token
val tokenToIssue = quantity of tokenType issuedBy ourIdentity heldBy elieAnonymousParty
// issue tokens for Elie on Users Node
val issuanceResult = Issuer.rpc.startFlow(
::IssueTokens,
listOf(tokenToIssue),
emptyList()
).returnValue.getOrThrow()

As far as host of Elie’s Account is on the User Node, the tokens are issued on it. Then Elie can easily move tokens to other Accounts, e.g. to Antoine’s Account. Thus, cash issuer allows to tokenize fiat and issue tokens to a certain account. The redemption procedure occurs in the same way as described for issuing.

For any further question or to learn more about VALK and innovative features built on Corda please get in touch at contact@valktech.io

This article was written by the team at VALK:

VALK is a London and Zurich based fintech that has developed an end-to-end digital solution for private markets that can be used by investment banks, asset managers and fund managers that want to digitize their processes and assets from end to end to reduce costs, time spent on processes, improve user experience and transactions and operate secondary market trades.

More info at www.valktech.io or contact@valktech.io