project icon indicating copy to clipboard operation
project copied to clipboard

Supporting bilateral net settlement

Open koekiebox opened this issue 9 months ago • 6 comments

nextGenSettlement currently supports multilateral net settlement which we normally use in that a settlement matrix contains a value which is the net of the transfers between each pair of DFSPs, rather than a value for each DFSP's net of its transfers with all other DFSPs.

So if we had the following set of transfers: image

A multilateral net settlement would look like this: image-1

And a bilateral net settlement would look like this: image-2

Example of the current SettlementMatrixSettledEvtPayload:

image

Tasks in order to support both models:

  • [ ] Update SettlementMatrixSettledEvtPayload and rename participantList to multilateralNetSettlement
  • [ ] Update SettlementMatrixSettledEvtPayload and add bilateralNetSettlement
  • [ ] Add settlementType to ISettlementConfig, with options: MULTILATERAL_DEFERRED_NET_SETTLEMENT and BILATERAL_DEFERRED_NET_SETTLEMENT, as well as API support
  • [ ] The aggregate.ts#handleTransfer needs to be updated to create accounts based on participant relationships instead of an account per batch. i.e. Referring to the above: DFSP A could have multiple accounts per batch, depending on whether transfers exists between DFSP B and DFSP C. Example of existing batch account logic:
// The existing settlement batch account logic:
const debitedAccount = batch.getAccount(transferDto.payerFspId, currency.code);
export interface ISettlementBatchAccount {
	accountExtId: string;
	participantId: string;//e08a603a-dc4c-4b03-8d91-5cc1a4b4e88b
	currencyCode: string;
	creditBalance: string;
	debitBalance: string;
}

// Suggested update:
const debitedAccount = batch.getAccountMultilateral(transferDto.payerFspId, currency.code);
const bilateralAcc = batch.getAccountBilateral(transferDto.payerFspId, transferDto.payeeFspId, transferDto.payerFspId);

export interface ISettlementBatchAccountMultilateral {
	accountExtId: string;
	participantId: string;//e08a603a-dc4c-4b03-8d91-5cc1a4b4e88b
	currencyCode: string;
	creditBalance: string;
	debitBalance: string;
	netBalance: string;//To be added
}

/*
[participantIdA] with id [a08a603a-dc4c-4b03-8d91-5cc1a4b4e88b] will always be first, due to the string comparison.
*/
export interface ISettlementBatchAccountBilateralMapping {
	accountExtId: string;
	pairId: string;//a08a603a-dc4c-4b03-8d91-5cc1a4b4e88b_b08a603a-dc4c-4b03-8d91-5cc1a4b4e88b
	participantA: IAccountBilateral;//a08a603a-dc4c-4b03-8d91-5cc1a4b4e88b
	participantB: IAccountBilateral;//b08a603a-dc4c-4b03-8d91-5cc1a4b4e88b
}
export interface IAccountBilateral {
	accountExtId: string;
	participantId: string;//a08a603a-dc4c-4b03-8d91-5cc1a4b4e88b
	bilateralAccountId: string;// UUID generated and assigned at time of account creation to avoid collision on participantId
	currencyCode: string;
	creditBalance: string;
	debitBalance: string;
	netBalance: string;//To be added
}

// The function would be as follows:
getAccountBilateral(
    participantIdA: string, 
    participantIdB: string,
    targetParticipantId: string
) : IAccountBilateral {
// 1. String comparison (sorted) for [participantIdA] and [participantIdB] and then concat
// 2. Lookup for existing relationship: [pairId] = concat_string
// 3. Fetch the IAccountBilateral where [IAccountBilateral#participantId] = [targetParticipantId]
}

  • [ ] Add net balances for ISettlementMatrixBalanceByCurrency / ISettlementMatrixBalanceByStateAndCurrency / ISettlementMatrixBalanceByParticipant

Mojaloop Business Documentation regarding settlement models

https://docs.mojaloop.io/mojaloop-business-docs/HubOperations/Settlement/settlement-basic-concepts.html#settlement-model

Goal:

As a <stakeholder|persona>

I want to

so that

Acceptance Criteria:

  • [ ] TBD

Complexity: <High|Medium|Low> > A short comment to remind the reason for the rating

Uncertainty: <High|Medium|Low> > A short comment to remind the reason for the rating


Tasks:

  • [ ] TBD [ @? ]

Done

  • [ ] Acceptance Criteria pass
  • [ ] Designs are up-to date
  • [ ] Unit Tests pass
  • [ ] Integration Tests pass
  • [ ] Code Style & Coverage meets standards
  • [ ] Changes made to config (default.json) are broadcast to team and follow-up tasks added to update helm charts and other deployment config.
  • [ ] TBD

Pull Requests:

  • [ ] TBD

Follow-up:

  • N/A

Dependencies:

  • N/A

Accountability:

  • Owner: TBC
  • QA/Review: TBC

koekiebox avatar May 08 '24 05:05 koekiebox

@koekiebox With regard to: "Add settlementType to ISettlementConfig, with options: MULTILATERAL_DEFERRED_NET_SETTLEMENT and BILATERAL_DEFERRED_NET_SETTLEMENT, as well as API support" Can you expand on the API support you are referring to?

PaulMakinMojaloop avatar May 29 '24 10:05 PaulMakinMojaloop

@koekiebox If I'm understanding this correctly, an ISettlementBatchAccountBilateralMapping reflects the bilateral settlement position between two participants; and a settlement batch would/could consist of multiple instances of ISettlementBatchAccountBilateralMapping.

Then ISettlementBatchAccountBilateralMapping consists of two instances of IAccountBilateral, one for each participant in the bilateral position.

Each IAccountBilateral includes creditBalance, debitBalance and netBalance for that participant, with regard to the other participant.

Can I ask why we need all three balances? Wouldn't netBalance be sufficient?

Further, why do we need two instances of IAccountBilateral? Why not just have participant IDs, and a netBalance, with sign indicating which it is in favour of?

Sorry if I'm oversimplifying, i'm just trying to understand the rationale.

PaulMakinMojaloop avatar May 29 '24 10:05 PaulMakinMojaloop

@koekiebox With regard to: "Add settlementType to ISettlementConfig, with options: MULTILATERAL_DEFERRED_NET_SETTLEMENT and BILATERAL_DEFERRED_NET_SETTLEMENT, as well as API support" Can you expand on the API support you are referring to?

@PaulMakinMojaloop This would be the API updates necessary in order to store and retrieve the models as part of a settlement config. The endpoints include:

  • GET /models - Fetch a settlement config by name
  • GET /models/:id - Fetch a config by id
  • POST /models - Create config

koekiebox avatar Jun 13 '24 09:06 koekiebox

Can I ask why we need all three balances? Wouldn't netBalance be sufficient?

@PaulMakinMojaloop We would be storing the debitBalance and creditBalance only. This is for tracking and traceability. It provides a clear picture of each balance. We would then calculate the netBalance on demand based on credit/debit.

koekiebox avatar Jun 13 '24 09:06 koekiebox

If I'm understanding this correctly, an ISettlementBatchAccountBilateralMapping reflects the bilateral settlement position between two participants; and a settlement batch would/could consist of multiple instances of ISettlementBatchAccountBilateralMapping.

Then ISettlementBatchAccountBilateralMapping consists of two instances of IAccountBilateral, one for each participant in the bilateral position.

Yes, this is correct. ✅

koekiebox avatar Jun 13 '24 09:06 koekiebox

Further, why do we need two instances of IAccountBilateral? Why not just have participant IDs, and a netBalance, with sign indicating which it is in favour of?

Sorry if I'm oversimplifying, i'm just trying to understand the rationale.

Not at all. This is something we can discuss. I would be in favour of the individual accounts, purely due to being able to see all of the debit/credit balances for each of the accounts, similar to what you brought up with regards to the netBalance. That being said, it would still be possible to lookup the transfers based on the "batchAccountId" in order to determine how the balance was calculated.

koekiebox avatar Jun 13 '24 09:06 koekiebox