Use Case

Fractional shares

Keep track of fractional shares in your ledger and handle multi-assets wallets


Your customers hold multiple kinds of assets: Maybe you broker stocks or cryptocurrencies, or you offer currency conversion services. Your customers will want to move value between assets, like buying shares in Google with Euros, or selling Japanese Yen for US Dollars. You want to avoid double-spending assets during the conversion process. Formance dger accounts can hold value split among different kinds of assets, and makes avoiding double-spending transparent and straightforward with temporary accounts.

Using this pattern

Let's suppose you are a stock brokerage app that lets customer buy and sell stocks. You want to be able to record ownership of various assets in each customer's account, including credits for sales. And of course you want to facilitate trading of stocks. Naturally, such transactions don't happen instantly. So there is a period of time during which the money being spent remains in the buyer's account, and that opens the door to double-spending. You need to be able to set the money aside during the transaction period. And when the transaction is over, of course you want to record the shares on the customer's account.

The flow might look like this: Suppose you have a customer who has accrued some credits as a result of selling shares in a stock. They now wish to purchase different stock. They place an order for so many US dollars worth of a stock. You determine how much that amount can buy, and you set that amount aside from their credit balance into a temporary account to prevent double spending. Behind the scenes you do what needs doing to acquire those shares. Then you deposit those shares in their account, and move the balance you set aside into your own account.

This may feel a little involved, but there are two benefits from structuring the transaction in this way:

  • Processing the transaction might take microseconds, or it might take longer. It certainly isn't instant. Unless you set the funds aside, there is nothing preventing the buyer from maliciously spending them a second time.

  • It lets you cleanly separate concerns. You can have one system that receives purchase requests from the customers, and a completely different system for processing the purchase requests with your brokerage system. The temporary account serves as a signaling mechanism between those two services to hand off the processing at different stages.

How does Formance Ledger enable this structure? Numscript allows you to create arbitrary temporary accounts for purposes like this one. Suppose customer with ID U1234 has requested to buy $1,000.00 shares of worth of GOOG at $2,248.01 / share. You can set aside the funds from the buyer's credit into a temporary account like this:

send [USD/2 100000] (
  source = @user:U1234:wallet
  destination = @user:U1234:transaction:T5678

At the same time, you create a transaction to indicate that you are acquiring the requested stock:

send [GOOG/6 444836] (
  source = @world
  destination = @user:U1234:transaction:T5678

And once you have the 0.444836 shares in GOOG, you can complete the transfer like this:

send [USD/2 *] (
  source = @user:U1234:transaction:T5678
  destination = @platform:holdings
send [GOOG/6 *] (
  source = @user:U1234:transaction:T5678
  destination = @user:U1234:wallet

These Numscript snippets take advantage of namespaces to name the accounts in a readable, hierarchical way. The account @user:U1234:wallet represents the user U1234's wallet. Likewise, suppose you assign the purchase request a unique transfer ID T5678. Then the account @user:U1234:transaction:T5678 is a temporary account that marks the transferred funds as part of transfer T5678. The account @platform:holdings represents your account where you hold various liquid assets available for trade. Finally, the special @world account represents the external world.

Notice how you can specify fractional quantities of US Dollars and shares in GOOG. USD/2 means that you want to specify a quantity in US Dollars, to two decimal places; hence $1,000.00 is expressed as USD/2 100000. Similarly GOOG/6 specifies a quantity of GOOG stock to six decimal places; hence a fractional 0.444836 share is expressed as GOOG/6 444836. In the final transactions, specifying a quantity as * means to flush the entire contents of the account, so you can avoid querying or calculating what should be in those accounts, exposing ourselves to error. Formance Ledger figures those quantities out for you.

Now for the four transactions themselves, what do they do? The first transaction marks the funds as unavailable for further use, by marking them as part of transaction T5678. The second transaction indicates that you will be acquiring the shares in GOOG from an outside source as part of the transaction.

Then, once you actually have acquired that fractional share, you can flush the temporary transaction account. The third transaction consists of two postings that will be executed sequentially. The first posting moves the purchasing funds from the buyer to you—the first half of the trade. And the second half of the trade is in second posting, in which you move the fractional share of GOOG from the temporary account into the buyer's wallet, marking it as available for future trading.

In addition to the security benefits and the separation of concerns mentioned above, the use of temporary accounts like this is also useful in building your user experience. By using temporary accounts, you can use the Formance Ledger API to discover and calculate the available balance of different assets in the customer's wallet, as well as displaying to the customer in a granular way when assets are in motion from one account to another (and hence unavailable, or soon to be available).

Use Cases

Model funds in flight on your ledger to enable deferred payouts and fund pending processing

Use multi-destination to collect fees on your ledger transactions

Improve your cash-flow by selling in-app credits

900+ payments innovators building on Formance and sharing best practices.