Exposing A Tenants Store of Value as a Wallet Type in Eclipse

Eclipse API’s for topups, payments, withdrawals, remittance, transfers etc typically result in a debit/credit pair across 2 wallets. Wallets in turn have a wallet type that determines the rules and underlying implementation of the wallets store of value. Tenants who already have a store of value and ledger and want to compliment it with Eclipse functionality have 2 options:

  1. The tenant controls the synchronisation between Eclipse and their store of value by using webhooks, the event stream and coordinating calls between their SoV and Eclipse as part of a distributed transaction and keeping their store of value eventually consistent
  2. The tenant always calls Eclipse for all wallet functionality and Eclipse in turn calls back to the tenant by having a wallet type whose implementation is the tenant's SoV.

Due to various scenarios like long-running payments, card transactions, ATM withdrawals etc, there are many cases where a tenant's wallet needs to be debited/credited without the tenant being the one that initiates the transaction at that point in time. For example an ATM withdrawal can happen 2 days after the withdrawal is created.
Without careful engineering, this can expose revenue leakage if there is even the slightest synchronisation delay or lack of transaction locking.

A tenant has their own SoV and keeps it in sync with Eclipse by using Eclipse webhooks to be notified of Eclipse transactions. For the opposite scenario, when the tenant has transactions they send these to Eclipse API’s just after they have happened. A customer has R1000 balance in a wallet on both Eclipse and the tenant and everything is in sync. The customer generates a CashXpress ATM withdrawal token for R1000. They go to an ATM and as they submit the withdrawal, they also at that same moment do a P2P transfer in the tenants App for R1000 to a friend. The withdrawal request hits Eclipse and is debited R1000. The P2P hits the tenants SoV that is not yet notified by webhook and it transfers R1000 to the friend's wallet. The customer walks away with R1000 in cash and their friend has R1000 in their tenant SoV and R0 in the Eclipse wallet. The systems are now out of sync as Eclipse would refuse to transfer the R1000 to the friends wallet on Eclipse as the source has insufficient balance. The friend could possibly spend the R1000 they have on goods available within the tenants App.

For this reason, the recommended approach to keeping wallets synchronised is to add the tenants SoV as a wallet type in Eclipse and have Eclipse delegate all ledger transactions to the SoV. The tenant can then utilise all of the Eclipse API’s and know that wallet movements will automatically happen against their ledger without them needing to listen for webhooks nor process event streams. Eclipse takes care of the complexities of dealing with calling the SoV and ensuring failures and timeouts are handled correctly without the possibility of lost transactions.

In order for a tenant's Store of Value to be plugged into Eclipse, the SoV needs to expose APIs that Eclipse can call in real time during transactions. These API’s are as follows:

Mandatory API’s for Tenant to expose

  • Create a new wallet and return a unique identifier for that wallet that will never change
  • Get a wallet's current and available balance. Available balance is the current balance less any reservations
  • Get the transaction history (ledger movements) for a wallet between 2 dates
  • Transfer funds between 2 wallets in a debit/credit pair.

While ensuring that

  • A debit will fail if the amount exceeds the available balance
  • All the transfers debit/credit legs obey all rules of an ACID transaction.
  • A transfer should be passed an idempotency key and should fail with an error if a transaction with this key already exists on the ledger (to avoid duplicates/retransmissions)

In addition to the mandatory API’s, wallets need to be able to reserve/lock funds for long running transactions. This can either be done by the tenant and expose reservation API’s, or if the tenants wallet does not support reservations, then for low volume use cases, Eclipse can cater for this by debiting the wallet and storing the funds in a special reservation wallet that is like a suspense account. If the SoV does support reserving funds, then the following API’s are required to be exposed:

Reservation API’s

  • Lock a certain amount in a wallet with a description for the lock, a session identifier for the lock and an expiry date for the lock. When the expiry date is reached, the funds should no longer be locked. When one or more reservations are created, they should sum up to the difference between a wallet's current and available balance. Transfers should not be able to exceed the available balance.
  • Get the list of reservations placed on a wallet
  • Delete a reservation
  • Support doing a transfer where if the session id of a reservation is included as a field in the transfer then the reservations with that session id will be deleted initially as part of the transfers ACID transaction on the SoV

Assuming the tenants store of value supports these API’s, the Eclipse team can write a specific wallet implementation to point to the tenants store of value.

A due diligence would however need to be done to ensure the tenants SoV can cater for their envisaged transaction throughput while maintaining a latency of less than 100ms for all transactions (excluding network overhead).