mojaloop / mojaloop-specification

This repo contains the specification document set of the Open API for FSP Interoperability

Home Page:https://docs.mojaloop.io/api

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Change Request: Currency conversion support in Mojaloop

mjbrichards opened this issue · comments

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

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:

  • 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.
  • 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?
  • 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.
  • Section 6.1.4: "Changes to the /transfers response" Change response to callback
  • 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.
  • 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".
  • Section 6.2.2, bullet 1: "conversionId" - Suggesting to rename this to fxQuoteId to align with above
  • 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.
  • Section 6.2.2, bullet 4: "fxp" - Suggesting to rename this to fxpId
  • 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.
  • 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.
  • 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..
  • 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.
  • 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.

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

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

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..

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

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.

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...

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 (#89 (comment)) too strict, as it seems like the transfer is not completely finalized in this stage.

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)

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

Please find some comments below:

  • Step 8: Why is it called denomination instead of currencies, as it seems to be the currency that is returned and not the denomination? (see for example https://en.wikipedia.org/wiki/Denomination_(currency)).
  • Step 13-19: Why does the Payer FSP need to know about which FXPs there are, as it will be the Payee FSP who asks for the conversion from the FXP? Is it a requirement on Payee FSP to use that specific FXP, or can it use other FXPs? What happens if the Payee FSP can't access the FXP in the conversion object? Maybe just include information that a currency conversion is needed, then it's up to the Payee FSP in that case to select one?
  • Step 20: There is a lot of repeated information in the request now to include the conversion object. There does not seem to be anything specific in the conversion object that is really needed by the Payee FSP that is not available in the existing data model for POST /quotes, at least not for this example. It should know the information from the existing POST /quotes request, unless there is a requirement that the Payer FSP decides the FXP (see above). The Payee FSP knows the currency of the Payee. In this example the Payer would like to send 100 USD from their account, which the Payee FSP then knows that this needs to be converted into a currency that the Payee can receive in. Any fees are deducted from the amount that the Payee will receive as it's a SEND amount.
  • Step 25: The Payee FSP could have created the conversion object (see above).
  • Step 29-30: The target->amount->currency should be RWF in the agreedConversion object?
  • Step 29-30: How will other participants know who should receive a charge in the agreedConversion object? Why does the Payer FSP need the agreedConversion object, is it just for knowing the fee, or because it is needed by the Switch in steps 44-45?
  • Step 35: Just for my confirmation, the payeeFspFee should contain both the Payee FSP fee and the FXP fee, which means the Payee FSP is required to handle this? It simplifies a bit for the Payer FSP as it does not need to actually check the signedConversion object, but makes the name of field a bit strange as it is not only the Payee FSP fee. Ideally, the Payer FSP should not even have to care about the signedConversion, a fxpFee could be added instead to know about the FXP fees. Additionally, an optional FX rate could be good to send as well in the PUT /quotes.
  • Step 41-46: Is it really necessary to include the entire signedConversion object again in the POST /transfers? For example for the quote, we just have the ID of the quote instead of resending the entire object again, so the API is not really consistent here. To me, it seems easier if the Switch would just reserve the funds for the Payer FSP in Step 43-45, and then reserve the FX part between Step 49 and 50 when it gets the POST /fxTransfers. This would also align better with a currency pre-purchase option, as the reservation should then happen in the POST /fxTransfers request to the Switch.
  • Step 45: How will the Switch know which fee should go to which participant?

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:

  • Possibly avoiding the conversion object in POST /quotes, or at least simplify it.
  • Avoid sending the signedConversion object in PUT /quotes and POST /transfers. If this is required just for sending the FXP fee to the Payer FSP and for knowing in Switch what should be reserved, I would rather have the FXP fee in a specific object and the reservation to be performed as part of POST /fxTransfers (which would be aligned with a currency pre-purchase). I don't see a need for the Payer FSP to validate the exact terms with the FXP, as long as the Payee is paid by the Payee FSP according to the terms in quote.

@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.

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.

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

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...

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)

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.

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

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:

  • Section 4.3: Please clarify that the quotation request discussed in the bullet points is the FX quote, and not the FSPIOP API quote
  • Section 4.4: What is the "validation request"? This is just mentioned in this section. Is it the POST /fxQuotes?
  • Section 5.3: The execution request, is this the POST /fxTransfers?
  • Section 6.1.1: "receiveCurrency" should be "receiveCurrencies"
  • Section 6.2: "New data objects in the FSPIOP API" This should probably be FXP API now?
  • Section 6.2.2: "One or more charges which the FXP intends to levy as part of the currency conversion, or which the payee DFSP intends to add to the amount transferred." How will we know which participant that wants which fee, as the charge does not say which one that would like to have the fee? Could we simplify this into two elements instead, one for the FXP and one for the Payee FSP? I don't really see why the FXP would want more than one single fee, as they could just handle any separation of fees internally as part of their logic, as such it seems a bit unnecessary to have more than one fee in the API. For the Payee FSP there is never more than one fee.
  • Section 6.2.5: Can we please include the FX rate in some element, as this is important to show to the customer?
  • Section 6.2.6: Duration is no longer used as far as I can see?
  • Section 6.3.1.1.2: Text says 10 participants, data model says up to 16. Additionally, could we simplify the services service a bit and for every type of service use the same callback? I.e. "providers" instead of "fxpProviders", "The FSP Id(s) of the participant(s) who offer the requested services." instead of "The FSP Id(s) of the participant(s) who offer currency conversion services.". You know the providers are FXPs as the the callback is PUT /services/FXP. The same data model could then be reused between services.
  • Section 6.3.2.1.2: Are both IDs in POST /fxQuotes and in Conversion needed? Seems a bit unnecessary to have two..
  • Section 6.3.3: Would it not make sense to have the POST /fxTransfer to be more similar to POST /transfers? Currently the signedConversion is and conversion is passed around a lot.

Some questions/comments from the sequence diagram:

  • Step 8/9: "denomination" should be "receiveCurrency" according to the document (which should be "receiveCurrencies" according to comment above)
  • Step 38: "It'll cost 175 XOF" , can we add a " ... in fees" to that to increase clarity?
  • Step 44: Would be great to detail the exact reservations as part of this step, including Payer FSP, Payee FSP, and FXP.
  • Step 48/49: The state here is "COMPLETED", but I guess it should just be "RESERVED"? And then completed in step 68 using PATCH /fxTransfer?
  • Step 51: Include the actual error callback
  • Step 55: The amount and/or currency must be incorrect. Amanda would just like to send 5000 XOF. The amount is now 9850 XOF. The 150 (10000-150=9850) is the FXP charge in RWF, but this must also be sent from the Payer FSP, or is this charge already handled as part of the /fxTransfers flow? I would assume that the Payer FSP requests a transfer of 5000 XOF, which is then converted to RFW in the Switch using the earlier agreed conversion with this relatedTransferId?
  • Step 57: Would be great to include the actual reservations here (analogous to comment in Step 44).
  • Step 63: The "output message from the queue" seems very specific to the actual implementation in Mojaloop, and does not have much to do with the currency conversion? Suggest to remove in that case.
  • Step 65: Should this not say "commit" instead of "cancel"?
  • Step 67: I guess this should be PATCH /fxTransfer?

Generic questions/comments:

  • Would be great to have a sequence flow example of RECEIVE amount as well.
  • In the current Mowali setup, each country (or currency) is divided in different monetary zones. This simplifies the scheme setup a bit, as every FSP does not need to know about every FSP in other monetary zones. An FSP only needs to know about FSPs and their certificates for signatures in the same monetary zone. Don't know know if something similar will be supported here, or if every FSPs needs to know about anyone? I haven't given this much thought yet, it was just something that popped up in my mind now..

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

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.

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.

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...

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.

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.

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:

  • Easier implementation in the Switch as it does not need to understand the SignedConversion object.
  • You could in theory support any type of FX quote if the end-to-end information was just an opaque data element, or at the very least easier change the existing FX quote without the Switch needing to update its implementation as it will still just be a transfer of amount from the FSP to the FXP.
  • The architecture would be more similar to the FSPIOP API.

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.

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

  • Step 8/9: receiveCurrency has been updated to receiveCurrencies in the attached document, but in the flow this has not been updated
  • Step 29: For clarity, can you update the comment in 29 to something like "Please quote for a transfer which sends 9850 RWF (5000 XOF converted to RWF minus 150 RWF in fee to FXP)"?
  • Step 34/35: The transfer amount here is in XOF. All currencies here should be RWF, the Payee FSP does not know about XOF.
  • Step 38: How does the Payer FSP know that the fees are exactly 175 XOF? It has received 200 RWF in fees Payee FSP, and 75 XOF from FXP. Is the Payer FSP supposed to calculate the FX rate from information in the conversionTerms? From the example you get that 1 XOF = 2 RWF. Would be good to state how it should be done as part of the flow so that the expectations are clear.
  • Step 41: 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.
  • Step 43/44: What would happen if there was a transfer ID with the associated ID? Errror callback?
  • Step 44/45: The reservations here are not consistent with reservations after Step 52 (extra "Orange Senegal has reservation of -9850 RWF"). When did that happen?
  • Step 55: Should this not be 9850 RWF, as that is what should be sent to MTN Rwanda for the transfer? The reserved funds for the conversion is then performed as a related FX transfer is found, where OrangeSenegal pays in XOF to get the RWF.
  • Step 55: "MTN_Senegal" should be "MTN_Rwanda". Similarly FSPs should be correct in "payeeFsp" and "payerFsp"
  • Step 57: Should there not be a reservation to Payee FSP here (MTN Rwanda) of 9850 RWF as well?
  • Step 57: Missing newline after "end note" causing issues in the generated image.
  • Step 60: "Get the output message from the queue" does not make much sense here...

Comments on the Payee FSP requests conversion:

  • Step 13: The note containing the data model and Step 15 seems correct, but the comment in Step 13 is in RWF, should be 5000 XOF.
  • Step 22: One extra activation here on MTN Rwanda causing the extra activity line.
  • Step 24/25: There should be some mention here that MTN Rwanda has rated their fee (the Payee FSP fee) of 200 RWF. This then goes into the charges data type in the FX quote.
  • Step 34/35/36: It would probably help a bit if we show how the payeeFspFee is calcuated to 175 XOF (75 XOF in Blue FX conversion fee + 100 XOF in MTN Rwanda fee).
  • Step 35/36: What is the use of the converter=PAYEE element? Should the Payer FSP care about this in some way? The only importance for them should be that the conversion is performed, or have I missed something?
  • Step 41/42: The amount here should be 5000 XOF (9850 is incorrect). The payee fspId should be MTN Rwanda. The payeeFsp and payerFsp elements should be corrected to MTN Rwanda and Orange Senegal.
  • Step 43: 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?
  • Step 47/48: See comment from other flow on requestingFsp and respondingFsp.
  • Step 60: Should probably be a deactivation here on MTN Rwanda.
  • Step 68: See comment from other flow about output message.

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

Thanks @mjbrichards,

Please find some minor comments for now:

  • Step 20 should probably say POST /quotes as in the note below between 20 and 21.
  • It seems like Blue FX is taking two fees for the conversion? One in the note between 23 and 24, and one between 32 and 33. The second one should probably just be the conversion of the first fee, but the text says "I will add a 75 XOF fee .."
  • Note between 39 and 40, the 5000 amount inside the transaction object should in XOF.
  • To avoid any possible changes for the FSPs in Mowali, could we have the relatedTransfer as a HTTP header instead for now, similar to what is said in the note between 20 and 21? As far as I can see our platform would not be affected by adding it to the body, but I can't say for other platforms.

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:

  • Completely correct. I've changed it.
  • What I intended was that the FXP should charge a fee (75 XOF/150 RWF) for the conversion, and that the payee DFSP should also charge a fee (100 XOF/200 RWF) for processing the transfer. So the first leg of the transfer will be for 5000 XOF and will have 75 XOF deducted from it. The amount less the deduction, converted into RWF, will be the amount sent in the second leg of the transfer (9850 RWF,) and the payee DFSP will receive that amount less the payee DFSP's deduction (9650 RWF.) The text in the note between 32 and 33 is another cut'n'paste disaster, and I have removed it.
  • Also correct. I have changed it.
  • While I appreciate your point about compatibility, I'm reluctant to put this information in the header. It seems to me that it definitely forms part of the message information rather than the ancillary information in the header, on the analogy of the transactionRequestId. However, I'm also happy to leave it in abeyance for the moment.

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

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 #89 (comment) and #89 (comment).

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

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:...

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

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

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?

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

Blue Bank Detailed FX transfer Version 2 - Payer conversion

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:

  • 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.
  • Note between step 29-30: "converter" is BLUE_BANK here, I guess this should be Blue_FX? Please note that this difference in names occurs in more places in the flow, so do a search and replace all if necessary.
  • Step 38: Instead of deriving an FX rate from source and target amounts, would it not be easier to have the FX rate instead of a target amount in the "conversionTerms" object? Because if you have the FX rate, you can easily calculate both the target amount and later also the fee in the Payer FSP currency without having to derive the FX rate which could potentially lead to issues.
  • Step 42: Instead of saying "your part", it is probably easier to understand if you write "the FX part" or similar, as using "your" requires that you know which party this will finally be sent to.
  • 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?
  • Step 49: Instead of "Confirmed", shouldn't this say "Reserved"?
  • Step 52: Instead of "Conversion succeeded", shouldn't this say "Conversion successfully reserved" or similar?
  • 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?
  • Note between step 62-63: Why does the Payee FSP need to know the details about the dependent transfer? In my view, only the FSP that actually requests the conversion should need to care about the details of the conversion, but again, there might be a very good reason for it..
  • Step 69: Move the "PATCH /fxTransfers/..." to the note between 69-70 instead to align with other notes.

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

  • 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. Done
  • Step 24-25: The note includes information about transaction object. I guess this is now moved to a later stage? It should say the quotation object. Fixed
  • 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. My thinking was that the FXP wouldn't care how the charge was recovered, and therefore there was no strong need to pass this information in...
  • Step 27: Text says signed transaction object, this should be a conversion object? Yes, done
  • 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.. The idea was that the dependent entry should show the amont that was being converted. The amount in the request for quotation itself is indeed 9850, because that's the amount the payee is being asked to quote for. I think it's logical, though I certainly concede that it's counter-intuitive...
  • Step 31: Text says 9850 XOF, should be RWF I guess? Entirely correct, as usual
  • 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.

Second set of comments:

  • 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.
  • Note between step 29-30: "converter" is BLUE_BANK here, I guess this should be Blue_FX? Please note that this difference in names occurs in more places in the flow, so do a search and replace all if necessary. Yep, done
  • Step 38: Instead of deriving an FX rate from source and target amounts, would it not be easier to have the FX rate instead of a target amount in the "conversionTerms" object? Because if you have the FX rate, you can easily calculate both the target amount and later also the fee in the Payer FSP currency without having to derive the FX rate which could potentially lead to issues.My thinking was: as we've already said, we should only fix two of the three values (source amount, target amount, rate). Since it's the amounts and not the rate which need to be fixed (and signed), it makes more sense to derive the rate from the two amounts than to derive one of the amounts from the rate. But I could be persuaded.
  • Step 42: Instead of saying "your part", it is probably easier to understand if you write "the FX part" or similar, as using "your" requires that you know which party this will finally be sent to. OK, done.
  • 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...
  • Step 49: Instead of "Confirmed", shouldn't this say "Reserved"? The conversion is confirmed in this step. The FXP is saying: you, Mr. Switch, may now decide if it succeeds or not...
  • Step 52: Instead of "Conversion succeeded", shouldn't this say "Conversion successfully reserved" or similar? Modified
  • 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.
  • Note between step 62-63: Why does the Payee FSP need to know the details about the dependent transfer? In my view, only the FSP that actually requests the conversion should need to care about the details of the conversion, but again, there might be a very good reason for it.. The payee FSP doesn't need to know; but the switch does, and non-repudiability insists that the message be transferred unmodified to the recipient, so the payee has to get all the information that the switch gets...
  • Step 69: Move the "PATCH /fxTransfers/..." to the note between 69-70 instead to align with other notes. Your wish is my command, O great one.

Revised version of the sequence diagram:

Blue Bank Detailed FX transfer Version 2 - Payer conversion

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 #13 but was never implemented in an actual solution.

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.

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 #89 (comment) 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:

  • Note between Step 20-21: Is there a reason for having both a conversionRequestId and a conversionId? I'm getting confused when which of these should be used, for example there are two conversionIds in POST /fxTransfers, and they are different (one is the conversionRequestId and the other is the conversionId from POST /fxQuotes..).
  • Note between Step 49-50: Shouldn't the PUT /fxTransfers/ callback include the expiration, so that it is clear for how long this reservation is valid?

Suggesting a call to further discuss the points above.

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:

  • Debtor DFSP: Please transfer these funds. Here's a verified currency conversion offer.
  • Creditor DFSP: I don't like that. Here's my currency conversion offer (verified, as you see.)
  • Debtor DFSP: Whatever. Let's just go ahead. OR:
  • Debtor DFSP: Well, I don't like yours. So let's just call the whole thing off.

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:

  • 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.
  • As I said above, I thought that the expiration wasn't needed for a PVP conversion, because the expiry of the conversion becomes the expiry of the transfer.

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.

@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?

@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 #25, which adds PartyType as part of the Party complex type.

With apologies for the delay, I attach a revised sequence diagram and API definition document which are intended to address the problem of privacy relating to currency conversion information, while still allowing the transfer information to contain sufficient information to allow the switch to record the correct obligations. The base idea is that the debtor and creditor FSPs maintain an optional list of one or more dependents. Each dependent is the creditor party in a part of the transfer, which will have been committed before the transfer as a whole is committed, but whose obligations are not finally recorded by the switch until the main transfer has completed. The dependent contains the condition and fulfilment which refer to the subsidiary task, and sufficient information to allow the switch correctly to record the obligations associated with all the subsidiary tasks as well as the main task itself.

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

FXNext Version 2 - Payer conversion

Thanks @MichaelJBRichards,

Comments including some follow up on earlier discussions, sorry if I'm repeating myself:

  • Why is dependents still part of the POST /quotes? The Payee FSP shouldn't care about the FX as the amount is already in the Payee FSP's currency, if the Payer FSP has already decided to use the FXP's service of performing the FX. As stated in earlier comments, the Payee FSP can't decide to offer any new terms in the quote callback, it can just either agree with an optional payeeFspFee, or reject the quote.
  • Why is the dependents part of POST /transfers? The FX transfer is already reserved in the POST /fxTransfers part (Step 42 to Step 53), it should just need to be committed. The condition and fulfillment for the FX transfer part should be enough for that?
  • Step 60 says "Let me check that the terms of the dependent transfer are the same as the ones I agreed to and that the fulfilment and condition match". Why would the Payee FSP care about the dependent transfer as long as it gets the correct amount? Payee FSP should just be interested in that it gets its 9850 RWF so that it can send the promised 9650 RWF to the Payee. How the Payer FSP converts XOF to RWF shouldn't be important for the Payee FSP.

By removing these two, you would remove potential business sensitive information containing the FX rate from the Payer FSP to the Payee FSP, while still allowing the message to be signed.

But surely both parties will always know the exchange rate, because the quote response contains both the send amount and the payee receive amount? And the sending customer needs to know both.

I still think that the currency conversion, whichever party executed it (and both might), needs to form part of the terms on which the payment was agreed; not least because one of our RESTful principles is that a message should contain all of the information which the recipient needs to act on it. This means, I think that the PUT /transfers message needs to contain all of the information that the switch will need to assign the values correctly to its ledgers. You will note that I have restricted the definition of a dependent to include only the participant and the amount; but these are, I think, necessary for the switch to be able correctly to distribute the obligations incurred as a consequence of the payment. So the payee institution will definitely need to know which FXP performed the conversion; and, since this is the case, I saw no good reason not to include the information in the terms of the payment.

But surely both parties will always know the exchange rate, because the quote response contains both the send amount and the payee receive amount? And the sending customer needs to know both.

No, the quote callback only contains the amounts in the Payee's currency (see note between Step 34 and 35 in your flow, where all amounts are in RWF). The Payer FSP already knows the currency conversion required from the POST /fxQuotes and its callback (see Steps 20 to 28), and can as such show the amounts in both currencies to the Payer in Step 39. The Payer FSP will then use POST /fxTransfers to perform the required conversion (see note between step 42 and 43). This way there is no need for the Payee FSP to know anything about if or how a currency conversion has been performed, perhaps the Payer FSP had an account in both currencies that could be used for the transfer.

I still think that the currency conversion, whichever party executed it (and both might), needs to form part of the terms on which the payment was agreed; not least because one of our RESTful principles is that a message should contain all of the information which the recipient needs to act on it.

We are not sending all information in all requests today. For example in the POST /transfers, we are relying on information that has earlier been agreed in the POST /quotes. We are not stating that we are fully RESTful compliant. Why is it necessary for the Payee FSP in the flow above to know that a currency conversion has been performed, as long as it receives the required funds in the correct currency in some way from the Payer FSP? Maybe there is some very important reason, but then I would like to understand it.

You will note that I have restricted the definition of a dependent to include only the participant and the amount; but these are, I think, necessary for the switch to be able correctly to distribute the obligations incurred as a consequence of the payment.

The Switch has already reserved the transfers related to the currency conversion in earlier steps (POST /fxTransfers and its related callback, Steps 42 to 53), now it just needs to commit what has earlier been reserved? Sending the same thing again in POST /transfers as in POST /fxTransfers would just introduce potential errors in my view. Minimizing the information in POST /transfers would also minimize the changes needed for existing implementers.

So the payee institution will definitely need to know which FXP performed the conversion; and, since this is the case, I saw no good reason not to include the information in the terms of the payment.

Is this necessary per transfer in the Payee FSP? What I as a Payee FSP is interested in per transfer is that I have received the funds from the Payer FSP in my account at the Switch in some way so that I can be assured that I can perform the transfer to my account holder. As a Payee FSP I don't really care about the internal accounting in the Switch, i.e. if there were some other participant in between, such as the FXP, that actually sent the funds to me. In the Switch it is vital information to keep track of the internal accounting. But in the integration between the Payer FSP and Payee FSP, I don't see it as required information. But maybe there are other principles in Mojaloop that requires this?

I like the fx flow above.
Doing the POST \fxQuote before the POST \transfers only works for the transfer amount type 'RECEIVE'.
To support receive transfer type presumably the POST \quotes would have to be called before the POST \fxQuote.
Maybe we should build another sequence diagram for that.

Thanks for your comments, @PaulGregoryBaker. I'm afraid we shan't be able to call quotes before we call fxQuotes, since the condition returned by fxQuotes forms part of the terms of the payment. Since this is the case, generation of a new condition in the process of re-quoting for currency conversion would invalidate the condition in the quote response for the transfer. In the case where the amountType was RECEIVE and the creditor party added fees, the debtor party would have to go round another quotation and approval cycle including the new conversion.

I've done some further thinking around the points raised by @henrka. Essentially, I think that reducing the information in the message to preserve the privacy of the conversion, as @henrka rightly proposes, implies further effort on the part of the switch. In previous incarnations, the burden on the switch (and especially the code changes required) were relatively light. I think that they are now more extensive, so I've included a separate document where I set out what I think they might be.

I've also revised the sequence diagram, and have aligned it with the latest state of the API document - in our various modifications it had got somewhat our of kilter. I attach all three documents, and await your comments with interest.

Converting dependencies to obligations.docx
API Candidate for currency conversion support in Mojaloop v2.4.docx
FXNext Version 2 4 - Payer conversion

Nice. There is a small error in the text description on 39.

FXNext Version 2 4 - Payee conversion

A version of the sequence diagram showing currency conversion being initiated by the creditor participant.

Thanks @MichaelJBRichards,

Please find my initial comments/questions on the new flow where the Payee FSP performs the currency conversion:

  • Minor layout issue, "Amanda" should be named "Mulenga Kapwepwe" instead according to the flow.
  • PUT /fxQuotes/ in note between Steps 29 and 30 should contain a validity field according to the Word document.
  • ilpPacket in note between Steps 35 and 36, shouldn't that be named transaction instead, as in note between Steps 42 and 43 for POST /transfers?
  • transferAmount in note between Steps 35 and 36 should use currency MWK, not MWS.
  • I don't know if I have already asked this before, but why are dependent transfers identified by their condition instead of their correlation ID? I guess there is a good reason for this?
  • Minor layout detail, the Payee FSP named Zoona seems to incorrectly activated around Step 37.
  • The payeeFspFee should preferably be in Payer FSP's currency (MWK), as the Payer FSP in this case wouldn't like to deal with the Payee's currency (ZMW). In Step 39-40 the fee of 5 ZMW is magically converted to 250 MWK, without the Payer FSP knowing the FX rate.
  • The transaction object (that is called ilpPacket in POST /quotes, see earlier comment) differs between PUT /quotes and POST /transfers, this should be the same.
  • In Steps 44-45, shouldn't there be some logic in the Mojaloop Switch to handle the Payee FSP's currency, stating that the Payee FSP doesn't have an account in MWK and that the dependent transfer needs to be executed by the Payee FSP for the transfer to be reserved?
  • In note between Steps 49 and 50, the targetAmount is different from the targetAmount in PUT /fxQuotes/, which is a bit confusing logic (3 ZMW in charges has been withdrawn). To me, the logical thing would be to have the same targetAmount, but also including the same charges as before.
  • In note between 53 and 54, shouldn't there be a reservation for Zoona in ZMW in the Switch as well, as they want to perform the currency conversion? The reservation for Zoona doesn't seem to be showed in the flow anywhere..
  • If the conversion failed in Steps 59-60, the FXP should also be informed of the failure using a PATCH notification (PATCH /fxTransfers/...)?

Thank you, @henrka , for your usual careful review. I have been doing some refactoring in order to align the FX API more closely with the way in which I would expect the ISO 20022 version of the FX API to work, and I will describe that later; but I will start, as usual, by commenting on your comments:

  • Amanda, I am happy to report, has left the building
  • Typos in points, 2, 3, 4, 6, 8 fixed
  • Point 5 superseded by refactoring - see below
  • Point 7: you're right, fixed
  • Point 9: added functionality in switch
  • Point 10: have changed this round to allow correct calculation of the exchange rate.
  • Point 11: there is no reservation against Zoona because a) they don't have an MWK account and b) their request for currency conversion is funded by the funds to be received from NBS, so they are not net debtors in the transfer.
  • Yes, this would ordinarily be the case; except that the failure at 59-60 is initiated by the FXP...

When I started thinking about how we might represent currency conversions in ISO 20022, it seemed to me that we wanted to make the content of the currency conversion endpoints as close as we could to the ordinary payment endpoints. So a currency conversion execution would be strongly analogous to an ordinary payment execution. The main obstacle to this seemed to me to be the dependents structure. I therefore propose that we should replace the dependents structure, in which the payment contains all the information about the subordinates (such as the conversion), with an additional field in the subordinate which links it to the master payment, using the master payment's transaction ID. This would, I think, achieve the same effect but with greater simplicity for the data structures (and it removes your reservation about using the condition...) I have produced a new version of the draft API specification incorporating this idea, and attach it, together with a new sequence diagram which shows the flow for a payment where conversion is done by the payee, but the amount is a RECEIVE amount (i.e. something like a merchant payment.) Let me know what you think.

API Candidate for currency conversion support in Mojaloop v2.6.docx
FXNext Version 2 6 - Payee conversion with RECEIVE amount

Thanks @MichaelJBRichards,

The changed flow without dependents is better! Please find my comments as usual (now with numbers instead to make it easier to relate to which one it is):

  1. Step 8: As per our recent discussion in Slack to allow the Payee FSP to know the Payer's currency in case the Payee FSP should perform the currency conversion, it would make sense to change receiveCurrencies to supportedCurrencies, or just currencies instead. The currency information of the Payer would then be sent as part of the Party information in the POST /quotes in Step 13.
  2. Step 13: See above to include Upile's currency.
  3. Step 17: The currency that Upile is using would need to be known at this step (see comments above)
  4. Note between 25 and 26: The amountType is SEND here, I would believe that is a copy-paste error and it should be RECEIVE?
  5. Note between 25 and 26: Could we remove the conversion type, and have its parameters on the root level of POST /fxQuotes instead? The conversion type doesn't seem to be reused, so I don't know if there is a need to have a specific type for it? This would make the PUT /quotes more similar to data models for other requests in the FSPIOP API.
  6. Note between 25 and 26: Is there a need for both the conversionRequestId and conversionId ? Neither seems to be reused outside of the scope of the POST/PUT /fxQuotes.
  7. Note between 29 and 30: I suspect you have read too many ISO specs now when you are abbreviating transaction in governingTx :). POST /fxTransfers seems to use relatedTransactionId, can we please change to that or governingTransaction or similar? Also related to governingTx, how does FDH FX know the transaction ID, it is not sent in the POST /fxQuotes?
  8. Note between 29 and 30: Could we remove the conversionTerms type, and have its parameters on the root level of PUT /fxQuotes instead? The conversionTerms type doesn't seem to be reused, so I don't know if there is a need to have a specific type for it? This would make the PUT /fxQuotes more similar to data models for other requests in the FSPIOP API.
  9. Step 34, The text "OK, so I will charge 2 ZMW for this" would be easier to follow if it said something like "OK, I will add 2 ZMW on top of the conversion fee".
  10. Note between 35 and 36: The Transaction type (at least in current version) doesn't contain a payeeReceiveAmount, is this something that should be added or is the payeeReceiveAmount in the PUT /quotes enough?
  11. Step 39: This should be 250 MWK instead of 5 ZMW.
  12. Step 40: Mulenga will receive 100 ZMW according to the payeeReceiveAmount.
  13. Note between 42 and 43: See earlier comment on payeeReceiveAmount in Transaction type.
  14. Note between 49 and 50: relatedTransactionId, is this same as the earlier governingTx? Can we stick to one?
  15. Note between 49 and 50: The key to perform the FX Quote, wouldn't it be more logical for the FXP to use the ID of the FX Quote instead of the ID of the transaction (relatedTransactionId)? For the Switch the transaction ID is probably more important, but for the FXP the FX Quote should be the important key, so for me it would be logical to include both.
  16. Step 52: "Does the sender have an account in this currency?" Which one of the currencies? :)

New version of the FX functionality, which now supports conversion via a reference currency. The basic thinking behind this is:

  • The debtor DFSP asks the creditor DFSP to perform currency conversion between the source and target currencies in the normal way.
  • The creditor DFSP asks an FXP (FXPA) to provide currency conversion between the source and target currencies.
  • The FXP knows that it can provide conversion between a reference currency and the target currency. It modifies the proposed conversion to propose conversion between a reference currency and the target currency.
  • The creditor DFSP accepts this, and modifies the proposed transfer to use the reference currency. It signs the modified transfer terms.
  • The debtor DFSP recognises that it can't provide funds in the reference currency. It asks an FXP (FXPB) to provide conversion between the source currency and the reference currency. Note that this does not require any revision to the terms of the transfer.
  • The debtor DFSP requests execution of the initial currency conversion from the source currency to the reference currency. It gives the transfer ID as the transfer on whose success it depends. Funds are reserved in the source currency against the debtor DFSP.
  • The debtor DFSP requests execution of the transfer. Funds are reserved against FXPB in the reference currency.
  • The creditor DFSP requests execution of the conversion from the reference currency to the target currency. It gives the transfer ID as the transfer on whose success it depends. Funds are reserved in the reference currency against FXPA.
  • The creditor DFSP confirms the success of the transfer. Obligations are recorded for all parties by the switch:
    • Debit the debtor DFSP and credit FXPB in the source currency
    • Debit FXPB and credit FXPA in the reference currency
    • Debit FXPA and credit the creditor DFSP in the target currency

I attach the revised draft API and a sequence diagram illustrating this. Any comments you might have would be most welcome.
API Candidate for currency conversion support in Mojaloop v2.7.docx
FXNext Version 2 6 - Conversion via a reference currency with RECEIVE amount

My comments on your comments on the previous version of the sequence diagram:

  • 1, 2, 3, 4: fixed.
  • 5 and 8: I kind of like the idea of a conversion object, which I think of as containing the terms of the conversion in the same way as the transaction object contains the terms of the transfer. But I wouldn't die for it...
  • 6, 7, 9: fixed.
  • 10, 13: You are correct; I propose adding it to the transaction object in Section 7.1.3 of the API candidate.
  • 11, 12: fixed
  • 14: all instances now changed to determiningTransactionId
  • 15: I had thought to use the condition as the key for the FXP to recognise the terms it was being asked to execute: please execute the conversion for which these are the signed terms. But I'm open to persuasion.
  • 16: fixed

I also made a couple of adjustments so that the creditor DFSP asks for its fee to be converted. This means that in the execution of the conversion the sums come out right...

In a belated attempt to make this issue easier for all of us, I have uploaded current versions of the documentation to our own repo in GitHub.

I attach the revised draft API and a sequence diagram illustrating this. Any comments you might have would be most welcome. API Candidate for currency conversion support in Mojaloop v2.7.docx FXNext Version 2 6 - Conversion via a reference currency with RECEIVE amount

Just some review comments:

  1. step 13, the POST /quotes has a typo suppoertedCurrencies -> suppoertedCurroencies
  2. step 62, this should go to the Payer FSP
  3. step 83, this should go to the Payer FSP
  4. step 84, this should go from Payer FSP back to the switch

@MichaelJBRichards FYI

My comments on your comments on the previous version of the sequence diagram:

  • 1, 2, 3, 4: fixed.
  • 5 and 8: I kind of like the idea of a conversion object, which I think of as containing the terms of the conversion in the same way as the transaction object contains the terms of the transfer. But I wouldn't die for it...
  • 6, 7, 9: fixed.
  • 10, 13: You are correct; I propose adding it to the transaction object in Section 7.1.3 of the API candidate.
  • 11, 12: fixed
  • 14: all instances now changed to determiningTransactionId
  • 15: I had thought to use the condition as the key for the FXP to recognise the terms it was being asked to execute: please execute the conversion for which these are the signed terms. But I'm open to persuasion.
  • 16: fixed

I also made a couple of adjustments so that the creditor DFSP asks for its fee to be converted. This means that in the execution of the conversion the sums come out right...

In a belated attempt to make this issue easier for all of us, I have uploaded current versions of the documentation to our own repo in GitHub.

Thanks @MichaelJBRichards,

Follow up on comments

  • 5 and 8: Even if it is on the root level, you could still refer to it as the conversion object, for example "The FX conversion as specified in the POST /fxQuotes".. The transaction is a separate type because it is reused in different messages. I would at least vote for having it on the root level to align with other similar APIs in FSPIOP API :)
  • 10 and 13: The payeeReceiveAmount will then be duplicated and sent both in root level of PUT /quotes and in the transaction object. If we are moving away from ILP1 and the ASN1 encoded ILP packet, then we could probably remove it from the root level to avoid duplication if it is required in the transaction object instead, as this should be easily read directly in the JSON instead of in ASN1 encoded ILP packet.. Let's discuss.
  • 15: I guess it should be consistent with POST /transfers to use condition, so I should be fine with how it is proposed.

Comments on the new flow in https://github.com/mojaloop/Currency-conversion/blob/main/FXNext%20Version%202.7%20-%20Payee%20conversion%20with%20RECEIVE%20amount.svg

  1. Note between step 46 and 47: How does the Switch here know that FDH_FX will be involved? Shouldn't it be NBS Bank (the Payer FSP) that the funds are reserved for? This seems to be corrected in note between 55 and 56, so probably just a typo..
  2. Step 62 and 65 both goes to Payee FSP. Shouldn't step 62 be a PATCH /fxTransfer with transferState=ABORTED to the FXP, to inform that the FX transfer was aborted due to the fulfillment mismatch?
  3. Step 72: NBS should probably be deactivated in the PlantUML code here...
  4. Step 76: Should we add Mulenga Kapwepwe as an actor that is actually receiving the 100 ZMW here, just for clarity?

Comments on the new flow in https://github.com/mojaloop/Currency-conversion/blob/main/FXNext%20Version%202.7%20-%20Payer%20conversion.svg

  1. Note between step 29 and 30: Following up on earlier discussions, I don't really understand why the Payer FSP should share their fees (the "charges") to do the FX conversion to the Payee FSP, this should be none of the Payee FSP business. The charges doesn't seem to be used by either the Switch or the Payee FSP. Shouldn't this instead contain a "converter": "PAYER" to inform that the Payer FSP has performed a currency conversion? This information is part of the PUT /quotes, so I guess this is just missed to be updated?
  2. Step 38: Currency should be MWK, not MWF.
  3. Step 52: If fulfillment doesn't match then the FXP should probably be informed of the same via a PATCH /fxTransfer with transferState=ABORTED.
  4. Note between 57 and 58: Should there be information in the POST /transfers that there is a dependent FX transfer, or will the Switch check in its database for each transfer if there is a dependent transfer?
  5. Step 65: Should we add Mulenga Kapwepwe as an actor that is actually receiving the 95 ZMW here, just for clarity?

Thanks very much for your comments, @henrka and @mdebarros .

On the sequence diagrams:

Conversion by the payee

  1. Editing failure. Fixed
  2. I think it should be added. Now have notification for both FXP and Payee DFSP.
  3. Done
  4. Good plan. Added her

Conversion by the payer

  1. Agree. Removed
  2. Done
  3. Again, added notification for FXP
  4. As you say, the intention is that the switch should check to see if there are any other transfers which depend on the transfer it is processing. I thought that this was a simpler way of structuring things.
  5. Added Mulengwa

Reference currency (per MdB)

  1. Fixed
  2. Fixed
  3. Fixed
  4. Fixed

I will upload new copies of the sequence diagrams to the repository, together with a copy of the new draft of the API and some further sequence diagrams.

I had a closer look at the optional converter field, and realised that it was no required for the reference currency flow that I was concerned about.
I no longer have any concerns.

Also, just adding a comment from todays CCB discussion:

Raised issue on the implementation of the FX specification, specifically that Transfer prepare processing will ALWAYS have to check if there is an associated fxTransfers using the transactionId from the transaction-object.

As discussed this would be resolved in two ways:

  1. The transaction-object will include the converter fields - if they are available in the transaction-object, it will signify that there is an fxTransfer
  2. There is another proposal to include the transact-object as part of the transfers, so no additional look-ups would be required to attain the converter fields and the transactionId

@MichaelJBRichards please review the above comment, and let me know if we require any corrections.

I have uploaded a revised version of the candidate API document (MD version, natch) to the repository. It addresses comments made by Vijay in his review of the document.

Hmm… one of the original design principles separates the transaction logic from the simple transfer of money. I’m reluctant to start down the slippery slope of consulting the transaction details from the transfer logic. Should it be possible to encode the currency and fx details that are relevant for transfer as instructions to the clearing engine (in the transfer object)? We should not pierce the veil of the transaction object from within the clearing engine.

In this case there are two (or possibly even three) transaction objects. Well, one (or possibly two) of those are Conversion objects, which are the FX version of a transaction object. The set of objects are available to the switch in the same way as the transaction object is; and the switch checks that all the objects have been received and the associated requests approved before it finalises the payment and records all the obligations. So I don't think that there is a requirement to pierce the veil of the transaction object: it's just that this is a dance of the two (or possibly three) veils.

The concept of a Transfer Set seems natural and obvious to me. If the set of related transfers (including the conversions and local transfers) are organized into a set object with deterministic processing rules we build on the Interledger guarantees. That suggests all-or-none, two-phase clearing and commit across the set, but should not necessarily require ordering of transfers.

And I am happy to report that I think that's just what our proposed switch processing does. I would look forward to explaining how at the convening, but Cici wants to go big on cross-scheme currency conversion scenarios (and I, of course, concur). However, I am available to give, for a small fee, my famed explanation in which transfers are semi-convincingly played by beer bottles.

I am all for prototypes using read-at-hand materials, especially when beer is involved.