Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

more clean up for min/max adjustments #873

Merged
merged 5 commits into from
Mar 22, 2018

Conversation

FredKSchott
Copy link
Contributor

@FredKSchott FredKSchott commented Mar 20, 2018

Builds on top of #870, should be okay to merge after that PR is merged in. #870 merged in, this is ready to review/merge.

Uses some TS magic to make type checking easier, and also consolidates some destination/source amount logic to reduce repeated code.

darkmemo and others added 3 commits March 19, 2018 10:52
Payment `source` and `destination` are defined as intersection types,  `Adjustment & MaxAdjustment` and  `Adjustment & MinAdjustment` respectively. But they should be union types instead. This problem was introduced during js to ts conversion.
@@ -30,11 +30,22 @@ import {Amount, Adjustment, MaxAdjustment,
limitQuality?: boolean
}

function isMaxAdjustment(
source: Adjustment | MaxAdjustment): source is MaxAdjustment {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: why is this on a new line?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

exceeds 80 character max, enforced by our linting config :/

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I see. Looks strange to me cause I'm used to the "standard" style

@@ -9,7 +9,7 @@ import {Amount, Adjustment, MaxAdjustment,
MinAdjustment, Memo} from '../common/types/objects'


export type Payment = {
export type Payment = {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be an interface rather than a type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

+1, I can change that here

Copy link
Collaborator

@intelliot intelliot left a comment

Choose a reason for hiding this comment

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

This looks right. To understand what's going on, I read the User-Defined Type Guards section from the TypeScript docs:

http://www.typescriptlang.org/docs/handbook/advanced-types.html

@sublimator
Copy link
Contributor

Worth considering if the test suite should be converted to TypeScript as well?

To handle cases like the following where accidentally specifying multiple properties:

const source = {
  address: fromAddress,
  maxAmount: {value: amount, currency: "XRP"},
  amount: {value: amount, currency: "XRP"}
};
const destination = {
  address: toAddress,
  amount: {value: amount, currency: "XRP"},
};

You can use optional fields, specified as undefined:

export interface Adjustment {
    address: string;
    amount: Amount;
    maxAmount?: undefined;
    minAmount?: undefined;
    tag?: number;
};
export interface MaxAdjustment  {
    address: string;
    amount?: undefined;
    maxAmount: Amount;
    tag?: number;
};
export interface MinAdjustment {
    address: string;
    amount?: undefined;
    minAmount: Amount;
    tag?: number;
};

Which yields:

      Type '{ address: string; amount: { value: string; currency: string; }; maxAmount: { value: string; curr...' is not assignable to type 'MaxAdjustment'.
        Types of property 'amount' are incompatible.
          Type '{ value: string; currency: string; }' is not assignable to type 'undefined'.

See also: now recommended that you just use "as foo" for consistency
image

@sublimator
Copy link
Contributor

You can also do:

export declare type Payment = {
    paths?: string;
    memos?: Array<Memo>;
    invoiceID?: string;
    allowPartialPayment?: boolean;
    noDirectRipple?: boolean;
    limitQuality?: boolean;
} & ({
  source: Adjustment;
  destination: MinAdjustment;
} | {
  source: MaxAdjustment;
  destination: Adjustment;
} | {
    source: Adjustment,
    destination: Adjustment
});

Though the error messages are gonna be for C++ fans :)

@sublimator
Copy link
Contributor

@sublimator
Copy link
Contributor

You could even use the typescript compiler programmatically, and add test cases of strings which should work or fail ...

@intelliot
Copy link
Collaborator

How does a3ae796 look?

@sublimator
Copy link
Contributor

Beginnings of TypeScript tests to build upon: sublimator@28e172a

@FredKSchott
Copy link
Contributor Author

FredKSchott commented Mar 22, 2018

+1 for converting the tests to TS as well (in a separate PR)


@intelliot 👍 looks good!


@sublimator judging by the code, it sounds like {source: Adjustment, destination: Adjustment} isn't actually valid either, which would simplify your example above 👌

If this function was user-facing I think your more complex but most strict type definition would be worth the gross error messages. But since it wouldn't simplify the createPaymentTransaction() implementation (I don't think?) and the user never actually interacts with this type directly, I'm inclined to value the more simple definition.

@intelliot intelliot merged commit 43c08e5 into XRPLF:develop Mar 22, 2018
@sublimator
Copy link
Contributor

it sounds like {source: Adjustment, destination: Adjustment} isn't actually valid either, which would simplify your example above 👌

@FredKSchott

I never use this library, just happened to be chatting to @intelliot on Google chat recently and this issue came up. This lib gives me headaches having to mentally map back and forth between ripple terms. But why wouldn't it be a valid combination? Are you just going by the error message I linked?

What about: https://github.com/ripple/ripple-lib/blob/develop/src/transaction/payment.ts#L98-L100

?

the user never actually interacts with this type directly
this type = Payment ?

api.preparePayment ?

Though the error messages are gonna be for C++ fans :)

^^^
lol, I don't think I was seriously suggesting it :)

@FredKSchott FredKSchott deleted the min-max-adjustments branch March 27, 2018 17:10
@FredKSchott
Copy link
Contributor Author

api.preparePayment

Whoops, of course! Okay, well then I could definitely see the more strict type being useful, if it could catch bad user input before runtime.

Why wouldn't it be a valid combination?

I was going by this validation check in the source code itself: https://github.com/ripple/ripple-lib/blob/develop/src/transaction/payment.ts#L91, which throws a ValidationError if that's encountered.

This lib gives me headaches having to mentally map back and forth between ripple terms.

Agreed! The work we've been doing since way back in November has been to move us towards a world where ripple-lib uses the exact same concepts/terms/types/commands you're already using with rippled.

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.

5 participants