You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

payment.js 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
  5. }) : (function(o, m, k, k2) {
  6. if (k2 === undefined) k2 = k;
  7. o[k2] = m[k];
  8. }));
  9. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  10. Object.defineProperty(o, "default", { enumerable: true, value: v });
  11. }) : function(o, v) {
  12. o["default"] = v;
  13. });
  14. var __importStar = (this && this.__importStar) || function (mod) {
  15. if (mod && mod.__esModule) return mod;
  16. var result = {};
  17. if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  18. __setModuleDefault(result, mod);
  19. return result;
  20. };
  21. Object.defineProperty(exports, "__esModule", { value: true });
  22. const _ = __importStar(require("lodash"));
  23. const utils = __importStar(require("./utils"));
  24. const validate = utils.common.validate;
  25. const paymentFlags = utils.common.txFlags.Payment;
  26. const ValidationError = utils.common.errors.ValidationError;
  27. const common_1 = require("../common");
  28. const utils_1 = require("./utils");
  29. function isMaxAdjustment(source) {
  30. return source.maxAmount != null;
  31. }
  32. function isMinAdjustment(destination) {
  33. return destination.minAmount != null;
  34. }
  35. function isXRPToXRPPayment(payment) {
  36. const { source, destination } = payment;
  37. const sourceCurrency = isMaxAdjustment(source)
  38. ? source.maxAmount.currency
  39. : source.amount.currency;
  40. const destinationCurrency = isMinAdjustment(destination)
  41. ? destination.minAmount.currency
  42. : destination.amount.currency;
  43. return ((sourceCurrency === 'XRP' || sourceCurrency === 'drops') &&
  44. (destinationCurrency === 'XRP' || destinationCurrency === 'drops'));
  45. }
  46. function isIOUWithoutCounterparty(amount) {
  47. return (amount &&
  48. amount.currency !== 'XRP' &&
  49. amount.currency !== 'drops' &&
  50. amount.counterparty == null);
  51. }
  52. function applyAnyCounterpartyEncoding(payment) {
  53. [payment.source, payment.destination].forEach((adjustment) => {
  54. ['amount', 'minAmount', 'maxAmount'].forEach((key) => {
  55. if (isIOUWithoutCounterparty(adjustment[key])) {
  56. adjustment[key].counterparty = adjustment.address;
  57. }
  58. });
  59. });
  60. }
  61. function createMaximalAmount(amount) {
  62. const maxXRPValue = '100000000000';
  63. const maxIOUValue = '999999999999999900000000000000000000000000000000000000000000000000000000000000000000000000000000';
  64. let maxValue;
  65. if (amount.currency === 'XRP') {
  66. maxValue = maxXRPValue;
  67. }
  68. else if (amount.currency === 'drops') {
  69. maxValue = common_1.xrpToDrops(maxXRPValue);
  70. }
  71. else {
  72. maxValue = maxIOUValue;
  73. }
  74. return Object.assign({}, amount, { value: maxValue });
  75. }
  76. function validateAndNormalizeAddress(address, expectedTag) {
  77. const classicAddress = utils_1.getClassicAccountAndTag(address, expectedTag);
  78. classicAddress.tag =
  79. classicAddress.tag === false ? undefined : classicAddress.tag;
  80. return classicAddress;
  81. }
  82. function createPaymentTransaction(address, paymentArgument) {
  83. const payment = _.cloneDeep(paymentArgument);
  84. applyAnyCounterpartyEncoding(payment);
  85. const sourceAddressAndTag = validateAndNormalizeAddress(payment.source.address, payment.source.tag);
  86. const addressToVerifyAgainst = validateAndNormalizeAddress(address, undefined);
  87. if (addressToVerifyAgainst.classicAccount !== sourceAddressAndTag.classicAccount) {
  88. throw new ValidationError('address must match payment.source.address');
  89. }
  90. if (addressToVerifyAgainst.tag != null &&
  91. sourceAddressAndTag.tag != null &&
  92. addressToVerifyAgainst.tag !== sourceAddressAndTag.tag) {
  93. throw new ValidationError('address includes a tag that does not match payment.source.tag');
  94. }
  95. const destinationAddressAndTag = validateAndNormalizeAddress(payment.destination.address, payment.destination.tag);
  96. if ((isMaxAdjustment(payment.source) && isMinAdjustment(payment.destination)) ||
  97. (!isMaxAdjustment(payment.source) && !isMinAdjustment(payment.destination))) {
  98. throw new ValidationError('payment must specify either (source.maxAmount ' +
  99. 'and destination.amount) or (source.amount and destination.minAmount)');
  100. }
  101. const destinationAmount = isMinAdjustment(payment.destination)
  102. ? payment.destination.minAmount
  103. : payment.destination.amount;
  104. const sourceAmount = isMaxAdjustment(payment.source)
  105. ? payment.source.maxAmount
  106. : payment.source.amount;
  107. const amount = isMinAdjustment(payment.destination) && !isXRPToXRPPayment(payment)
  108. ? createMaximalAmount(destinationAmount)
  109. : destinationAmount;
  110. const txJSON = {
  111. TransactionType: 'Payment',
  112. Account: sourceAddressAndTag.classicAccount,
  113. Destination: destinationAddressAndTag.classicAccount,
  114. Amount: common_1.toRippledAmount(amount),
  115. Flags: 0
  116. };
  117. if (payment.invoiceID != null) {
  118. txJSON.InvoiceID = payment.invoiceID;
  119. }
  120. if (sourceAddressAndTag.tag != null) {
  121. txJSON.SourceTag = sourceAddressAndTag.tag;
  122. }
  123. if (destinationAddressAndTag.tag != null) {
  124. txJSON.DestinationTag = destinationAddressAndTag.tag;
  125. }
  126. if (payment.memos != null) {
  127. txJSON.Memos = payment.memos.map(utils.convertMemo);
  128. }
  129. if (payment.noDirectRipple === true) {
  130. txJSON.Flags |= paymentFlags.NoRippleDirect;
  131. }
  132. if (payment.limitQuality === true) {
  133. txJSON.Flags |= paymentFlags.LimitQuality;
  134. }
  135. if (!isXRPToXRPPayment(payment)) {
  136. if (payment.allowPartialPayment || isMinAdjustment(payment.destination)) {
  137. txJSON.Flags |= paymentFlags.PartialPayment;
  138. }
  139. txJSON.SendMax = common_1.toRippledAmount(sourceAmount);
  140. if (isMinAdjustment(payment.destination)) {
  141. txJSON.DeliverMin = common_1.toRippledAmount(destinationAmount);
  142. }
  143. if (payment.paths != null) {
  144. txJSON.Paths = JSON.parse(payment.paths);
  145. }
  146. }
  147. else if (payment.allowPartialPayment === true) {
  148. throw new ValidationError('XRP to XRP payments cannot be partial payments');
  149. }
  150. return txJSON;
  151. }
  152. function preparePayment(address, payment, instructions = {}) {
  153. try {
  154. validate.preparePayment({ address, payment, instructions });
  155. const txJSON = createPaymentTransaction(address, payment);
  156. return utils.prepareTransaction(txJSON, this, instructions);
  157. }
  158. catch (e) {
  159. return Promise.reject(e);
  160. }
  161. }
  162. exports.default = preparePayment;
  163. //# sourceMappingURL=payment.js.map