Skip to content

Conversation

@yomarion
Copy link
Contributor

@yomarion yomarion commented Nov 2, 2022

Description of the changes

In order to type strongly the Payment Network creation parameters, I had to change the way we declare Payment Network IDs.
This highlighted a few type mistakes, potentially runtime mistakes, for example for the type of from (cf. comments).

This strong typing would have avoided the mistake fixed by this previous change.

chore: enforce the typing of creation parameters with the type PaymentNetworkCreateParameters
chore: deprecate the IPaymentNetworkCreateParameters interface
chore: remove enum PaymentTypes.PAYMENT_NETWORK_ID
chore: created enums ExtensionTypes.OTHER_ID and ExtensionTypes.PAYMENT_NETWORK_ID, ExtensionTypes.ID is defined by their union

Note for validators

Most changes are automatic replacements as explained below.
The main changes are highlighted by comments.

(Type) Breaking change and notice

This change is type-breaking but not runtime-breaking, as the enum values are the same.
For uses of PaymentTypes.PAYMENT_NETWORK_ID.<SOME_ID>, they can be easily replaced with ExtensionTypes.PAYMENT_NETWORK_ID.<SOME_ID>, except for DECLARATIVE and ANY_TO_NATIVE that are named ANY_DECLARATIVE and ANY_TO_NATIVE_TOKEN.
(example 1 and example 2)

References to ExtensionTypes.ID.PAYMENT_NETWORK_<SOME_ID> should be replaced with ExtensionTypes.PAYMENT_NETWORK_ID.<SOME_ID>.
(example)

References to IPaymentNetworkCreateParameters interface should be replaced with PaymentNetworkCreateParameters type.

export abstract class AnyToAnyDetector<
TExtension extends ExtensionTypes.PnFeeReferenceBased.IFeeReferenceBased,
TPaymentEventParameters,
TPaymentEventParameters extends Partial<ExtensionTypes.PnFeeReferenceBased.IAddFeeParameters>,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an example of a hidden mistyping that cannot be missed anymore.

export abstract class AnyToNativeDetector extends AnyToAnyDetector<
ExtensionTypes.PnAnyToEth.IAnyToEth,
PaymentTypes.IETHPaymentEventParameters
PaymentTypes.IETHFeePaymentEventParameters
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an example of a hidden mistyping that cannot be missed anymore.

export abstract class DeclarativePaymentDetectorBase<
TExtension extends ExtensionTypes.PnAnyDeclarative.IAnyDeclarative,
TPaymentEventParameters extends PaymentTypes.IDeclarativePaymentEventParameters,
TPaymentEventParameters extends PaymentTypes.IDeclarativePaymentEventParameters<unknown>,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an example of a hidden mistyping that cannot be missed anymore.
More specifically, Declarative payment events are at the root of many detectors, but when events are declarative for real, they use IIdentity type for from, whereas it's string for overriding children (when it's not declarative)

export abstract class FeeReferenceBasedDetector<
TExtension extends ExtensionTypes.PnFeeReferenceBased.IFeeReferenceBased,
TPaymentEventParameters extends { feeAmount?: string; feeAddress?: string },
TPaymentEventParameters extends PaymentTypes.IDeclarativePaymentEventParameters<string> & {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an example of a hidden mistyping that cannot be missed anymore.

requestInfo: RequestLogic.ICreateParameters | IRequestInfo;
signer: Identity.IIdentity;
paymentNetwork?: Payment.IPaymentNetworkCreateParameters;
paymentNetwork?: Payment.PaymentNetworkCreateParameters;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main change: from interface to type

PAYMENT_NETWORK_ANY_TO_ETH_PROXY = 'pn-any-to-eth-proxy',
}

export enum PAYMENT_NETWORK_ID {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strong impact required for the main change: instead of mapping a new enum out of ID to qualify payment network IDs, we now have 2 enums.

parameters: T;
}

export type PaymentNetworkCreateParameters =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main change. We strongly type creation parameters based on the different payment networks.

};

/** Payment network IDs with known Create Parameters */
export type PAYMENT_NETWORK_ID = PaymentNetworkCreateParameters['id'];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not an enum anymore, and is probably useless outside PaymentTypes.


/** Parameters for events of Declarative payments */
export interface IDeclarativePaymentEventParameters {
export interface IDeclarativePaymentEventParameters<TFrom = IIdentity> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(cf. other comment about this interface) Declarative payment events are at the root of many detectors, but when events are declarative for real, they use IIdentity type for from, whereas it's string for overriding children (when it's not declarative)

}
/** Parameters for events of ERC777 payments */
export interface IERC777PaymentEventParameters {
export interface IERC777PaymentEventParameters extends GenericEventParameters {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side-improvement. (and a few other similare replacements)

for (const pn in PaymentTypes.PAYMENT_NETWORK_ID) {
if (PaymentTypes.PAYMENT_NETWORK_ID[pn] === value) {
export function isPaymentNetworkId(value: any): value is ExtensionTypes.PAYMENT_NETWORK_ID {
for (const pn of enumKeys(ExtensionTypes.PAYMENT_NETWORK_ID)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old trick was not working anymore

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if isPaymentNetworkId is still necessary. It seems to be there to account for the possibility of the ID not being a payment network ID, but now we have a strong type to enforce it?

btw, you could also do Object.values(ExtensionTypes.PAYMENT_NETWORK_ID).includes(value)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, it should probably be removed or at least accept only ID values.

@yomarion yomarion marked this pull request as ready for review November 3, 2022 07:33
Copy link
Contributor

@benjlevesque benjlevesque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great change 👏

for (const pn in PaymentTypes.PAYMENT_NETWORK_ID) {
if (PaymentTypes.PAYMENT_NETWORK_ID[pn] === value) {
export function isPaymentNetworkId(value: any): value is ExtensionTypes.PAYMENT_NETWORK_ID {
for (const pn of enumKeys(ExtensionTypes.PAYMENT_NETWORK_ID)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if isPaymentNetworkId is still necessary. It seems to be there to account for the possibility of the ID not being a payment network ID, but now we have a strong type to enforce it?

btw, you could also do Object.values(ExtensionTypes.PAYMENT_NETWORK_ID).includes(value)

}

/** Interface to create a payment network */
export interface IPaymentNetworkCreateParameters<T = any> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we still need the default any?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have actually deprecated this interface in the meantime @benjlevesque

Copy link
Contributor

@alexandre-abrioux alexandre-abrioux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I remember wanting to do something like this in my previous refactor but refrained as it was already too many changes 🤩 Awesome!

Copy link
Contributor

@olivier7delf olivier7delf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great job!

@coveralls
Copy link

coveralls commented Nov 3, 2022

Coverage Status

Coverage decreased (-0.02%) to 88.896% when pulling d0107e5 on chore/refactor-pn-ids-ble into abc53c7 on master.

@yomarion yomarion merged commit 796d3f4 into master Nov 3, 2022
@yomarion yomarion deleted the chore/refactor-pn-ids-ble branch November 3, 2022 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants