add more flow annotations to RippleApi

This commit is contained in:
Ivan Tivonenko
2015-10-06 06:47:18 +03:00
parent 462e440d5b
commit d47bb2749a
32 changed files with 685 additions and 158 deletions

55
src/api/common/types.js Normal file
View File

@@ -0,0 +1,55 @@
/* @flow */
'use strict';
export type RippledAmountIOU = {
currency: string,
value: string,
issuer?: string
}
export type RippledAmount = string | RippledAmountIOU
export type Amount = {
value: string,
currency: string,
counterparty?: string
}
// Amount where counterparty and value are optional
export type LaxLaxAmount = {
currency: string,
value?: string,
counterparty?: string
}
// A currency-counterparty pair, or just currency if it's XRP
export type Issue = {
currency: string,
counterparty?: string
}
export type Adjustment = {
address: string,
amount: Amount,
tag?: number
}
export type MaxAdjustment = {
address: string,
maxAmount: Amount,
tag?: number
}
export type MinAdjustment = {
address: string,
minAmount: Amount,
tag?: number
}
export type Memo = {
type?: string,
format?: string,
data?: string
}

View File

@@ -7,7 +7,7 @@ const errors = require('./errors');
const es6promisify = require('es6-promisify'); const es6promisify = require('es6-promisify');
const keypairs = require('ripple-keypairs'); const keypairs = require('ripple-keypairs');
type Amount = {currency: string, issuer: string, value: string} import type {Amount, RippledAmount} from './types.js';
function dropsToXrp(drops: string): string { function dropsToXrp(drops: string): string {
return (new BigNumber(drops)).dividedBy(1000000.0).toString(); return (new BigNumber(drops)).dividedBy(1000000.0).toString();
@@ -17,13 +17,14 @@ function xrpToDrops(xrp: string): string {
return (new BigNumber(xrp)).times(1000000.0).floor().toString(); return (new BigNumber(xrp)).times(1000000.0).floor().toString();
} }
function toRippledAmount(amount: Amount): string|Amount { function toRippledAmount(amount: Amount): RippledAmount {
if (amount.currency === 'XRP') { if (amount.currency === 'XRP') {
return xrpToDrops(amount.value); return xrpToDrops(amount.value);
} }
return { return {
currency: amount.currency, currency: amount.currency,
issuer: amount.counterparty ? amount.counterparty : amount.issuer, issuer: amount.counterparty ? amount.counterparty :
(amount.issuer ? amount.issuer : undefined),
value: amount.value value: amount.value
}; };
} }

View File

@@ -1,3 +1,4 @@
/* @flow */
'use strict'; 'use strict';
const _ = require('lodash'); const _ = require('lodash');
@@ -5,8 +6,23 @@ const utils = require('./utils');
const validate = utils.common.validate; const validate = utils.common.validate;
const composeAsync = utils.common.composeAsync; const composeAsync = utils.common.composeAsync;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
import type {Amount} from '../common/types.js';
function formatBalanceSheet(balanceSheet) { type BalanceSheetOptions = {
excludeAddresses?: Array<string>,
ledgerVersion?: number
}
type GetBalanceSheet = {
balances?: Array<Amount>,
assets?: Array<Amount>,
obligations?: Array<{
currency: string,
value: string
}>
}
function formatBalanceSheet(balanceSheet): GetBalanceSheet {
const result = {}; const result = {};
if (!_.isUndefined(balanceSheet.balances)) { if (!_.isUndefined(balanceSheet.balances)) {
@@ -33,7 +49,9 @@ function formatBalanceSheet(balanceSheet) {
return result; return result;
} }
function getBalanceSheetAsync(address, options, callback) { function getBalanceSheetAsync(address: string, options: BalanceSheetOptions,
callback
) {
validate.address(address); validate.address(address);
validate.getBalanceSheetOptions(options); validate.getBalanceSheetOptions(options);
@@ -61,7 +79,8 @@ function getBalanceSheetAsync(address, options, callback) {
}); });
} }
function getBalanceSheet(address: string, options = {}) { function getBalanceSheet(address: string, options: BalanceSheetOptions = {}
): Promise<GetBalanceSheet> {
return utils.promisify(getBalanceSheetAsync).call(this, address, options); return utils.promisify(getBalanceSheetAsync).call(this, address, options);
} }

View File

@@ -7,11 +7,20 @@ 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 convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
import type {Remote} from '../../core/remote'; import type {Remote, GetLedgerSequenceCallback} from '../../core/remote';
import type {GetLedgerSequenceCallback} from '../../core/remote';
import type {TrustlinesOptions, Trustline} from './trustlines-types.js';
function getTrustlineBalanceAmount(trustline) { type Balance = {
value: string,
currency: string,
counterparty?: string
}
type GetBalances = Array<Balance>
function getTrustlineBalanceAmount(trustline: Trustline) {
return { return {
currency: trustline.specification.currency, currency: trustline.specification.currency,
counterparty: trustline.specification.counterparty, counterparty: trustline.specification.counterparty,
@@ -28,7 +37,9 @@ function formatBalances(balances) {
balances.trustlines.map(getTrustlineBalanceAmount)); balances.trustlines.map(getTrustlineBalanceAmount));
} }
function getTrustlinesAsync(account, options, callback) { function getTrustlinesAsync(account: string, options: TrustlinesOptions,
callback
) {
getTrustlines.call(this, account, options) getTrustlines.call(this, account, options)
.then(data => callback(null, data)) .then(data => callback(null, data))
.catch(callback); .catch(callback);
@@ -44,7 +55,9 @@ function getLedgerVersionHelper(remote: Remote, optionValue?: number,
} }
} }
function getBalancesAsync(account, options, callback) { function getBalancesAsync(account: string, options: TrustlinesOptions,
callback
) {
validate.address(account); validate.address(account);
validate.getBalancesOptions(options); validate.getBalancesOptions(options);
@@ -57,7 +70,8 @@ function getBalancesAsync(account, options, callback) {
}, composeAsync(formatBalances, convertErrors(callback))); }, composeAsync(formatBalances, convertErrors(callback)));
} }
function getBalances(account: string, options = {}) { function getBalances(account: string, options: TrustlinesOptions = {}
): Promise<GetBalances> {
return utils.promisify(getBalancesAsync).call(this, account, options); return utils.promisify(getBalancesAsync).call(this, account, options);
} }

View File

@@ -5,8 +5,17 @@ const validate = utils.common.validate;
const composeAsync = utils.common.composeAsync; const composeAsync = utils.common.composeAsync;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
const parseLedger = require('./parse/ledger'); const parseLedger = require('./parse/ledger');
import type {GetLedger} from './types.js';
function getLedgerAsync(options, callback) { type LedgerOptions = {
ledgerVersion?: number,
includeAllData?: boolean,
includeTransactions?: boolean,
includeState?: boolean
}
function getLedgerAsync(options: LedgerOptions, callback) {
validate.getLedgerOptions(options); validate.getLedgerOptions(options);
const request = { const request = {
@@ -21,7 +30,7 @@ function getLedgerAsync(options, callback) {
convertErrors(callback))); convertErrors(callback)));
} }
function getLedger(options = {}) { function getLedger(options: LedgerOptions = {}): Promise<GetLedger> {
return utils.promisify(getLedgerAsync).call(this, options); return utils.promisify(getLedgerAsync).call(this, options);
} }

View File

@@ -7,11 +7,40 @@ const validate = utils.common.validate;
const composeAsync = utils.common.composeAsync; const composeAsync = utils.common.composeAsync;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
const parseOrderbookOrder = require('./parse/orderbook-order'); const parseOrderbookOrder = require('./parse/orderbook-order');
import type {Remote} from '../../core/remote';
import type {OrdersOptions, OrderSpecification} from './types.js';
import type {Amount, Issue} from '../common/types.js';
type Orderbook = {
base: Issue,
counter: Issue
}
type OrderbookItem = {
specification: OrderSpecification,
properties: {
maker: string,
sequence: number,
makerExchangeRate: string
},
state?: {
fundedAmount: Amount,
priceOfFundedAmount: Amount
}
}
type OrderbookOrders = Array<OrderbookItem>
type GetOrderbook = {
bids: OrderbookOrders,
asks: OrderbookOrders
}
// account is to specify a "perspective", which affects which unfunded offers // account is to specify a "perspective", which affects which unfunded offers
// are returned // are returned
function getBookOffers(remote, account, ledgerVersion, limit, function getBookOffers(remote: Remote, account: string,
takerGets, takerPays, callback ledgerVersion?: number, limit?: number, takerGets: Issue,
takerPays: Issue, callback
) { ) {
remote.requestBookOffers(utils.renameCounterpartyToIssuerInOrder({ remote.requestBookOffers(utils.renameCounterpartyToIssuerInOrder({
taker_gets: takerGets, taker_gets: takerGets,
@@ -22,15 +51,15 @@ function getBookOffers(remote, account, ledgerVersion, limit,
}), composeAsync(data => data.offers, convertErrors(callback))); }), composeAsync(data => data.offers, convertErrors(callback)));
} }
function isSameIssue(a, b) { function isSameIssue(a: Amount, b: Amount) {
return a.currency === b.currency && a.counterparty === b.counterparty; return a.currency === b.currency && a.counterparty === b.counterparty;
} }
function directionFilter(direction, order) { function directionFilter(direction: string, order: OrderbookItem) {
return order.specification.direction === direction; return order.specification.direction === direction;
} }
function flipOrder(order) { function flipOrder(order: OrderbookItem) {
const specification = order.specification; const specification = order.specification;
const flippedSpecification = { const flippedSpecification = {
quantity: specification.totalPrice, quantity: specification.totalPrice,
@@ -41,12 +70,12 @@ function flipOrder(order) {
return _.merge({}, order, {specification: newSpecification}); return _.merge({}, order, {specification: newSpecification});
} }
function alignOrder(base, order) { function alignOrder(base: Amount, order: OrderbookItem) {
const quantity = order.specification.quantity; const quantity = order.specification.quantity;
return isSameIssue(quantity, base) ? order : flipOrder(order); return isSameIssue(quantity, base) ? order : flipOrder(order);
} }
function formatBidsAndAsks(orderbook, offers) { function formatBidsAndAsks(orderbook: Orderbook, offers) {
// the "base" currency is the currency that you are buying or selling // the "base" currency is the currency that you are buying or selling
// the "counter" is the currency that the "base" is priced in // the "counter" is the currency that the "base" is priced in
// a "bid"/"ask" is an order to buy/sell the base, respectively // a "bid"/"ask" is an order to buy/sell the base, respectively
@@ -64,7 +93,9 @@ function formatBidsAndAsks(orderbook, offers) {
return {bids, asks}; return {bids, asks};
} }
function getOrderbookAsync(account, orderbook, options, callback) { function getOrderbookAsync(account: string, orderbook: Orderbook,
options: OrdersOptions, callback
) {
validate.address(account); validate.address(account);
validate.orderbook(orderbook); validate.orderbook(orderbook);
validate.getOrderbookOptions(options); validate.getOrderbookOptions(options);
@@ -78,7 +109,9 @@ function getOrderbookAsync(account, orderbook, options, callback) {
callback)); callback));
} }
function getOrderbook(account: string, orderbook: Object, options = {}) { function getOrderbook(account: string, orderbook: Orderbook,
options: OrdersOptions = {}
): Promise<GetOrderbook> {
return utils.promisify(getOrderbookAsync).call(this, return utils.promisify(getOrderbookAsync).call(this,
account, orderbook, options); account, orderbook, options);
} }

View File

@@ -7,9 +7,13 @@ const validate = utils.common.validate;
const composeAsync = utils.common.composeAsync; const composeAsync = utils.common.composeAsync;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
const parseAccountOrder = require('./parse/account-order'); const parseAccountOrder = require('./parse/account-order');
import type {Remote} from '../../core/remote';
import type {OrdersOptions, Order} from './types.js';
function requestAccountOffers(remote, address, ledgerVersion, marker, limit, type GetOrders = Array<Order>
callback
function requestAccountOffers(remote: Remote, address: string,
ledgerVersion: number, marker: string, limit: number, callback
) { ) {
remote.requestAccountOffers({ remote.requestAccountOffers({
account: address, account: address,
@@ -23,7 +27,7 @@ function requestAccountOffers(remote, address, ledgerVersion, marker, limit,
}), convertErrors(callback))); }), convertErrors(callback)));
} }
function getOrdersAsync(account, options, callback) { function getOrdersAsync(account: string, options: OrdersOptions, callback) {
validate.address(account); validate.address(account);
validate.getOrdersOptions(options); validate.getOrdersOptions(options);
@@ -34,7 +38,8 @@ function getOrdersAsync(account, options, callback) {
(order) => order.properties.sequence), callback)); (order) => order.properties.sequence), callback));
} }
function getOrders(account: string, options = {}) { function getOrders(account: string, options: OrdersOptions = {}
): Promise<GetOrders> {
return utils.promisify(async.seq( return utils.promisify(async.seq(
utils.getLedgerOptionsWithLedgerVersion, utils.getLedgerOptionsWithLedgerVersion,
getOrdersAsync)).call(this, account, options); getOrdersAsync)).call(this, account, options);

View File

@@ -1,13 +1,10 @@
/* @flow */ /* @flow */
'use strict'; 'use strict';
const utils = require('./utils'); const utils = require('./utils');
import type {Amount, RippledAmount} from '../../common/types.js';
type Amount = string | {currency: string, issuer: string, value: string}
type XRPAmount = {currency: string, value: string}
type IOUAmount = {currency: string, value: string, counterparty: string}
type Output = XRPAmount | IOUAmount
function parseAmount(amount: Amount): Output { function parseAmount(amount: RippledAmount): Amount {
if (typeof amount === 'string') { if (typeof amount === 'string') {
return { return {
currency: 'XRP', currency: 'XRP',

View File

@@ -3,6 +3,7 @@
const _ = require('lodash'); const _ = require('lodash');
const removeUndefined = require('./utils').removeUndefined; const removeUndefined = require('./utils').removeUndefined;
const parseTransaction = require('./transaction'); const parseTransaction = require('./transaction');
import type {GetLedger} from '../types.js';
function parseTransactions(transactions) { function parseTransactions(transactions) {
if (_.isEmpty(transactions)) { if (_.isEmpty(transactions)) {
@@ -27,7 +28,7 @@ function parseState(state) {
return {rawState: JSON.stringify(state)}; return {rawState: JSON.stringify(state)};
} }
function parseLedger(ledger: Object): Object { function parseLedger(ledger: Object): GetLedger {
return removeUndefined(_.assign({ return removeUndefined(_.assign({
accepted: ledger.accepted, accepted: ledger.accepted,
closed: ledger.closed, closed: ledger.closed,

View File

@@ -2,13 +2,15 @@
'use strict'; 'use strict';
const _ = require('lodash'); const _ = require('lodash');
const parseAmount = require('./amount'); const parseAmount = require('./amount');
import type {Amount, RippledAmount} from '../../common/types.js';
import type {GetPaths, RippledPathsResponse} from '../pathfind-types.js';
function parsePaths(paths) { function parsePaths(paths) {
return paths.map(steps => steps.map(step => return paths.map(steps => steps.map(step =>
_.omit(step, ['type', 'type_hex']))); _.omit(step, ['type', 'type_hex'])));
} }
function removeAnyCounterpartyEncoding(address: string, amount: Object) { function removeAnyCounterpartyEncoding(address: string, amount: Amount) {
return amount.counterparty === address ? return amount.counterparty === address ?
_.omit(amount, 'counterparty') : amount; _.omit(amount, 'counterparty') : amount;
} }
@@ -21,7 +23,7 @@ function createAdjustment(address: string, adjustmentWithoutAddress: Object) {
} }
function parseAlternative(sourceAddress: string, destinationAddress: string, function parseAlternative(sourceAddress: string, destinationAddress: string,
destinationAmount: Object, alternative: Object destinationAmount: RippledAmount, alternative: Object
) { ) {
// we use "maxAmount"/"minAmount" here so that the result can be passed // we use "maxAmount"/"minAmount" here so that the result can be passed
// directly to preparePayment // directly to preparePayment
@@ -38,7 +40,7 @@ function parseAlternative(sourceAddress: string, destinationAddress: string,
}; };
} }
function parsePathfind(pathfindResult: Object): Object { function parsePathfind(pathfindResult: RippledPathsResponse): GetPaths {
const sourceAddress = pathfindResult.source_account; const sourceAddress = pathfindResult.source_account;
const destinationAddress = pathfindResult.destination_account; const destinationAddress = pathfindResult.destination_account;
const destinationAmount = pathfindResult.destination_amount; const destinationAmount = pathfindResult.destination_amount;

View File

@@ -0,0 +1,54 @@
/* @flow */
'use strict';
import type {Amount, LaxLaxAmount, RippledAmount, Adjustment, MaxAdjustment,
MinAdjustment} from '../common/types.js';
type Path = {
source: Adjustment | MaxAdjustment,
destination: Adjustment | MinAdjustment,
paths: string
}
export type GetPaths = Array<Path>
export type PathFind = {
source: {
address: string,
amount?: Amount,
currencies?: Array<{currency: string, counterparty?:string}>
},
destination: {
address: string,
amount: LaxLaxAmount
}
}
export type PathFindParams = {
src_account: string,
dst_amount: RippledAmount,
dst_account: string,
src_amount?: RippledAmount,
src_currencies?: Array<string>
}
export type RippledPathsResponse = {
alternatives: Array<{
paths_computed: Array<Array<{
type: number,
type_hex: string,
account?: string,
issuer?: string,
currency?: string
}>>,
source_amount: RippledAmount
}>,
type: string,
destination_account: string,
destination_amount: RippledAmount,
destination_currencies?: Array<string>,
source_account?: string,
source_currencies?: Array<{currency: string}>,
full_reply?: boolean
}

View File

@@ -11,27 +11,20 @@ const ValidationError = utils.common.errors.ValidationError;
const composeAsync = utils.common.composeAsync; const composeAsync = utils.common.composeAsync;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
const toRippledAmount = utils.common.toRippledAmount; const toRippledAmount = utils.common.toRippledAmount;
import type {Remote} from '../../core/remote';
import type {RippledAmount} from '../common/types.js';
import type {GetPaths, PathFind, PathFindParams,
RippledPathsResponse} from './pathfind-types.js';
type PathFindParams = {
src_currencies?: Array<string>, src_account: string,
dst_amount: string | Object, dst_account?: string,
src_amount?: string | Object
}
function addParams(params: PathFindParams, result: {}) { function addParams(params: PathFindParams, result: RippledPathsResponse) {
return _.assign({}, result, { return _.defaults(_.assign({}, result, {
source_account: params.src_account, source_account: params.src_account,
source_currencies: params.src_currencies, source_currencies: params.src_currencies
destination_amount: params.dst_amount }), {destination_amount: params.dst_amount});
});
} }
type PathFind = { function requestPathFind(remote: Remote, pathfind: PathFind, callback) {
source: {address: string, currencies: Array<string>},
destination: {address: string, amount: string}
}
function requestPathFind(remote, pathfind: PathFind, callback) {
const destinationAmount = _.assign({value: -1}, pathfind.destination.amount); const destinationAmount = _.assign({value: -1}, pathfind.destination.amount);
const params: PathFindParams = { const params: PathFindParams = {
src_account: pathfind.source.address, src_account: pathfind.source.address,
@@ -65,7 +58,8 @@ function requestPathFind(remote, pathfind: PathFind, callback) {
composeAsync(_.partial(addParams, params), convertErrors(callback))); composeAsync(_.partial(addParams, params), convertErrors(callback)));
} }
function addDirectXrpPath(paths, xrpBalance) { function addDirectXrpPath(paths: RippledPathsResponse, xrpBalance: string
): RippledPathsResponse {
// Add XRP "path" only if the source acct has enough XRP to make the payment // Add XRP "path" only if the source acct has enough XRP to make the payment
const destinationAmount = paths.destination_amount; const destinationAmount = paths.destination_amount;
if ((new BigNumber(xrpBalance)).greaterThanOrEqualTo(destinationAmount)) { if ((new BigNumber(xrpBalance)).greaterThanOrEqualTo(destinationAmount)) {
@@ -77,13 +71,15 @@ function addDirectXrpPath(paths, xrpBalance) {
return paths; return paths;
} }
function isRippledIOUAmount(amount) { function isRippledIOUAmount(amount: RippledAmount) {
// rippled XRP amounts are specified as decimal strings // rippled XRP amounts are specified as decimal strings
return (typeof amount === 'object') && return (typeof amount === 'object') &&
amount.currency && (amount.currency !== 'XRP'); amount.currency && (amount.currency !== 'XRP');
} }
function conditionallyAddDirectXRPPath(remote, address, paths, callback) { function conditionallyAddDirectXRPPath(remote: Remote, address: string,
paths: RippledPathsResponse, callback
) {
if (isRippledIOUAmount(paths.destination_amount) if (isRippledIOUAmount(paths.destination_amount)
|| !_.includes(paths.destination_currencies, 'XRP')) { || !_.includes(paths.destination_currencies, 'XRP')) {
callback(null, paths); callback(null, paths);
@@ -93,7 +89,7 @@ function conditionallyAddDirectXRPPath(remote, address, paths, callback) {
} }
} }
function formatResponse(pathfind, paths) { function formatResponse(pathfind: PathFind, paths: RippledPathsResponse) {
if (paths.alternatives && paths.alternatives.length > 0) { if (paths.alternatives && paths.alternatives.length > 0) {
return parsePathfind(paths); return parsePathfind(paths);
} }
@@ -118,7 +114,7 @@ function formatResponse(pathfind, paths) {
} }
} }
function getPathsAsync(pathfind, callback) { function getPathsAsync(pathfind: PathFind, callback) {
validate.pathfind(pathfind); validate.pathfind(pathfind);
const address = pathfind.source.address; const address = pathfind.source.address;
@@ -128,7 +124,7 @@ function getPathsAsync(pathfind, callback) {
], composeAsync(_.partial(formatResponse, pathfind), callback)); ], composeAsync(_.partial(formatResponse, pathfind), callback));
} }
function getPaths(pathfind: Object) { function getPaths(pathfind: PathFind): Promise<GetPaths> {
return utils.promisify(getPathsAsync).call(this, pathfind); return utils.promisify(getPathsAsync).call(this, pathfind);
} }

View File

@@ -8,6 +8,31 @@ const composeAsync = utils.common.composeAsync;
const AccountFlags = utils.common.constants.AccountFlags; const AccountFlags = utils.common.constants.AccountFlags;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
type SettingsOptions = {
ledgerVersion?: number
}
type GetSettings = {
passwordSpent?: boolean,
requireDestinationTag?: boolean,
requireAuthorization?: boolean,
disallowIncomingXRP?: boolean,
disableMasterKey?: boolean,
enableTransactionIDTracking?: boolean,
noFreeze?: boolean,
globalFreeze?: boolean,
defaultRipple?: boolean,
emailHash?: ?string,
walletLocator?: ?string,
walletSize?: ?number,
messageKey?: string,
domain?: string,
transferRate?: ?number,
signers?: string,
regularKey?: string
}
function parseFlags(value) { function parseFlags(value) {
const settings = {}; const settings = {};
for (const flagName in AccountFlags) { for (const flagName in AccountFlags) {
@@ -25,7 +50,7 @@ function formatSettings(response) {
return _.assign({}, parsedFlags, parsedFields); return _.assign({}, parsedFlags, parsedFields);
} }
function getSettingsAsync(account, options, callback) { function getSettingsAsync(account: string, options: SettingsOptions, callback) {
validate.address(account); validate.address(account);
validate.getSettingsOptions(options); validate.getSettingsOptions(options);
@@ -38,7 +63,8 @@ function getSettingsAsync(account, options, callback) {
composeAsync(formatSettings, convertErrors(callback))); composeAsync(formatSettings, convertErrors(callback)));
} }
function getSettings(account: string, options = {}) { function getSettings(account: string, options: SettingsOptions = {}
): Promise<GetSettings> {
return utils.promisify(getSettingsAsync).call(this, account, options); return utils.promisify(getSettingsAsync).call(this, account, options);
} }

View File

@@ -1,14 +1,16 @@
/* @flow */ /* @flow */
'use strict'; 'use strict';
import type {Amount, Memo} from '../common/types.js';
type Outcome = { type Outcome = {
result: string, result: string,
timestamp?: string, ledgerVersion: number,
indexInLedger: number,
fee: string, fee: string,
balanceChanges: Object, balanceChanges: Object,
orderbookChanges: Object, orderbookChanges: Object,
ledgerVersion: number, timestamp?: string
indexInLedger: number
} }
type Adjustment = { type Adjustment = {
@@ -56,18 +58,6 @@ type OrderCancellation = {
orderSequence: number orderSequence: number
} }
type Memo = {
type?: string,
format?: string,
data?: string
}
type Amount = {
value: string,
currency: string,
counterparty?: string
}
type Payment = { type Payment = {
source: Adjustment, source: Adjustment,
destination: Adjustment, destination: Adjustment,
@@ -88,7 +78,7 @@ type PaymentTransaction = {
sequence: number sequence: number
} }
type Order = { export type Order = {
direction: string, direction: string,
quantity: Amount, quantity: Amount,
totalPrice: Amount, totalPrice: Amount,
@@ -138,10 +128,10 @@ export type TransactionOptions = {
maxLedgerVersion?: number maxLedgerVersion?: number
} }
export type GetTransactionResponse = PaymentTransaction | OrderTransaction | export type TransactionType = PaymentTransaction | OrderTransaction |
OrderCancellationTransaction | TrustlineTransaction | SettingsTransaction OrderCancellationTransaction | TrustlineTransaction | SettingsTransaction
export type GetTransactionResponseCallback = export type GetTransactionResponseCallback =
(err?: ?Error, data?: GetTransactionResponse) => void (err?: ?Error, data?: TransactionType) => void
export type CallbackType = (err?: ?Error, data?: Object) => void export type CallbackType = (err?: ?Error, data?: Object) => void

View File

@@ -11,7 +11,7 @@ const RippleError = require('../../core/rippleerror').RippleError;
import type {Remote} from '../../core/remote'; import type {Remote} from '../../core/remote';
import type {CallbackType, GetTransactionResponse, import type {CallbackType, TransactionType,
GetTransactionResponseCallback, TransactionOptions} GetTransactionResponseCallback, TransactionOptions}
from './transaction-types'; from './transaction-types';
@@ -106,7 +106,7 @@ function getTransactionAsync(identifier: string, options: TransactionOptions,
function getTransaction(identifier: string, function getTransaction(identifier: string,
options: TransactionOptions = {} options: TransactionOptions = {}
): Promise<GetTransactionResponse> { ): Promise<TransactionType> {
return utils.promisify(getTransactionAsync).call(this, identifier, options); return utils.promisify(getTransactionAsync).call(this, identifier, options);
} }

View File

@@ -9,6 +9,29 @@ const validate = utils.common.validate;
const composeAsync = utils.common.composeAsync; const composeAsync = utils.common.composeAsync;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
import type {Remote} from '../../core/remote';
import type {TransactionType} from './transaction-types';
type TransactionsOptions = {
start?: string,
limit?: number,
minLedgerVersion?: number,
maxLedgerVersion?: number,
earliestFirst?: boolean,
excludeFailures?: boolean,
initiated?: boolean,
counterparty?: string,
types?: Array<string>,
binary?: boolean,
startTx?: TransactionType
}
type GetTransactionsResponse = Array<TransactionType>
type CallbackType = (err?: ?Error, data?: GetTransactionsResponse) => void
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'
tx.tx.meta = tx.meta; tx.tx.meta = tx.meta;
@@ -16,7 +39,7 @@ function parseAccountTxTransaction(tx) {
return parseTransaction(tx.tx); return parseTransaction(tx.tx);
} }
function counterpartyFilter(filters, tx) { function counterpartyFilter(filters, tx: TransactionType) {
if (!filters.counterparty) { if (!filters.counterparty) {
return true; return true;
} }
@@ -31,7 +54,9 @@ function counterpartyFilter(filters, tx) {
return false; return false;
} }
function transactionFilter(address, filters, tx) { function transactionFilter(address: string, filters: TransactionsOptions,
tx: TransactionType
) {
if (filters.excludeFailures && tx.outcome.result !== 'tesSUCCESS') { if (filters.excludeFailures && tx.outcome.result !== 'tesSUCCESS') {
return false; return false;
} }
@@ -50,13 +75,15 @@ function transactionFilter(address, filters, tx) {
return true; return true;
} }
function orderFilter(options, tx) { function orderFilter(options: TransactionsOptions, tx: TransactionType) {
return !options.startTx || (options.earliestFirst ? return !options.startTx || (options.earliestFirst ?
utils.compareTransactions(tx, options.startTx) > 0 : utils.compareTransactions(tx, options.startTx) > 0 :
utils.compareTransactions(tx, options.startTx) < 0); utils.compareTransactions(tx, options.startTx) < 0);
} }
function formatPartialResponse(address, options, data) { function formatPartialResponse(address: string,
options: TransactionsOptions, data
) {
return { return {
marker: data.marker, marker: data.marker,
results: data.transactions results: data.transactions
@@ -67,7 +94,9 @@ function formatPartialResponse(address, options, data) {
}; };
} }
function getAccountTx(remote, address, options, marker, limit, callback) { function getAccountTx(remote: Remote, address: string,
options: TransactionsOptions, marker: string, limit: number, callback
) {
const params = { const params = {
account: address, account: address,
// -1 is equivalent to earliest available validated ledger // -1 is equivalent to earliest available validated ledger
@@ -85,7 +114,9 @@ function getAccountTx(remote, address, options, marker, limit, callback) {
convertErrors(callback))); convertErrors(callback)));
} }
function checkForLedgerGaps(remote, options, transactions) { function checkForLedgerGaps(remote: Remote, options: TransactionsOptions,
transactions: GetTransactionsResponse
) {
let {minLedgerVersion, maxLedgerVersion} = options; let {minLedgerVersion, maxLedgerVersion} = options;
// if we reached the limit on number of transactions, then we can shrink // if we reached the limit on number of transactions, then we can shrink
@@ -105,7 +136,9 @@ function checkForLedgerGaps(remote, options, transactions) {
} }
} }
function formatResponse(remote, options, transactions) { function formatResponse(remote: Remote, options: TransactionsOptions,
transactions: GetTransactionsResponse
) {
const compare = options.earliestFirst ? utils.compareTransactions : const compare = options.earliestFirst ? utils.compareTransactions :
_.rearg(utils.compareTransactions, 1, 0); _.rearg(utils.compareTransactions, 1, 0);
const sortedTransactions = transactions.sort(compare); const sortedTransactions = transactions.sort(compare);
@@ -113,13 +146,17 @@ function formatResponse(remote, options, transactions) {
return sortedTransactions; return sortedTransactions;
} }
function getTransactionsInternal(remote, address, options, callback) { function getTransactionsInternal(remote: Remote, address: string,
options: TransactionsOptions, callback
) {
const getter = _.partial(getAccountTx, remote, address, options); const getter = _.partial(getAccountTx, remote, address, options);
const format = _.partial(formatResponse, remote, options); const format = _.partial(formatResponse, remote, options);
utils.getRecursive(getter, options.limit, composeAsync(format, callback)); utils.getRecursive(getter, options.limit, composeAsync(format, callback));
} }
function getTransactionsAsync(account, options, callback) { function getTransactionsAsync(account: string,
options: TransactionsOptions, callback: CallbackType
) {
validate.address(account); validate.address(account);
validate.getTransactionsOptions(options); validate.getTransactionsOptions(options);
@@ -138,7 +175,8 @@ function getTransactionsAsync(account, options, callback) {
} }
} }
function getTransactions(account: string, options = {}) { function getTransactions(account: string, options: TransactionsOptions = {}
): Promise<GetTransactionsResponse> {
return utils.promisify(getTransactionsAsync).call(this, account, options); return utils.promisify(getTransactionsAsync).call(this, account, options);
} }

View File

@@ -0,0 +1,33 @@
/* @flow */
'use strict';
export type TrustLineSpecification = {
currency: string,
counterparty: string,
limit: string,
qualityIn?: number,
qualityOut?: number,
ripplingDisabled?: boolean,
authorized?: boolean,
frozen?: boolean
}
export type Trustline = {
specification: TrustLineSpecification,
counterparty: {
limit: string,
ripplingDisabled?: boolean,
frozen?: boolean,
authorized?: boolean
},
state: {
balance: string
}
}
export type TrustlinesOptions = {
counterparty?: string,
currency?: string,
limit?: number,
ledgerVersion?: number
}

View File

@@ -8,11 +8,17 @@ const composeAsync = utils.common.composeAsync;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
const parseAccountTrustline = require('./parse/account-trustline'); const parseAccountTrustline = require('./parse/account-trustline');
function currencyFilter(currency, trustline) { import type {Remote} from '../../core/remote';
import type {TrustlinesOptions, Trustline} from './trustlines-types.js';
type GetTrustlinesResponse = Array<Trustline>
function currencyFilter(currency: string, trustline: Trustline) {
return currency === null || trustline.specification.currency === currency; return currency === null || trustline.specification.currency === currency;
} }
function formatResponse(options, data) { function formatResponse(options: TrustlinesOptions, data) {
return { return {
marker: data.marker, marker: data.marker,
results: data.lines.map(parseAccountTrustline) results: data.lines.map(parseAccountTrustline)
@@ -20,8 +26,8 @@ function formatResponse(options, data) {
}; };
} }
function getAccountLines(remote, address, ledgerVersion, options, marker, limit, function getAccountLines(remote: Remote, address: string, ledgerVersion: number,
callback options: TrustlinesOptions, marker: string, limit: number, callback
) { ) {
const requestOptions = { const requestOptions = {
account: address, account: address,
@@ -36,8 +42,7 @@ function getAccountLines(remote, address, ledgerVersion, options, marker, limit,
convertErrors(callback))); convertErrors(callback)));
} }
function getTrustlinesAsync(account: string, options: {currency: string, function getTrustlinesAsync(account: string, options: TrustlinesOptions,
counterparty: string, limit: number, ledgerVersion: number},
callback: () => void callback: () => void
): void { ): void {
validate.address(account); validate.address(account);
@@ -48,7 +53,8 @@ function getTrustlinesAsync(account: string, options: {currency: string,
utils.getRecursive(getter, options.limit, callback); utils.getRecursive(getter, options.limit, callback);
} }
function getTrustlines(account: string, options = {}) { function getTrustlines(account: string, options: TrustlinesOptions = {}
): Promise<GetTrustlinesResponse> {
return utils.promisify(async.seq( return utils.promisify(async.seq(
utils.getLedgerOptionsWithLedgerVersion, utils.getLedgerOptionsWithLedgerVersion,
getTrustlinesAsync)).call(this, account, options); getTrustlinesAsync)).call(this, account, options);

50
src/api/ledger/types.js Normal file
View File

@@ -0,0 +1,50 @@
/* @flow */
'use strict';
import type {Amount} from '../common/types.js';
export type OrdersOptions = {
limit?: number,
ledgerVersion?: number
}
export type OrderSpecification = {
direction: string,
quantity: Amount,
totalPrice: Amount,
immediateOrCancel?: boolean,
fillOrKill?: boolean,
// If enabled, the offer will not consume offers that exactly match it, and
// instead becomes an Offer node in the ledger. It will still consume offers
// that cross it.
passive?: boolean
}
export type Order = {
specification: OrderSpecification,
properties: {
maker: string,
sequence: number,
makerExchangeRate: string
}
}
export type GetLedger = {
accepted: boolean,
closed: boolean,
stateHash: string,
closeTime: number,
closeTimeResolution: number,
closeFlags: number,
ledgerHash: string,
ledgerVersion: number,
parentLedgerHash: string,
parentCloseTime: number,
totalDrops: string,
transactionHash: string,
transactions?: Array<Object>,
rawTransactions?: string,
transactionHashes?: Array<string>,
rawState?: string,
stateHashes?: Array<string>
}

View File

@@ -6,9 +6,18 @@ const common = require('../common');
const dropsToXrp = common.dropsToXrp; const dropsToXrp = common.dropsToXrp;
const composeAsync = common.composeAsync; const composeAsync = common.composeAsync;
import type {Remote} from '../../core/remote'; import type {Remote} from '../../core/remote';
import type {TransactionType} from './transaction-types';
import type {Issue} from '../common/types.js';
type Callback = (err: any, data: any) => void type Callback = (err: any, data: any) => void
type RecursiveData = {
marker: string,
results: Array<any>
}
type RecursiveCallback = (err: any, data: RecursiveData) => void
function clamp(value: number, min: number, max: number): number { function clamp(value: number, min: number, max: number): number {
assert(min <= max, 'Illegal clamp bounds'); assert(min <= max, 'Illegal clamp bounds');
return Math.min(Math.max(value, min), max); return Math.min(Math.max(value, min), max);
@@ -21,7 +30,8 @@ function getXRPBalance(remote: Remote, address: string, ledgerVersion?: number,
composeAsync((data) => dropsToXrp(data.account_data.Balance), callback)); composeAsync((data) => dropsToXrp(data.account_data.Balance), callback));
} }
type Getter = (marker: ?string, limit: number, callback: Callback) => void type Getter = (marker: ?string, limit: number,
callback: RecursiveCallback) => void
// If the marker is omitted from a response, you have reached the end // If the marker is omitted from a response, you have reached the end
// getter(marker, limit, callback), callback(error, {marker, results}) // getter(marker, limit, callback), callback(error, {marker, results})
@@ -48,21 +58,20 @@ function getRecursive(getter: Getter, limit?: number, callback: Callback) {
getRecursiveRecur(getter, undefined, limit || Infinity, callback); getRecursiveRecur(getter, undefined, limit || Infinity, callback);
} }
type Amount = {counterparty?: string, issuer?: string, value: string} function renameCounterpartyToIssuer(amount?: Issue): ?{issuer?: string} {
function renameCounterpartyToIssuer(amount?: Amount): ?{issuer?: string} {
if (amount === undefined) { if (amount === undefined) {
return undefined; return undefined;
} }
const issuer = amount.counterparty === undefined ? const issuer = amount.counterparty === undefined ?
amount.issuer : amount.counterparty; (amount.issuer !== undefined ? amount.issuer : undefined) :
amount.counterparty;
const withIssuer = _.assign({}, amount, {issuer: issuer}); const withIssuer = _.assign({}, amount, {issuer: issuer});
return _.omit(withIssuer, 'counterparty'); return _.omit(withIssuer, 'counterparty');
} }
type Order = {taker_gets: Amount, taker_pays: Amount} type RequestBookOffersArgs = {taker_gets: Issue, taker_pays: Issue}
function renameCounterpartyToIssuerInOrder(order: Order) { function renameCounterpartyToIssuerInOrder(order: RequestBookOffersArgs) {
const taker_gets = renameCounterpartyToIssuer(order.taker_gets); const taker_gets = renameCounterpartyToIssuer(order.taker_gets);
const taker_pays = renameCounterpartyToIssuer(order.taker_pays); const taker_pays = renameCounterpartyToIssuer(order.taker_pays);
const changes = {taker_gets: taker_gets, taker_pays: taker_pays}; const changes = {taker_gets: taker_gets, taker_pays: taker_pays};
@@ -84,9 +93,8 @@ function signum(num) {
* @returns {Number} [-1, 0, 1] * @returns {Number} [-1, 0, 1]
*/ */
type Outcome = {outcome: {ledgerVersion: number, indexInLedger: number}}; function compareTransactions(first: TransactionType, second: TransactionType
): number {
function compareTransactions(first: Outcome, second: Outcome): number {
if (!first.outcome || !second.outcome) { if (!first.outcome || !second.outcome) {
return 0; return 0;
} }

View File

@@ -3,6 +3,8 @@
const utils = require('./utils'); const utils = require('./utils');
const validate = utils.common.validate; const validate = utils.common.validate;
const Transaction = utils.common.core.Transaction; const Transaction = utils.common.core.Transaction;
import type {Instructions, Prepare} from './types.js';
import type {Order} from '../ledger/transaction-types.js';
const OfferCreateFlags = { const OfferCreateFlags = {
passive: {set: 'Passive'}, passive: {set: 'Passive'},
@@ -10,7 +12,7 @@ const OfferCreateFlags = {
fillOrKill: {set: 'FillOrKill'} fillOrKill: {set: 'FillOrKill'}
}; };
function createOrderTransaction(account, order) { function createOrderTransaction(account: string, order: Order): Transaction {
validate.address(account); validate.address(account);
validate.order(order); validate.order(order);
@@ -30,12 +32,16 @@ function createOrderTransaction(account, order) {
return transaction; return transaction;
} }
function prepareOrderAsync(account, order, instructions, callback) { function prepareOrderAsync(account: string, order: Order,
instructions: Instructions, callback
) {
const transaction = createOrderTransaction(account, order); const transaction = createOrderTransaction(account, order);
utils.prepareTransaction(transaction, this.remote, instructions, callback); utils.prepareTransaction(transaction, this.remote, instructions, callback);
} }
function prepareOrder(account: string, order: Object, instructions = {}) { function prepareOrder(account: string, order: Order,
instructions: Instructions = {}
): Promise<Prepare> {
return utils.promisify(prepareOrderAsync.bind(this))( return utils.promisify(prepareOrderAsync.bind(this))(
account, order, instructions); account, order, instructions);
} }

View File

@@ -3,8 +3,11 @@
const utils = require('./utils'); const utils = require('./utils');
const validate = utils.common.validate; const validate = utils.common.validate;
const Transaction = utils.common.core.Transaction; const Transaction = utils.common.core.Transaction;
import type {Instructions, Prepare} from './types.js';
function createOrderCancellationTransaction(account, sequence) { function createOrderCancellationTransaction(account: string,
sequence: number
): Transaction {
validate.address(account); validate.address(account);
validate.sequence(sequence); validate.sequence(sequence);
@@ -13,16 +16,16 @@ function createOrderCancellationTransaction(account, sequence) {
return transaction; return transaction;
} }
function prepareOrderCancellationAsync(account, sequence, instructions, function prepareOrderCancellationAsync(account: string, sequence: number,
callback instructions: Instructions, callback
) { ) {
const transaction = createOrderCancellationTransaction(account, sequence); const transaction = createOrderCancellationTransaction(account, sequence);
utils.prepareTransaction(transaction, this.remote, instructions, callback); utils.prepareTransaction(transaction, this.remote, instructions, callback);
} }
function prepareOrderCancellation(account: string, sequence: number, function prepareOrderCancellation(account: string, sequence: number,
instructions = {} instructions: Instructions = {}
) { ): Promise<Prepare> {
return utils.promisify(prepareOrderCancellationAsync.bind(this))( return utils.promisify(prepareOrderCancellationAsync.bind(this))(
account, sequence, instructions); account, sequence, instructions);
} }

View File

@@ -6,19 +6,44 @@ const validate = utils.common.validate;
const toRippledAmount = utils.common.toRippledAmount; const toRippledAmount = utils.common.toRippledAmount;
const Transaction = utils.common.core.Transaction; const Transaction = utils.common.core.Transaction;
const ValidationError = utils.common.errors.ValidationError; const ValidationError = utils.common.errors.ValidationError;
import type {Instructions, Prepare} from './types.js';
import type {Amount, Adjustment, MaxAdjustment,
MinAdjustment, Memo} from '../common/types.js';
function isXRPToXRPPayment(payment) {
type Payment = {
source: Adjustment | MaxAdjustment,
destination: Adjustment | MinAdjustment,
paths?: string,
memos?: Array<Memo>,
// A 256-bit hash that can be used to identify a particular payment
invoiceID?: string,
// A boolean that, if set to true, indicates that this payment should go
// through even if the whole amount cannot be delivered because of a lack of
// liquidity or funds in the source_account account
allowPartialPayment?: boolean,
// A boolean that can be set to true if paths are specified and the sender
// would like the Ripple Network to disregard any direct paths from
// the source_account to the destination_account. This may be used to take
// advantage of an arbitrage opportunity or by gateways wishing to issue
// balances from a hot wallet to a user who has mistakenly set a trustline
// directly to the hot wallet
noDirectRipple?: boolean,
limitQuality?: boolean
}
function isXRPToXRPPayment(payment: Payment): boolean {
const sourceCurrency = _.get(payment, 'source.maxAmount.currency'); const sourceCurrency = _.get(payment, 'source.maxAmount.currency');
const destinationCurrency = _.get(payment, 'destination.amount.currency'); const destinationCurrency = _.get(payment, 'destination.amount.currency');
return sourceCurrency === 'XRP' && destinationCurrency === 'XRP'; return sourceCurrency === 'XRP' && destinationCurrency === 'XRP';
} }
function isIOUWithoutCounterparty(amount) { function isIOUWithoutCounterparty(amount: Amount): boolean {
return amount && amount.currency !== 'XRP' return amount && amount.currency !== 'XRP'
&& amount.counterparty === undefined; && amount.counterparty === undefined;
} }
function applyAnyCounterpartyEncoding(payment) { function applyAnyCounterpartyEncoding(payment: Payment): void {
// Convert blank counterparty to sender or receiver's address // Convert blank counterparty to sender or receiver's address
// (Ripple convention for 'any counterparty') // (Ripple convention for 'any counterparty')
// https://ripple.com/build/transactions/ // https://ripple.com/build/transactions/
@@ -33,14 +58,15 @@ function applyAnyCounterpartyEncoding(payment) {
}); });
} }
function createMaximalAmount(amount) { function createMaximalAmount(amount: Amount): Amount {
const maxXRPValue = '100000000000'; const maxXRPValue = '100000000000';
const maxIOUValue = '9999999999999999e80'; const maxIOUValue = '9999999999999999e80';
const maxValue = amount.currency === 'XRP' ? maxXRPValue : maxIOUValue; const maxValue = amount.currency === 'XRP' ? maxXRPValue : maxIOUValue;
return _.assign(amount, {value: maxValue}); return _.assign(amount, {value: maxValue});
} }
function createPaymentTransaction(account, paymentArgument) { function createPaymentTransaction(account: string, paymentArgument: Payment
): Transaction {
const payment = _.cloneDeep(paymentArgument); const payment = _.cloneDeep(paymentArgument);
applyAnyCounterpartyEncoding(payment); applyAnyCounterpartyEncoding(payment);
validate.address(account); validate.address(account);
@@ -115,12 +141,16 @@ function createPaymentTransaction(account, paymentArgument) {
return transaction; return transaction;
} }
function preparePaymentAsync(account, payment, instructions, callback) { function preparePaymentAsync(account: string, payment: Payment,
instructions: Instructions, callback
) {
const transaction = createPaymentTransaction(account, payment); const transaction = createPaymentTransaction(account, payment);
utils.prepareTransaction(transaction, this.remote, instructions, callback); utils.prepareTransaction(transaction, this.remote, instructions, callback);
} }
function preparePayment(account: string, payment: Object, instructions = {}) { function preparePayment(account: string, payment: Payment,
instructions: Instructions = {}
): Promise<Prepare> {
return utils.promisify(preparePaymentAsync.bind(this))( return utils.promisify(preparePaymentAsync.bind(this))(
account, payment, instructions); account, payment, instructions);
} }

View File

@@ -0,0 +1,62 @@
/* @flow */
'use strict';
type SettingPasswordSpent = {
passwordSpent?: boolean,
}
type SettingRequireDestinationTag = {
requireDestinationTag?: boolean,
}
type SettingRequireAuthorization = {
requireAuthorization?: boolean,
}
type SettingDisallowIncomingXRP = {
disallowIncomingXRP?: boolean,
}
type SettingDisableMasterKey = {
disableMasterKey?: boolean,
}
type SettingEnableTransactionIDTracking = {
enableTransactionIDTracking?: boolean,
}
type SettingNoFreeze = {
noFreeze?: boolean,
}
type SettingGlobalFreeze = {
globalFreeze?: boolean,
}
type SettingDefaultRipple = {
defaultRipple?: boolean,
}
type SettingEmailHash = {
emailHash?: ?string,
}
type SettingWalletLocator = {
walletLocator?: ?string,
}
type SettingWalletSize = {
walletSize?: ?number,
}
type SettingMessageKey = {
messageKey?: string,
}
type SettingDomain = {
domain?: string,
}
type SettingTransferRate = {
transferRate?: ?number,
}
type SettingSigners = {
signers?: string,
}
type SettingRegularKey = {
regularKey?: string
}
export type Settings = SettingRegularKey | SettingSigners |
SettingTransferRate | SettingDomain | SettingMessageKey | SettingWalletSize |
SettingWalletLocator | SettingEmailHash | SettingDefaultRipple |
SettingGlobalFreeze | SettingNoFreeze | SettingEnableTransactionIDTracking |
SettingDisableMasterKey | SettingDisallowIncomingXRP |
SettingRequireAuthorization | SettingRequireDestinationTag |
SettingPasswordSpent

View File

@@ -7,11 +7,14 @@ const validate = utils.common.validate;
const AccountFlagIndices = utils.common.constants.AccountFlagIndices; const AccountFlagIndices = utils.common.constants.AccountFlagIndices;
const AccountFields = utils.common.constants.AccountFields; const AccountFields = utils.common.constants.AccountFields;
const Transaction = utils.common.core.Transaction; 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 // Emptry string passed to setting will clear it
const CLEAR_SETTING = null; const CLEAR_SETTING = null;
function setTransactionFlags(transaction, values) {
function setTransactionFlags(transaction: Transaction, values: Settings) {
const keys = Object.keys(values); const keys = Object.keys(values);
assert(keys.length === 1, 'ERROR: can only set one setting per transaction'); assert(keys.length === 1, 'ERROR: can only set one setting per transaction');
const flagName = keys[0]; const flagName = keys[0];
@@ -26,7 +29,7 @@ function setTransactionFlags(transaction, values) {
} }
} }
function setTransactionFields(transaction, input) { function setTransactionFields(transaction: Transaction, input: Settings) {
const fieldSchema = AccountFields; const fieldSchema = AccountFields;
for (const fieldName in fieldSchema) { for (const fieldName in fieldSchema) {
const field = fieldSchema[fieldName]; const field = fieldSchema[fieldName];
@@ -63,11 +66,12 @@ function setTransactionFields(transaction, input) {
* are returned * are returned
*/ */
function convertTransferRate(transferRate) { function convertTransferRate(transferRate: number | string): number | string {
return (new BigNumber(transferRate)).shift(9).toNumber(); return (new BigNumber(transferRate)).shift(9).toNumber();
} }
function createSettingsTransaction(account, settings) { function createSettingsTransaction(account: string, settings: Settings
): Transaction {
validate.address(account); validate.address(account);
validate.settings(settings); validate.settings(settings);
@@ -90,12 +94,16 @@ function createSettingsTransaction(account, settings) {
return transaction; return transaction;
} }
function prepareSettingsAsync(account, settings, instructions, callback) { function prepareSettingsAsync(account: string, settings: Settings,
instructions: Instructions, callback
) {
const transaction = createSettingsTransaction(account, settings); const transaction = createSettingsTransaction(account, settings);
utils.prepareTransaction(transaction, this.remote, instructions, callback); utils.prepareTransaction(transaction, this.remote, instructions, callback);
} }
function prepareSettings(account: string, settings: Object, instructions = {}) { function prepareSettings(account: string, settings: Object,
instructions: Instructions = {}
): Promise<Prepare> {
return utils.promisify(prepareSettingsAsync.bind(this))( return utils.promisify(prepareSettingsAsync.bind(this))(
account, settings, instructions); account, settings, instructions);
} }

View File

@@ -6,7 +6,16 @@ const validate = utils.common.validate;
const Request = utils.common.core.Request; const Request = utils.common.core.Request;
const convertErrors = utils.common.convertErrors; const convertErrors = utils.common.convertErrors;
function isImmediateRejection(engineResult) { type Submit = {
success: boolean,
engineResult: string,
engineResultCode: number,
engineResultMessage?: string,
txBlob?: string,
txJson?: Object
}
function isImmediateRejection(engineResult: string): boolean {
// note: "tel" errors mean the local server refused to process the // note: "tel" errors mean the local server refused to process the
// transaction *at that time*, but it could potentially buffer the // transaction *at that time*, but it could potentially buffer the
// transaction and then process it at a later time, for example // transaction and then process it at a later time, for example
@@ -37,7 +46,7 @@ function submitAsync(txBlob: string, callback: (err: any, data: any) => void
convertSubmitErrors(convertErrors(callback)))); convertSubmitErrors(convertErrors(callback))));
} }
function submit(txBlob: string) { function submit(txBlob: string): Promise<Submit> {
return utils.promisify(submitAsync.bind(this))(txBlob); return utils.promisify(submitAsync.bind(this))(txBlob);
} }

View File

@@ -4,8 +4,18 @@ const _ = require('lodash');
const utils = require('./utils'); const utils = require('./utils');
const validate = utils.common.validate; const validate = utils.common.validate;
const Transaction = utils.common.core.Transaction; const Transaction = utils.common.core.Transaction;
import type {Instructions, Prepare} from './types.js';
import type {Memo} from '../common/types.js';
function createSuspendedPaymentCancellationTransaction(account, payment) { type SuspendedPaymentCancellation = {
owner: string,
paymentSequence: number,
memos?: Array<Memo>
}
function createSuspendedPaymentCancellationTransaction(account: string,
payment: SuspendedPaymentCancellation
): Transaction {
validate.address(account); validate.address(account);
validate.suspendedPaymentCancellation(payment); validate.suspendedPaymentCancellation(payment);
@@ -24,15 +34,17 @@ function createSuspendedPaymentCancellationTransaction(account, payment) {
return transaction; return transaction;
} }
function prepareSuspendedPaymentCancellationAsync(account, payment, function prepareSuspendedPaymentCancellationAsync(account: string,
instructions, callback) { payment: SuspendedPaymentCancellation, instructions: Instructions, callback
) {
const transaction = const transaction =
createSuspendedPaymentCancellationTransaction(account, payment); createSuspendedPaymentCancellationTransaction(account, payment);
utils.prepareTransaction(transaction, this.remote, instructions, callback); utils.prepareTransaction(transaction, this.remote, instructions, callback);
} }
function prepareSuspendedPaymentCancellation(account: string, payment: Object, function prepareSuspendedPaymentCancellation(account: string,
instructions = {}) { payment: SuspendedPaymentCancellation, instructions: Instructions = {}
): Promise<Prepare> {
return utils.promisify(prepareSuspendedPaymentCancellationAsync) return utils.promisify(prepareSuspendedPaymentCancellationAsync)
.call(this, account, payment, instructions); .call(this, account, payment, instructions);
} }

View File

@@ -5,8 +5,21 @@ const utils = require('./utils');
const validate = utils.common.validate; const validate = utils.common.validate;
const toRippledAmount = utils.common.toRippledAmount; const toRippledAmount = utils.common.toRippledAmount;
const Transaction = utils.common.core.Transaction; const Transaction = utils.common.core.Transaction;
import type {Instructions, Prepare} from './types.js';
import type {Adjustment, MaxAdjustment, Memo} from '../common/types.js';
function createSuspendedPaymentCreationTransaction(account, payment) { type SuspendedPaymentCreation = {
source: MaxAdjustment,
destination: Adjustment,
memos?: Array<Memo>,
digest?: string,
allowCancelAfter?: number,
allowExecuteAfter?: number
}
function createSuspendedPaymentCreationTransaction(account: string,
payment: SuspendedPaymentCreation
): Transaction {
validate.address(account); validate.address(account);
validate.suspendedPaymentCreation(payment); validate.suspendedPaymentCreation(payment);
@@ -41,15 +54,17 @@ function createSuspendedPaymentCreationTransaction(account, payment) {
return transaction; return transaction;
} }
function prepareSuspendedPaymentCreationAsync(account, payment, instructions, function prepareSuspendedPaymentCreationAsync(account: string,
callback) { payment: SuspendedPaymentCreation, instructions: Instructions, callback
) {
const transaction = const transaction =
createSuspendedPaymentCreationTransaction(account, payment); createSuspendedPaymentCreationTransaction(account, payment);
utils.prepareTransaction(transaction, this.remote, instructions, callback); utils.prepareTransaction(transaction, this.remote, instructions, callback);
} }
function prepareSuspendedPaymentCreation(account: string, payment: Object, function prepareSuspendedPaymentCreation(account: string,
instructions = {}) { payment: SuspendedPaymentCreation, instructions: Instructions = {}
): Promise<Prepare> {
return utils.promisify(prepareSuspendedPaymentCreationAsync) return utils.promisify(prepareSuspendedPaymentCreationAsync)
.call(this, account, payment, instructions); .call(this, account, payment, instructions);
} }

View File

@@ -4,8 +4,21 @@ const _ = require('lodash');
const utils = require('./utils'); const utils = require('./utils');
const validate = utils.common.validate; const validate = utils.common.validate;
const Transaction = utils.common.core.Transaction; const Transaction = utils.common.core.Transaction;
import type {Instructions, Prepare} from './types.js';
import type {Memo} from '../common/types.js';
function createSuspendedPaymentExecutionTransaction(account, payment) { type SuspendedPaymentExecution = {
owner: string,
paymentSequence: number,
memos?: Array<Memo>,
method?: number,
digest?: string,
proof?: string
}
function createSuspendedPaymentExecutionTransaction(account: string,
payment: SuspendedPaymentExecution
): Transaction {
validate.address(account); validate.address(account);
validate.suspendedPaymentExecution(payment); validate.suspendedPaymentExecution(payment);
@@ -34,15 +47,17 @@ function createSuspendedPaymentExecutionTransaction(account, payment) {
return transaction; return transaction;
} }
function prepareSuspendedPaymentExecutionAsync(account, payment, instructions, function prepareSuspendedPaymentExecutionAsync(account: string,
callback) { payment: SuspendedPaymentExecution, instructions: Instructions, callback
) {
const transaction = const transaction =
createSuspendedPaymentExecutionTransaction(account, payment); createSuspendedPaymentExecutionTransaction(account, payment);
utils.prepareTransaction(transaction, this.remote, instructions, callback); utils.prepareTransaction(transaction, this.remote, instructions, callback);
} }
function prepareSuspendedPaymentExecution(account: string, payment: Object, function prepareSuspendedPaymentExecution(account: string,
instructions = {}) { payment: SuspendedPaymentExecution, instructions: Instructions = {}
): Promise<Prepare> {
return utils.promisify(prepareSuspendedPaymentExecutionAsync) return utils.promisify(prepareSuspendedPaymentExecutionAsync)
.call(this, account, payment, instructions); .call(this, account, payment, instructions);
} }

View File

@@ -4,6 +4,8 @@ const utils = require('./utils');
const validate = utils.common.validate; const validate = utils.common.validate;
const Transaction = utils.common.core.Transaction; const Transaction = utils.common.core.Transaction;
const BigNumber = require('bignumber.js'); const BigNumber = require('bignumber.js');
import type {Instructions, Prepare} from './types.js';
import type {TrustLineSpecification} from '../ledger/trustlines-types.js';
const TrustSetFlags = { const TrustSetFlags = {
authorized: {set: 'SetAuth'}, authorized: {set: 'SetAuth'},
@@ -16,7 +18,9 @@ function convertQuality(quality) {
(new BigNumber(quality)).shift(9).truncated().toNumber(); (new BigNumber(quality)).shift(9).truncated().toNumber();
} }
function createTrustlineTransaction(account, trustline) { function createTrustlineTransaction(account: string,
trustline: TrustLineSpecification
): Transaction {
validate.address(account); validate.address(account);
validate.trustline(trustline); validate.trustline(trustline);
@@ -33,13 +37,16 @@ function createTrustlineTransaction(account, trustline) {
return transaction; return transaction;
} }
function prepareTrustlineAsync(account, trustline, instructions, callback) { function prepareTrustlineAsync(account: string,
trustline: TrustLineSpecification, instructions: Instructions, callback
) {
const transaction = createTrustlineTransaction(account, trustline); const transaction = createTrustlineTransaction(account, trustline);
utils.prepareTransaction(transaction, this.remote, instructions, callback); utils.prepareTransaction(transaction, this.remote, instructions, callback);
} }
function prepareTrustline(account: string, trustline: Object, instructions = {} function prepareTrustline(account: string,
) { trustline: TrustLineSpecification, instructions: Instructions = {}
): Promise<Prepare> {
return utils.promisify(prepareTrustlineAsync.bind(this))( return utils.promisify(prepareTrustlineAsync.bind(this))(
account, trustline, instructions); account, trustline, instructions);
} }

View File

@@ -0,0 +1,19 @@
/* @flow */
'use strict';
export type Instructions = {
sequence?: number,
fee?: string,
maxFee?: string,
maxLedgerVersion?: number,
maxLedgerVersionOffset?: number
}
export type Prepare = {
txJSON: string,
instructions: {
fee: string,
sequence: number,
maxLedgerVersion?: number
}
}

View File

@@ -5,8 +5,12 @@ const async = require('async');
const BigNumber = require('bignumber.js'); const BigNumber = require('bignumber.js');
const common = require('../common'); const common = require('../common');
const composeAsync = common.composeAsync; const composeAsync = common.composeAsync;
import type {Remote} from '../../core/remote';
import type {Transaction} from '../../core/transaction';
import type {Instructions} from './types.js';
function setTransactionBitFlags(transaction: any, values: any, flags: any function setTransactionBitFlags(transaction: Transaction, values: any,
flags: any
): void { ): void {
for (const flagName in flags) { for (const flagName in flags) {
const flagValue = values[flagName]; const flagValue = values[flagName];
@@ -21,14 +25,14 @@ function setTransactionBitFlags(transaction: any, values: any, flags: any
} }
} }
function getFeeDrops(remote, callback) { function getFeeDrops(remote: Remote, callback) {
const feeUnits = 10; // all transactions currently have a fee of 10 fee units const feeUnits = 10; // all transactions currently have a fee of 10 fee units
remote.feeTxAsync(feeUnits, (err, data) => { remote.feeTxAsync(feeUnits, (err, data) => {
callback(err, data ? data.to_text() : undefined); callback(err, data ? data.to_text() : undefined);
}); });
} }
function formatPrepareResponse(txJSON) { function formatPrepareResponse(txJSON: Object): Object {
const instructions = { const instructions = {
fee: txJSON.Fee, fee: txJSON.Fee,
sequence: txJSON.Sequence, sequence: txJSON.Sequence,
@@ -41,9 +45,9 @@ function formatPrepareResponse(txJSON) {
} }
type Callback = (err: ?(typeof Error), type Callback = (err: ?(typeof Error),
data: {txJSON: string, instructions: any}) => void; data: {txJSON: string, instructions: Instructions}) => void;
function prepareTransaction(transaction: any, remote: any, instructions: any, function prepareTransaction(transaction: Transaction, remote: Remote,
callback: Callback instructions: Instructions, callback: Callback
): void { ): void {
common.validate.instructions(instructions); common.validate.instructions(instructions);
@@ -54,11 +58,11 @@ function prepareTransaction(transaction: any, remote: any, instructions: any,
function prepareMaxLedgerVersion(callback_) { function prepareMaxLedgerVersion(callback_) {
if (instructions.maxLedgerVersion !== undefined) { if (instructions.maxLedgerVersion !== undefined) {
txJSON.LastLedgerSequence = parseInt(instructions.maxLedgerVersion, 10); txJSON.LastLedgerSequence = instructions.maxLedgerVersion;
callback_(); callback_();
} else { } else {
const offset = instructions.maxLedgerVersionOffset !== undefined ? const offset = instructions.maxLedgerVersionOffset !== undefined ?
parseInt(instructions.maxLedgerVersionOffset, 10) : 3; instructions.maxLedgerVersionOffset : 3;
remote.getLedgerSequence((error, ledgerVersion) => { remote.getLedgerSequence((error, ledgerVersion) => {
txJSON.LastLedgerSequence = ledgerVersion + offset; txJSON.LastLedgerSequence = ledgerVersion + offset;
callback_(error); callback_(error);
@@ -84,7 +88,7 @@ function prepareTransaction(transaction: any, remote: any, instructions: any,
function prepareSequence(callback_) { function prepareSequence(callback_) {
if (instructions.sequence !== undefined) { if (instructions.sequence !== undefined) {
txJSON.Sequence = parseInt(instructions.sequence, 10); txJSON.Sequence = instructions.sequence;
callback_(null, formatPrepareResponse(txJSON)); callback_(null, formatPrepareResponse(txJSON));
} else { } else {
remote.findAccount(account).getNextSequence(function(error, sequence) { remote.findAccount(account).getNextSequence(function(error, sequence) {