Skip to content

Commit

Permalink
Clean up min/max adjustments (#873)
Browse files Browse the repository at this point in the history
  • Loading branch information
FredKSchott authored and intelliot committed Mar 22, 2018
1 parent 3f22b12 commit 43c08e5
Showing 1 changed file with 33 additions and 16 deletions.
49 changes: 33 additions & 16 deletions src/transaction/payment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {Amount, Adjustment, MaxAdjustment,
MinAdjustment, Memo} from '../common/types/objects'


export type Payment = {
export interface Payment {
source: Adjustment | MaxAdjustment,
destination: Adjustment | MinAdjustment,
paths?: string,
Expand All @@ -30,11 +30,22 @@ import {Amount, Adjustment, MaxAdjustment,
limitQuality?: boolean
}

function isMaxAdjustment(
source: Adjustment | MaxAdjustment): source is MaxAdjustment {
return (source as MaxAdjustment).maxAmount !== undefined
}

function isMinAdjustment(
destination: Adjustment | MinAdjustment): destination is MinAdjustment {
return (destination as MinAdjustment).minAmount !== undefined
}

function isXRPToXRPPayment(payment: Payment): boolean {
const sourceCurrency = _.get(payment, 'source.maxAmount.currency',
_.get(payment, 'source.amount.currency'))
const destinationCurrency = _.get(payment, 'destination.amount.currency',
_.get(payment, 'destination.minAmount.currency'))
const {source, destination} = payment
const sourceCurrency = isMaxAdjustment(source)
? source.maxAmount.currency : source.amount.currency
const destinationCurrency = isMinAdjustment(destination)
? destination.minAmount.currency : destination.amount.currency
return sourceCurrency === 'XRP' && destinationCurrency === 'XRP'
}

Expand Down Expand Up @@ -74,21 +85,29 @@ function createPaymentTransaction(address: string, paymentArgument: Payment
throw new ValidationError('address must match payment.source.address')
}

if (((<MaxAdjustment>payment.source).maxAmount && (<MinAdjustment>payment.destination).minAmount) ||
((<Adjustment>payment.source).amount && (<Adjustment>payment.destination).amount)) {
if (
(isMaxAdjustment(payment.source) && isMinAdjustment(payment.destination))
||
(!isMaxAdjustment(payment.source) && !isMinAdjustment(payment.destination))
) {
throw new ValidationError('payment must specify either (source.maxAmount '
+ 'and destination.amount) or (source.amount and destination.minAmount)')
}

const destinationAmount = isMinAdjustment(payment.destination)
? payment.destination.minAmount : payment.destination.amount
const sourceAmount = isMaxAdjustment(payment.source)
? payment.source.maxAmount : payment.source.amount

// when using destination.minAmount, rippled still requires that we set
// a destination amount in addition to DeliverMin. the destination amount
// is interpreted as the maximum amount to send. we want to be sure to
// send the whole source amount, so we set the destination amount to the
// maximum possible amount. otherwise it's possible that the destination
// cap could be hit before the source cap.
const amount = (<MinAdjustment>payment.destination).minAmount && !isXRPToXRPPayment(payment) ?
createMaximalAmount((<MinAdjustment>payment.destination).minAmount) :
((<Adjustment>payment.destination).amount || (<MinAdjustment>payment.destination).minAmount)
const amount =
(isMinAdjustment(payment.destination) && !isXRPToXRPPayment(payment))
? createMaximalAmount(destinationAmount) : destinationAmount

const txJSON: any = {
TransactionType: 'Payment',
Expand Down Expand Up @@ -121,16 +140,14 @@ function createPaymentTransaction(address: string, paymentArgument: Payment
// temREDUNDANT_SEND_MAX removed in:
// https://github.com/ripple/rippled/commit/
// c522ffa6db2648f1d8a987843e7feabf1a0b7de8/
if (payment.allowPartialPayment === true
|| (<MinAdjustment>payment.destination).minAmount !== undefined) {
if (payment.allowPartialPayment || isMinAdjustment(payment.destination)) {
txJSON.Flags |= paymentFlags.PartialPayment
}

txJSON.SendMax = toRippledAmount(
(<MaxAdjustment>payment.source).maxAmount || (<Adjustment>payment.source).amount)
txJSON.SendMax = toRippledAmount(sourceAmount)

if ((<MinAdjustment>payment.destination).minAmount !== undefined) {
txJSON.DeliverMin = toRippledAmount((<MinAdjustment>payment.destination).minAmount)
if (isMinAdjustment(payment.destination)) {
txJSON.DeliverMin = toRippledAmount(destinationAmount)
}

if (payment.paths !== undefined) {
Expand Down

0 comments on commit 43c08e5

Please sign in to comment.