mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-21 12:45:50 +00:00
Add unit test for generateWallet and reorganize API files
This commit is contained in:
@@ -1,55 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const ripple = require('./common').core;
|
|
||||||
const generateWallet = require('./generate/wallet');
|
|
||||||
const server = require('./server/server');
|
|
||||||
const balances = require('./ledger/balances');
|
|
||||||
const settings = require('./ledger/settings');
|
|
||||||
const transactions = require('./ledger/transactions');
|
|
||||||
const trustlines = require('./ledger/trustlines');
|
|
||||||
const payments = require('./ledger/payments');
|
|
||||||
const orders = require('./ledger/orders');
|
|
||||||
const preparePayment = require('./transaction/payment');
|
|
||||||
const prepareOrder = require('./transaction/order');
|
|
||||||
const prepareOrderCancellation = require('./transaction/ordercancellation');
|
|
||||||
const prepareTrustline = require('./transaction/trustline');
|
|
||||||
const prepareSettings = require('./transaction/settings');
|
|
||||||
const sign = require('./transaction/sign');
|
|
||||||
const submit = require('./transaction/submit');
|
|
||||||
const errors = require('./common').errors;
|
|
||||||
|
|
||||||
function RippleAPI(options) {
|
|
||||||
this.remote = new ripple.Remote(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
RippleAPI.prototype = {
|
|
||||||
generateWallet: generateWallet,
|
|
||||||
|
|
||||||
connect: server.connect,
|
|
||||||
getServerStatus: server.getServerStatus,
|
|
||||||
getFee: server.getFee,
|
|
||||||
isConnected: server.isConnected,
|
|
||||||
|
|
||||||
getBalances: balances.getBalances,
|
|
||||||
getPayment: payments.getPayment,
|
|
||||||
getAccountPayments: payments.getAccountPayments,
|
|
||||||
getPathFind: payments.getPathFind,
|
|
||||||
getTrustlines: trustlines.getTrustlines,
|
|
||||||
getOrder: orders.getOrder,
|
|
||||||
getOrders: orders.getOrders,
|
|
||||||
getOrderBook: orders.getOrderBook,
|
|
||||||
getSettings: settings.getSettings,
|
|
||||||
getTransaction: transactions.getTransaction,
|
|
||||||
getAccountTransactions: transactions.getAccountTransactions,
|
|
||||||
|
|
||||||
preparePayment: preparePayment,
|
|
||||||
prepareTrustline: prepareTrustline,
|
|
||||||
prepareOrder: prepareOrder,
|
|
||||||
prepareOrderCancellation: prepareOrderCancellation,
|
|
||||||
prepareSettings: prepareSettings,
|
|
||||||
sign: sign,
|
|
||||||
submit: submit,
|
|
||||||
|
|
||||||
errors: errors
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = RippleAPI;
|
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
|
|
||||||
function generateWallet(callback) {
|
function generateWallet() {
|
||||||
const wallet = common.core.Wallet.generate();
|
const wallet = common.core.Wallet.generate();
|
||||||
if (wallet) {
|
if (!wallet) {
|
||||||
callback(null, {wallet: wallet});
|
throw new common.errors.ApiError('Could not generate wallet');
|
||||||
} else {
|
|
||||||
callback(new common.errors.ApiError('Could not generate wallet'));
|
|
||||||
}
|
}
|
||||||
|
return wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = generateWallet;
|
module.exports = generateWallet;
|
||||||
|
|||||||
57
src/api/index.js
Normal file
57
src/api/index.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
'use strict';
|
||||||
|
const ripple = require('./common').core;
|
||||||
|
const server = require('./server/server');
|
||||||
|
const connect = server.connect;
|
||||||
|
// const getServerStatus = server.getServerStatus;
|
||||||
|
// const getFee = server.getFee;
|
||||||
|
// const isConnected = server.isConnected;
|
||||||
|
const getTransaction = require('./ledger/transaction');
|
||||||
|
const getAccountTransactions = require('./ledger/transactions');
|
||||||
|
const getTrustlines = require('./ledger/trustlines');
|
||||||
|
const getBalances = require('./ledger/balances');
|
||||||
|
// const getPathFind = require('./ledger/pathfind');
|
||||||
|
// const getOrders = require('./ledger/orders');
|
||||||
|
// const getOrderBook = require('./ledger/orderbook');
|
||||||
|
// const getSettings = require('./ledger/settings');
|
||||||
|
const preparePayment = require('./transaction/payment');
|
||||||
|
const prepareTrustline = require('./transaction/trustline');
|
||||||
|
const prepareOrder = require('./transaction/order');
|
||||||
|
const prepareOrderCancellation = require('./transaction/ordercancellation');
|
||||||
|
const prepareSettings = require('./transaction/settings');
|
||||||
|
const sign = require('./transaction/sign');
|
||||||
|
const submit = require('./transaction/submit');
|
||||||
|
const generateWallet = require('./generate/wallet');
|
||||||
|
const errors = require('./common').errors;
|
||||||
|
|
||||||
|
function RippleAPI(options) {
|
||||||
|
this.remote = new ripple.Remote(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
RippleAPI.prototype = {
|
||||||
|
connect,
|
||||||
|
// getServerStatus,
|
||||||
|
// getFee,
|
||||||
|
// isConnected,
|
||||||
|
|
||||||
|
getTransaction,
|
||||||
|
getAccountTransactions,
|
||||||
|
getTrustlines,
|
||||||
|
getBalances,
|
||||||
|
// getPathFind,
|
||||||
|
// getOrders,
|
||||||
|
// getOrderBook,
|
||||||
|
// getSettings,
|
||||||
|
|
||||||
|
preparePayment,
|
||||||
|
prepareTrustline,
|
||||||
|
prepareOrder,
|
||||||
|
prepareOrderCancellation,
|
||||||
|
prepareSettings,
|
||||||
|
sign,
|
||||||
|
submit,
|
||||||
|
|
||||||
|
generateWallet,
|
||||||
|
errors
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = RippleAPI;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const getTrustlines = require('./trustlines').getTrustlines;
|
const getTrustlines = require('./trustlines');
|
||||||
const validate = utils.common.validate;
|
const validate = utils.common.validate;
|
||||||
const composeAsync = utils.common.composeAsync;
|
const composeAsync = utils.common.composeAsync;
|
||||||
const dropsToXrp = utils.common.dropsToXrp;
|
const dropsToXrp = utils.common.dropsToXrp;
|
||||||
@@ -12,7 +12,7 @@ function getXRPBalance(remote, address, ledgerVersion, callback) {
|
|||||||
composeAsync((data) => dropsToXrp(data.account_data.Balance), callback));
|
composeAsync((data) => dropsToXrp(data.account_data.Balance), callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseBalanceAmount(trustline) {
|
function getTrustlineBalanceAmount(trustline) {
|
||||||
return {
|
return {
|
||||||
currency: trustline.specification.currency,
|
currency: trustline.specification.currency,
|
||||||
counterparty: trustline.specification.counterparty,
|
counterparty: trustline.specification.counterparty,
|
||||||
@@ -25,7 +25,7 @@ function formatBalances(balances) {
|
|||||||
currency: 'XRP',
|
currency: 'XRP',
|
||||||
value: balances[0]
|
value: balances[0]
|
||||||
};
|
};
|
||||||
return [xrpBalance].concat(balances[1].map(parseBalanceAmount));
|
return [xrpBalance].concat(balances[1].map(getTrustlineBalanceAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBalances(account, options, callback) {
|
function getBalances(account, options, callback) {
|
||||||
@@ -40,4 +40,4 @@ function getBalances(account, options, callback) {
|
|||||||
], composeAsync(formatBalances, callback));
|
], composeAsync(formatBalances, callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getBalances = getBalances;
|
module.exports = getBalances;
|
||||||
|
|||||||
171
src/api/ledger/orderbook.js
Normal file
171
src/api/ledger/orderbook.js
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
'use strict';
|
||||||
|
const _ = require('lodash');
|
||||||
|
const utils = require('./utils');
|
||||||
|
const ripple = utils.common.core;
|
||||||
|
const validate = utils.common.validate;
|
||||||
|
const bignum = require('bignumber.js');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the most recent spapshot of the order book for a currency pair
|
||||||
|
*
|
||||||
|
* @url
|
||||||
|
* @param {RippleAddress} request.params.account
|
||||||
|
* - The ripple address to use as point-of-view
|
||||||
|
* (returns unfunded orders for this account)
|
||||||
|
* @param {String ISO 4217 Currency Code + RippleAddress} request.params.base
|
||||||
|
* - Base currency as currency+issuer
|
||||||
|
* @param {String ISO 4217 Currency Code + RippleAddress}
|
||||||
|
* request.params.counter - Counter currency as currency+issuer
|
||||||
|
*
|
||||||
|
* @query
|
||||||
|
* @param {String} [request.query.limit]
|
||||||
|
* - Set a limit to the number of results returned
|
||||||
|
*
|
||||||
|
* @param {Express.js Request} request
|
||||||
|
*/
|
||||||
|
function getOrderBook(account, orderbook, options, callback) {
|
||||||
|
const self = this;
|
||||||
|
validate.address(account);
|
||||||
|
validate.orderbook(orderbook);
|
||||||
|
validate.options(options);
|
||||||
|
|
||||||
|
const params = _.assign({}, orderbook, options, {
|
||||||
|
validated: true,
|
||||||
|
order_book: orderbook.base + '/' + orderbook.counter
|
||||||
|
});
|
||||||
|
|
||||||
|
function getLastValidatedLedger(parameters) {
|
||||||
|
const promise = new Promise(function(resolve, reject) {
|
||||||
|
const ledgerRequest = self.remote.requestLedger('validated');
|
||||||
|
|
||||||
|
ledgerRequest.once('success', function(res) {
|
||||||
|
parameters.ledger = res.ledger.ledger_index;
|
||||||
|
resolve(parameters);
|
||||||
|
});
|
||||||
|
|
||||||
|
ledgerRequest.once('error', reject);
|
||||||
|
ledgerRequest.request();
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBookOffers(taker_gets, taker_pays, parameters) {
|
||||||
|
const promise = new Promise(function(resolve, reject) {
|
||||||
|
const bookOffersRequest = self.remote.requestBookOffers({
|
||||||
|
taker_gets: {currency: taker_gets.currency,
|
||||||
|
issuer: taker_gets.counterparty},
|
||||||
|
taker_pays: {currency: taker_pays.currency,
|
||||||
|
issuer: taker_pays.counterparty},
|
||||||
|
ledger: parameters.ledger,
|
||||||
|
limit: parameters.limit,
|
||||||
|
taker: account
|
||||||
|
});
|
||||||
|
|
||||||
|
bookOffersRequest.once('success', resolve);
|
||||||
|
bookOffersRequest.once('error', reject);
|
||||||
|
bookOffersRequest.request();
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBids(parameters) {
|
||||||
|
const taker_gets = parameters.counter;
|
||||||
|
const taker_pays = parameters.base;
|
||||||
|
|
||||||
|
return getBookOffers(taker_gets, taker_pays, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAsks(parameters) {
|
||||||
|
const taker_gets = parameters.base;
|
||||||
|
const taker_pays = parameters.counter;
|
||||||
|
|
||||||
|
return getBookOffers(taker_gets, taker_pays, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBidsAndAsks(parameters) {
|
||||||
|
return Promise.join(
|
||||||
|
getBids(parameters),
|
||||||
|
getAsks(parameters),
|
||||||
|
function(bids, asks) {
|
||||||
|
return [bids, asks, parameters];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParsedBookOffers(offers, isAsk) {
|
||||||
|
return offers.reduce(function(orderBook, off) {
|
||||||
|
let price;
|
||||||
|
const order_maker = off.Account;
|
||||||
|
const sequence = off.Sequence;
|
||||||
|
|
||||||
|
// Transaction Flags
|
||||||
|
const passive = (off.Flags & ripple.Remote.flags.offer.Passive) !== 0;
|
||||||
|
const sell = (off.Flags & ripple.Remote.flags.offer.Sell) !== 0;
|
||||||
|
|
||||||
|
const taker_gets_total = utils.parseCurrencyAmount(off.TakerGets);
|
||||||
|
const taker_gets_funded = off.taker_gets_funded ?
|
||||||
|
utils.parseCurrencyAmount(off.taker_gets_funded) : taker_gets_total;
|
||||||
|
|
||||||
|
const taker_pays_total = utils.parseCurrencyAmount(off.TakerPays);
|
||||||
|
const taker_pays_funded = off.taker_pays_funded ?
|
||||||
|
utils.parseCurrencyAmount(off.taker_pays_funded) : taker_pays_total;
|
||||||
|
|
||||||
|
if (isAsk) {
|
||||||
|
price = {
|
||||||
|
currency: taker_pays_total.currency,
|
||||||
|
counterparty: taker_pays_total.counterparty,
|
||||||
|
value: bignum(taker_pays_total.value).div(
|
||||||
|
bignum(taker_gets_total.value))
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
price = {
|
||||||
|
currency: taker_gets_total.currency,
|
||||||
|
counterparty: taker_gets_total.counterparty,
|
||||||
|
value: bignum(taker_gets_total.value).div(
|
||||||
|
bignum(taker_pays_total.value))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
price.value = price.value.toString();
|
||||||
|
|
||||||
|
orderBook.push({
|
||||||
|
price: price,
|
||||||
|
taker_gets_funded: taker_gets_funded,
|
||||||
|
taker_gets_total: taker_gets_total,
|
||||||
|
taker_pays_funded: taker_pays_funded,
|
||||||
|
taker_pays_total: taker_pays_total,
|
||||||
|
order_maker: order_maker,
|
||||||
|
sequence: sequence,
|
||||||
|
passive: passive,
|
||||||
|
sell: sell
|
||||||
|
});
|
||||||
|
|
||||||
|
return orderBook;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function respondWithOrderBook(bids, asks, parameters) {
|
||||||
|
const promise = new Promise(function(resolve) {
|
||||||
|
const orderBook = {
|
||||||
|
order_book: parameters.order_book,
|
||||||
|
ledger: parameters.ledger,
|
||||||
|
validated: parameters.validated,
|
||||||
|
bids: getParsedBookOffers(bids.offers),
|
||||||
|
asks: getParsedBookOffers(asks.offers, true)
|
||||||
|
};
|
||||||
|
|
||||||
|
resolve(callback(null, orderBook));
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastValidatedLedger(params)
|
||||||
|
.then(getBidsAndAsks)
|
||||||
|
.spread(respondWithOrderBook)
|
||||||
|
.catch(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = getOrderBook;
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
/* globals Promise: true */
|
|
||||||
/* eslint-disable valid-jsdoc */
|
/* eslint-disable valid-jsdoc */
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const bignum = require('bignumber.js');
|
|
||||||
const asyncify = require('simple-asyncify');
|
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const ripple = utils.common.core;
|
const ripple = utils.common.core;
|
||||||
const errors = utils.common.errors;
|
|
||||||
const validate = utils.common.validate;
|
const validate = utils.common.validate;
|
||||||
const parseTransaction = require('./parse/transaction');
|
|
||||||
|
|
||||||
const DefaultPageLimit = 200;
|
const DefaultPageLimit = 200;
|
||||||
|
|
||||||
@@ -121,202 +116,4 @@ function getOrders(account, options, callback) {
|
|||||||
.catch(callback);
|
.catch(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
module.exports = getOrders;
|
||||||
* Get the most recent spapshot of the order book for a currency pair
|
|
||||||
*
|
|
||||||
* @url
|
|
||||||
* @param {RippleAddress} request.params.account
|
|
||||||
* - The ripple address to use as point-of-view
|
|
||||||
* (returns unfunded orders for this account)
|
|
||||||
* @param {String ISO 4217 Currency Code + RippleAddress} request.params.base
|
|
||||||
* - Base currency as currency+issuer
|
|
||||||
* @param {String ISO 4217 Currency Code + RippleAddress}
|
|
||||||
* request.params.counter - Counter currency as currency+issuer
|
|
||||||
*
|
|
||||||
* @query
|
|
||||||
* @param {String} [request.query.limit]
|
|
||||||
* - Set a limit to the number of results returned
|
|
||||||
*
|
|
||||||
* @param {Express.js Request} request
|
|
||||||
*/
|
|
||||||
function getOrderBook(account, orderbook, options, callback) {
|
|
||||||
const self = this;
|
|
||||||
validate.address(account);
|
|
||||||
validate.orderbook(orderbook);
|
|
||||||
validate.options(options);
|
|
||||||
|
|
||||||
const params = _.assign({}, orderbook, options, {
|
|
||||||
validated: true,
|
|
||||||
order_book: orderbook.base + '/' + orderbook.counter
|
|
||||||
});
|
|
||||||
|
|
||||||
function getLastValidatedLedger(parameters) {
|
|
||||||
const promise = new Promise(function(resolve, reject) {
|
|
||||||
const ledgerRequest = self.remote.requestLedger('validated');
|
|
||||||
|
|
||||||
ledgerRequest.once('success', function(res) {
|
|
||||||
parameters.ledger = res.ledger.ledger_index;
|
|
||||||
resolve(parameters);
|
|
||||||
});
|
|
||||||
|
|
||||||
ledgerRequest.once('error', reject);
|
|
||||||
ledgerRequest.request();
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBookOffers(taker_gets, taker_pays, parameters) {
|
|
||||||
const promise = new Promise(function(resolve, reject) {
|
|
||||||
const bookOffersRequest = self.remote.requestBookOffers({
|
|
||||||
taker_gets: {currency: taker_gets.currency,
|
|
||||||
issuer: taker_gets.counterparty},
|
|
||||||
taker_pays: {currency: taker_pays.currency,
|
|
||||||
issuer: taker_pays.counterparty},
|
|
||||||
ledger: parameters.ledger,
|
|
||||||
limit: parameters.limit,
|
|
||||||
taker: account
|
|
||||||
});
|
|
||||||
|
|
||||||
bookOffersRequest.once('success', resolve);
|
|
||||||
bookOffersRequest.once('error', reject);
|
|
||||||
bookOffersRequest.request();
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBids(parameters) {
|
|
||||||
const taker_gets = parameters.counter;
|
|
||||||
const taker_pays = parameters.base;
|
|
||||||
|
|
||||||
return getBookOffers(taker_gets, taker_pays, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAsks(parameters) {
|
|
||||||
const taker_gets = parameters.base;
|
|
||||||
const taker_pays = parameters.counter;
|
|
||||||
|
|
||||||
return getBookOffers(taker_gets, taker_pays, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBidsAndAsks(parameters) {
|
|
||||||
return Promise.join(
|
|
||||||
getBids(parameters),
|
|
||||||
getAsks(parameters),
|
|
||||||
function(bids, asks) {
|
|
||||||
return [bids, asks, parameters];
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getParsedBookOffers(offers, isAsk) {
|
|
||||||
return offers.reduce(function(orderBook, off) {
|
|
||||||
let price;
|
|
||||||
const order_maker = off.Account;
|
|
||||||
const sequence = off.Sequence;
|
|
||||||
|
|
||||||
// Transaction Flags
|
|
||||||
const passive = (off.Flags & ripple.Remote.flags.offer.Passive) !== 0;
|
|
||||||
const sell = (off.Flags & ripple.Remote.flags.offer.Sell) !== 0;
|
|
||||||
|
|
||||||
const taker_gets_total = utils.parseCurrencyAmount(off.TakerGets);
|
|
||||||
const taker_gets_funded = off.taker_gets_funded ?
|
|
||||||
utils.parseCurrencyAmount(off.taker_gets_funded) : taker_gets_total;
|
|
||||||
|
|
||||||
const taker_pays_total = utils.parseCurrencyAmount(off.TakerPays);
|
|
||||||
const taker_pays_funded = off.taker_pays_funded ?
|
|
||||||
utils.parseCurrencyAmount(off.taker_pays_funded) : taker_pays_total;
|
|
||||||
|
|
||||||
if (isAsk) {
|
|
||||||
price = {
|
|
||||||
currency: taker_pays_total.currency,
|
|
||||||
counterparty: taker_pays_total.counterparty,
|
|
||||||
value: bignum(taker_pays_total.value).div(
|
|
||||||
bignum(taker_gets_total.value))
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
price = {
|
|
||||||
currency: taker_gets_total.currency,
|
|
||||||
counterparty: taker_gets_total.counterparty,
|
|
||||||
value: bignum(taker_gets_total.value).div(
|
|
||||||
bignum(taker_pays_total.value))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
price.value = price.value.toString();
|
|
||||||
|
|
||||||
orderBook.push({
|
|
||||||
price: price,
|
|
||||||
taker_gets_funded: taker_gets_funded,
|
|
||||||
taker_gets_total: taker_gets_total,
|
|
||||||
taker_pays_funded: taker_pays_funded,
|
|
||||||
taker_pays_total: taker_pays_total,
|
|
||||||
order_maker: order_maker,
|
|
||||||
sequence: sequence,
|
|
||||||
passive: passive,
|
|
||||||
sell: sell
|
|
||||||
});
|
|
||||||
|
|
||||||
return orderBook;
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
function respondWithOrderBook(bids, asks, parameters) {
|
|
||||||
const promise = new Promise(function(resolve) {
|
|
||||||
const orderBook = {
|
|
||||||
order_book: parameters.order_book,
|
|
||||||
ledger: parameters.ledger,
|
|
||||||
validated: parameters.validated,
|
|
||||||
bids: getParsedBookOffers(bids.offers),
|
|
||||||
asks: getParsedBookOffers(asks.offers, true)
|
|
||||||
};
|
|
||||||
|
|
||||||
resolve(callback(null, orderBook));
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLastValidatedLedger(params)
|
|
||||||
.then(getBidsAndAsks)
|
|
||||||
.spread(respondWithOrderBook)
|
|
||||||
.catch(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an Order transaction (`OfferCreate` or `OfferCancel`)
|
|
||||||
*
|
|
||||||
* @url
|
|
||||||
* @param {RippleAddress} request.params.account
|
|
||||||
* @param {String} request.params.identifier
|
|
||||||
*
|
|
||||||
* @param {Express.js Request} request
|
|
||||||
*/
|
|
||||||
function getOrder(account, identifier, callback) {
|
|
||||||
validate.address(account);
|
|
||||||
validate.identifier(identifier);
|
|
||||||
|
|
||||||
const txRequest = this.remote.requestTx({
|
|
||||||
hash: identifier
|
|
||||||
});
|
|
||||||
|
|
||||||
txRequest.once('error', callback);
|
|
||||||
txRequest.once('transaction', function(tx) {
|
|
||||||
if (tx.TransactionType !== 'OfferCreate'
|
|
||||||
&& tx.TransactionType !== 'OfferCancel') {
|
|
||||||
callback(new errors.InvalidRequestError('Invalid parameter: identifier. '
|
|
||||||
+ 'The transaction corresponding to the given identifier '
|
|
||||||
+ 'is not an order'));
|
|
||||||
} else {
|
|
||||||
asyncify(parseTransaction)(tx, callback);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
txRequest.request();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getOrders: getOrders,
|
|
||||||
getOrderBook: getOrderBook,
|
|
||||||
getOrder: getOrder
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,128 +1,14 @@
|
|||||||
/* eslint-disable valid-jsdoc */
|
/* eslint-disable valid-jsdoc */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const asyncify = require('simple-asyncify');
|
const asyncify = require('simple-asyncify');
|
||||||
const bignum = require('bignumber.js');
|
const bignum = require('bignumber.js');
|
||||||
const transactions = require('./transactions');
|
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const validate = utils.common.validate;
|
const validate = utils.common.validate;
|
||||||
const parseTransaction = require('./parse/transaction');
|
|
||||||
const parsePathfind = require('./parse/pathfind');
|
const parsePathfind = require('./parse/pathfind');
|
||||||
|
|
||||||
const ValidationError = utils.common.errors.ValidationError;
|
|
||||||
const NotFoundError = utils.common.errors.NotFoundError;
|
const NotFoundError = utils.common.errors.NotFoundError;
|
||||||
const TimeOutError = utils.common.errors.TimeOutError;
|
const TimeOutError = utils.common.errors.TimeOutError;
|
||||||
|
|
||||||
const DEFAULT_RESULTS_PER_PAGE = 10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a transaction into ripple-rest Payment format
|
|
||||||
*
|
|
||||||
* @param {RippleAddress} account
|
|
||||||
* @param {Transaction} transaction
|
|
||||||
* @param {Function} callback
|
|
||||||
*
|
|
||||||
* @callback
|
|
||||||
* @param {Error} error
|
|
||||||
* @param {RippleRestTransaction} transaction
|
|
||||||
*/
|
|
||||||
function formatPaymentHelper(account, txJSON) {
|
|
||||||
if (!(txJSON && /^payment$/i.test(txJSON.TransactionType))) {
|
|
||||||
throw new ValidationError('Not a payment. The transaction '
|
|
||||||
+ 'corresponding to the given identifier is not a payment.');
|
|
||||||
}
|
|
||||||
return parseTransaction(txJSON);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the details of a particular payment from the Remote
|
|
||||||
* and return it in the ripple-rest Payment format.
|
|
||||||
*
|
|
||||||
* @param {Remote} remote
|
|
||||||
* @param {RippleAddress} req.params.account
|
|
||||||
* @param {Hex-encoded String|ASCII printable character String}
|
|
||||||
* req.params.identifier
|
|
||||||
*/
|
|
||||||
function getPayment(account, identifier, callback) {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
validate.address(account);
|
|
||||||
validate.identifier(identifier);
|
|
||||||
|
|
||||||
function getTransaction(_callback) {
|
|
||||||
transactions.getTransaction(self, account, identifier, {}, _callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
const steps = [
|
|
||||||
getTransaction,
|
|
||||||
asyncify(_.partial(formatPaymentHelper, account))
|
|
||||||
];
|
|
||||||
|
|
||||||
async.waterfall(steps, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the details of multiple payments from the Remote
|
|
||||||
*
|
|
||||||
* This function calls transactions.getAccountTransactions
|
|
||||||
* recursively to retrieve results_per_page number of transactions
|
|
||||||
* and filters the results by type "payment", along with the other
|
|
||||||
* client-specified parameters.
|
|
||||||
*
|
|
||||||
* @param {Remote} remote
|
|
||||||
* @param {RippleAddress} req.params.account
|
|
||||||
* @param {RippleAddress} req.query.source_account
|
|
||||||
* @param {RippleAddress} req.query.destination_account
|
|
||||||
* @param {String "incoming"|"outgoing"} req.query.direction
|
|
||||||
* @param {Number} [-1] req.query.start_ledger
|
|
||||||
* @param {Number} [-1] req.query.end_ledger
|
|
||||||
* @param {Boolean} [false] req.query.earliest_first
|
|
||||||
* @param {Boolean} [false] req.query.exclude_failed
|
|
||||||
* @param {Number} [20] req.query.results_per_page
|
|
||||||
* @param {Number} [1] req.query.page
|
|
||||||
*/
|
|
||||||
function getAccountPayments(account, source_account, destination_account,
|
|
||||||
direction, options, callback) {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
function getTransactions(_callback) {
|
|
||||||
const args = {
|
|
||||||
account: account,
|
|
||||||
source_account: source_account,
|
|
||||||
destination_account: destination_account,
|
|
||||||
direction: direction,
|
|
||||||
min: options.results_per_page,
|
|
||||||
max: options.results_per_page,
|
|
||||||
offset: (options.results_per_page || DEFAULT_RESULTS_PER_PAGE)
|
|
||||||
* ((options.page || 1) - 1),
|
|
||||||
types: ['payment'],
|
|
||||||
earliestFirst: options.earliest_first
|
|
||||||
};
|
|
||||||
|
|
||||||
transactions.getAccountTransactions(self,
|
|
||||||
_.merge(options, args), _callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatTransactions(_transactions) {
|
|
||||||
return _transactions.map(_.partial(formatPaymentHelper, account));
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatResponse(_transactions) {
|
|
||||||
return {payments: _transactions};
|
|
||||||
}
|
|
||||||
|
|
||||||
const steps = [
|
|
||||||
getTransactions,
|
|
||||||
_.partial(utils.attachDate, self),
|
|
||||||
asyncify(formatTransactions),
|
|
||||||
asyncify(formatResponse)
|
|
||||||
];
|
|
||||||
|
|
||||||
async.waterfall(steps, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a ripple path find, a.k.a. payment options,
|
* Get a ripple path find, a.k.a. payment options,
|
||||||
* for a given set of parameters and respond to the
|
* for a given set of parameters and respond to the
|
||||||
@@ -258,8 +144,4 @@ function getPathFind(pathfind, callback) {
|
|||||||
async.waterfall(steps, callback);
|
async.waterfall(steps, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = getPathFind;
|
||||||
getPayment: getPayment,
|
|
||||||
getAccountPayments: getAccountPayments,
|
|
||||||
getPathFind: getPathFind
|
|
||||||
};
|
|
||||||
@@ -41,6 +41,4 @@ function getSettings(account, callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = getSettings;
|
||||||
getSettings: getSettings
|
|
||||||
};
|
|
||||||
|
|||||||
74
src/api/ledger/transaction.js
Normal file
74
src/api/ledger/transaction.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
'use strict';
|
||||||
|
const _ = require('lodash');
|
||||||
|
const async = require('async');
|
||||||
|
const utils = require('./utils');
|
||||||
|
const parseTransaction = require('./parse/transaction');
|
||||||
|
const validate = utils.common.validate;
|
||||||
|
const errors = utils.common.errors;
|
||||||
|
const MIN_LEDGER_VERSION = 32570; // earlier versions have been completely lost
|
||||||
|
|
||||||
|
function hasCompleteLedgerRange(remote, options) {
|
||||||
|
const minLedgerVersion = options.minLedgerVersion || MIN_LEDGER_VERSION;
|
||||||
|
const maxLedgerVersion = options.maxLedgerVersion
|
||||||
|
|| remote.getLedgerSequence();
|
||||||
|
for (let i = minLedgerVersion; i <= maxLedgerVersion; i++) {
|
||||||
|
if (!remote.getServer().hasLedger(i)) { // TODO: optimize this
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachTransactionDate(remote, tx, callback) {
|
||||||
|
if (tx.date) {
|
||||||
|
callback(null, tx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!tx.ledger_index) {
|
||||||
|
callback(new errors.ApiError('ledger_index not found in tx'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
remote.requestLedger(tx.ledger_index, (error, data) => {
|
||||||
|
if (error) {
|
||||||
|
callback(new errors.NotFoundError('Transaction ledger not found'));
|
||||||
|
} else if (typeof data.ledger.close_time === 'number') {
|
||||||
|
callback(null, _.assign({date: data.ledger.close_time, tx}));
|
||||||
|
} else {
|
||||||
|
callback(new errors.ApiError('Ledger missing close_time'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTransactionInRange(tx, options) {
|
||||||
|
return (!options.minLedgerVersion
|
||||||
|
|| tx.ledger_index >= options.minLedgerVersion)
|
||||||
|
&& (!options.maxLedgerVersion
|
||||||
|
|| tx.ledger_index <= options.maxLedgerVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTransaction(identifier, options, callback) {
|
||||||
|
validate.identifier(identifier);
|
||||||
|
validate.options(options);
|
||||||
|
|
||||||
|
const remote = this.remote;
|
||||||
|
|
||||||
|
function callbackWrapper(error, tx) {
|
||||||
|
if (error instanceof errors.NotFoundError
|
||||||
|
&& !hasCompleteLedgerRange(remote, options)) {
|
||||||
|
callback(new errors.MissingLedgerHistoryError('Transaction not found,'
|
||||||
|
+ ' but the server\'s ledger history is incomplete'));
|
||||||
|
} else if (!error && !isTransactionInRange(tx, options)) {
|
||||||
|
callback(new errors.NotFoundError('Transaction not found'));
|
||||||
|
} else {
|
||||||
|
callback(error, parseTransaction(tx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
_.partial(remote.requestTx.bind(remote), {hash: identifier}),
|
||||||
|
_.partial(attachTransactionDate, remote)
|
||||||
|
], callbackWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = utils.wrapCatch(getTransaction);
|
||||||
@@ -1,79 +1,11 @@
|
|||||||
/* eslint-disable valid-jsdoc */
|
|
||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const async = require('async');
|
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const parseTransaction = require('./parse/transaction');
|
const parseTransaction = require('./parse/transaction');
|
||||||
|
const getTransaction = require('./transaction');
|
||||||
const validate = utils.common.validate;
|
const validate = utils.common.validate;
|
||||||
const errors = utils.common.errors;
|
|
||||||
const composeAsync = utils.common.composeAsync;
|
const composeAsync = utils.common.composeAsync;
|
||||||
|
|
||||||
const DEFAULT_LIMIT = 100;
|
const DEFAULT_LIMIT = 100;
|
||||||
const MIN_LEDGER_VERSION = 32570; // earlier versions have been completely lost
|
|
||||||
|
|
||||||
function hasCompleteLedgerRange(remote, options) {
|
|
||||||
const minLedgerVersion = options.minLedgerVersion || MIN_LEDGER_VERSION;
|
|
||||||
const maxLedgerVersion = options.maxLedgerVersion
|
|
||||||
|| remote.getLedgerSequence();
|
|
||||||
for (let i = minLedgerVersion; i <= maxLedgerVersion; i++) {
|
|
||||||
if (!remote.getServer().hasLedger(i)) { // TODO: optimize this
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachTransactionDate(remote, tx, callback) {
|
|
||||||
if (tx.date) {
|
|
||||||
callback(null, tx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!tx.ledger_index) {
|
|
||||||
callback(new errors.ApiError('ledger_index not found in tx'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
remote.requestLedger(tx.ledger_index, (error, data) => {
|
|
||||||
if (error) {
|
|
||||||
callback(new errors.NotFoundError('Transaction ledger not found'));
|
|
||||||
} else if (typeof data.ledger.close_time === 'number') {
|
|
||||||
callback(null, _.assign({date: data.ledger.close_time, tx}));
|
|
||||||
} else {
|
|
||||||
callback(new errors.ApiError('Ledger missing close_time'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function isTransactionInRange(tx, options) {
|
|
||||||
return (!options.minLedgerVersion
|
|
||||||
|| tx.ledger_index >= options.minLedgerVersion)
|
|
||||||
&& (!options.maxLedgerVersion
|
|
||||||
|| tx.ledger_index <= options.maxLedgerVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTransaction(identifier, options, callback) {
|
|
||||||
validate.identifier(identifier);
|
|
||||||
validate.options(options);
|
|
||||||
|
|
||||||
const remote = this.remote;
|
|
||||||
|
|
||||||
function callbackWrapper(error, tx) {
|
|
||||||
if (error instanceof errors.NotFoundError
|
|
||||||
&& !hasCompleteLedgerRange(remote, options)) {
|
|
||||||
callback(new errors.MissingLedgerHistoryError('Transaction not found,'
|
|
||||||
+ ' but the server\'s ledger history is incomplete'));
|
|
||||||
} else if (!error && !isTransactionInRange(tx, options)) {
|
|
||||||
callback(new errors.NotFoundError('Transaction not found'));
|
|
||||||
} else {
|
|
||||||
callback(error, parseTransaction(tx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async.waterfall([
|
|
||||||
_.partial(remote.requestTx.bind(remote), {hash: identifier}),
|
|
||||||
_.partial(attachTransactionDate, remote)
|
|
||||||
], callbackWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseAccountTxTransaction(tx) {
|
function parseAccountTxTransaction(tx) {
|
||||||
// rippled uses a different response format for 'account_tx' than 'tx'
|
// rippled uses a different response format for 'account_tx' than 'tx'
|
||||||
@@ -158,7 +90,4 @@ function getAccountTransactions(address, options, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = utils.wrapCatch(getAccountTransactions);
|
||||||
getTransaction: utils.wrapCatch(getTransaction),
|
|
||||||
getAccountTransactions: utils.wrapCatch(getAccountTransactions)
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -45,4 +45,4 @@ function getTrustlines(account: string, options: Options,
|
|||||||
utils.getRecursive(getter, limit, callback);
|
utils.getRecursive(getter, limit, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getTrustlines = getTrustlines;
|
module.exports = getTrustlines;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const core = require('./core');
|
const core = require('./core');
|
||||||
const RippleAPI = require('./api/api');
|
const RippleAPI = require('./api');
|
||||||
|
|
||||||
module.exports = _.assign({}, core, {RippleAPI: RippleAPI});
|
module.exports = _.assign({}, core, {RippleAPI: RippleAPI});
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const transactionResponse = require('./fixtures/transaction-response');
|
|||||||
const accountTransactionsResponse =
|
const accountTransactionsResponse =
|
||||||
require('./fixtures/account-transactions-response');
|
require('./fixtures/account-transactions-response');
|
||||||
const trustlinesResponse = require('./fixtures/trustlines-response');
|
const trustlinesResponse = require('./fixtures/trustlines-response');
|
||||||
|
const walletResponse = require('./fixtures/wallet.json');
|
||||||
|
|
||||||
function checkResult(expected, done, error, response) {
|
function checkResult(expected, done, error, response) {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -117,4 +118,10 @@ describe('RippleAPI', function() {
|
|||||||
this.api.getTrustlines(address, options,
|
this.api.getTrustlines(address, options,
|
||||||
_.partial(checkResult, trustlinesResponse, done));
|
_.partial(checkResult, trustlinesResponse, done));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('generateWallet', function() {
|
||||||
|
withDeterministicPRNG(() => {
|
||||||
|
assert.deepEqual(this.api.generateWallet(), walletResponse);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
4
test/fixtures/wallet.json
vendored
Normal file
4
test/fixtures/wallet.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"address": "ra2d1wnhDFyZGFz62wT3GSRhAEjpLuqfnj",
|
||||||
|
"secret": "ss4JedFMSQJa4mHQz3VZ58ZG4TYWg"
|
||||||
|
}
|
||||||
@@ -12,6 +12,10 @@ function MockPRNG(seed) {
|
|||||||
this.seed = seed || SEED;
|
this.seed = seed || SEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eslint-disable no-unused-vars */
|
||||||
|
MockPRNG.prototype.addEntropy = function(data, estimatedEntropy, source) {};
|
||||||
|
/* eslint-enable no-unused-vars */
|
||||||
|
|
||||||
MockPRNG.prototype.randomWord = function() {
|
MockPRNG.prototype.randomWord = function() {
|
||||||
const i = this.position;
|
const i = this.position;
|
||||||
this.position = (i + 8) % this.seed.length;
|
this.position = (i + 8) % this.seed.length;
|
||||||
|
|||||||
Reference in New Issue
Block a user