Convert from Flow to Typescript (#816)

* convert to typescript
* add docs for custom node typing
* update webpack, gulpfile
This commit is contained in:
Fred K. Schott
2017-12-24 00:39:18 -08:00
committed by Elliot Lee
parent 5979ff6197
commit 8204f6c648
86 changed files with 1629 additions and 1532 deletions

View File

@@ -1,21 +1,22 @@
/* eslint-disable no-var, no-param-reassign */
/* these eslint rules are disabled because gulp does not support babel yet */
'use strict';
var _ = require('lodash');
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var webpack = require('webpack');
var bump = require('gulp-bump');
var argv = require('yargs').argv;
var assert = require('assert');
var fs = require('fs');
const _ = require('lodash');
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const gulp = require('gulp');
const rename = require('gulp-rename');
const webpack = require('webpack');
const bump = require('gulp-bump');
const argv = require('yargs').argv;
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
var pkg = require('./package.json');
var uglifyOptions = {
mangle: {
except: ['_', 'RippleError', 'RippledError', 'UnexpectedError',
reserved: ['_', 'RippleError', 'RippledError', 'UnexpectedError',
'LedgerVersionError', 'ConnectionError', 'NotConnectedError',
'DisconnectedError', 'TimeoutError', 'ResponseFormatError',
'ValidationError', 'NotFoundError', 'MissingLedgerHistoryError',
@@ -24,17 +25,17 @@ var uglifyOptions = {
}
};
function webpackConfig(extension, overrides) {
function getWebpackConfig(extension, overrides) {
overrides = overrides || {};
var defaults = {
let defaults = {
cache: true,
externals: [{
'lodash': '_'
}],
entry: './src/index.js',
entry: './src/index.ts',
output: {
library: 'ripple',
path: './build/',
path: path.join(__dirname, 'build/'),
filename: ['ripple-', extension].join(pkg.version)
},
plugins: [
@@ -44,18 +45,21 @@ function webpackConfig(extension, overrides) {
'./setup-api-web')
],
module: {
loaders: [{
rules: [{
test: /jayson/,
loader: 'null'
use: 'null',
}, {
test: /\.js$/,
exclude: [/node_modules/],
loader: 'babel-loader'
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/,
}, {
test: /\.json/,
loader: 'json-loader'
use: 'json-loader',
}]
}
},
resolve: {
extensions: [ '.ts', '.js' ]
},
};
return _.assign({}, defaults, overrides);
}
@@ -78,7 +82,7 @@ function webpackConfigForWebTest(testFileName, path) {
filename: match[1] + '-test.js'
}
};
return webpackConfig('.js', configOverrides);
return getWebpackConfig('.js', configOverrides);
}
gulp.task('build-tests', function(callback) {
@@ -112,30 +116,29 @@ function createBuildLink(callback) {
}
gulp.task('build', function(callback) {
webpack(webpackConfig('.js'), createBuildLink(callback));
webpack(getWebpackConfig('.js'), createBuildLink(callback));
});
gulp.task('build-min', ['build'], function() {
return gulp.src(['./build/ripple-', '.js'].join(pkg.version))
.pipe(uglify(uglifyOptions))
.pipe(rename(['ripple-', '-min.js'].join(pkg.version)))
.pipe(gulp.dest('./build/'))
.on('end', function() {
gulp.task('build-min', function(callback) {
const webpackConfig = getWebpackConfig('-min.js');
webpackConfig.plugins.push(new UglifyJsPlugin({uglifyOptions}));
webpack(webpackConfig, function() {
createLink('./build/ripple-' + pkg.version + '-min.js',
'./build/ripple-latest-min.js');
callback();
});
});
gulp.task('build-debug', function(callback) {
var configOverrides = {debug: true, devtool: 'eval'};
webpack(webpackConfig('-debug.js', configOverrides), callback);
const webpackConfig = getWebpackConfig('-debug.js', {devtool: 'eval'});
webpackConfig.plugins.unshift(new webpack.LoaderOptionsPlugin({debug: true}));
webpack(webpackConfig, callback);
});
/**
* Generate a WebPack external for a given unavailable module which replaces
* that module's constructor with an error-thrower
*/
function buildUseError(cons) {
return ('var {<CONS>:function(){throw new Error('
+ '"Class is unavailable in this build: <CONS>")}}')
@@ -145,7 +148,7 @@ function buildUseError(cons) {
gulp.task('build-core', function(callback) {
var configOverrides = {
cache: false,
entry: './src/remote.js',
entry: './src/remote.ts',
externals: [{
'./transaction': buildUseError('Transaction'),
'./orderbook': buildUseError('OrderBook'),
@@ -153,10 +156,10 @@ gulp.task('build-core', function(callback) {
'./serializedobject': buildUseError('SerializedObject')
}],
plugins: [
new webpack.optimize.UglifyJsPlugin()
new UglifyJsPlugin()
]
};
webpack(webpackConfig('-core.js', configOverrides), callback);
webpack(getWebpackConfig('-core.js', configOverrides), callback);
});
gulp.task('bower-build', ['build'], function() {

9
custom_typings/node.d.ts vendored Normal file
View File

@@ -0,0 +1,9 @@
/**
* This is an extension of Node's `process` object to include the browser
* property, which is added by webpack.
*/
interface AmbiguousProcess extends NodeJS.Process {
browser?: true
}
declare var process: AmbiguousProcess;

View File

@@ -15,6 +15,8 @@
"test": "test"
},
"dependencies": {
"@types/lodash": "^4.14.85",
"@types/ws": "^3.2.0",
"bignumber.js": "^4.1.0",
"https-proxy-agent": "^1.0.0",
"jsonschema": "^1.1.1",
@@ -27,25 +29,16 @@
"ws": "^3.3.1"
},
"devDependencies": {
"@types/node": "^8.0.53",
"assert-diff": "^1.0.1",
"babel-cli": "^6.26.0",
"babel-core": "^6.4.0",
"babel-eslint": "^6.0.4",
"babel-loader": "^6.2.1",
"babel-preset-es2015": "^6.3.13",
"babel-preset-flow": "^6.23.0",
"babel-preset-stage-1": "^6.3.13",
"babel-register": "^6.3.13",
"coveralls": "^2.13.1",
"doctoc": "^0.15.0",
"ejs": "^2.3.4",
"eslint": "^2.9.0",
"eventemitter2": "^0.4.14",
"flow-bin": "^0.59.0",
"gulp": "^3.8.10",
"gulp-bump": "^0.1.13",
"gulp-rename": "^1.2.0",
"gulp-uglify": "^1.1.0",
"http-server": "^0.8.5",
"istanbul": "^1.1.0-alpha.1",
"jayson": "^1.2.2",
@@ -55,8 +48,12 @@
"mocha-in-sauce": "^0.0.1",
"mocha-junit-reporter": "^1.9.1",
"null-loader": "^0.1.1",
"webpack": "^1.5.3",
"yargs": "^1.3.1"
"ts-loader": "^3.2.0",
"ts-node": "^3.3.0",
"typescript": "^2.6.1",
"uglifyjs-webpack-plugin": "^1.1.4",
"webpack": "^3.10.0",
"yargs": "^8.0.2"
},
"scripts": {
"build": "gulp",
@@ -64,11 +61,11 @@
"docgen": "node --harmony scripts/build_docs.js",
"clean": "rm -rf dist/npm",
"typecheck": "flow check",
"compile": "babel -D --optional runtime -d dist/npm/ src/",
"watch": "babel -w -D --optional runtime -d dist/npm/ src/",
"compile": "mkdir -p dist/npm/common && cp -r src/common/schemas dist/npm/common/ && tsc",
"watch": "tsc -w",
"compile-with-source-maps": "babel -D --optional runtime -s -t -d dist/npm/ src/",
"prepublish": "npm run clean && npm run compile",
"test": "babel-node ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha",
"test": "istanbul cover _mocha",
"coveralls": "cat ./coverage/lcov.info | coveralls",
"lint": "if ! [ -f .eslintrc ]; then curl -o .eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; echo 'parser: babel-eslint' >> .eslintrc; fi; eslint -c .eslintrc src/",
"perf": "./scripts/perf_test.sh",

View File

@@ -1,7 +1,5 @@
/* @flow */
import * as _ from 'lodash'
import events from 'events'
import {EventEmitter} from 'events'
import {Connection, errors, validate} from './common'
import * as server from './server/server'
const connect = server.connect
@@ -56,7 +54,7 @@ type APIOptions = {
// prevent access to non-validated ledger versions
class RestrictedConnection extends Connection {
request(request, timeout) {
request(request: any, timeout?: number) {
const ledger_index = request.ledger_index
if (ledger_index !== undefined && ledger_index !== 'validated') {
if (!_.isNumber(ledger_index) || ledger_index > this._ledgerVersion) {
@@ -69,7 +67,7 @@ class RestrictedConnection extends Connection {
}
}
class RippleAPI extends events.EventEmitter {
class RippleAPI extends EventEmitter {
_feeCushion: number
connection: RestrictedConnection
@@ -80,11 +78,11 @@ class RippleAPI extends events.EventEmitter {
RangeSet,
ledgerUtils,
schemaValidator
};
}
constructor(options: APIOptions = {}) {
validate.apiOptions(options)
super()
validate.apiOptions(options)
this._feeCushion = options.feeCushion || 1.2
const serverURL = options.server
if (serverURL !== undefined) {
@@ -107,51 +105,49 @@ class RippleAPI extends events.EventEmitter {
this.connection = new RestrictedConnection(null, options)
}
}
connect = connect
disconnect = disconnect
isConnected = isConnected
getServerInfo = getServerInfo
getFee = getFee
getLedgerVersion = getLedgerVersion
getTransaction = getTransaction
getTransactions = getTransactions
getTrustlines = getTrustlines
getBalances = getBalances
getBalanceSheet = getBalanceSheet
getPaths = getPaths
getOrders = getOrders
getOrderbook = getOrderbook
getSettings = getSettings
getAccountInfo = getAccountInfo
getPaymentChannel = getPaymentChannel
getLedger = getLedger
preparePayment = preparePayment
prepareTrustline = prepareTrustline
prepareOrder = prepareOrder
prepareOrderCancellation = prepareOrderCancellation
prepareEscrowCreation = prepareEscrowCreation
prepareEscrowExecution = prepareEscrowExecution
prepareEscrowCancellation = prepareEscrowCancellation
preparePaymentChannelCreate = preparePaymentChannelCreate
preparePaymentChannelFund = preparePaymentChannelFund
preparePaymentChannelClaim = preparePaymentChannelClaim
prepareSettings = prepareSettings
sign = sign
combine = combine
submit = submit
generateAddress = generateAddressAPI
computeLedgerHash = computeLedgerHash
signPaymentChannelClaim = signPaymentChannelClaim
verifyPaymentChannelClaim = verifyPaymentChannelClaim
errors = errors
}
_.assign(RippleAPI.prototype, {
connect,
disconnect,
isConnected,
getServerInfo,
getFee,
getLedgerVersion,
getTransaction,
getTransactions,
getTrustlines,
getBalances,
getBalanceSheet,
getPaths,
getOrders,
getOrderbook,
getSettings,
getAccountInfo,
getPaymentChannel,
getLedger,
preparePayment,
prepareTrustline,
prepareOrder,
prepareOrderCancellation,
prepareEscrowCreation,
prepareEscrowExecution,
prepareEscrowCancellation,
preparePaymentChannelCreate,
preparePaymentChannelFund,
preparePaymentChannelClaim,
prepareSettings,
sign,
combine,
submit,
generateAddress: generateAddressAPI,
computeLedgerHash,
signPaymentChannelClaim,
verifyPaymentChannelClaim,
errors
})
export {
RippleAPI
}

View File

@@ -3,11 +3,15 @@ import * as _ from 'lodash'
import {RippleAPI} from './api'
class RippleAPIBroadcast extends RippleAPI {
// TODO: Should this default to 0, or null/undefined?
ledgerVersion: number = 0
private _apis: RippleAPI[]
constructor(servers, options) {
super(options)
this.ledgerVersion = 0
const apis = servers.map(server => new RippleAPI(
const apis: RippleAPI[] = servers.map(server => new RippleAPI(
_.assign({}, options, {server})
))
@@ -21,14 +25,14 @@ class RippleAPIBroadcast extends RippleAPI {
})
// connection methods must be overridden to apply to all api instances
this.connect = function() {
return Promise.all(apis.map(api => api.connect()))
this.connect = async function() {
await Promise.all(apis.map(api => api.connect()))
}
this.disconnect = function() {
return Promise.all(apis.map(api => api.disconnect()))
this.disconnect = async function() {
await Promise.all(apis.map(api => api.disconnect()))
}
this.isConnected = function() {
return _.every(apis.map(api => api.isConnected()))
return apis.map(api => api.isConnected()).every(Boolean)
}
// synchronous methods are all passed directly to the first api instance
@@ -53,12 +57,11 @@ class RippleAPIBroadcast extends RippleAPI {
}
getMethodNames() {
const methodNames = []
for (const name in RippleAPI.prototype) {
if (RippleAPI.prototype.hasOwnProperty(name)) {
if (typeof RippleAPI.prototype[name] === 'function') {
methodNames.push(name)
}
const methodNames: string[] = []
const rippleAPI = this._apis[0]
for (const name of Object.getOwnPropertyNames(rippleAPI)) {
if (typeof rippleAPI[name] === 'function') {
methodNames.push(name)
}
}
return methodNames

View File

@@ -1,18 +1,17 @@
function setPrototypeOf(object, prototype) {
// Object.setPrototypeOf not supported on Internet Explorer 9
/* eslint-disable */
Object.setPrototypeOf ? Object.setPrototypeOf(object, prototype) :
// @ts-ignore: Specifically a fallback for IE9
object.__proto__ = prototype
/* eslint-enable */
}
function getConstructorName(object) {
function getConstructorName(object: Object): string {
// hack for internet explorer
return process.browser ?
object.constructor.toString().match(/^function\s+([^(]*)/)[1] :
object.constructor.name
if (!object.constructor.name) {
return object.constructor.toString().match(/^function\s+([^(]*)/)![1]
}
return object.constructor.name
}
export {

View File

@@ -1,9 +1,7 @@
import * as _ from 'lodash'
import events from 'events'
import WebSocket from 'ws'
import urlLib from 'url'
import {EventEmitter} from 'events'
import {parse as parseUrl} from 'url'
import * as WebSocket from 'ws'
import RangeSet from './rangeset'
import {RippledError, DisconnectedError, NotConnectedError,
TimeoutError, ResponseFormatError, ConnectionError,
@@ -15,12 +13,48 @@ function isStreamMessageType(type) {
type === 'path_find'
}
class Connection extends events.EventEmitter {
constructor(url, options = {}) {
interface ConnectionOptions {
trace?: boolean,
proxy?: string
proxyAuthorization?: string
authorization?: string
trustedCertificates?: string[]
key?: string
passphrase?: string
certificate?: string
timeout?: number
}
class Connection extends EventEmitter {
private _url: string
private _trace: boolean
private _console?: Console
private _proxyURL?: string
private _proxyAuthorization?: string
private _authorization?: string
private _trustedCertificates?: string[]
private _key?: string
private _passphrase?: string
private _certificate?: string
private _timeout: number
private _isReady: boolean = false
private _ws: null|WebSocket = null
protected _ledgerVersion: null|number = null
private _availableLedgerVersions = new RangeSet()
private _nextRequestID: number = 1
private _retry: number = 0
private _retryTimer: null|NodeJS.Timer = null
private _onOpenErrorBound: null| null|((...args: any[]) => void) = null
private _onUnexpectedCloseBound: null|((...args: any[]) => void) = null
private _fee_base: null|number = null
private _fee_ref: null|number = null
constructor(url, options: ConnectionOptions = {}) {
super()
this.setMaxListeners(Infinity)
this._url = url
this._trace = options.trace
this._trace = options.trace || false
if (this._trace) {
// for easier unit testing
this._console = console
@@ -33,17 +67,6 @@ class Connection extends events.EventEmitter {
this._passphrase = options.passphrase
this._certificate = options.certificate
this._timeout = options.timeout || (20 * 1000)
this._isReady = false
this._ws = null
this._ledgerVersion = null
this._availableLedgerVersions = new RangeSet()
this._nextRequestID = 1
this._retry = 0
this._retryTimer = null
this._onOpenErrorBound = null
this._onUnexpectedCloseBound = null
this._fee_base = null
this._fee_ref = null
}
_updateLedgerVersions(data) {
@@ -63,7 +86,7 @@ class Connection extends events.EventEmitter {
}
// return value is array of arguments to Connection.emit
_parseMessage(message) {
_parseMessage(message): [string, Object] | ['error', string, string, Object] {
const data = JSON.parse(message)
if (data.type === 'response') {
if (!(Number.isInteger(data.id) && data.id >= 0)) {
@@ -83,10 +106,10 @@ class Connection extends events.EventEmitter {
}
_onMessage(message) {
let parameters
if (this._trace) {
this._console.log(message)
this._console!.log(message)
}
let parameters
try {
parameters = this._parseMessage(message)
} catch (error) {
@@ -95,7 +118,7 @@ class Connection extends events.EventEmitter {
}
// we don't want this inside the try/catch or exceptions in listener
// will be caught
this.emit(...parameters)
this.emit.apply(this, parameters)
}
get _state() {
@@ -112,11 +135,11 @@ class Connection extends events.EventEmitter {
_onUnexpectedClose(beforeOpen, resolve, reject, code) {
if (this._onOpenErrorBound) {
this._ws.removeListener('error', this._onOpenErrorBound)
this._ws!.removeListener('error', this._onOpenErrorBound)
this._onOpenErrorBound = null
}
// just in case
this._ws.removeAllListeners('open')
this._ws!.removeAllListeners('open')
this._ws = null
this._isReady = false
if (beforeOpen) {
@@ -155,8 +178,10 @@ class Connection extends events.EventEmitter {
}
_clearReconnectTimer() {
clearTimeout(this._retryTimer)
this._retryTimer = null
if (this._retryTimer !== null) {
clearTimeout(this._retryTimer)
this._retryTimer = null
}
}
_onOpen() {
@@ -172,7 +197,7 @@ class Connection extends events.EventEmitter {
command: 'subscribe',
streams: ['ledger']
}
return this.request(request).then(data => {
return this.request(request).then((data: any) => {
if (_.isEmpty(data) || !data.ledger_index) {
// rippled instance doesn't have validated ledgers
return this._disconnect(false).then(() => {
@@ -186,7 +211,8 @@ class Connection extends events.EventEmitter {
this._retry = 0
this._ws.on('error', error => {
if (process.browser && error && error.type === 'error') {
// TODO: "type" does not exist on official error type, safe to remove?
if (process.browser && error && (<any>error).type === 'error') {
// we are in browser, ignore error - `close` event will be fired
// after error
return
@@ -223,11 +249,11 @@ class Connection extends events.EventEmitter {
reject(new NotConnectedError(error && error.message))
}
_createWebSocket() {
const options = {}
_createWebSocket(): WebSocket {
const options: WebSocket.ClientOptions = {}
if (this._proxyURL !== undefined) {
const parsedURL = urlLib.parse(this._url)
const parsedProxyURL = urlLib.parse(this._proxyURL)
const parsedURL = parseUrl(this._url)
const parsedProxyURL = parseUrl(this._proxyURL)
const proxyOverrides = _.omitBy({
secureEndpoint: (parsedURL.protocol === 'wss:'),
secureProxy: (parsedProxyURL.protocol === 'https:'),
@@ -337,7 +363,7 @@ class Connection extends events.EventEmitter {
return this.disconnect().then(() => this.connect())
}
_whenReady(promise) {
_whenReady<T>(promise: Promise<T>): Promise<T> {
return new Promise((resolve, reject) => {
if (!this._shouldBeConnected) {
reject(new NotConnectedError())
@@ -349,44 +375,44 @@ class Connection extends events.EventEmitter {
})
}
getLedgerVersion() {
return this._whenReady(Promise.resolve(this._ledgerVersion))
getLedgerVersion(): Promise<number> {
return this._whenReady(Promise.resolve(this._ledgerVersion!))
}
hasLedgerVersions(lowLedgerVersion, highLedgerVersion) {
hasLedgerVersions(lowLedgerVersion, highLedgerVersion): Promise<boolean> {
return this._whenReady(Promise.resolve(
this._availableLedgerVersions.containsRange(
lowLedgerVersion, highLedgerVersion || this._ledgerVersion)))
}
hasLedgerVersion(ledgerVersion) {
hasLedgerVersion(ledgerVersion): Promise<boolean> {
return this.hasLedgerVersions(ledgerVersion, ledgerVersion)
}
getFeeBase() {
getFeeBase(): Promise<number> {
return this._whenReady(Promise.resolve(Number(this._fee_base)))
}
getFeeRef() {
getFeeRef(): Promise<number> {
return this._whenReady(Promise.resolve(Number(this._fee_ref)))
}
_send(message) {
_send(message: string): Promise<void> {
if (this._trace) {
this._console.log(message)
}
return new Promise((resolve, reject) => {
this._ws.send(message, undefined, (error, result) => {
this._ws.send(message, undefined, error => {
if (error) {
reject(new DisconnectedError(error.message))
} else {
resolve(result)
resolve()
}
})
})
}
request(request, timeout) {
request(request, timeout?: number): Promise<any> {
return new Promise((resolve, reject) => {
if (!this._shouldBeConnected) {
reject(new NotConnectedError())

View File

@@ -1,33 +1,28 @@
import util from 'util'
import {inspect} from 'util'
import * as browserHacks from './browser-hacks'
// this is needed because extending builtins doesn't work in babel 6.x
function extendableBuiltin(cls) {
function ExtendableBuiltin() {
cls.apply(this, arguments)
}
ExtendableBuiltin.prototype = Object.create(cls.prototype)
browserHacks.setPrototypeOf(ExtendableBuiltin, cls)
return ExtendableBuiltin
}
class RippleError extends Error {
class RippleError extends extendableBuiltin(Error) {
constructor(message, data) {
name: string
message: string
data?: any
constructor(message = '', data?: any) {
super(message)
this.name = browserHacks.getConstructorName(this)
this.message = message
this.data = data
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor.name)
Error.captureStackTrace(this, this.constructor)
}
}
toString() {
let result = '[' + this.name + '(' + this.message
if (this.data) {
result += ', ' + util.inspect(this.data)
result += ', ' + inspect(this.data)
}
result += ')]'
return result
@@ -62,21 +57,21 @@ class ResponseFormatError extends ConnectionError {}
class ValidationError extends RippleError {}
class NotFoundError extends RippleError {
constructor(message) {
super(message || 'Not found')
constructor(message = 'Not found') {
super(message)
}
}
class MissingLedgerHistoryError extends RippleError {
constructor(message) {
constructor(message?: string) {
super(message || 'Server is missing ledger history in the specified range')
}
}
class PendingLedgerVersionError extends RippleError {
constructor(message) {
super(message || 'maxLedgerVersion is greater than server\'s'
+ ' most recent validated ledger')
constructor(message?: string) {
super(message || 'maxLedgerVersion is greater than server\'s most recent ' +
' validated ledger')
}
}

View File

@@ -1,12 +1,12 @@
/* @flow */
import * as _ from 'lodash'
import assert from 'assert'
import * as assert from 'assert'
function mergeIntervals(intervals: Array<[number, number]>) {
const stack = [[-Infinity, -Infinity]]
_.forEach(_.sortBy(intervals, x => x[0]), interval => {
const lastInterval = stack.pop()
type Interval = [number, number]
function mergeIntervals(intervals: Interval[]): Interval[] {
const stack: Interval[] = [[-Infinity, -Infinity]]
_.sortBy(intervals, x => x[0]).forEach(interval => {
const lastInterval: Interval = stack.pop()!
if (interval[0] <= lastInterval[1] + 1) {
stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])])
} else {

View File

@@ -1,9 +1,6 @@
// flow is disabled for this file until support for requiring json is added:
// https://github.com/facebook/flow/issues/167
import * as _ from 'lodash'
import assert from 'assert'
import {Validator} from 'jsonschema'
import * as assert from 'assert'
const {Validator} = require('jsonschema')
import {ValidationError} from './errors'
import {isValidAddress} from 'ripple-address-codec'
import {isValidSecret} from './utils'
@@ -111,20 +108,20 @@ function loadSchemas() {
require('./schemas/input/verify-payment-channel-claim.json'),
require('./schemas/input/combine.json')
]
const titles = _.map(schemas, schema => schema.title)
const duplicates = _.keys(_.pick(_.countBy(titles), count => count > 1))
const titles = schemas.map(schema => schema.title)
const duplicates = _.keys(_.pickBy(_.countBy(titles), count => count > 1))
assert(duplicates.length === 0, 'Duplicate schemas for: ' + duplicates)
const v = new Validator()
const validator = new Validator()
// Register custom format validators that ignore undefined instances
// since jsonschema will still call the format validator on a missing
// (optional) property
v.customFormats.address = function(instance) {
validator.customFormats.address = function(instance) {
if (instance === undefined) {
return true
}
return isValidAddress(instance)
}
v.customFormats.secret = function(instance) {
validator.customFormats.secret = function(instance) {
if (instance === undefined) {
return true
}
@@ -132,19 +129,19 @@ function loadSchemas() {
}
// Register under the root URI '/'
_.forEach(schemas, schema => v.addSchema(schema, '/' + schema.title))
return v
_.forEach(schemas, schema => validator.addSchema(schema, '/' + schema.title))
return validator
}
const v = loadSchemas()
const schemaValidator = loadSchemas()
function schemaValidate(schemaName: string, object: any): void {
// Lookup under the root URI '/'
const schema = v.getSchema('/' + schemaName)
const schema = schemaValidator.getSchema('/' + schemaName)
if (schema === undefined) {
throw new ValidationError('no schema for ' + schemaName)
}
const result = v.validate(object, schema)
const result = schemaValidator.validate(object, schema)
if (!result.valid) {
throw new ValidationError(result.errors.join())
}

View File

@@ -1,6 +1,6 @@
import * as _ from 'lodash'
import {convertKeysFromSnakeCaseToCamelCase} from './utils'
import type Connection from './connection'
import Connection from './connection'
export type GetServerInfoResponse = {
buildVersion: string,
@@ -60,16 +60,19 @@ function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
})
}
// TODO: This was originally annotated to return a number, but actually
// returned a toString'ed number. Should this actually be returning a number?
function computeFeeFromServerInfo(cushion: number,
serverInfo: GetServerInfoResponse
): number {
): string {
return (Number(serverInfo.validatedLedger.baseFeeXRP)
* Number(serverInfo.loadFactor) * cushion).toString()
}
function getFee(connection: Connection, cushion: number) {
return getServerInfo(connection).then(
_.partial(computeFeeFromServerInfo, cushion))
function getFee(connection: Connection, cushion: number): Promise<string> {
return getServerInfo(connection).then(serverInfo => {
return computeFeeFromServerInfo(cushion, serverInfo)
})
}
export {

View File

@@ -1,5 +1,3 @@
/* @flow */
export type RippledAmountIOU = {
currency: string,
@@ -13,6 +11,7 @@ export type RippledAmount = string | RippledAmountIOU
export type Amount = {
value: string,
currency: string,
issuer?: string,
counterparty?: string
}
@@ -21,12 +20,14 @@ export type Amount = {
export type LaxLaxAmount = {
currency: string,
value?: string,
issuer?: string,
counterparty?: string
}
// A currency-counterparty pair, or just currency if it's XRP
export type Issue = {
currency: string,
issuer?: string,
counterparty?: string
}
@@ -53,3 +54,10 @@ export type Memo = {
format?: string,
data?: string
}
export type ApiMemo = {
MemoData?: string,
MemoType?: string,
MemoFormat?: string
}

View File

@@ -1,10 +1,8 @@
/* @flow */
import * as _ from 'lodash'
import BigNumber from 'bignumber.js'
import {deriveKeypair} from 'ripple-keypairs'
const {deriveKeypair} = require('ripple-keypairs')
import type {Amount, RippledAmount} from './types'
import {Amount, RippledAmount} from './types'
function isValidSecret(secret: string): boolean {
try {
@@ -27,7 +25,6 @@ function toRippledAmount(amount: Amount): RippledAmount {
if (amount.currency === 'XRP') {
return xrpToDrops(amount.value)
}
// $FlowFixMe: amount.issuer is not a Amount type property. Safe to remove?
return {
currency: amount.currency,
issuer: amount.counterparty ? amount.counterparty :
@@ -53,8 +50,8 @@ function convertKeysFromSnakeCaseToCamelCase(obj: any): any {
return obj
}
function removeUndefined(obj: Object): Object {
return _.omitBy(obj, _.isUndefined)
function removeUndefined<T extends object>(obj: T): T {
return _.omitBy(obj, _.isUndefined) as T
}
/**

View File

@@ -1,5 +1,3 @@
/* @flow */
import * as _ from 'lodash'
import {ValidationError} from './errors'
import {schemaValidate} from './schema-validator'

View File

@@ -1,18 +1,31 @@
import {EventEmitter} from 'events'
import events from 'events'
function unsused() {}
// Define the global WebSocket class found on the native browser
declare class WebSocket {
onclose?: Function
onopen?: Function
onerror?: Function
onmessage?: Function
readyState: number
constructor(url: string)
close()
send(message: string)
}
/**
* Provides `EventEmitter` interface for native browser `WebSocket`,
* same, as `ws` package provides.
*/
class WSWrapper extends events.EventEmitter {
constructor(url, protocols = null, websocketOptions = {}) {
class WSWrapper extends EventEmitter {
private _ws: WebSocket
static CONNECTING = 0
static OPEN = 1
static CLOSING = 2
static CLOSED = 3
constructor(url, _protocols: any, _websocketOptions: any) {
super()
unsused(protocols)
unsused(websocketOptions)
this.setMaxListeners(Infinity)
this._ws = new WebSocket(url)
@@ -50,10 +63,5 @@ class WSWrapper extends events.EventEmitter {
}
WSWrapper.CONNECTING = 0
WSWrapper.OPEN = 1
WSWrapper.CLOSING = 2
WSWrapper.CLOSED = 3
export default WSWrapper
export = WSWrapper

View File

@@ -1,6 +1,6 @@
/* eslint-disable new-cap */
import assert from 'assert'
import * as assert from 'assert'
import * as _ from 'lodash'
import jayson from 'jayson'
import {RippleAPI} from './api'

View File

@@ -1,5 +1,3 @@
/* @flow */
import {validate, removeUndefined, dropsToXrp} from '../common'
type AccountData = {

View File

@@ -1,9 +1,7 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
import {validate} from '../common'
import type {Amount} from '../common/types'
import {Amount} from '../common/types'
type BalanceSheetOptions = {
excludeAddresses?: Array<string>,
@@ -20,7 +18,7 @@ type GetBalanceSheet = {
}
function formatBalanceSheet(balanceSheet): GetBalanceSheet {
const result = {}
const result: GetBalanceSheet = {}
if (!_.isUndefined(balanceSheet.balances)) {
result.balances = []
@@ -39,8 +37,10 @@ function formatBalanceSheet(balanceSheet): GetBalanceSheet {
})
}
if (!_.isUndefined(balanceSheet.obligations)) {
result.obligations = _.map(balanceSheet.obligations, (value, currency) =>
({currency, value}))
result.obligations = _.map(
balanceSheet.obligations as {[key: string]: string},
(value, currency) => ({currency, value})
)
}
return result

View File

@@ -1,9 +1,7 @@
/* @flow */
import * as utils from './utils'
import {validate} from '../common'
import type {Connection} from '../common'
import type {TrustlinesOptions, Trustline} from './trustlines-types'
import {Connection} from '../common'
import {TrustlinesOptions, Trustline} from './trustlines-types'
type Balance = {

View File

@@ -1,8 +1,6 @@
/* @flow */
import {validate} from '../common'
import parseLedger from './parse/ledger'
import type {GetLedger} from './types'
import {GetLedger} from './types'
type LedgerOptions = {
ledgerVersion?: number,

View File

@@ -1,12 +1,10 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
import parseOrderbookOrder from './parse/orderbook-order'
import {validate} from '../common'
import type {Connection} from '../common'
import type {OrdersOptions, OrderSpecification} from './types'
import type {Amount, Issue} from '../common/types'
import {Connection} from '../common'
import {OrdersOptions, OrderSpecification} from './types'
import {Amount, Issue} from '../common/types'
type Orderbook = {
base: Issue,
@@ -36,21 +34,25 @@ type GetOrderbook = {
// account is to specify a "perspective", which affects which unfunded offers
// are returned
function getBookOffers(connection: Connection, account: string,
ledgerVersion?: number, limit?: number, takerGets: Issue,
ledgerVersion: number|undefined, limit: number|undefined, takerGets: Issue,
takerPays: Issue
): Promise<Object[]> {
return connection.request(utils.renameCounterpartyToIssuerInOrder({
command: 'book_offers',
const orderData = utils.renameCounterpartyToIssuerInOrder({
taker_gets: takerGets,
taker_pays: takerPays,
taker_pays: takerPays
})
return connection.request({
command: 'book_offers',
taker_gets: orderData.taker_gets,
taker_pays: orderData.taker_pays,
ledger_index: ledgerVersion || 'validated',
limit: limit,
taker: account
})).then(data => data.offers)
}).then(data => data.offers)
}
function isSameIssue(a: Amount, b: Amount) {
return a.currency === b.currency && a.counterparty === b.counterparty
return a.currency === b.currency && a.issuer === b.issuer
}
function directionFilter(direction: string, order: OrderbookItem) {

View File

@@ -1,11 +1,9 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
import {validate} from '../common'
import type {Connection} from '../common'
import {Connection} from '../common'
import parseAccountOrder from './parse/account-order'
import type {OrdersOptions, Order} from './types'
import {OrdersOptions, Order} from './types'
type GetOrders = Array<Order>
@@ -18,12 +16,10 @@ function requestAccountOffers(connection: Connection, address: string,
marker: marker,
limit: utils.clamp(limit, 10, 400),
ledger_index: ledgerVersion
}).then(data => {
return {
marker: data.marker,
results: data.offers.map(_.partial(parseAccountOrder, address))
}
})
}).then(data => ({
marker: data.marker,
results: data.offers.map(_.partial(parseAccountOrder, address))
}))
}
function getOrders(address: string, options: OrdersOptions = {}

View File

@@ -1,5 +1,3 @@
/* @flow */
import BigNumber from 'bignumber.js'
import parseAmount from './amount'
import {parseTimestamp, adjustQualityForXRP} from './utils'
@@ -14,7 +12,7 @@ function computeQuality(takerGets, takerPays) {
// rippled 'account_offers' returns a different format for orders than 'tx'
// the flags are also different
function parseAccountOrder(address: string, order: Object): Object {
function parseAccountOrder(address: string, order: any): Object {
const direction = (order.flags & orderFlags.Sell) === 0 ? 'buy' : 'sell'
const takerGetsAmount = parseAmount(order.taker_gets)
const takerPaysAmount = parseAmount(order.taker_pays)

View File

@@ -1,11 +1,9 @@
/* @flow */
import {parseQuality} from './utils'
import {removeUndefined} from '../../common'
type Trustline = {
account: string, limit: number, currency: string, quality_in: ?number,
quality_out: ?number, no_ripple: boolean, freeze: boolean,
account: string, limit: number, currency: string, quality_in: number|null,
quality_out: number|null, no_ripple: boolean, freeze: boolean,
authorized: boolean, limit_peer: string, no_ripple_peer: boolean,
freeze_peer: boolean, peer_authorized: boolean, balance: any
}

View File

@@ -1,6 +1,6 @@
function parseAmendment(tx: Object) {
function parseAmendment(tx: any) {
return {
amendment: tx.Amendment
}

View File

@@ -1,7 +1,5 @@
/* @flow */
import * as common from '../../common'
import type {Amount, RippledAmount} from '../../common/types'
import {Amount, RippledAmount} from '../../common/types'
function parseAmount(amount: RippledAmount): Amount {

View File

@@ -1,8 +1,6 @@
/* @flow */
import * as assert from 'assert'
import assert from 'assert'
function parseOrderCancellation(tx: Object): Object {
function parseOrderCancellation(tx: any): Object {
assert(tx.TransactionType === 'OfferCancel')
return {
orderSequence: tx.OfferSequence

View File

@@ -1,10 +1,8 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import {parseMemos} from './utils'
import {removeUndefined} from '../../common'
function parseEscrowCancellation(tx: Object): Object {
function parseEscrowCancellation(tx: any): Object {
assert(tx.TransactionType === 'EscrowCancel')
return removeUndefined({

View File

@@ -1,11 +1,9 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import parseAmount from './amount'
import {parseTimestamp, parseMemos} from './utils'
import {removeUndefined} from '../../common'
function parseEscrowCreation(tx: Object): Object {
function parseEscrowCreation(tx: any): Object {
assert(tx.TransactionType === 'EscrowCreate')
return removeUndefined({

View File

@@ -1,10 +1,8 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import {parseMemos} from './utils'
import {removeUndefined} from '../../common'
function parseEscrowExecution(tx: Object): Object {
function parseEscrowExecution(tx: any): Object {
assert(tx.TransactionType === 'EscrowFinish')
return removeUndefined({

View File

@@ -2,7 +2,7 @@
import BigNumber from 'bignumber.js'
import {dropsToXrp} from '../../common'
function parseFeeUpdate(tx: Object) {
function parseFeeUpdate(tx: any) {
const baseFeeDrops = (new BigNumber(tx.BaseFee, 16)).toString()
return {
baseFeeXRP: dropsToXrp(baseFeeDrops),

View File

@@ -1,5 +1,3 @@
/* @flow */
import * as _ from 'lodash'
import BigNumber from 'bignumber.js'
import {constants} from '../../common'
@@ -15,8 +13,8 @@ function parseField(info, value) {
return value
}
function parseFields(data: Object): Object {
const settings = {}
function parseFields(data: any): Object {
const settings: any = {}
for (const fieldName in AccountFields) {
const fieldValue = data[fieldName]
if (fieldValue !== undefined) {
@@ -39,7 +37,7 @@ function parseFields(data: Object): Object {
if (data.signer_lists[0].SignerEntries) {
settings.signers.weights = _.map(
data.signer_lists[0].SignerEntries,
entry => {
(entry: any) => {
return {
address: entry.SignerEntry.Account,
weight: entry.SignerEntry.SignerWeight

View File

@@ -1,9 +1,7 @@
/* @flow */
import * as _ from 'lodash'
import {removeUndefined, rippleTimeToISO8601} from '../../common'
import parseTransaction from './transaction'
import type {GetLedger} from '../types'
import {GetLedger} from '../types'
function parseTransactionWrapper(ledgerVersion, tx) {
const transaction = _.assign({}, _.omit(tx, 'metaData'), {
@@ -41,9 +39,9 @@ function parseState(state) {
return {rawState: JSON.stringify(state)}
}
function parseLedger(ledger: Object): GetLedger {
function parseLedger(ledger: any): GetLedger {
const ledgerVersion = parseInt(ledger.ledger_index || ledger.seqNum, 10)
return removeUndefined(_.assign({
return removeUndefined(Object.assign({
stateHash: ledger.account_hash,
closeTime: rippleTimeToISO8601(ledger.close_time),
closeTimeResolution: ledger.close_time_resolution,

View File

@@ -1,12 +1,10 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import {parseTimestamp} from './utils'
import parseAmount from './amount'
import {removeUndefined, txFlags} from '../../common'
const flags = txFlags.OfferCreate
function parseOrder(tx: Object): Object {
function parseOrder(tx: any): Object {
assert(tx.TransactionType === 'OfferCreate')
const direction = (tx.Flags & flags.Sell) === 0 ? 'buy' : 'sell'

View File

@@ -1,5 +1,3 @@
/* @flow */
import * as _ from 'lodash'
import {parseTimestamp, adjustQualityForXRP} from './utils'
import {removeUndefined} from '../../common'
@@ -7,7 +5,7 @@ import {removeUndefined} from '../../common'
import {orderFlags} from './flags'
import parseAmount from './amount'
function parseOrderbookOrder(order: Object): Object {
function parseOrderbookOrder(order: any): Object {
const direction = (order.Flags & orderFlags.Sell) === 0 ? 'buy' : 'sell'
const takerGetsAmount = parseAmount(order.TakerGets)
const takerPaysAmount = parseAmount(order.TakerPays)

View File

@@ -1,9 +1,7 @@
/* @flow */
import * as _ from 'lodash'
import parseAmount from './amount'
import type {Amount, RippledAmount} from '../../common/types'
import type {GetPaths, RippledPathsResponse} from '../pathfind-types'
import {Amount, RippledAmount} from '../../common/types'
import {Path, GetPaths, RippledPathsResponse} from '../pathfind-types'
function parsePaths(paths) {
return paths.map(steps => steps.map(step =>
@@ -15,7 +13,8 @@ function removeAnyCounterpartyEncoding(address: string, amount: Amount) {
_.omit(amount, 'counterparty') : amount
}
function createAdjustment(address: string, adjustmentWithoutAddress: Object) {
function createAdjustment(
address: string, adjustmentWithoutAddress: Object): any {
const amountKey = _.keys(adjustmentWithoutAddress)[0]
const amount = adjustmentWithoutAddress[amountKey]
return _.set({address: address}, amountKey,
@@ -23,8 +22,8 @@ function createAdjustment(address: string, adjustmentWithoutAddress: Object) {
}
function parseAlternative(sourceAddress: string, destinationAddress: string,
destinationAmount: RippledAmount, alternative: Object
) {
destinationAmount: RippledAmount, alternative: any
): Path {
// we use "maxAmount"/"minAmount" here so that the result can be passed
// directly to preparePayment
const amounts = (alternative.destination_amount !== undefined) ?
@@ -44,8 +43,8 @@ function parsePathfind(pathfindResult: RippledPathsResponse): GetPaths {
const sourceAddress = pathfindResult.source_account
const destinationAddress = pathfindResult.destination_account
const destinationAmount = pathfindResult.destination_amount
return pathfindResult.alternatives.map(_.partial(parseAlternative,
sourceAddress, destinationAddress, destinationAmount))
return pathfindResult.alternatives.map(alt =>
parseAlternative(sourceAddress, destinationAddress, destinationAmount, alt))
}
export default parsePathfind

View File

@@ -1,11 +1,9 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import {removeUndefined, txFlags} from '../../common'
import parseAmount from './amount'
const claimFlags = txFlags.PaymentChannelClaim
function parsePaymentChannelClaim(tx: Object): Object {
function parsePaymentChannelClaim(tx: any): Object {
assert(tx.TransactionType === 'PaymentChannelClaim')
return removeUndefined({

View File

@@ -1,11 +1,9 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import {parseTimestamp} from './utils'
import {removeUndefined} from '../../common'
import parseAmount from './amount'
function parsePaymentChannelCreate(tx: Object): Object {
function parsePaymentChannelCreate(tx: any): Object {
assert(tx.TransactionType === 'PaymentChannelCreate')
return removeUndefined({

View File

@@ -1,11 +1,9 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import {parseTimestamp} from './utils'
import {removeUndefined} from '../../common'
import parseAmount from './amount'
function parsePaymentChannelFund(tx: Object): Object {
function parsePaymentChannelFund(tx: any): Object {
assert(tx.TransactionType === 'PaymentChannelFund')
return removeUndefined({

View File

@@ -1,23 +1,49 @@
/* @flow */
import {parseTimestamp} from './utils'
import {removeUndefined, dropsToXrp} from '../../common'
export type PaymentChannel = {
Sequence: number,
Account: string,
Amount: string,
Balance: string,
PublicKey: number,
Destination: string,
SettleDelay: number,
Expiration?: number,
CancelAfter?: number,
SourceTag?: number,
DestinationTag?: number,
OwnerNode: string,
LedgerEntryType: string,
PreviousTxnID: string,
PreviousTxnLgrSeq: number,
index: string
}
export type LedgerEntryResponse = {
node: PaymentChannel,
ledger_current_index?: number,
ledger_hash?: string,
ledger_index: number,
validated: boolean
}
type PaymentChannelResponse = {
account: string,
balance: string,
publicKey: number,
destination: string,
settleDelay: number,
expiration?: number,
cancelAfter?: number,
expiration?: string,
cancelAfter?: string,
sourceTag?: number,
destinationTag?: number,
previousAffectingTransactionID: string,
previousAffectingTransactionLedgerVersion: number
}
function parsePaymentChannel(data: Object): PaymentChannelResponse {
function parsePaymentChannel(data: PaymentChannel): PaymentChannelResponse {
return removeUndefined({
account: data.Account,
amount: dropsToXrp(data.Amount),

View File

@@ -1,7 +1,5 @@
/* @flow */
import * as _ from 'lodash'
import assert from 'assert'
import * as assert from 'assert'
import * as utils from './utils'
import {txFlags, removeUndefined} from '../../common'
import parseAmount from './amount'
@@ -19,7 +17,7 @@ function removeGenericCounterparty(amount, address) {
_.omit(amount, 'counterparty') : amount
}
function parsePayment(tx: Object): Object {
function parsePayment(tx: any): Object {
assert(tx.TransactionType === 'Payment')
const source = {

View File

@@ -1,20 +1,18 @@
/* @flow */
import * as _ from 'lodash'
import assert from 'assert'
import * as assert from 'assert'
import {constants} from '../../common'
const AccountFlags = constants.AccountFlags
import parseFields from './fields'
function getAccountRootModifiedNode(tx: Object) {
function getAccountRootModifiedNode(tx: any) {
const modifiedNodes = tx.meta.AffectedNodes.filter(node =>
node.ModifiedNode.LedgerEntryType === 'AccountRoot')
assert(modifiedNodes.length === 1)
return modifiedNodes[0].ModifiedNode
}
function parseFlags(tx: Object) {
const settings = {}
function parseFlags(tx: any): any {
const settings: any = {}
if (tx.TransactionType !== 'AccountSet') {
return settings
}
@@ -51,7 +49,7 @@ function parseFlags(tx: Object) {
return settings
}
function parseSettings(tx: Object) {
function parseSettings(tx: any) {
const txType = tx.TransactionType
assert(txType === 'AccountSet' || txType === 'SetRegularKey' ||
txType === 'SignerListSet')

View File

@@ -1,6 +1,4 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import {parseOutcome} from './utils'
import {removeUndefined} from '../../common'
import parsePayment from './payment'
@@ -38,7 +36,7 @@ function parseTransactionType(type) {
return mapping[type] || null
}
function parseTransaction(tx: Object): Object {
function parseTransaction(tx: any): any {
const type = parseTransactionType(tx.TransactionType)
const mapping = {
'payment': parsePayment,
@@ -55,7 +53,7 @@ function parseTransaction(tx: Object): Object {
'feeUpdate': parseFeeUpdate,
'amendment': parseAmendment
}
const parser: Function = (mapping: Object)[type]
const parser: Function = mapping[type]
assert(parser !== undefined, 'Unrecognized transaction type')
const specification = parser(tx)
const outcome = parseOutcome(tx)

View File

@@ -1,6 +1,4 @@
/* @flow */
import assert from 'assert'
import * as assert from 'assert'
import {parseQuality} from './utils'
import {txFlags, removeUndefined} from '../../common'
const flags = txFlags.TrustSet
@@ -15,7 +13,7 @@ function parseFlag(flagsValue, trueValue, falseValue) {
return undefined
}
function parseTrustline(tx: Object): Object {
function parseTrustline(tx: any): Object {
assert(tx.TransactionType === 'TrustSet')
return removeUndefined({

View File

@@ -1,12 +1,10 @@
/* @flow */
import * as _ from 'lodash'
import transactionParser from 'ripple-lib-transactionparser'
import transactionParser = require('ripple-lib-transactionparser')
import BigNumber from 'bignumber.js'
import * as common from '../../common'
import parseAmount from './amount'
import type {Amount} from '../../common/types'
import {Amount, Memo} from '../../common/types'
function adjustQualityForXRP(
quality: string, takerGetsCurrency: string, takerPaysCurrency: string
@@ -20,15 +18,18 @@ function adjustQualityForXRP(
(new BigNumber(quality)).shift(shift).toString()
}
function parseQuality(quality: ?number) {
if (typeof quality === 'number') {
return (new BigNumber(quality)).shift(-9).toNumber()
function parseQuality(quality?: number|null): number|undefined {
if (typeof quality !== 'number') {
return undefined
}
return undefined
return (new BigNumber(quality)).shift(-9).toNumber()
}
function parseTimestamp(rippleTime: number): string | void {
return rippleTime ? common.rippleTimeToISO8601(rippleTime) : undefined
function parseTimestamp(rippleTime?: number|null): string|undefined {
if (typeof rippleTime !== 'number') {
return undefined
}
return common.rippleTimeToISO8601(rippleTime)
}
function removeEmptyCounterparty(amount) {
@@ -51,11 +52,11 @@ function removeEmptyCounterpartyInOrderbookChanges(orderbookChanges) {
})
}
function isPartialPayment(tx: Object) {
function isPartialPayment(tx: any) {
return (tx.Flags & common.txFlags.Payment.PartialPayment) !== 0
}
function parseDeliveredAmount(tx: Object): Amount | void {
function parseDeliveredAmount(tx: any): Amount | void {
if (tx.TransactionType !== 'Payment' ||
tx.meta.TransactionResult !== 'tesSUCCESS') {
@@ -95,7 +96,7 @@ function parseDeliveredAmount(tx: Object): Amount | void {
return undefined
}
function parseOutcome(tx: Object): ?Object {
function parseOutcome(tx: any): any|undefined {
const metadata = tx.meta || tx.metaData
if (!metadata) {
return undefined
@@ -117,11 +118,11 @@ function parseOutcome(tx: Object): ?Object {
})
}
function hexToString(hex: string): ?string {
function hexToString(hex: string): string|undefined {
return hex ? new Buffer(hex, 'hex').toString('utf-8') : undefined
}
function parseMemos(tx: Object): ?Array<Object> {
function parseMemos(tx: any): Array<Memo>|undefined {
if (!Array.isArray(tx.Memos) || tx.Memos.length === 0) {
return undefined
}

View File

@@ -1,11 +1,9 @@
/* @flow */
import type {Amount, LaxLaxAmount, RippledAmount, Adjustment, MaxAdjustment,
import {Amount, LaxLaxAmount, RippledAmount, Adjustment, MaxAdjustment,
MinAdjustment} from '../common/types'
type Path = {
export type Path = {
source: Adjustment | MaxAdjustment,
destination: Adjustment | MinAdjustment,
paths: string
@@ -30,7 +28,7 @@ export type PathFindRequest = {
source_account: string,
destination_amount: RippledAmount,
destination_account: string,
source_currencies?: Array<string>,
source_currencies?: {currency: string, issuer?: string}[],
send_max?: RippledAmount
}
@@ -49,7 +47,7 @@ export type RippledPathsResponse = {
destination_account: string,
destination_amount: RippledAmount,
destination_currencies?: Array<string>,
source_account?: string,
source_account: string,
source_currencies?: Array<{currency: string}>,
full_reply?: boolean
}

View File

@@ -1,13 +1,11 @@
/* @flow */
import * as _ from 'lodash'
import BigNumber from 'bignumber.js'
import {getXRPBalance} from './utils'
import {getXRPBalance, renameCounterpartyToIssuer} from './utils'
import {validate, toRippledAmount, errors} from '../common'
import type {Connection} from '../common'
import {Connection} from '../common'
import parsePathfind from './parse/pathfind'
import type {RippledAmount} from '../common/types'
import type {
import {RippledAmount, Amount} from '../common/types'
import {
GetPaths, PathFind, RippledPathsResponse, PathFindRequest
} from './pathfind-types'
const NotFoundError = errors.NotFoundError
@@ -24,7 +22,10 @@ function addParams(request: PathFindRequest, result: RippledPathsResponse
function requestPathFind(connection: Connection, pathfind: PathFind
): Promise<RippledPathsResponse> {
const destinationAmount = _.assign({value: -1}, pathfind.destination.amount)
const destinationAmount: Amount = _.assign(
{value: '-1'},
pathfind.destination.amount
)
const request: PathFindRequest = {
command: 'ripple_path_find',
source_account: pathfind.source.address,
@@ -41,8 +42,8 @@ function requestPathFind(connection: Connection, pathfind: PathFind
request.destination_amount.issuer = request.destination_account
}
if (pathfind.source.currencies && pathfind.source.currencies.length > 0) {
request.source_currencies = pathfind.source.currencies.map(amount =>
_.omit(toRippledAmount(amount), 'value'))
request.source_currencies = pathfind.source.currencies.map(
amount => renameCounterpartyToIssuer(amount))
}
if (pathfind.source.amount) {
if (pathfind.destination.amount.value !== undefined) {
@@ -50,7 +51,7 @@ function requestPathFind(connection: Connection, pathfind: PathFind
+ ' and destination.amount.value in getPaths')
}
request.send_max = toRippledAmount(pathfind.source.amount)
if (request.send_max.currency && !request.send_max.issuer) {
if (typeof request.send_max !== 'string' && !request.send_max.issuer) {
request.send_max.issuer = pathfind.source.address
}
}
@@ -62,6 +63,7 @@ function addDirectXrpPath(paths: RippledPathsResponse, xrpBalance: string
): RippledPathsResponse {
// Add XRP "path" only if the source acct has enough XRP to make the payment
const destinationAmount = paths.destination_amount
// @ts-ignore: destinationAmount can be a currency amount object! Fix!
if ((new BigNumber(xrpBalance)).greaterThanOrEqualTo(destinationAmount)) {
paths.alternatives.unshift({
paths_computed: [],
@@ -93,11 +95,13 @@ function filterSourceFundsLowPaths(pathfind: PathFind,
): RippledPathsResponse {
if (pathfind.source.amount &&
pathfind.destination.amount.value === undefined && paths.alternatives) {
paths.alternatives = _.filter(paths.alternatives, alt => {
return alt.source_amount &&
pathfind.source.amount &&
paths.alternatives = _.filter(paths.alternatives, alt =>
!!alt.source_amount &&
!!pathfind.source.amount &&
// TODO: Returns false when alt.source_amount is a string. Fix?
typeof alt.source_amount !== 'string' &&
new BigNumber(alt.source_amount.value).eq(pathfind.source.amount.value)
})
)
}
return paths
}

View File

@@ -1,35 +1,9 @@
/* @flow */
import parsePaymentChannel from './parse/payment-channel'
import parsePaymentChannel, {
LedgerEntryResponse, PaymentChannel
} from './parse/payment-channel'
import {validate, errors} from '../common'
const NotFoundError = errors.NotFoundError
type PaymentChannel = {
Sequence: number,
Account: string,
Balance: string,
PublicKey: number,
Destination: string,
SettleDelay: number,
Expiration?: number,
CancelAfter?: number,
SourceTag?: number,
DestinationTag?: number,
OwnerNode: string,
LedgerEntryType: string,
PreviousTxnID: string,
PreviousTxnLgrSeq: number,
index: string
}
type LedgerEntryResponse = {
node: PaymentChannel,
ledger_current_index?: number,
ledger_hash?: string,
ledger_index: number,
validated: boolean
}
function formatResponse(response: LedgerEntryResponse) {
if (response.node !== undefined &&
response.node.LedgerEntryType === 'PayChannel') {

View File

@@ -1,5 +1,3 @@
/* @flow */
import * as _ from 'lodash'
import parseFields from './parse/fields'
import {validate, constants} from '../common'
@@ -19,10 +17,10 @@ type GetSettings = {
noFreeze?: boolean,
globalFreeze?: boolean,
defaultRipple?: boolean,
emailHash?: ?string,
emailHash?: string|null,
messageKey?: string,
domain?: string,
transferRate?: ?number,
transferRate?: number|null,
regularKey?: string
}

View File

@@ -1,7 +1,5 @@
/* @flow */
import type {Amount, Memo} from '../common/types'
import {Amount, Memo} from '../common/types'
type Outcome = {
result: string,
@@ -87,7 +85,10 @@ export type Order = {
totalPrice: Amount,
immediateOrCancel?: boolean,
fillOrKill?: boolean,
passive?: boolean
passive?: boolean,
expirationTime?: string,
orderToReplace?: number,
memos?: Memo[]
}
type OrderTransaction = {
@@ -133,3 +134,10 @@ export type TransactionOptions = {
export type TransactionType = PaymentTransaction | OrderTransaction |
OrderCancellationTransaction | TrustlineTransaction | SettingsTransaction
export type TransactionResponse = TransactionType & {
hash: string,
ledger_index: number,
meta: any,
validated?: boolean
}

View File

@@ -1,13 +1,13 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
import parseTransaction from './parse/transaction'
import {validate, errors} from '../common'
import type {Connection} from '../common'
import type {TransactionType, TransactionOptions} from './transaction-types'
import {Connection} from '../common'
import {
TransactionType, TransactionResponse, TransactionOptions
} from './transaction-types'
function attachTransactionDate(connection: Connection, tx: Object
function attachTransactionDate(connection: Connection, tx: any
): Promise<TransactionType> {
if (tx.date) {
return Promise.resolve(tx)
@@ -40,7 +40,7 @@ function attachTransactionDate(connection: Connection, tx: Object
})
}
function isTransactionInRange(tx: Object, options: TransactionOptions) {
function isTransactionInRange(tx: any, options: TransactionOptions) {
return (!options.minLedgerVersion
|| tx.ledger_index >= options.minLedgerVersion)
&& (!options.maxLedgerVersion
@@ -70,10 +70,10 @@ function convertError(connection: Connection, options: TransactionOptions,
return Promise.resolve(_error)
}
function formatResponse(options: TransactionOptions, tx: TransactionType
function formatResponse(options: TransactionOptions, tx: TransactionResponse
): TransactionType {
if (tx.validated !== true || !isTransactionInRange(tx, options)) {
throw new errors.NotFoundError('Transaction not found')
throw new errors.NotFoundError('Transaction not found')
}
return parseTransaction(tx)
}
@@ -89,7 +89,7 @@ function getTransaction(id: string, options: TransactionOptions = {}
}
return utils.ensureLedgerVersion.call(this, options).then(_options => {
return this.connection.request(request).then(tx =>
return this.connection.request(request).then((tx: TransactionResponse) =>
attachTransactionDate(this.connection, tx)
).then(_.partial(formatResponse, _options))
.catch(error => {

View File

@@ -1,14 +1,12 @@
/* @flow */
import * as _ from 'lodash'
import binary from 'ripple-binary-codec'
import {computeTransactionHash} from 'ripple-hashes'
import binary = require('ripple-binary-codec')
const {computeTransactionHash} = require('ripple-hashes')
import * as utils from './utils'
import parseTransaction from './parse/transaction'
import getTransaction from './transaction'
import {validate, errors} from '../common'
import type {Connection} from '../common'
import type {TransactionType} from './transaction-types'
import {Connection} from '../common'
import {TransactionType} from './transaction-types'
type TransactionsOptions = {
@@ -46,14 +44,15 @@ function parseAccountTxTransaction(tx) {
}
function counterpartyFilter(filters, tx: TransactionType) {
if (tx.address === filters.counterparty || (
tx.specification && (
(tx.specification.destination &&
tx.specification.destination.address === filters.counterparty) ||
(tx.specification.counterparty === filters.counterparty)
))) {
if (tx.address === filters.counterparty) {
return true
}
const specification: any = tx.specification
if (specification && ((specification.destination &&
specification.destination.address === filters.counterparty) ||
(specification.counterparty === filters.counterparty))) {
return true
}
return false
}
@@ -127,9 +126,9 @@ function checkForLedgerGaps(connection: Connection,
// the range of ledgers spanned by those transactions
if (options.limit && transactions.length === options.limit) {
if (options.earliestFirst) {
maxLedgerVersion = _.last(transactions).outcome.ledgerVersion
maxLedgerVersion = _.last(transactions)!.outcome.ledgerVersion
} else {
minLedgerVersion = _.last(transactions).outcome.ledgerVersion
minLedgerVersion = _.last(transactions)!.outcome.ledgerVersion
}
}
@@ -169,8 +168,8 @@ function getTransactions(address: string, options: TransactionsOptions = {}
const ledgerVersion = tx.outcome.ledgerVersion
const bound = options.earliestFirst ?
{minLedgerVersion: ledgerVersion} : {maxLedgerVersion: ledgerVersion}
const newOptions = _.assign({}, defaults, options, {startTx: tx}, bound)
return getTransactionsInternal(this.connection, address, newOptions)
const startOptions = _.assign({}, defaults, options, {startTx: tx}, bound)
return getTransactionsInternal(this.connection, address, startOptions)
})
}
const newOptions = _.assign({}, defaults, options)

View File

@@ -1,5 +1,4 @@
/* @flow */
import {Memo} from '../common/types'
export type TrustLineSpecification = {
currency: string,
@@ -9,7 +8,8 @@ export type TrustLineSpecification = {
qualityOut?: number,
ripplingDisabled?: boolean,
authorized?: boolean,
frozen?: boolean
frozen?: boolean,
memos?: Memo[]
}
export type Trustline = {

View File

@@ -1,20 +1,22 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
import {validate} from '../common'
import type {Connection} from '../common'
import {Connection} from '../common'
import parseAccountTrustline from './parse/account-trustline'
import type {TrustlinesOptions, Trustline} from './trustlines-types'
import {TrustlinesOptions, Trustline} from './trustlines-types'
type GetTrustlinesResponse = Array<Trustline>
interface GetAccountLinesResponse {
marker?: any,
results: Trustline[]
}
function currencyFilter(currency: string, trustline: Trustline) {
return currency === null || trustline.specification.currency === currency
}
function formatResponse(options: TrustlinesOptions, data) {
function formatResponse(options: TrustlinesOptions, data: any) {
return {
marker: data.marker,
results: data.lines.map(parseAccountTrustline)
@@ -25,7 +27,7 @@ function formatResponse(options: TrustlinesOptions, data) {
function getAccountLines(connection: Connection, address: string,
ledgerVersion: number, options: TrustlinesOptions, marker: string,
limit: number
): Promise<GetTrustlinesResponse> {
): Promise<GetAccountLinesResponse> {
const request = {
command: 'account_lines',
account: address,

View File

@@ -1,7 +1,5 @@
/* @flow */
import type {Amount} from '../common/types'
import {Amount} from '../common/types'
export type OrdersOptions = {
limit?: number,
@@ -30,16 +28,17 @@ export type Order = {
}
export type GetLedger = {
accepted: boolean,
closed: boolean,
// TODO: properties in type don't match response object. Fix!
// accepted: boolean,
// closed: boolean,
stateHash: string,
closeTime: number,
closeTime: string,
closeTimeResolution: number,
closeFlags: number,
ledgerHash: string,
ledgerVersion: number,
parentLedgerHash: string,
parentCloseTime: number,
parentCloseTime: string,
totalDrops: string,
transactionHash: string,
transactions?: Array<Object>,

View File

@@ -1,18 +1,16 @@
/* @flow */
import * as _ from 'lodash'
import assert from 'assert'
import * as assert from 'assert'
import * as common from '../common'
import type {Connection} from '../common'
import type {TransactionType} from './transaction-types'
import type {Issue} from '../common/types'
import {Connection} from '../common'
import {TransactionType} from './transaction-types'
import {Issue} from '../common/types'
type RecursiveData = {
marker: string,
results: Array<any>
}
type Getter = (marker: ?string, limit: number) => Promise<RecursiveData>
type Getter = (marker?: string, limit?: number) => Promise<RecursiveData>
function clamp(value: number, min: number, max: number): number {
assert(min <= max, 'Illegal clamp bounds')
@@ -32,7 +30,8 @@ function getXRPBalance(connection: Connection, address: string,
}
// If the marker is omitted from a response, you have reached the end
function getRecursiveRecur(getter: Getter, marker?: string, limit: number
function getRecursiveRecur(
getter: Getter, marker: string | undefined, limit: number
): Promise<Array<any>> {
return getter(marker, limit).then(data => {
const remaining = limit - data.results.length
@@ -49,15 +48,15 @@ function getRecursive(getter: Getter, limit?: number): Promise<Array<any>> {
return getRecursiveRecur(getter, undefined, limit || Infinity)
}
function renameCounterpartyToIssuer(amount?: Issue): ?{issuer?: string} {
if (amount === undefined) {
return undefined
}
const issuer = amount.counterparty === undefined ?
(amount.issuer !== undefined ? amount.issuer : undefined) :
amount.counterparty
const withIssuer = _.assign({}, amount, {issuer: issuer})
return _.omit(withIssuer, 'counterparty')
function renameCounterpartyToIssuer<T>(
obj: T & {counterparty?: string, issuer?: string}
): (T & {issuer?: string}) {
const issuer = (obj.counterparty !== undefined) ?
obj.counterparty :
((obj.issuer !== undefined) ? obj.issuer : undefined)
const withIssuer = Object.assign({}, obj, {issuer})
delete withIssuer.counterparty
return withIssuer
}
type RequestBookOffersArgs = {taker_gets: Issue, taker_pays: Issue}
@@ -65,7 +64,7 @@ type RequestBookOffersArgs = {taker_gets: Issue, taker_pays: Issue}
function renameCounterpartyToIssuerInOrder(order: RequestBookOffersArgs) {
const taker_gets = renameCounterpartyToIssuer(order.taker_gets)
const taker_pays = renameCounterpartyToIssuer(order.taker_pays)
const changes = {taker_gets: taker_gets, taker_pays: taker_pays}
const changes = {taker_gets, taker_pays}
return _.assign({}, order, _.omitBy(changes, _.isUndefined))
}
@@ -78,12 +77,7 @@ function signum(num) {
* If two transactions took place in the same ledger, sort
* them based on TransactionIndex
* See: https://ripple.com/build/transactions/
*
* @param {Object} first
* @param {Object} second
* @returns {Number} [-1, 0, 1]
*/
function compareTransactions(first: TransactionType, second: TransactionType
): number {
if (!first.outcome || !second.outcome) {
@@ -104,13 +98,13 @@ function hasCompleteLedgerRange(connection: Connection,
}
function isPendingLedgerVersion(connection: Connection,
maxLedgerVersion: ?number
maxLedgerVersion?: number
): Promise<boolean> {
return connection.getLedgerVersion().then(ledgerVersion =>
ledgerVersion < (maxLedgerVersion || 0))
}
function ensureLedgerVersion(options: Object
function ensureLedgerVersion(options: any
): Promise<Object> {
if (Boolean(options) && options.ledgerVersion !== undefined &&
options.ledgerVersion !== null
@@ -125,6 +119,7 @@ export {
getXRPBalance,
ensureLedgerVersion,
compareTransactions,
renameCounterpartyToIssuer,
renameCounterpartyToIssuerInOrder,
getRecursive,
hasCompleteLedgerRange,

View File

@@ -1,6 +1,4 @@
/* @flow */
import keypairs from 'ripple-keypairs'
import keypairs = require('ripple-keypairs')
import * as common from '../common'
const {errors, validate} = common

View File

@@ -1,10 +1,8 @@
/* @flow */
import * as _ from 'lodash'
import hashes = require('ripple-hashes')
import * as common from '../common'
import hashes from 'ripple-hashes'
function convertLedgerHeader(header) {
function convertLedgerHeader(header): any {
return {
account_hash: header.stateHash,
close_time: common.iso8601ToRippleTime(header.closeTime),
@@ -31,7 +29,7 @@ function computeTransactionHash(ledger, version) {
if (ledger.rawTransactions === undefined) {
return ledger.transactionHash
}
const transactions = JSON.parse(ledger.rawTransactions)
const transactions: any[] = JSON.parse(ledger.rawTransactions)
const txs = _.map(transactions, tx => {
const mergeTx = _.assign({}, _.omit(tx, 'tx'), tx.tx || {})
const renameMeta = _.assign({}, _.omit(mergeTx, 'meta'),
@@ -62,7 +60,7 @@ function computeStateHash(ledger, version) {
const sLCF_SHAMapV2 = 0x02
function computeLedgerHash(ledger: Object): string {
function computeLedgerHash(ledger: any): string {
const version = ((ledger.closeFlags & sLCF_SHAMapV2) === 0) ? 1 : 2
const subhashes = {
transactionHash: computeTransactionHash(ledger, version),

View File

@@ -1,8 +1,6 @@
/* @flow */
import * as common from '../common'
import keypairs from 'ripple-keypairs'
import binary from 'ripple-binary-codec'
import keypairs = require('ripple-keypairs')
import binary = require('ripple-binary-codec')
const {validate, xrpToDrops} = common
function signPaymentChannelClaim(channel: string, amount: string,

View File

@@ -1,9 +1,6 @@
/* @flow */
import * as common from '../common'
import keypairs from 'ripple-keypairs'
import binary from 'ripple-binary-codec'
const {validate, xrpToDrops} = common
import keypairs = require('ripple-keypairs')
import binary = require('ripple-binary-codec')
import {validate, xrpToDrops} from '../common'
function verifyPaymentChannelClaim(channel: string, amount: string,
signature: string, publicKey: string

View File

@@ -1,7 +1,5 @@
/* @flow */
import * as common from '../common'
import type {GetServerInfoResponse} from '../common/serverinfo'
import {GetServerInfoResponse} from '../common/serverinfo'
function isConnected(): boolean {
return this.connection.isConnected()
@@ -23,12 +21,12 @@ function getServerInfo(): Promise<GetServerInfoResponse> {
return common.serverInfo.getServerInfo(this.connection)
}
function getFee(): Promise<number> {
function getFee(): Promise<string> {
const cushion = this._feeCushion || 1.2
return common.serverInfo.getFee(this.connection, cushion)
}
function formatLedgerClose(ledgerClose: Object): Object {
function formatLedgerClose(ledgerClose: any): Object {
return {
baseFeeXRP: common.dropsToXrp(ledgerClose.fee_base),
ledgerHash: ledgerClose.ledger_hash,

View File

@@ -1,7 +1,5 @@
/* @flow */
import * as _ from 'lodash'
import binary from 'ripple-binary-codec'
import binary = require('ripple-binary-codec')
import * as utils from './utils'
import BigNumber from 'bignumber.js'
import {decodeAddress} from 'ripple-address-codec'
@@ -21,7 +19,9 @@ function compareSigners(a, b) {
function combine(signedTransactions: Array<string>): Object {
validate.combine({signedTransactions})
const txs = _.map(signedTransactions, binary.decode)
// TODO: signedTransactions is an array of strings in the documentation, but
// tests and this code handle it as an array of objects. Fix!
const txs: any[] = _.map(signedTransactions, binary.decode)
const tx = _.omit(txs[0], 'Signers')
if (!_.every(txs, _tx => _.isEqual(tx, _.omit(_tx, 'Signers')))) {
throw new utils.common.errors.ValidationError(

View File

@@ -1,10 +1,8 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
const validate = utils.common.validate
import type {Instructions, Prepare} from './types'
import type {Memo} from '../common/types'
import {Instructions, Prepare} from './types'
import {Memo} from '../common/types'
type EscrowCancellation = {
owner: string,
@@ -15,7 +13,7 @@ type EscrowCancellation = {
function createEscrowCancellationTransaction(account: string,
payment: EscrowCancellation
): Object {
const txJSON: Object = {
const txJSON: any = {
TransactionType: 'EscrowCancel',
Account: account,
Owner: payment.owner,

View File

@@ -1,11 +1,9 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
import {validate, iso8601ToRippleTime, xrpToDrops} from '../common'
const ValidationError = utils.common.errors.ValidationError
import type {Instructions, Prepare} from './types'
import type {Memo} from '../common/types'
import {Instructions, Prepare} from './types'
import {Memo} from '../common/types'
type EscrowCreation = {
amount: string,
@@ -21,7 +19,7 @@ type EscrowCreation = {
function createEscrowCreationTransaction(account: string,
payment: EscrowCreation
): Object {
const txJSON: Object = {
const txJSON: any = {
TransactionType: 'EscrowCreate',
Account: account,
Destination: payment.destination,

View File

@@ -1,11 +1,9 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
const validate = utils.common.validate
const ValidationError = utils.common.errors.ValidationError
import type {Instructions, Prepare} from './types'
import type {Memo} from '../common/types'
import {Instructions, Prepare} from './types'
import {Memo} from '../common/types'
type EscrowExecution = {
owner: string,
@@ -18,7 +16,7 @@ type EscrowExecution = {
function createEscrowExecutionTransaction(account: string,
payment: EscrowExecution
): Object {
const txJSON: Object = {
const txJSON: any = {
TransactionType: 'EscrowFinish',
Account: account,
Owner: payment.owner,

View File

@@ -1,11 +1,9 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
const offerFlags = utils.common.txFlags.OfferCreate
import {validate, iso8601ToRippleTime} from '../common'
import type {Instructions, Prepare} from './types'
import type {Order} from '../ledger/transaction-types'
import {Instructions, Prepare} from './types'
import {Order} from '../ledger/transaction-types'
function createOrderTransaction(account: string, order: Order): Object {
const takerPays = utils.common.toRippledAmount(order.direction === 'buy' ?
@@ -13,7 +11,7 @@ function createOrderTransaction(account: string, order: Order): Object {
const takerGets = utils.common.toRippledAmount(order.direction === 'buy' ?
order.totalPrice : order.quantity)
const txJSON: Object = {
const txJSON: any = {
TransactionType: 'OfferCreate',
Account: account,
TakerGets: takerGets,

View File

@@ -1,14 +1,12 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
const validate = utils.common.validate
import type {Instructions, Prepare} from './types'
import {Instructions, Prepare} from './types'
function createOrderCancellationTransaction(account: string,
orderCancellation: Object
orderCancellation: any
): Object {
const txJSON: Object = {
const txJSON: any = {
TransactionType: 'OfferCancel',
Account: account,
OfferSequence: orderCancellation.orderSequence

View File

@@ -1,10 +1,8 @@
/* @flow */
import * as utils from './utils'
const ValidationError = utils.common.errors.ValidationError
const claimFlags = utils.common.txFlags.PaymentChannelClaim
import {validate, xrpToDrops} from '../common'
import type {Instructions, Prepare} from './types'
import {Instructions, Prepare} from './types'
type PaymentChannelClaim = {
channel: string,
@@ -19,7 +17,7 @@ type PaymentChannelClaim = {
function createPaymentChannelClaimTransaction(account: string,
claim: PaymentChannelClaim
): Object {
const txJSON: Object = {
const txJSON: any = {
Account: account,
TransactionType: 'PaymentChannelClaim',
Channel: claim.channel,

View File

@@ -1,8 +1,6 @@
/* @flow */
import * as utils from './utils'
import {validate, iso8601ToRippleTime, xrpToDrops} from '../common'
import type {Instructions, Prepare} from './types'
import {Instructions, Prepare} from './types'
type PaymentChannelCreate = {
amount: string,
@@ -17,7 +15,7 @@ type PaymentChannelCreate = {
function createPaymentChannelCreateTransaction(account: string,
paymentChannel: PaymentChannelCreate
): Object {
const txJSON: Object = {
const txJSON: any = {
Account: account,
TransactionType: 'PaymentChannelCreate',
Amount: xrpToDrops(paymentChannel.amount),

View File

@@ -1,8 +1,6 @@
/* @flow */
import * as utils from './utils'
import {validate, iso8601ToRippleTime, xrpToDrops} from '../common'
import type {Instructions, Prepare} from './types'
import {Instructions, Prepare} from './types'
type PaymentChannelFund = {
channel: string,
@@ -13,7 +11,7 @@ type PaymentChannelFund = {
function createPaymentChannelFundTransaction(account: string,
fund: PaymentChannelFund
): Object {
const txJSON: Object = {
const txJSON: any = {
Account: account,
TransactionType: 'PaymentChannelFund',
Channel: fund.channel,

View File

@@ -1,19 +1,17 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
const validate = utils.common.validate
const toRippledAmount = utils.common.toRippledAmount
const paymentFlags = utils.common.txFlags.Payment
const ValidationError = utils.common.errors.ValidationError
import type {Instructions, Prepare} from './types'
import type {Amount, Adjustment, MaxAdjustment,
import {Instructions, Prepare} from './types'
import {Amount, Adjustment, MaxAdjustment,
MinAdjustment, Memo} from '../common/types'
type Payment = {
source: Adjustment | MaxAdjustment,
destination: Adjustment | MinAdjustment,
source: Adjustment & MaxAdjustment,
destination: Adjustment & MinAdjustment,
paths?: string,
memos?: Array<Memo>,
// A 256-bit hash that can be used to identify a particular payment
@@ -92,7 +90,7 @@ function createPaymentTransaction(address: string, paymentArgument: Payment
createMaximalAmount(payment.destination.minAmount) :
(payment.destination.amount || payment.destination.minAmount)
const txJSON: Object = {
const txJSON: any = {
TransactionType: 'Payment',
Account: payment.source.address,
Destination: payment.destination.address,

View File

@@ -1,14 +1,18 @@
/* @flow */
import * as _ from 'lodash'
import assert from 'assert'
import * as assert from 'assert'
import BigNumber from 'bignumber.js'
import * as utils from './utils'
const validate = utils.common.validate
const AccountFlagIndices = utils.common.constants.AccountFlagIndices
const AccountFields = utils.common.constants.AccountFields
import type {Instructions, Prepare} from './types'
import {Instructions, Prepare} from './types'
import {Memo} from '../common/types'
type WeightedSigner = {address: string, weight: number}
type SettingsSigners = {
threshold?: number,
weights: WeightedSigner[]
}
type Settings = {
passwordSpent?: boolean,
requireDestinationTag?: boolean,
@@ -19,25 +23,23 @@ type Settings = {
noFreeze?: boolean,
globalFreeze?: boolean,
defaultRipple?: boolean,
emailHash?: ?string,
emailHash?: string,
messageKey?: string,
domain?: string,
transferRate?: ?number,
transferRate?: number,
regularKey?: string,
signers?: {
threshold?: number,
weights: {address: string, weight: number}[],
},
signers?: SettingsSigners,
memos?: Memo[]
}
// Emptry string passed to setting will clear it
const CLEAR_SETTING = null
function setTransactionFlags(txJSON: Object, values: Settings) {
function setTransactionFlags(txJSON: any, values: Settings) {
const keys = Object.keys(values)
assert(keys.length === 1, 'ERROR: can only set one setting per transaction')
const flagName = keys[0]
const value = (values: Object)[flagName]
const value = values[flagName]
const index = AccountFlagIndices[flagName]
if (index !== undefined) {
if (value) {
@@ -89,7 +91,7 @@ function convertTransferRate(transferRate: number | string): number | string {
return (new BigNumber(transferRate)).shift(9).toNumber()
}
function formatSignerEntry(signer: Object): Object {
function formatSignerEntry(signer: WeightedSigner): Object {
return {
SignerEntry: {
Account: signer.address,
@@ -100,7 +102,7 @@ function formatSignerEntry(signer: Object): Object {
function createSettingsTransactionWithoutMemos(
account: string, settings: Settings
): Object {
): any {
if (settings.regularKey !== undefined) {
const removeRegularKey = {
TransactionType: 'SetRegularKey',
@@ -121,7 +123,7 @@ function createSettingsTransactionWithoutMemos(
}
}
const txJSON: Object = {
const txJSON: any = {
TransactionType: 'AccountSet',
Account: account
}

View File

@@ -1,18 +1,16 @@
/* @flow */
import * as utils from './utils'
import keypairs from 'ripple-keypairs'
import binary from 'ripple-binary-codec'
import keypairs = require('ripple-keypairs')
import binary = require('ripple-binary-codec')
import {computeBinaryTransactionHash} from 'ripple-hashes'
const validate = utils.common.validate
function computeSignature(tx: Object, privateKey: string, signAs: ?string) {
function computeSignature(tx: Object, privateKey: string, signAs?: string) {
const signingData = signAs ?
binary.encodeForMultisigning(tx, signAs) : binary.encodeForSigning(tx)
return keypairs.sign(signingData, privateKey)
}
function sign(txJSON: string, secret: string, options: Object = {}
function sign(txJSON: string, secret: string, options: {signAs?: string} = {}
): {signedTransaction: string; id: string} {
validate.sign({txJSON, secret})
// we can't validate that the secret matches the account because

View File

@@ -1,9 +1,7 @@
/* @flow */
import * as _ from 'lodash'
import * as utils from './utils'
import {validate} from '../common'
import type {Submit} from './types'
import {Submit} from './types'
function isImmediateRejection(engineResult: string): boolean {
// note: "tel" errors mean the local server refused to process the

View File

@@ -1,12 +1,10 @@
/* @flow */
import * as _ from 'lodash'
import BigNumber from 'bignumber.js'
import * as utils from './utils'
const validate = utils.common.validate
const trustlineFlags = utils.common.txFlags.TrustSet
import type {Instructions, Prepare} from './types'
import type {TrustLineSpecification} from '../ledger/trustlines-types'
import {Instructions, Prepare} from './types'
import {TrustLineSpecification} from '../ledger/trustlines-types'
function convertQuality(quality) {
return (new BigNumber(quality)).shift(9).truncated().toNumber()
@@ -21,7 +19,7 @@ function createTrustlineTransaction(account: string,
value: trustline.limit
}
const txJSON: Object = {
const txJSON: any = {
TransactionType: 'TrustSet',
Account: account,
LimitAmount: limit,

View File

@@ -1,5 +1,3 @@
/* @flow */
export type Instructions = {
sequence?: number,

View File

@@ -1,12 +1,11 @@
/* @flow */
import * as _ from 'lodash'
import BigNumber from 'bignumber.js'
import * as common from '../common'
import {Memo, ApiMemo} from '../common/types'
const txFlags = common.txFlags
import type {Instructions, Prepare} from './types'
import {Instructions, Prepare} from './types'
import {RippleAPI} from '../api'
function formatPrepareResponse(txJSON: Object): Object {
function formatPrepareResponse(txJSON: any): Prepare {
const instructions = {
fee: common.dropsToXrp(txJSON.Fee),
sequence: txJSON.Sequence,
@@ -15,7 +14,7 @@ function formatPrepareResponse(txJSON: Object): Object {
}
return {
txJSON: JSON.stringify(txJSON),
instructions: _.omitBy(instructions, _.isUndefined)
instructions
}
}
@@ -31,7 +30,7 @@ function scaleValue(value, multiplier, extra = 0) {
return (new BigNumber(value)).times(multiplier).plus(extra).toString()
}
function prepareTransaction(txJSON: Object, api: Object,
function prepareTransaction(txJSON: any, api: RippleAPI,
instructions: Instructions
): Promise<Prepare> {
common.validate.instructions(instructions)
@@ -104,17 +103,16 @@ function prepareTransaction(txJSON: Object, api: Object,
]).then(() => formatPrepareResponse(txJSON))
}
function convertStringToHex(string: string) {
return string ? (new Buffer(string, 'utf8')).toString('hex').toUpperCase() :
undefined
function convertStringToHex(string: string): string {
return new Buffer(string, 'utf8').toString('hex').toUpperCase()
}
function convertMemo(memo: Object): Object {
function convertMemo(memo: Memo): {Memo: ApiMemo} {
return {
Memo: common.removeUndefined({
MemoData: convertStringToHex(memo.data),
MemoType: convertStringToHex(memo.type),
MemoFormat: convertStringToHex(memo.format)
MemoData: memo.data ? convertStringToHex(memo.data) : undefined,
MemoType: memo.type ? convertStringToHex(memo.type) : undefined,
MemoFormat: memo.format ? convertStringToHex(memo.format) : undefined
})
}
}

View File

@@ -1455,9 +1455,14 @@ describe('RippleAPI', function() {
});
it('ledger utils - renameCounterpartyToIssuerInOrder', function() {
const order = {taker_gets: {issuer: '1'}};
const expected = {taker_gets: {issuer: '1'}};
const order = {
taker_gets: {counterparty: '1'},
taker_pays: {counterparty: '1'}
};
const expected = {
taker_gets: {issuer: '1'},
taker_pays: {issuer: '1'}
};
assert.deepEqual(utils.renameCounterpartyToIssuerInOrder(order), expected);
});

View File

@@ -1 +1 @@
--reporter spec --timeout 5000 --slow 500 --compilers js:babel-register
--reporter spec --timeout 5000 --slow 500 --require ts-node/register

26
tsconfig.json Normal file
View File

@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es6",
"lib": [
"es2017"
],
"outDir": "dist/npm",
"rootDir": "src",
"module": "commonjs",
"moduleResolution": "node",
"strictNullChecks": false,
"noImplicitAny": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": false,
"preserveConstEnums": false,
"suppressImplicitAnyIndexErrors": false,
"declaration": false,
"sourceMap": true,
"skipLibCheck": true
},
"include": [
"custom_typings/**/*.ts",
"src/**/*.ts"
]
}

1923
yarn.lock

File diff suppressed because it is too large Load Diff