mojaloop / mojaloop-specification

This repo contains the specification document set of the Open API for FSP Interoperability
https://docs.mojaloop.io/api
Other
20 stars 40 forks source link

Change Request: Currency conversion support in Mojaloop #89

Open mjbrichards opened 3 years ago

mjbrichards commented 3 years ago

Open API for FSP Interoperability - Change Request

Table of Contents

1. Preface


This section contains basic information regarding the change request.

1.1 Change Request Information

Requested By Michael Richards, ModusBox
Change Request Status In review ☒ / Approved ☐ / Rejected ☐
Approved/Rejected Date

1.2 Document Version Information

Version Date Author Change Description
1.0 2021-06-15 Michael Richards Initial statement.

2. Problem Description


2.1 Background

There has been discussion for some time in the Mojaloop community about how to manage currency conversion as part of funds transfers. A version of this has been implemented by Mowali, but this has operational drawbacks which have prompted a search for a simpler and more robust alternative. Following discussions with interested parties, an initial statement of a proposed solution has been created and is attached to this document.

This solution (like any solution to the problem of currency conversion) will require some changes to the FSPIOP API, and these are described in Section 6.1 of the attached document. It is proposed that the required changes should be non-breaking, but this is a matter for review.

2.2 Current Behaviour

The API does not support currency conversion at present.

Explain how you would like the API to behave.

The attached document explains the proposed behaviour

3. Proposed Solution Options


API Candidate for currency conversion support in Mojaloop.docx

henrka commented 3 years ago

Thanks @mjbrichards!

In general, it would be great to include sequence diagrams as discussed in CCB meeting. Please find some initial comments below before the sequence diagrams are shared:

mjbrichards commented 3 years ago

Thanks very much as usual, @ehenrka, for your detailed and penetrating comments. I attach a revised version of the proposal with changes tracked, and a commentary on your points below:

- Section 2, bullet 2: "We assume that the list of currencies in which a payee’s account(s) can receive is returned as part of the discovery process (i.e. by an existing PUT /parties call in the FSPIOP API.)" - There is no existing PUT /parties callback that returns a list of currencies. There have been different proposals for this, but it's not part of version 1.1. This should then also be part of Section 6.1. Agreed. Added as Section 6.1.1 - Section 3.2: Is the currency purchase as described here is related to a specific transfer, you just buy some amount in another currency that can later be used for a number of different transfers, or is it meant for just one specific transfer? The plan is to add support for bulk currency purchases by DFSPs; but a detailed proposal for this is outside the scope of V1. - Section 5.2.1: "It adds an expiry date, ..." in Section 6.3.5 it seems like a duration would be added. An expiry time seems more approriate than a duration, as you would in general be interested in when the conversion will expire, not the duration of it. We've been talking in the DA about using durations instead of times where we're talking about times which will be used to do things like time transfers out. This is based on the idea that, where a time is generated by one party (such as the payer DFSP) but enforced by another party (such as the switch) it makes more sense for the originating party to send a duration, which will allow the enforcing party to use its internal clock directly. However, this is not the case here (or in a PUT /quotes,) since the originating and evaluating parties are the same; so I thought a DateTime was appropriate. I'm not wedded to it, though... - Section 6.1.4: "Changes to the /transfers response" Change response to callback Done (and for 6.1.2) - Section 6.2.1.1.2: There is a maximum of 10 FXPs now, suggesting to change to 8, 16 or 32 as we usually have powers of two (2^n) for sizes in at least FSPIOP API. Done - Section 6.2.2: "agreeFx" - Suggesting to rename this to fxQuote to align with FSPIOP, as its "used to ask an FXP to provide a quotation for a currency conversion". Done - Section 6.2.2, bullet 1: "conversionId" - Suggesting to rename this to fxQuoteId to align with above Done - Section 6.2.2, bullet 2: "source.account" - Suggesting to move configuration regarding ledger account type to Settlement API or similar. This should not be decided per transaction, rather it should be a generic configuration based on for example currency pair, or FXP, or a combination. I put this in to support bulk currency purchases, to allow the payer DFSP to specify that it wanted a conversion to be sourced from the bulk purchase (which would not, for instance, be liquidity checked by the switch...) But I'm happy to leave it out for now until we consider bulk purchases in more detail. - Section 6.2.2, bullet 4: "fxp" - Suggesting to rename this to fxpId Done - Section 6.2.2, bullet 5: "source.amount.currency" - There is no currency as part of data type Amount. To include a currency, data type Money should be used. But note that data type Money requires both an amount and a currency, so you would probably want a source.amount and a source.currency, where the amount is optional. Well spotted. Added to the document - Section 6.2.2, bullet 8: "target.amount.currency" - See comment above regarding source - Section 6.2.3: "commitFx" - Suggesting to rename this to fxTransfer to align with FSPIOP. Done - Section 6.3.2: To keep this simple in the first version as it seems like for example Mowali would like to have this sooner rather than later, can we remove the charges from the data model, and let the FXP incorporate any charges/fees in the FX quote? Has it been required from anyone to have charges as a specific field? This should also allow the amountType to be removed, as there would not be any fees.. Henrik, Henrik: I only put these in because of the long discussion we had about how we might need them. I'm leaving them for now... - Section 6.3.2 and 6.3.3: Suggesting to rename FxpParticipant to FxParticipant, as it is a participant in the FX conversion, not in the FXP itself. Done - Section 6.3.4 (and 6.3.5): Why the use of duration instead of an expiry time? To know when the conversion will expire (which is what you generally would want to know), you now need to know the start of the duration and calculate the end time from there. See my discussion above, but you're right: I let my enthusiasm get the better of me. Modified

The revised document: API Candidate for currency conversion support in Mojaloop v1.1.docx

mjbrichards commented 3 years ago

Sequence diagram to illustrate the transfer flow: Transferring with Currency Conversion(DFSP-based)

henrka commented 3 years ago

Thanks @mjbrichards, just a quick follow-up comment regarding my own comment. It should be fxQuotes instead of just fxQuote, and similarly fxTransfers instead of just fxTransfer (missing s in the end) to align with FSPIOP API. Sorry for that.

One more comment for now regarding the sequence diagram, there is a comment between step 29 and 30 which talks about fees charged in target currency and how they should be converted. In the data model for Conversion, there is only a currency and amount, the FXP don't know about the actual transfer and any fees as part of it. Have I missed something, or is the sequence diagram not correct for this part? The sequence diagram way seems more complicated, as the FXP would need to know more about the FSPIOP API than what should be necessary..

mjbrichards commented 3 years ago

Thanks for your comments, @ehenrka, and my apologies for not responding to them sooner. I should have said "charges" rather than "fees". The FXP will, I think, need to ensure that it quotes its charges in the source currency as well as in the target currency, so that the payee DFSP can include them in the fees it quotes to the payer DFSP if required. I have also completed a candidate version of the API for review:

API Candidate for currency conversion support in Mojaloop v1.2.docx

henrka commented 3 years ago

Thank you @mjbrichards, please find a new round of comments on the latest version:

May I please ask you to add some more detailed example sequence diagrams, where it is possible to see the source and target amounts, and the different fees/charges and who is paying them (if we really want to have charges from the FXP, which I preferably would like to avoid for now)? It would help a lot to have more specific examples to validate the proposed changes.

One thing to consider is that it will not be possible for a FSP to completely subsidize a transaction that is using FX (see for example Section 5.1.2.1 in FSPIOP API), as the FXP can add additional fees after the Payee FSP has determined its final terms of the transfer. The FXP fees would at least be invisible if there is only a FX rate which includes fees.

millerabel commented 3 years ago

Hi Henrik,

I am not completely following the change proposal details, though I’d like to understand the point you make at the end…

“One thing to consider is that it will not be possible for a FSP to completely subsidize a transaction that is using FX (see for example Section 5.1.2.1 in FSPIOP API), as the FXP can add additional fees after the Payee FSP has determined its final terms of the transfer. The FXP fees would at least be invisible if there is only a FX rate which includes fees.”

It has been our intention that a payer is fully aware of fees to be paid before authorizing a transaction, and that no fees are added after that authorization has been given. Do you mean by the above that an FXP might choose to inflate their FX rate to compensate for lower fees in its quotation? It is a design invariant that all terms of the transaction that affect the principal value and retail fees must be recorded in the transaction details and signed by the receiving DFSP. At that point, the terms are final. No on-transaction retail fees can be added after that point and the retail FX rate is firm.

So while additional off-transaction fees might be accumulated at the wholesale level, they would be unconnected to the retail fees to be collected from the payer, and a matter of negotiation between the participants as to how to split (interchange).

I’d like to understand the point you raise better. Sorry if this is a bit random, given the many other points you are progressing in this thread… happy to cleave this off into a separate thread.

— Miller

Sent from my iPad

On Aug 23, 2021, at 6:15 AM, Henrik Karlsson @.***> wrote:

 Thank you @mjbrichards, please find a new round of comments on the latest version:

Section 1.1, "Custodian" could be removed as a term as it is never actually used in the document as far as I can see, expect in the definition of FXP. FSP can be used there instead as this term should be known by the existing FSPIOP API. Section 5.2, Reference to Section 6.3.1 is not correct, should probably be 6.2.2. There also seems to be other references in the document that are not really correct.. Section 5.2.1, "It adds a duration, ...", as my earlier comment I would like to have an expiry time instead of a duration (the original problem was the inconsistency between sections), as it's much easier to know when the conversion is expired. A duration would just move the problem into calculating when the message was sent from the other party to find the actual expiry. Section 6.2.5 uses expiration. Section 5.3, Step 2.c.i, "commitFx" should be "POST /fxTransfers" Section 6.1.1, There is a maximum of 10 currencies now, suggesting to change to 8 or 16 as we usually have powers of two (2^n) for sizes in at least FSPIOP API. Section 6.1.3.1, the description for sendAmount is not correct. This is also a breaking change from the existing amount in the Transaction object. Section 6.2.2, I'm still not convinced on the need of having specific fees/charges for FXP instead of just having any charges as part of the FX rate.. It's strange to me to have fees in two entirely different elements; in the payeeFspFee in PUT /quotes and then in the new SignedConversion object. See also Assumption nr 8 (in Section 2 in the document). This inconsistency will probably lead to implementation errors. Section 6.2.6, "Duration" is never used now, expect in text in Section 5.2.1 (see other comment above). Section 6.3.2, Step 7, both alternatives seems to be that the amount in target currency should be calculated. One of them should probably be amount in source currency? Section 6.4 can be removed (is empty). May I please ask you to add some more detailed example sequence diagrams, where it is possible to see the source and target amounts, and the different fees/charges and who is paying them (if we really want to have charges from the FXP, which I preferably would like to avoid for now)? It would help a lot to have more specific examples to validate the proposed changes.

One thing to consider is that it will not be possible for a FSP to completely subsidize a transaction that is using FX (see for example Section 5.1.2.1 in FSPIOP API), as the FXP can add additional fees after the Payee FSP has determined its final terms of the transfer. The FXP fees would at least be invisible if there is only a FX rate which includes fees.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

mjbrichards commented 3 years ago

My thinking on this point was as follows.

If the FXP can only express charges by incorporating them into the conversion rate, then the charges will inevitably be passed on to the debtor customer. I did not want to rule out the possibility that the creditor FSP might decide to bear some or all of the conversion charges itself.

So the FXP can return one or more charges as part of its response to the creditor FSP. It will add these either to the amount to be sent or the amount to be received, depending on the setting of the amountType field in the base transaction. Now, the creditor DFSP can decide either to leave the amounts as they stand, or can remove charges from the total amounts to be transferred if it proposes to bear some or all of those charges itself. If the amounts are left as they stand, then of course the creditor need do no more than accept the quotation as it is returned by the FXP, and adjust the send and receive amounts of the quotation appropriately.

All of this activity has taken place prior to the creditor DFSP's signature of the terms of the transfer (which will include the information returned by the FXP.) So the final terms of the transfer have not yet been determined, and hence it is still legitimate for the creditor DFSP to make any changes it wants to before finally signing the terms and adding an expiry to them.

It seemed to me that this structure would allow individual schemes to be flexible in their approach, while not adding intolerably to the complexity of individual implementations. If the FXP does not want to include charges, or if the creditor FSP simply wants to pass charges on to the debtor FSP, then nothing more need be done (except, in the latter case, accepting the amounts returned by the FXP; but that would be good practice in any case.) I am sensitive to your point about avoiding complexities which might cause problems in implementation; but I hope I've done enough to clear myself of that charge. I will include some of this thinking in the detailed sequence diagram I'm working on...

henrka commented 3 years ago

Hi @millerabel, my point was just regarding the possibility for a Payee FSP to subsidize fees for a Payer. For example in a cash-in where the Payer FSP would like to receive a fee to be able to pay out the commission to its agent, the Payee FSP could subsidize the fees so that the cash-in is free for the consumer. An example of this can be seen in https://docs.mojaloop.io/mojaloop-specification/fspiop-api/documents/API%20Definition%20v1.1.html#5162-agent-initiated-cash-in-send-amount. If it was not possible for the Payee FSP to subsidize the FXP fees, then this would not be possible.

But after @mjbrichards further comment regarding this, I might have interpreted the text in Step 25 ("Here is the finalised version of the transfer") in the sequence diagram (https://github.com/mojaloop/mojaloop-specification/issues/89#issuecomment-869488207) too strict, as it seems like the transfer is not completely finalized in this stage.

mjbrichards commented 3 years ago

Attached is a detailed sequence diagram of a transfer including currency conversion. Let me know if you have any comments. Transferring with Currency Conversion(DFSP-based)

henrka commented 3 years ago

Thanks @mjbrichards, great to have a more complete example to review where it is easier to understand your thoughts.

Please find some comments below:

To me, based on the comments above, it seems like there are some simplifications that could possibly be done which should make the API easier and more consistent:

jmssebunnya commented 2 years ago

@MichaelJBRichards will be happy to chat about this in our next session to further align/understand how the proposal is better or improve on insistence such as the current Mowali implementation.

lewisdaly commented 2 years ago

Step 20: There is a lot of repeated information in the request now to include the conversion object. I agree @ehenrka - it seems to me that if a Payee DFSP is going to do the conversion, then the Payee DFSP should imply this based on the quote#amount.currency field.

I think the Payee DFSP should be free to choose whichever FXP they want, and also create the conversionId themselves, since it is the Payee who is asking for the conversion to take place.

mjbrichards commented 2 years ago

Apologies for the delay, folks, but I have now completed a general revision of the structure of the FX API, based on @ehenrka's comments. I have versioned it as 2.0. I will produce two new sequence diagrams showing how the process will work depending on whether it is the payer DFSP or the payee DFSP who undertakes the currency conversion. Hopefully you will have enough time to take a brief look before this afternoon.

API Candidate for currency conversion support in Mojaloop v2.0.docx

millerabel commented 2 years ago

In the case of sender pays, shouldn’t the sender select the FXP?

Sent from my iPad

On Sep 20, 2021, at 8:22 PM, Lewis Daly @.***> wrote:

 Step 20: There is a lot of repeated information in the request now to include the conversion object. I agree @ehenrka - it seems to me that if a Payee DFSP is going to do the conversion, then the Payee DFSP should imply this based on the quote#amount.currency field.

I think the Payee DFSP should be free to choose whichever FXP they want, and also create the conversionId themselves, since it is the Payee who is asking for the conversion to take place.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

mjbrichards commented 2 years ago

In this model, the sender can select the FXP (and manage the conversion) if they want to. If they don't, they can resign the task to the payee. If the payee doesn't either, then the transfer is rejected. Similarly, the FXP can decline to execute a requested conversion...

mjbrichards commented 2 years ago

Please find attached a revised API definition, together with sequence diagrams showing how the new API will work when the payer DFSP does the currency conversion, and when the payee DFSP does the currency conversion. API Candidate for currency conversion support in Mojaloop v2.0.docx ![Transferring with Currency ConversionPayee DFSP requests conversion](https://user-images.githubusercontent.com/35496554/136356953-2f4925cf-915b-4743-b Transferring with Currency ConversionPayer DFSP requests conversion 186-0ab9e085e5bd.png)

millerabel commented 2 years ago

I love the narrative + message details format, makes this very easy to follow.

I’m noting in step 42 that the 202 is towards the wrong actor. The 202 should acknowledge receipt from Orange Senegal, not MTN Rwanda (MTN has no outstanding request that requires ack, Orange Senegal is the sender of the message that is to be acknowledged).

So in step 42, arrow should go from Switch to the left to Orange Senegal, not to the right to MTN Rwanda.

The 202 in step 42 should condition Orange Senegal to expect a PUT in step 51 or 52, as shown.

— Miller

Miller Abel @.***

On Oct 7, 2021, at 2:22 AM, mjbrichards @.***> wrote:

Please find attached a revised API definition, together with sequence diagrams showing how the new API will work when the payer DFSP does the currency conversion, and when the payee DFSP does the currency conversion. API Candidate for currency conversion support in Mojaloop v2.0.docx https://github.com/mojaloop/mojaloop-specification/files/7301045/API.Candidate.for.currency.conversion.support.in.Mojaloop.v2.0.docx ![Transferring with Currency ConversionPayee DFSP requests conversion](https://user-images.githubusercontent.com/35496554/136356953-2f4925cf-915b-4743-b https://user-images.githubusercontent.com/35496554/136356953-2f4925cf-915b-4743-b https://user-images.githubusercontent.com/35496554/136356996-85ad4351-d369-482a-b2bf-b444bdf9429d.png 186-0ab9e085e5bd.png)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mojaloop/mojaloop-specification/issues/89#issuecomment-937612382, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB6OJ6ET4P7BKUGMI3RPNADUFVRF3ANCNFSM46XDYC2A. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

lewisdaly commented 2 years ago

Thanks @MichaelJBRichards for the updated doc and sequence diagram. I'm reading through the doc now.

The case where the Payer DFSP specifies a SEND amount is clear to me, since the Payer DFSP can know the total amount before sending the POST /quotes to the Payee, but I'm still unclear on how the RECEIVE amount works.

From your doc:

• If the amount is a RECEIVE amount, then the payer DFSP will have been informed of the amount to be received before it makes the request, and will use that amount in the quotation request.

The Payer DFSP knows the "amount to be received", but this doesn't include any fees added by the Payee DFSP, so the Payer DFSP can't know (until after receiving the PUT /quotes/{ID} back from the Payee DFSP) what to put in the POST /fxQuotes API call.

mjbrichards commented 2 years ago

There goes cut'n'paste again, @millerabel, showing me up for the lazy drone I am... I attach a revised version.

The way I think this would work, @lewisdaly, is as follows. If the payee DFSP intends to add fees, then it will do so in the normal way and return the quote to the payer DFSP. The payer DFSP now knows the total amount that must be received by the payee DFSP in the target currency, so it can ask the FXP: "what amount of the source currency do I need to send you to get that total in the target currency?" This requires, of course, a further call to the FXP to obtain the new amount in the source currency. Does that answer your question? Transferring with Currency ConversionPayer DFSP requests conversion

henrka commented 2 years ago

Thanks @mjbrichards for the updated document and sequence diagram! Please find some initial comments from me below.

First some quick comments/questions from the document:

Some questions/comments from the sequence diagram:

Generic questions/comments:

mjbrichards commented 2 years ago

Thanks (I should say, as usual,) @ehenrka, for your detailed and perceptive comments. I have incorporated most of them in a revised version of the specification; but there are a couple of points that I wanted to discuss further.

First, the question on charges in 6.2.2. The underlying idea was that there might be a number of charges associated with a transfer. Each participant in the currency conversion process would be clear about which charge was theirs and how the charges were to be borne; but all the charges would need to be expressed both in the source and in the target currency, so that they could eventually be borne in either. With regard to the question of multiple charges, the question I asked myself was not, do we need more than two specific charges; but rather, is there a compelling reason to constrain the number and type of charges that we would allow? I thought that the answer to that was no - or, at least, I couldn't think of one. But perhaps you can. I should say that, for me, the fact that at present we only allow the payee DFSP to specify a single charge did not seem to me a compelling reason. I also imagined a situation where an FXP might have a mandatory charge (such as a government tax) and a voluntary (processing) charge, and might want to distinguish those for a customer. I'm open to persuasion about this, but wasn't yet completely convinced.

I excluded the exchange rate from the definition because I am, in general, allergic to defining things in two different ways (that is: amount B = amount A*rate, and rate=amount A/amount B.) It seemed to me that any participant could trivially derive an exchange rate from the given source and target currencies. Expressing it in this way seemed to me to have the advantage that a DFSP could elect to fold any charges into the exchange rate if it wanted to, or could show the charges separately to the customer.

My reason for having two different identifiers was that I imagined a situation where there was a single conversion request, but that it needed to be requested twice. For instance, if a RECEIVE transfer had conversion requested by the Payer, but the Payee subsequently added fees, the Payer would need to add the fees to the conversion request. This would (or could) be the same conversion, but in order to pass the duplicate check it would need a different request identifier. I'm not wedded to this one, though.

I imagined that the POST /fxTransfers call would look like the proposed new form of the POST /transfers call: that is, with the terms of the conversion or transfer expressed in plain text rather than encoded as part of the ILP packet. Is that wrong?

Thanks also for your comments on the sequence diagrams - I'll get to them later, but I wanted to return the specification document quickly. Let me know what you think. API Candidate for currency conversion support in Mojaloop v2.0.docx

henrka commented 2 years ago

Thanks @mjbrichards!

Regarding the charges, it might be possible that the the participant itself knows which charge is theirs, but I'm still trying to understand how will the Switch will know which charge should go to which participant? Or is this handled in some other way? This is also why I would like to see all actual reservations as part of Step 44 and 57, because this part is not clear to me after reading the document or the flow. One compelling reason to only have one fee per participant, is that it makes the implementation and understanding easier. If we later need to have more, then it should not be that hard to add more. At least none of our operators need to break down a fee that the Payer should pay. We do separate the tax and the fee for an end user, but any tax is handled internally within our platform (at least that is how it works today). Otherwise they are handled as a fee, where we then show just the total amount to the end user. Do you have any examples where it is required to break it down further? If this is required somewhere, then of course we can have multiple charges, but then I would like to understand how it is supposed to work end to end (maybe it's just me that does not fully comprehend how it will work..).

Regarding the exchange rate, fine by me, then I know why it is excluded.

Regarding the two different identifiers, OK let's keep it as is now and see when we have the RECEIVE flow if we can simplify.

Regarding the POST /fxTransfers, my comment probably needed some more context, sorry about that. The POST /transfers as it is today does not require the Switch to know any details regarding the quote, as far as I know it should not even be necessary for the Switch to read the ILP Packet. The Switch just needs to know that the amount in the request should be sent from the Payer FSP to the Payee FSP if the correct fulfilment is delivered by the Payee FSP. The ILP Packet that we have is also not a quote, it is just information regarding the transaction that can be interesting for the the Payer FSP and Payee FSP. In the POST /fxTransfers, the Switch needs to understand the SignedConversion and perform logic based on that. This means that the implementation in the Switch will be tightly coupled to the FXP API, instead of potentially supporting other FX APIs. My thought was if we could decouple the POST /fxTransfers from the FXP API, and include the transfer that needs to be performed between FSP and the FXP instead. The SignedConversion is then the end-to-end information between the FSP and the FXP.

henrka commented 2 years ago

One addition to my last point is that it might even be possible to reuse the POST /transfers for the FX transfer, in case a relatedTransferId is added to the POST /transfers , and the FSP and the FXP stores the SignedConversion instead of passing it around (similar to that the FSPIOP quote is stored in both FSPs today). The relatedTransferId could then be used for other purposes as well, for example if a transfer to a Payee FSP also includes for example a tax being sent to the government in another FSP in a related transfer that depends on the other transfer being performed.

mjbrichards commented 2 years ago

Please accept my apologies for my delay in replying, @ehenrka; but I am now back on the case...

With respect to the charges, it was my expectation that they would be managed in the same way as they are in the current quote/transfer flow. That is to say, they provide information to the payer and to the payee about the charges that will be levied as part of the transfer rather than instructions to the switch to credit the fees to an account in the switch. The fees charged by the payee need to be included, because the FXP needs to express the amount in both currencies for use by the participants. The fee(s) that the FXP proposes to charge will in fact be deducted by the FXP as part of the conversion, and will therefore not appear in the switch's ledgers at all; but they need to be made explicit so that, for instance, the sending customer can be shown the fees.

I agree, of course, that they could all be folded into a single currency conversion fee; my thinking was that I wanted to treat the FX fees and the payee fees in the same context and, having introduced an array of fees, I saw no problem, and possibly an opportunity, in allowing for more fees.

On the question of the Transaction object: we know that there is an outstanding problem with having it in an encoded form at present. It was originally reported by the implementers at Mowali, and it was that they needed to know what the transaction ID was for a given transfer. As you know, the transfer ID does not provide a link between the transfer and the quotation, where the signature is applied; so the transaction ID was necessary for them to be able to ensure that the correct private key was being used by the payee DFSP to check the bona fides of the transfer. We eventually kludged this by asking the Mowali DFSPs to use the same value for the transaction ID and the transfer ID; but in my view this is not a satisfactory long-term solution, not least because it makes it impossible to retry a transfer using a different transfer ID. In addition, later versions of the ILP specification have, I believe, dropped the requirement for an encoded version of the material signed by ILP to be included in the data packet.

The work that Adrian and I originally did on cross-network wound up proposing that the Transaction object should be included in the body of the transfer request in plain JSON. This will be required in any case for ancillary processing around the transfer, such as the new version of settlement. So we should have this as a separate discussion; but I think that I want to continue assuming it in this definition and in the definition of settlement.

Your final comments on multiple associations between transfers are very interesting. I included the reference field in the FX transfer for two reasons. First, because I wanted not to make any changes in the transfer message itself; and, second and perhaps more important, because I envisaged that, in conformity with the reference architecture we've been developing, FX processing would be done by a functionally separate module in the switch. It would listen for transfer completions on the Kafka stream, but would not require any other integration with the switch code to do its job. This would mean that implementations which did not need to support currency conversion would incur no processing overhead as a consequence.

That said, I'm still interested in the idea. My worry about it is about the hierarchy between messages. In the FX case, there is a clear hierarchy: if the transfer does not succeed, then the conversion should not succeed; but, as I say in the document, for the FXP to approve the conversion means that it resigns the determination of the final outcome of the conversion to the switch. If the transfer succeeds, then the FXP is obliged to settle with the creditor FI. However, when we looked with SSNAPP at the question of payments with mutiple components, it was clear that one of the use cases we would need to support was all-or-nothing: in your example, if either the principal transfer or the tax payment were to fail, then the other should fail too. I think that makes that a different case; but, as I say, I'm very happy to discuss it.

I'll get on to the sequence diagrams before our next meeting, promise...

henrka commented 2 years ago

Thanks @mjbrichards. I'll just comment one thing for now: My comment regarding POST /transfers and ILP packet is not related to if an encoded version should be used or not. I'm fully aligned that this information does not need to be encoded, as is discussed in for example #14.

My point is that the Switch does not need to care about the end to end information in the POST /transfers between FSPs (the current ILP packet), all the Switch needs to know is the amount that should be transferred from the Payer FSP to the Payee FSP. In the POST /fxTransfers proposal, the Switch needs to understand the SignedConversion and perform logic based on that, which means that it is tightly coupled to the FXP API.

mjbrichards commented 2 years ago

I think I understand your point, @ehenrka; but let me re-state it to make sure. The switch does not need to understand the information in the transaction object to process a transfer. This is because the pieces of information relevant to processing the transfer (the payer FSP, the payee FSP and the amount) are separated from the end-to-end transaction information. In the /fxTransfers endpoint, however, the information required by the switch to register the conversion is all contained within the signedConversion object, together with the end-to-end information.

This is certainly true; and, as you say, it means that the information is tightly coupled to the FX API. But part of the point of the new version of currency conversion is that it should be decoupled from the processing of transfers (apart from the dependency relationship.) It will arrive on different endpoints, and be processed by different services in the switch. I therefore felt that having it tightly coupled to the FX API was not a drawback.

henrka commented 2 years ago

Yes, your understanding is correct @mjbrichards. The following are the advantages that I see with decoupling it so that the Switch only needs to know which amounts that should be transferred from the FSP to the FXP:

mjbrichards commented 2 years ago

Please find attached revised versions of the specification and of sequence diagrams for for the use cases where currency conversion is performed by the payer and by the payee API Candidate for currency conversion support in Mojaloop v2.1.docx Blue Bank Detailed FX transfer Version 2 - Payer conversion Blue Bank Detailed FX transfer Version 2 - Payee conversion

I will forward copies of the presentation to be used in tomorrow's discussion by mail. Let me know if you have any comments or questions in advance of the meeting.

henrka commented 2 years ago

Thanks @mjbrichards! Please find my comments on the Payer FSP requests conversion-flow. I will try to add comments on the other flow soon...

henrka commented 2 years ago

Comments on the Payee FSP requests conversion:

mjbrichards commented 2 years ago

Please find attached a sequence diagram describing the latest proposal for a currency conversion method that requires no changes by participants. It currently covers only the happy path: I will extend it to show how it addresses the current issues with the two-transfer approach in Mowali. Blue Bank Detailed FX transfer Version 3 - Revised switch conversion

henrka commented 2 years ago

Thanks @mjbrichards,

Please find some minor comments for now:

mjbrichards commented 2 years ago

Thanks for your comments, @ehenrka, and my apologies for being late in responding to them. My answers to each of your points are as follows:

I attch a corrected version of the sequence diagram: Blue Bank Detailed FX transfer Version 3 - Revised switch conversion

henrka commented 2 years ago

Thanks @mjbrichards, then it's just my comments on when it is one of the FSPs that is performing the currency conversion that should be addressed, please see https://github.com/mojaloop/mojaloop-specification/issues/89#issuecomment-983674131 and https://github.com/mojaloop/mojaloop-specification/issues/89#issuecomment-984694658.

mjbrichards commented 2 years ago

Finally, @ehenrka, I arrive at responding to your comments on the sequence diagrams. I have incorporated your suggestions, except in the following cases:

Would it not make sense to use same (or at least similar) terminology as in the FSPIOP API transfers request for "requestingFsp" (suggesting PayerFsp) and "respondingFxp" (suggesting "payeeFsp")? The terms requesting and responding does not seem fitting on a financial level, more on a message level.

It seemed to me that the problem was that, in a currency conversion, the parties are both payers and payees. I don't have a strong preference for what we call them, but I don't think that payer and payee are appropriate.

The converter element is used in the quote request as well as the response. I originally started from the idea that the payee DFSP should infer whether it was supposed to make the currency conversion or not from the currency of the amount. But I thought that it would be possible that a sender might want to specify what the beneficiary should receive, which would be in the target currency, and the payer DFSP might still want the payee DFSP to undertake the conversion. So I thought that we needed to add a parameter to specify.

How does the Switch know here that it should not reserve for MTN Rwanda as well? I guess in the normal flow that Switch performs all reservations in this step? If you don't do this reservation, can you be certain that the transfer will be successful?

This is an interesting question, and I wasn't sure which way to jump on it. In the end, my reasoning was as follows. For a PvP transfer, each ledger reservation in a currency other than the DFSP's home currency refers solely to the particular transfer. It's not like a reservation in the home currency, whose purpose is to stop funds being spent twice on different transfers. When the payer DFSP was doing the transfer, I thought it was important to make the reservation, because then the switch can process the transfer request in the normal way. But when the payee is doing the conversion, I thought that the switch would be doing different processing in any case, to ensure that the conversion did not succeed unless the transfer did, and that it was therefore sufficient to make the ledgers balance correctly, without needing to make a reservation in advance. But, as I say, I'm not wedded to the idea...

Revised sequence diagrams: Blue Bank Detailed FX transfer Version 2 - Payee conversion Blue Bank Detailed FX transfer Version 2 - Payer conversion

henrka commented 2 years ago

Thanks for the update @mjbrichards!

I think we had the same discussion regarding requestingFsp in the mail thread about where the Switch handled the conversion. One possibility that we discussed there was responsibleFsp, but I'm probably fine with requestingFsp as well..

On a quick look now, there is still at least an issue in the Payer FSP requests conversion-flow, see note between Step 57 and 58. After end note, there should be an actual new line (carriage return). Currently is:

end noteS1->S2:...

Should be:

end note S1->S2:...

MichaelJBRichards commented 1 year ago

At the convening I agreed to look again at the currency conversion proposal, to take account of the comments made by participants at the convening. The attached document proposes an alternative mechanism for undertaking currency conversion which, I hope, removes the features which were felt to be problematic. Please comment ad lib.

Revised proposal for currency conversion - the Mechanism.docx

MichaelJBRichards commented 1 year ago

A sequence diagram illustrating the process described in the document above when currency conversion is being performed by the debtor DFSP. Blue Bank Detailed FX transfer Version 2 - Payer conversion

henrka commented 1 year ago

Thanks Michael, please find my initial comments:

MichaelJBRichards commented 1 year ago

Sorry for the mistake, @ehenrka . I think this is the correct version:

Blue Bank Detailed FX transfer Version 2 - Payer conversion

henrka commented 1 year ago

Thanks Michael, please find my initial comments:

  • Step 22: Text should say "please quote me .." instead of "confirm", similar to step 20 as the Switch just forwards the quote request to the FXP.
  • Step 24-25: The note includes information about transaction object. I guess this is now moved to a later stage?
  • Step 24-25: Would be good if it was possible to know directly in the data model if the charge is included already in the quoted conversion, or if it is on top of the quoted conversion. Don't have any good suggestion at the moment though..
  • Step 27: Text says signed transaction object, this should be a conversion object?
  • Step 29-30: The handling of charges and amounts seems a bit illogical here, where the target amount is still 10000 RWF but the target will never receive that and that is not what is stated as the sent amount from the Payer FSP as well. Maybe I just need some more coffee..
  • Step 31: Text says 9850 XOF, should be RWF I guess?
  • Step 31: Is the conversion object sent to the Payee FSP as well? It seems a bit strange to send this information to the Payee FSP as well, containing exactly how the conversion was performed by the Payer FSP, but at the same time it should be required if message signing on the whole object is used..
  • Step 34: Unfortunately I can only see less than half of the note, then the image ends. Could you please attach the PUML file as well?

Thanks @MichaelJBRichards, please find my additional initial comments from looking at the complete flow:

MichaelJBRichards commented 1 year ago

Hi @ehenrka , here are my responses to your comments. First, the original set...

Second set of comments:

Revised version of the sequence diagram:

Blue Bank Detailed FX transfer Version 2 - Payer conversion

henrka commented 1 year ago

Thanks @MichaelJBRichards for the reply!

As a start, I'm trying to understand a bit more on your replies below (including my comments first to give context). The dependent data model is sent both in POST /quotes and POST /transfers as it is now, so I don't fully understand the part "That means it's available to the switch as part of the POST /transfers call, which becomes important later.". To me it seems like either the dependent information does not need to be sent in the POST /quotes, or it does not need to be sent in POST /transfers as it is already part of the transaction object as is stated below?

Step 31: Is the conversion object sent to the Payee FSP as well? It seems a bit strange to send this information to the Payee FSP as well, containing exactly how the conversion was performed by the Payer FSP, but at the same time it should be required if message signing on the whole object is used..

Yes, my idea was that it should be sent to the payee DFSP so that it could be signed. But it's also importnt for it to be included in the Transaction object, which is constructed by the payee DFSP. That means it's available to the switch as part of the POST /transfers call, which becomes important later.

Note between step 29-30: Is the conversion details (the "dependent" data model) really needed to be sent again in the POST /quotes (basically same question as in earlier quoted comment but rephrased a bit)? The switch should already have the details from the POST /fxQuotes, and the information is not needed by the Payee FSP and might also risk leaking unnecessary business information from Payer FSP to Payee. The Switch doesn't seem to do anything with the information based on the information in the flow.

As I said before, this is really about making sure that the currency conversion information is available to the switch as part of the information transmitted in the POST /transfers call. It's true that the information is available in the POST /fxQuotes call; but we have tried to ensure that the switch supports transfer calls which do not have a corresponding quotes call, and this is intended to be consistent with that pattern.

Could you please also explain the last part above, where would you not have a quotes call? The FSP Interoperability API requires you to do a quote first. Is it the FX API that supports transfers without a quote, and in that case why would you not do a quote first to get the conversion terms even it is for a bulk conversion? I'm sorry that I don't quite follow you here..

Note between step 42-43: Isn't there redundant information in this request? The "conversion" and the "dependent" seem to say basically the same thing, but in different ways. Could you please explain why both are necessary?

The currency conversion API supports both PvP conversion and bulk conversion, where the sender DFSP purchases currency for use in supporting future transfers. The two use cases are distinguished from each other by the presence in the first use case of an optional dependent structure. This structure contains information which is used by the switch to update the ledgers when the main transfer completes. It does duplicate information in the conversion itself, but the information is (I think) being used for different purposes here. However, I can see that there might be a better way...

What is the information in the dependent object used for in the POST /fxTransfers? For example the condition is available in both the top level data model, and in the dependent object. The conversionId seems to be set to the FX quote ID from POST /fxQuotes in note between step 20-21, which I guess should always be present (unless there is an actual use case where you don't do a FX quote first to get the conversion terms, see above). To me it also seems like the conversionTerms is what is used for the condition and fulfilment, and not the dependent, as this is what is returned in the callback PUT /fxQuotes. To summarise, I don't really understand the use of the dependent here, more than the conversionId could be moved to the top level to indicate the previous FX quote.

A minor comment for the note between step 42-43 is that POST /fxTransfers uses dependents instead of dependent, which other services seem to use. Can there be multiple dependents for this service, or is it a typo?

Note between step 55-56: Do we need to send the conversion details in the "dependent" data model here? In my opinion, the FX transfer should be dependent on the actual transfer that the Payer would like to perform, and there should not be a need for both to depend on the other, but maybe there is a good reason for it?

The reason (I leave it to you to decide if it's a good reason) is that the switch needs to know about the fulfilment for the currency conversion, so that it can satisfy itself that the conversion has been approved by the FXP. As a general principle, we don't want to rely on the switch needing to have prior knowledge of this conversation; so this seemed to me to be a possible solution. But there may well be a better way.

Sounds like a valid reason to include it in this case :). Another minor note here is that the data model for POST /transfers shown in the note between step 55 and step 56 does not contain the condition for the FSPIOP transfer between the Payer and Payee FSP, and the use of a transaction element instead of a ilpPacket element, which was discussed in https://github.com/mojaloop/mojaloop-specification/issues/13 but was never implemented in an actual solution.

MichaelJBRichards commented 1 year ago

Sorry for my long delay in replying, @ehenrka. Let me respond briefly to your points, at least so that we can have a basis for discussion in the SIG.

First, the dependent information needs to be sent in the POST /quotes phase because currency conversion is being performed by the debtor DFSP. I wanted the currency conversion information to be available in any case when the transaction object was constructed; but if conversion were being performed by the creditor DFSP, then the information would not be available in the POST /quotes phase and would be added directly to the transaction object by the creditor DFSP.

You are, of course, entirely correct about the duplication of information in the POST /transfers phase. I had two reasons for including it in the body of the message as well as in the transaction object. First, the same as the reason for including the debtor and creditor DFSP identifiers and the amount of the transfer in the body of the message: so that the switch can process the transfer without needing to decode the transaction object. Now, I would be relatively relaxed about including all of the information required to execute the transfer in an ILP v4 packet and allowing the switch to process using that; but, for the moment, I tried to follow the pattern that we use for the other pieces of information relating to the execution of the payment.

My second reason was that the switch needs to have the fulfilment which was added to the dependent object in the put /fxTransfers call. The switch needs to be able to satisfy itself that the FXP has approved the conversion before it can proceed with the transfer; and, for obvious reasons, this information can't be added to the transaction object. Again, it would be possible just to have the fulfilment without the rest of the dependent information; but I erred on the side of completeness.

Ah yes, the transfer without a quote. In my mind, this question has the same status as maintaining the ability of the API to function in a peer-to-peer context. It's something that we have always said is a characteristic of the API that we have tried to maintain, without ever really asking whether we still need to. When I say without a quote I don't, of course, mean that there is no condition/fulfilment pair. What I mean is that we've always allowed for the possibility that the condition and the transaction object could be generated and sent to the debtor DFSP out of band.

The presence of a dependentobject in the POST /fxTransfers call marks the difference between a bulk conversion (which the FXP can complete immediately) and a PVP conversion (where the FXP has to wait for confirmation from the switch before finally clearing the amounts.) It's true that the same function could be performed by a marker flag, and the fulfilment returned as a separate data item in the put /fxTransfers body; but I thought it simpler and more comprehensible to supplement the existing structure.

Yes, I wondered whether I should make dependent into an array or not and in the end fell between two stools, as you point out. The reason for thinking that more than one dependent might be needed was so that in the future we could support conversion via a reference currency. In that case, two conversions would be required: one from the debtor DFSP to the first FXP, and one from the second FXP to the creditor DFSP. So I think that I want to make all of the instances into multiples. But thanks for pointing that out.

I wrote out the transaction object just so that everybody could understand what was in it - I would expect, of course, that it would be encoded in the eventual API...

So that concludes my comments for the moment; I hope that we can discuss them further today.

henrka commented 1 year ago

Thanks @MichaelJBRichards,

First, the dependent information needs to be sent in the POST /quotes phase because currency conversion is being performed by the debtor DFSP. I wanted the currency conversion information to be available in any case when the transaction object was constructed; but if conversion were being performed by the creditor DFSP, then the information would not be available in the POST /quotes phase and would be added directly to the transaction object by the creditor DFSP.

I'm sorry, but I still fail to understand why the Payee FSP or the Switch needs to know in the POST /quotes that the Payer FSP has performed a currency conversion (the information in the dependent object). The amount is already in a currency that the Payee FSP can handle, so it shouldn't really care. The switch doesn't seem to be doing anything with the information either as per the flow for the quote. Your reason in https://github.com/mojaloop/mojaloop-specification/issues/89#issuecomment-1301845526 was because that it should be signed. Why is it important that this is signed, as the FX transaction is between the Payer FSP and the FXP?

You are, of course, entirely correct about the duplication of information in the POST /transfers phase. I had two reasons for including it in the body of the message as well as in the transaction object. First, the same as the reason for including the debtor and creditor DFSP identifiers and the amount of the transfer in the body of the message: so that the switch can process the transfer without needing to decode the transaction object. Now, I would be relatively relaxed about including all of the information required to execute the transfer in an ILP v4 packet and allowing the switch to process using that; but, for the moment, I tried to follow the pattern that we use for the other pieces of information relating to the execution of the payment. My second reason was that the switch needs to have the fulfilment which was added to the dependent object in the put /fxTransfers call. The switch needs to be able to satisfy itself that the FXP has approved the conversion before it can proceed with the transfer; and, for obvious reasons, this information can't be added to the transaction object. Again, it would be possible just to have the fulfilment without the rest of the dependent information; but I erred on the side of completeness.

Shouldn't the Switch anyway try to look up information regarding the currency conversion in Step 57, before reserving funds, using the conversionId of the dependent, for example to verify the dependent transfer, to see that it has been marked as conversionState=RESERVED, and that the conversion hasn't expired. Step 65 mentions "Get the transfer confirmation", what does that mean in more detail? My thinking is that it should be possible for the switch to get both the amounts and the fulfilment on its own (either from DB or cache), as there is a risk that the Switch will commit an expired conversion in Step 67 if it doesn't verify it in some way. The Switch should already know without the fulfilment in this stage that the FXP has approved the conversion, as the Switch was part of the /fxTransfer flow which means that it already received the fulfilment then...

The presence of a dependentobject in the POST /fxTransfers call marks the difference between a bulk conversion (which the FXP can complete immediately) and a PVP conversion (where the FXP has to wait for confirmation from the switch before finally clearing the amounts.) It's true that the same function could be performed by a marker flag, and the fulfilment returned as a separate data item in the put /fxTransfers body; but I thought it simpler and more comprehensible to supplement the existing structure.

In my mind it is confusing, as well as a possibility for errors, to repeat the same values in two different objects ("conversion" and "dependents").. (Coming back to your comment earlier that you didn't want the FX rate to be included as well in the PUT /fxQuotes/ as the amounts were already included..). I would suggest just having the ID of the dependent transfer (or similar) to indicate if there is a dependent transfer which the Switch should wait for, or not.

Some new comments:

Suggesting a call to further discuss the points above.

MichaelJBRichards commented 1 year ago

On the first point, @ehenrka: the debtor institution hasn't performed a currency conversion yet. It has said that it is prepared to, and that it has obtained the provisional agreement of its FXP. This is not yet an agreed part of the transfer; and it is, in my mind, the creditor DFSP which has the power to decide whether the currency conversion proposed by the debtor DFSP should be used or not, in the same way as it has the power to set all the other terms of the transfer. If the creditor DFSP decided that, for any reason, it did not wish to use the debtor DFSP's currency conversion proposal then I think it is consistent with the FSPIOP pattern that it should be able to do so. But if the debtor DFSP does not send the information in the first place, this is impossible. If the debtor DFSP wants to insist on undertaking the conversion itself, then it has another avenue open to it: it can perform the conversion itself, separate from the PVP transfer. So I think that the following is a perfectly acceptable conversation:

On your second point: step 57 is misleading because I put the apostrophe in the wrong place: it should read "reserve debtors' funds." The example shows the result correctly. The switch doesn't need to check the status of the conversion because it has the fulfilment for the conversion in the dependent object, which is sufficient proof that the conversion was approved; and it doesn't need to check the time-out because the time-out for the conversion has been subsumed in the transfer request. By assenting to the conversion, the FXP has resigned its control over the transfer: the whole transfer (including the conversion) will now either succeed or fail. IT is possible, of course, that the conversion might have timed out before it was returned to the debtor DFSP for inclusion in the POST /transfers request: but if that had been the case, then the switch would have notified the debtor DFSP and would not have returned the fulfilment. So I think that's covered...

I am certainly sensible of the justice of your arguments in your third point. Let me see if I can work things round a different way; and I'll send out a new and hopefully improved version.

Finally:

henrka commented 1 year ago

Thanks @MichaelJBRichards,

Some comments for now, let's discuss in the FSP Interoperability API meeting tomorrow as well.

On the first point, @ehenrka: the debtor institution hasn't performed a currency conversion yet. It has said that it is prepared to, and that it has obtained the provisional agreement of its FXP. This is not yet an agreed part of the transfer; and it is, in my mind, the creditor DFSP which has the power to decide whether the currency conversion proposed by the debtor DFSP should be used or not, in the same way as it has the power to set all the other terms of the transfer.

The Payee FSP does not have the power to set all other terms of the transfer as part of the quote. It will only use the terms that the Payer FSP has sent in the quote request. It can either reject or accept this quote, it can't change any important terms of it as far as I'm aware. For example it can't change the amount or the Payer or the Payee, or the transaction type. I would like to know which terms you are referring to that can be changed?

Is this a specific request from some potential customer that the Payee FSP can decide to change the currency conversion?

I thought that it was a standard pattern of ours to have a request ID separate from the ID of the thing requested; if the request needs to be reissued, it has the same conversionId but a different conversionRequestId.

No, if you don't get a callback you will send the same request again with the same correlation ID. If you want for example a new quote that happens to have the same content, then you send the same request but with a new correlation ID to indicate that it is a new quote.

MichaelJBRichards commented 1 year ago

@henrka: On the question of the payee DFSP changing the terms of the transfer... Let's assume that a customer asks to send a transfer to the ALIAS "Ericsson". This gets routed to Ericsson's bank, which knows a) that Ericsson is a company, not a person; and b) what the balance of payments code is for Ericsson's business. Neither of those things would be reliably known by the payer DFSP. So shouldn't the payee DFSP set the transaction type entries correctly, and shouldn't the payer DFSP accept those changed terms?

henrka commented 1 year ago

@MichaelJBRichards, my understanding of Balance of Payments is that it is more of an informational field used for statistics, which wouldn't change the terms of the transaction in any way for any of the involved parties (Payer, Payee, Payer FSP, or Payee FSP). But I might very well be incorrect.

If the Payer FSP would like to know that Ericsson is a company, then this will be possible using GET /parties from version 2.0 of the API, see https://github.com/mojaloop/mojaloop-specification/issues/25, which adds PartyType as part of the Party complex type.