Add unit test for prepareOrder and fix bugs

This commit is contained in:
Chris Clark
2015-06-08 13:28:03 -07:00
parent 87b6c09de3
commit a114bf42c4
13 changed files with 99 additions and 56 deletions

View File

@@ -32,7 +32,7 @@ function loadSchemas(dir) {
function formatSchemaError(error) {
return error.field + ' ' + error.message
+ (error.value ? ' (' + error.value + ')' : '');
+ (error.value ? ' (' + JSON.stringify(error.value) + ')' : '');
}
function formatSchemaErrors(errors) {
@@ -42,7 +42,7 @@ function formatSchemaErrors(errors) {
function schemaValidate(schemaName, object) {
const formats = {address: isValidAddress,
ledgerHash: isValidLedgerHash};
const options = {schema: SCHEMAS, formats: formats,
const options = {schemas: SCHEMAS, formats: formats,
verbose: true, greedy: true};
const schema = SCHEMAS[schemaName];
if (schema === undefined) {

View File

@@ -3,12 +3,11 @@
"title": "cancellation",
"type": "object",
"properties": {
"address": {"$ref": "address"},
"orderSequence": {
"type": "integer",
"minimum": 0
}
},
"required": ["address", "orderSequence"],
"required": ["orderSequence"],
"additionalProperties": false
}

View File

@@ -3,7 +3,6 @@
"title": "order",
"type": "object",
"properties": {
"address": {"$ref": "address"},
"direction": {
"type": "string",
"enum": ["buy", "sell"]
@@ -17,7 +16,7 @@
"type": "boolean"
}
},
"required": ["address", "direction", "quantity", "totalPrice"],
"required": ["direction", "quantity", "totalPrice"],
"additionalProperties": false,
"not": {
"description": "immediateOrCancel and fillOrKill are mutually exclusive",

View File

@@ -3,10 +3,9 @@
"title": "settings",
"type": "object",
"properties": {
"address": {"$ref": "address"},
"name": {"type": "string"},
"value": {"type": "string"}
},
"required": ["address", "name", "value"],
"required": ["name", "value"],
"additionalProperties": false
}

View File

@@ -3,7 +3,6 @@
"title": "trustline",
"type": "object",
"properties": {
"address": {"$ref": "address"},
"currency": {"$ref": "currency"},
"counterparty": {"$ref": "address"},
"limit": {"$ref": "value"},
@@ -12,6 +11,6 @@
"allowRippling": {"type": "boolean"},
"frozen": {"type": "boolean"}
},
"required": ["address", "currency", "counterparty", "limit"],
"required": ["currency", "counterparty", "limit"],
"additionalProperties": false
}

View File

@@ -4,10 +4,11 @@ const _ = require('lodash');
const utils = require('./utils');
const ripple = utils.common.core;
const validate = utils.common.validate;
const xrpToDrops = utils.common.xrpToDrops;
function renameCounterpartyToIssuer(amount) {
if (amount === undefined) {
return undefined;
if (amount === undefined || amount.counterparty === undefined) {
return amount;
}
const issuer = amount.counterparty === undefined ?
amount.issuer : amount.counterparty;
@@ -15,39 +16,36 @@ function renameCounterpartyToIssuer(amount) {
return _.omit(withIssuer, 'counterparty');
}
function renameCounterpartyToIssuerInOrder(order) {
const taker_gets = renameCounterpartyToIssuer(order.taker_gets);
const taker_pays = renameCounterpartyToIssuer(order.taker_pays);
const changes = {taker_gets: taker_gets, taker_pays: taker_pays};
return _.assign({}, order, _.omit(changes, _.isUndefined));
}
const OfferCreateFlags = {
Passive: {name: 'passive', set: 'Passive'},
ImmediateOrCancel: {name: 'immediate_or_cancel', set: 'ImmediateOrCancel'},
FillOrKill: {name: 'fill_or_kill', set: 'FillOrKill'}
ImmediateOrCancel: {name: 'immediateOrCancel', set: 'ImmediateOrCancel'},
FillOrKill: {name: 'fillOrKill', set: 'FillOrKill'}
};
function toRippledAmount(amount) {
return amount.currency === 'XRP' ?
xrpToDrops(amount.value) : renameCounterpartyToIssuer(amount);
}
function createOrderTransaction(account, order) {
validate.address(account);
validate.order(order);
const _order = renameCounterpartyToIssuerInOrder(order);
const transaction = new ripple.Transaction();
const takerPays = _order.taker_pays.currency !== 'XRP'
? _order.taker_pays : utils.common.xrpToDrops(_order.taker_pays.value);
const takerGets = _order.taker_gets.currency !== 'XRP'
? _order.taker_gets : utils.common.xrpToDrops(_order.taker_gets.value);
const takerPays = toRippledAmount(order.direction === 'buy' ?
order.quantity : order.totalPrice);
const takerGets = toRippledAmount(order.direction === 'buy' ?
order.totalPrice : order.quantity);
transaction.offerCreate(account, ripple.Amount.from_json(takerPays),
ripple.Amount.from_json(takerGets));
utils.setTransactionBitFlags(transaction, {
input: _order,
input: order,
flags: OfferCreateFlags
});
if (_order.type === 'sell') {
if (order.direction === 'sell') {
transaction.setFlags('Sell');
}
return transaction;

View File

@@ -77,8 +77,8 @@ function createPaymentTransaction(account, payment) {
const maxValue = new BigNumber(payment.source.amount.value)
.plus(payment.source.slippage || 0).toString();
if (payment.source_amount.currency === 'XRP') {
transaction.sendMax(utils.common.utils.xrpToDrops(maxValue));
if (payment.source.amount.currency === 'XRP') {
transaction.sendMax(utils.common.xrpToDrops(maxValue));
} else {
transaction.sendMax({
value: maxValue,

View File

@@ -55,36 +55,35 @@ function createTxJSON(transaction: any, remote: any,
transaction.complete();
const account = transaction.getAccount();
const tx_json = transaction.tx_json;
const txJSON = transaction.tx_json;
if (instructions.maxLedgerVersion !== undefined) {
tx_json.LastLedgerSequence =
parseInt(instructions.maxLedgerVersion, 10);
txJSON.LastLedgerSequence = parseInt(instructions.maxLedgerVersion, 10);
} else {
const offset = instructions.maxLedgerVersionOffset !== undefined ?
parseInt(instructions.maxLedgerVersionOffset, 10) : 3;
tx_json.LastLedgerSequence = remote.getLedgerSequence() + offset;
txJSON.LastLedgerSequence = remote.getLedgerSequence() + offset;
}
if (instructions.fee !== undefined) {
tx_json.Fee = common.xrpToDrops(instructions.fee);
txJSON.Fee = common.xrpToDrops(instructions.fee);
} else {
const serverFeeDrops = getFeeDrops(remote);
if (instructions.maxFee !== undefined) {
const maxFeeDrops = common.xrpToDrops(instructions.maxFee);
tx_json.Fee = BigNumber.min(serverFeeDrops, maxFeeDrops).toString();
txJSON.Fee = BigNumber.min(serverFeeDrops, maxFeeDrops).toString();
} else {
tx_json.Fee = serverFeeDrops;
txJSON.Fee = serverFeeDrops;
}
}
if (instructions.sequence !== undefined) {
tx_json.Sequence = parseInt(instructions.sequence, 10);
callback(null, {tx_json: tx_json});
txJSON.Sequence = parseInt(instructions.sequence, 10);
callback(null, txJSON);
} else {
remote.findAccount(account).getNextSequence(function(error, sequence) {
tx_json.Sequence = sequence;
callback(null, {tx_json: tx_json});
txJSON.Sequence = sequence;
callback(null, txJSON);
});
}
}

View File

@@ -4,6 +4,8 @@ const setupAPI = require('./setup-api');
const address = require('./fixtures/addresses').ACCOUNT;
const paymentSpecification = require('./fixtures/payment-specification');
const paymentResponse = require('./fixtures/payment-response');
const orderSpecification = require('./fixtures/order-specification');
const orderResponse = require('./fixtures/order-response');
const balancesResponse = require('./fixtures/balances-response');
describe('RippleAPI', function() {
@@ -23,6 +25,19 @@ describe('RippleAPI', function() {
});
});
it('prepareOrder', function(done) {
const instructions = {maxLedgerVersionOffset: 100};
this.api.prepareOrder(address, orderSpecification, instructions,
(error, response) => {
if (error) {
done(error);
return;
}
assert.deepEqual(response, orderResponse);
done();
});
});
it('getBalances', function(done) {
this.api.getBalances(address, {}, (error, response) => {
if (error) {

14
test/fixtures/order-response.json vendored Normal file
View File

@@ -0,0 +1,14 @@
{
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"Fee": "12",
"Flags": 131072,
"LastLedgerSequence": 8820052,
"Sequence": 23,
"TakerGets": "2000000",
"TakerPays": {
"currency": "USD",
"issuer": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"value": "10.1"
},
"TransactionType": "OfferCreate"
}

13
test/fixtures/order-specification.json vendored Normal file
View File

@@ -0,0 +1,13 @@
{
"direction": "buy",
"quantity": {
"currency": "USD",
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"value": "10.1"
},
"totalPrice": {
"currency": "XRP",
"value": "2"
},
"immediateOrCancel": true
}

View File

@@ -1,16 +1,19 @@
{
"tx_json": {
"Flags": 0,
"TransactionType": "Payment",
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"Destination": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"Amount": {
"value": "0.01",
"currency": "USD",
"issuer": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"LastLedgerSequence": 8820052,
"Fee": "12",
"Sequence": 23
}
"Flags": 0,
"TransactionType": "Payment",
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"Destination": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",
"Amount": {
"value": "0.01",
"currency": "USD",
"issuer": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
},
"LastLedgerSequence": 8820052,
"SendMax": {
"currency": "USD",
"issuer": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM",
"value": "0.01"
},
"Fee": "12",
"Sequence": 23
}

View File

@@ -1,6 +1,11 @@
{
"source": {
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
"address": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"amount": {
"value": "0.01",
"currency": "USD",
"counterparty": "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"
}
},
"destination": {
"address": "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo",