Skip to content

Commit

Permalink
Decouple core.Transaction from API
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Clark committed Oct 21, 2015
1 parent 98422e4 commit c324682
Show file tree
Hide file tree
Showing 20 changed files with 224 additions and 186 deletions.
2 changes: 1 addition & 1 deletion src/api/common/constants.js
@@ -1,6 +1,6 @@
'use strict';
const core = require('./utils').core;
const flagIndices = core.Transaction.set_clear_flags.AccountSet;
const flagIndices = require('./txflags').txFlagIndices.AccountSet;
const flags = core.Remote.flags.account_root;

const AccountFlags = {
Expand Down
1 change: 1 addition & 0 deletions src/api/common/index.js
Expand Up @@ -7,6 +7,7 @@ module.exports = {
constants: require('./constants'),
errors: require('./errors'),
validate: require('./validate'),
txFlags: require('./txflags').txFlags,
dropsToXrp: utils.dropsToXrp,
xrpToDrops: utils.xrpToDrops,
toRippledAmount: utils.toRippledAmount,
Expand Down
8 changes: 4 additions & 4 deletions src/api/transaction/txflags.js → src/api/common/txflags.js
@@ -1,6 +1,6 @@
'use strict';

const transactionFlags = {
const txFlags = {
// Universal flags can apply to any transaction type
Universal: {
FullyCanonicalSig: 0x80000000
Expand Down Expand Up @@ -41,7 +41,7 @@ const transactionFlags = {
// The following are integer (as opposed to bit) flags
// that can be set for particular transactions in the
// SetFlag or ClearFlag field
const transactionFlagIndices = {
const txFlagIndices = {
AccountSet: {
asfRequireDest: 1,
asfRequireAuth: 2,
Expand All @@ -55,6 +55,6 @@ const transactionFlagIndices = {
};

module.exports = {
transactionFlags,
transactionFlagIndices
txFlags,
txFlagIndices
};
2 changes: 1 addition & 1 deletion src/api/ledger/parse/order.js
Expand Up @@ -3,7 +3,7 @@
const assert = require('assert');
const utils = require('./utils');
const parseAmount = require('./amount');
const flags = utils.core.Transaction.flags.OfferCreate;
const flags = utils.txFlags.OfferCreate;

function parseOrder(tx: Object): Object {
assert(tx.TransactionType === 'OfferCreate');
Expand Down
8 changes: 4 additions & 4 deletions src/api/ledger/parse/payment.js
Expand Up @@ -4,18 +4,18 @@ const _ = require('lodash');
const assert = require('assert');
const utils = require('./utils');
const parseAmount = require('./amount');
const Transaction = utils.core.Transaction;
const txFlags = utils.txFlags;

function isPartialPayment(tx) {
return (tx.Flags & Transaction.flags.Payment.PartialPayment) !== 0;
return (tx.Flags & txFlags.Payment.PartialPayment) !== 0;
}

function isNoDirectRipple(tx) {
return (tx.Flags & Transaction.flags.Payment.NoRippleDirect) !== 0;
return (tx.Flags & txFlags.Payment.NoRippleDirect) !== 0;
}

function isQualityLimited(tx) {
return (tx.Flags & Transaction.flags.Payment.LimitQuality) !== 0;
return (tx.Flags & txFlags.Payment.LimitQuality) !== 0;
}

function removeGenericCounterparty(amount, address) {
Expand Down
2 changes: 1 addition & 1 deletion src/api/ledger/parse/trustline.js
Expand Up @@ -2,7 +2,7 @@
'use strict';
const assert = require('assert');
const utils = require('./utils');
const flags = utils.core.Transaction.flags.TrustSet;
const flags = utils.txFlags.TrustSet;
const BigNumber = require('bignumber.js');

function parseFlag(flagsValue, trueValue, falseValue) {
Expand Down
1 change: 1 addition & 0 deletions src/api/ledger/parse/utils.js
Expand Up @@ -91,5 +91,6 @@ module.exports = {
adjustQualityForXRP,
dropsToXrp: utils.common.dropsToXrp,
constants: utils.common.constants,
txFlags: utils.common.txFlags,
core: utils.common.core
};
37 changes: 21 additions & 16 deletions src/api/transaction/order.js
Expand Up @@ -2,40 +2,45 @@
'use strict';
const utils = require('./utils');
const validate = utils.common.validate;
const Transaction = utils.common.core.Transaction;
const offerFlags = utils.common.txFlags.OfferCreate;
import type {Instructions, Prepare} from './types.js';
import type {Order} from '../ledger/transaction-types.js';

const OfferCreateFlags = {
passive: {set: 'Passive'},
immediateOrCancel: {set: 'ImmediateOrCancel'},
fillOrKill: {set: 'FillOrKill'}
};

function createOrderTransaction(account: string, order: Order): Transaction {
function createOrderTransaction(account: string, order: Order): Object {
validate.address(account);
validate.order(order);

const transaction = new Transaction();
const takerPays = utils.common.toRippledAmount(order.direction === 'buy' ?
order.quantity : order.totalPrice);
const takerGets = utils.common.toRippledAmount(order.direction === 'buy' ?
order.totalPrice : order.quantity);

transaction.offerCreate(account, takerPays, takerGets);

utils.setTransactionBitFlags(transaction, order, OfferCreateFlags);
const txJSON: Object = {
TransactionType: 'OfferCreate',
Account: account,
TakerGets: takerGets,
TakerPays: takerPays,
Flags: 0
};
if (order.direction === 'sell') {
transaction.setFlags('Sell');
txJSON.Flags |= offerFlags.Sell;
}

return transaction;
if (order.passive === true) {
txJSON.Flags |= offerFlags.Passive;
}
if (order.immediateOrCancel === true) {
txJSON.Flags |= offerFlags.ImmediateOrCancel;
}
if (order.fillOrKill === true) {
txJSON.Flags |= offerFlags.FillOrKill;
}
return txJSON;
}

function prepareOrderAsync(account: string, order: Order,
instructions: Instructions, callback
) {
const txJSON = createOrderTransaction(account, order).tx_json;
const txJSON = createOrderTransaction(account, order);
utils.prepareTransaction(txJSON, this.remote, instructions, callback);
}

Expand Down
13 changes: 7 additions & 6 deletions src/api/transaction/ordercancellation.js
Expand Up @@ -2,24 +2,25 @@
'use strict';
const utils = require('./utils');
const validate = utils.common.validate;
const Transaction = utils.common.core.Transaction;
import type {Instructions, Prepare} from './types.js';

function createOrderCancellationTransaction(account: string,
sequence: number
): Transaction {
): Object {
validate.address(account);
validate.sequence(sequence);

const transaction = new Transaction();
transaction.offerCancel(account, sequence);
return transaction;
return {
TransactionType: 'OfferCancel',
Account: account,
OfferSequence: sequence
};
}

function prepareOrderCancellationAsync(account: string, sequence: number,
instructions: Instructions, callback
) {
const txJSON = createOrderCancellationTransaction(account, sequence).tx_json;
const txJSON = createOrderCancellationTransaction(account, sequence);
utils.prepareTransaction(txJSON, this.remote, instructions, callback);
}

Expand Down
66 changes: 33 additions & 33 deletions src/api/transaction/payment.js
Expand Up @@ -4,7 +4,7 @@ const _ = require('lodash');
const utils = require('./utils');
const validate = utils.common.validate;
const toRippledAmount = utils.common.toRippledAmount;
const Transaction = utils.common.core.Transaction;
const paymentFlags = utils.common.txFlags.Payment;
const ValidationError = utils.common.errors.ValidationError;
import type {Instructions, Prepare} from './types.js';
import type {Amount, Adjustment, MaxAdjustment,
Expand Down Expand Up @@ -66,7 +66,7 @@ function createMaximalAmount(amount: Amount): Amount {
}

function createPaymentTransaction(account: string, paymentArgument: Payment
): Transaction {
): Object {
const payment = _.cloneDeep(paymentArgument);
applyAnyCounterpartyEncoding(payment);
validate.address(account);
Expand All @@ -88,63 +88,63 @@ function createPaymentTransaction(account: string, paymentArgument: Payment
createMaximalAmount(payment.destination.minAmount) :
(payment.destination.amount || payment.destination.minAmount);

const transaction = new Transaction();
transaction.payment({
from: payment.source.address,
to: payment.destination.address,
amount: toRippledAmount(amount)
});
const txJSON: Object = {
TransactionType: 'Payment',
Account: payment.source.address,
Destination: payment.destination.address,
Amount: toRippledAmount(amount),
Flags: 0
};

if (payment.invoiceID) {
transaction.invoiceID(payment.invoiceID);
if (payment.invoiceID !== undefined) {
txJSON.InvoiceID = payment.invoiceID;
}
if (payment.source.tag) {
transaction.sourceTag(payment.source.tag);
if (payment.source.tag !== undefined) {
txJSON.SourceTag = payment.source.tag;
}
if (payment.destination.tag) {
transaction.destinationTag(payment.destination.tag);
if (payment.destination.tag !== undefined) {
txJSON.DestinationTag = payment.destination.tag;
}
if (payment.memos) {
_.forEach(payment.memos, memo =>
transaction.addMemo(memo.type, memo.format, memo.data)
);
if (payment.memos !== undefined) {
txJSON.Memos = _.map(payment.memos, utils.convertMemo);
}
if (payment.noDirectRipple) {
transaction.setFlags(['NoRippleDirect']);
if (payment.noDirectRipple === true) {
txJSON.Flags |= paymentFlags.NoRippleDirect;
}
if (payment.limitQuality) {
transaction.setFlags(['LimitQuality']);
if (payment.limitQuality === true) {
txJSON.Flags |= paymentFlags.LimitQuality;
}
if (!isXRPToXRPPayment(payment)) {
// Don't set SendMax for XRP->XRP payment
// temREDUNDANT_SEND_MAX removed in:
// https://github.com/ripple/rippled/commit/
// c522ffa6db2648f1d8a987843e7feabf1a0b7de8/
if (payment.allowPartialPayment || payment.destination.minAmount) {
transaction.setFlags(['PartialPayment']);
if (payment.allowPartialPayment === true
|| payment.destination.minAmount !== undefined) {
txJSON.Flags |= paymentFlags.PartialPayment;
}

transaction.setSendMax(toRippledAmount(
payment.source.maxAmount || payment.source.amount));
txJSON.SendMax = toRippledAmount(
payment.source.maxAmount || payment.source.amount);

if (payment.destination.minAmount) {
transaction.setDeliverMin(toRippledAmount(payment.destination.minAmount));
if (payment.destination.minAmount !== undefined) {
txJSON.DeliverMin = toRippledAmount(payment.destination.minAmount);
}

if (payment.paths) {
transaction.paths(JSON.parse(payment.paths));
if (payment.paths !== undefined) {
txJSON.Paths = JSON.parse(payment.paths);
}
} else if (payment.allowPartialPayment) {
} else if (payment.allowPartialPayment === true) {
throw new ValidationError('XRP to XRP payments cannot be partial payments');
}

return transaction;
return txJSON;
}

function preparePaymentAsync(account: string, payment: Payment,
instructions: Instructions, callback
) {
const txJSON = createPaymentTransaction(account, payment).tx_json;
const txJSON = createPaymentTransaction(account, payment);
utils.prepareTransaction(txJSON, this.remote, instructions, callback);
}

Expand Down
41 changes: 21 additions & 20 deletions src/api/transaction/settings.js
Expand Up @@ -6,30 +6,29 @@ const utils = require('./utils');
const validate = utils.common.validate;
const AccountFlagIndices = utils.common.constants.AccountFlagIndices;
const AccountFields = utils.common.constants.AccountFields;
const Transaction = utils.common.core.Transaction;
import type {Instructions, Prepare} from './types.js';
import type {Settings} from './settings-types.js';

// Emptry string passed to setting will clear it
const CLEAR_SETTING = null;


function setTransactionFlags(transaction: Transaction, values: Settings) {
function setTransactionFlags(txJSON: Object, values: Settings) {
const keys = Object.keys(values);
assert(keys.length === 1, 'ERROR: can only set one setting per transaction');
const flagName = keys[0];
const value = values[flagName];
const index = AccountFlagIndices[flagName];
if (index !== undefined) {
if (value) {
transaction.tx_json.SetFlag = index;
txJSON.SetFlag = index;
} else {
transaction.tx_json.ClearFlag = index;
txJSON.ClearFlag = index;
}
}
}

function setTransactionFields(transaction: Transaction, input: Settings) {
function setTransactionFields(txJSON: Object, input: Settings) {
const fieldSchema = AccountFields;
for (const fieldName in fieldSchema) {
const field = fieldSchema[fieldName];
Expand All @@ -49,7 +48,7 @@ function setTransactionFields(transaction: Transaction, input: Settings) {
value = new Buffer(value, 'ascii').toString('hex').toUpperCase();
}

transaction.tx_json[fieldName] = value;
txJSON[fieldName] = value;
}
}

Expand All @@ -71,33 +70,35 @@ function convertTransferRate(transferRate: number | string): number | string {
}

function createSettingsTransaction(account: string, settings: Settings
): Transaction {
): Object {
validate.address(account);
validate.settings(settings);

const transaction = new Transaction();
if (settings.regularKey) {
return transaction.setRegularKey({
account: account,
regular_key: settings.regularKey
});
return {
TransactionType: 'SetRegularKey',
Account: account,
RegularKey: settings.regularKey
};
}

transaction.accountSet(account);
setTransactionFlags(transaction, settings);
setTransactionFields(transaction, settings);
const txJSON: Object = {
TransactionType: 'AccountSet',
Account: account
};
setTransactionFlags(txJSON, settings);
setTransactionFields(txJSON, settings);

if (transaction.tx_json.TransferRate !== undefined) {
transaction.tx_json.TransferRate = convertTransferRate(
transaction.tx_json.TransferRate);
if (txJSON.TransferRate !== undefined) {
txJSON.TransferRate = convertTransferRate(txJSON.TransferRate);
}
return transaction;
return txJSON;
}

function prepareSettingsAsync(account: string, settings: Settings,
instructions: Instructions, callback
) {
const txJSON = createSettingsTransaction(account, settings).tx_json;
const txJSON = createSettingsTransaction(account, settings);
utils.prepareTransaction(txJSON, this.remote, instructions, callback);
}

Expand Down

0 comments on commit c324682

Please sign in to comment.