Compare commits

...

71 Commits

Author SHA1 Message Date
Elliot Lee
823d93b86c Add checksums for 0.22.0 2018-05-10 15:26:43 -07:00
Elliot Lee
7a42db99c9 Bump version to 0.22.0 2018-05-10 00:33:20 -07:00
Elliot Lee
f28ec27614 getOrderbook - return raw order data (#886)
Fix #799
2018-05-08 15:05:41 -07:00
Elliot Lee
a36e23ebfa Release 0.21.0 2018-04-11 21:33:44 -07:00
Elliot Lee
e978ef1888 Add getAccountObjects (#881)
Squashed commit of the following:

commit 361ead8cbbbe4fa25ecba614f8f11930ff679996
commit 5ff26d7d2defbbaaa7c50d6b3b5b74bf30be19ef
commit 97f5dfc86d4730082fd016197b0c025e499912e3
commit d48654098601f2a19484d9bbae7c65786e3c5dd4
commit 4790401123e7836f6bea8d03111bce60dcf95114
commit 57512f7fc000689bb8224f33173ba91221f27281
commit e75a7e95b11368b26c40e8e6e7b583d978475e95
2018-04-11 14:37:37 -07:00
Chris Yuen
9af3968508 Upgrade https-proxy-agent to version 2 (#883) 2018-04-10 12:59:24 -07:00
Elliot Lee
86ce7b707c Release 0.20.0 2018-04-09 12:03:05 -07:00
Elliot Lee
e0eb27ed8e Use jsonschema v1.2.2 and run yarn upgrade (#882)
- Fixes #880
2018-04-09 11:54:30 -07:00
amougel
2570e2a6d8 Add signWithKeypair (#769) 2018-04-03 15:33:24 -07:00
Rome Reginelli
c71540e77a Merge pull request #877 from mDuo13/add-tx-types
Improve Payment Channel documentation
2018-03-30 18:57:17 -07:00
mDuo13
8eba827d11 Improve Payment Channel documentation 2018-03-28 11:54:05 -07:00
Elliot Lee
90be539b09 Release 0.19.1 2018-03-22 14:12:22 -07:00
Fred K. Schott
43c08e5ea7 Clean up min/max adjustments (#873) 2018-03-22 12:31:44 -07:00
Fred K. Schott
3f22b12216 Add linting to travis (#872) 2018-03-20 14:30:37 -07:00
darkmemo
a72041a321 Fix Payment source & destination types (#870)
Payment `source` and `destination` are defined as intersection types, `Adjustment & MaxAdjustment` and  `Adjustment & MinAdjustment` respectively. But they should be union types instead. This problem was introduced during js to ts conversion.

Fixes #866
2018-03-20 11:26:41 -07:00
Elliot Lee
71a0c16fec Ledger object - accountState supersedes accounts (#868)
This appears to originate from a mistake in the docs.
The actual name of the field is `accountState`.

See:
9af994ceb4/src/ripple/app/ledger/impl/LedgerToJson.cpp (L167)

* Remove TODOs addressed by docs PR

https://github.com/ripple/ripple-dev-portal/pull/324
2018-03-19 14:52:18 -07:00
Elliot Lee
27ab98160a Fix link to checkCash (#871)
Fix source file for 4eaaa8188d
2018-03-19 14:41:18 -07:00
Ryan Young
4eaaa8188d Fix link to checkCash (#871)
#checkCash -- > #check-cash
2018-03-19 14:39:54 -07:00
Fred K. Schott
187154a2b0 Types cleanup + more API methods onto new request method (#857)
* major types cleanup, more formatted api methods onto new request method

- getPaymentChannel() now uses this.request()
- getSettings() now uses this.request()
- getLedger() now uses this.request()
- transaction types cleaned up a bit, but still some work left to do
2018-03-14 16:08:57 -07:00
Elliot Lee
c175e3f58e Point to types in package.json (#863) 2018-03-06 23:15:55 -08:00
Fred K. Schott
2ea22a099e Don't generate TS definitions for browser build (#864) 2018-03-06 23:15:11 -08:00
Elliot Lee
c3aa062edd Bump version to 0.19.0 and add release notes 2018-03-02 13:58:39 -08:00
Elliot Lee
0ad8c577c0 Export Check* transaction param types 2018-03-01 21:46:20 -08:00
Elliot Lee
facc513a52 Add support for Checks (#853)
- See https://github.com/ripple/rippled/pull/2245

* Add support for depositAuth flag

* Upgrade ripple-binary-codec to 0.1.13
2018-03-01 21:42:46 -08:00
Elliot Lee
df711ecb06 Import from 'server' to fix TS4029 2018-03-01 21:23:02 -08:00
Elliot Lee
144be08af0 Export types used by exported variables (#858)
Fixes TypeScript compile errors due to generating TS declaration files.

See #851
2018-03-01 17:48:28 -08:00
Fred K. Schott
c53db4844a Add .travis.yml (#859) 2018-03-01 17:32:31 -08:00
Elliot Lee
68b34f7532 Improve documentation of getTransactions params (#856)
* Improve documentation of getTransactions params

- Resolve #855
2018-02-26 17:39:06 -08:00
cryptcoin-junkey
3fe5d715a5 Generate/publish *.ts.d (#851)
For TypeScript
2018-02-24 23:52:45 -08:00
Elliot Lee
ca74cf1028 Apply automatic formatting 2018-02-23 16:50:40 -08:00
Elliot Lee
5b51ff6071 Support for the Deposit Authorization account root flag (#852)
* Add depositAuth flag tests
* Add support for depositAuth flag
2018-02-21 17:15:23 -08:00
Elliot Lee
3cad4f4aa3 Apply code formatting to API unit tests 2018-02-21 16:05:57 -08:00
Fred K. Schott
365de6d18a Add new request interface, implement first few request typings (#843)
* Add request interface & typings

- src/api: add basic implementation of request/requestAll()
- src/ledgers/account_info: refactor to simplify with request()
- src/ledgers/balances: refactor to simplify with request()
- src/ledgers/orderbook: refactor to simplify with requestAll()
- src/ledgers/orders: refactor to simplify with requestAll()
- src/ledgers/trustlines: refactor to simplify with requestAll()

* standardize on Formatted prefix
2018-02-20 11:44:36 -08:00
Elliot Lee
4a21360e37 Alphabetize properties for Settings object
- Generate docs to fix earlier typo (yarn run docgen)
2018-02-14 16:22:05 -08:00
Elliot Lee
43a3cfa010 HISTORY.md - remove broken link (404) 2018-02-14 16:00:51 -08:00
Elliot Lee
b89eae5cb1 Add test of getTrustlines with multiple pages of results (#850) 2018-02-14 15:57:35 -08:00
Elliot Lee
e311b74dac Add release notes for 0.18.2 2018-02-13 13:59:02 -08:00
Elliot Lee
e3748e070b Bump version to 0.18.2 2018-02-13 13:53:42 -08:00
Elliot Lee
0c318816cc Remove unnecessary files from npm
- `"bin/*"`, `"test/*"`, and `"Gulpfile.js"` can be removed
- See #844
2018-02-13 13:36:02 -08:00
Fred K. Schott
55e6801f4a Add build to prepublish in package.json (#849)
Continue to publish the build/ directory so that users can easily grab it from CDNs.
2018-02-12 09:47:25 -08:00
Elliot Lee
4f60fc301f Add "browser" property to package.json (#847)
* Use wswrapper shim for browserify
2018-02-11 08:52:19 -08:00
Elliot Lee
139159bf1a webpack config - include src instead of excluding node_modules 2018-02-07 14:14:35 -08:00
Elliot Lee
3ebbca0083 instructions.json - fix typo 2018-02-02 10:49:32 -08:00
Elliot Lee
51aaa75a05 Use BigNumber internally to compute fee 2018-01-30 15:29:28 -08:00
Elliot Lee
01a25f55f2 Initialize ledgerVersion to undefined 2018-01-30 14:58:59 -08:00
Fred K. Schott
94196ab268 post flow-to-ts cleanup 2018-01-29 12:11:32 -08:00
Elliot Lee
dc39343899 HISTORY.md - Add 0.18.1 2018-01-27 19:38:25 -08:00
Elliot Lee
272eabd1cd v0.18.1 2018-01-27 00:46:23 -08:00
Elliot Lee
7a653e6e63 Fix: isSameIssue() should check counterparty 2018-01-26 16:06:25 -08:00
Elliot Lee
994a6d5e76 Add SHA-256 checksums for 0.18.0 release 2018-01-25 15:36:02 -08:00
Elliot Lee
3db72716b4 HISTORY.md - Add release date for 0.18.0 2018-01-25 15:30:02 -08:00
Elliot Lee
6d39e072f8 Docs: getFee() returns a string 2018-01-23 16:13:27 -08:00
Elliot Lee
b7d636d157 Rerun docgen to update docs 2018-01-23 16:11:35 -08:00
Elliot Lee
e8ac4f3d40 Set PublicKey type to string 2018-01-23 16:08:40 -08:00
Elliot Lee
ae2ccd9887 Add SHA-256 checksums 2018-01-23 15:24:18 -08:00
Elliot Lee
4fff85096c Bump version to 0.18.0 and update HISTORY.md 2018-01-17 16:03:57 -08:00
Elliot Lee
b4d8684740 Update escrow creation response fixture
- Request fixture was changed by #820
- Add an ExecuteAfter (aka FinishAfter) timestamp
2018-01-17 15:50:34 -08:00
Fred K. Schott
d3fb4b6260 Add TypeScript linting (#827)
* add tslint, create tslint.json ruleset from .eslintrc

* remove leftover rules

* fix up meta files
2018-01-17 14:41:24 -08:00
Nicolás López Jullian
19eaedf50d Change yarn install to yarn add 2018-01-16 23:18:17 -08:00
Elliot Lee
c56e6a6c08 Update yarn.lock 2018-01-16 23:16:22 -08:00
Fred K. Schott
01ecfb0a07 update istanbul to nyc (their new cli) to get typescript coverage 2018-01-11 17:20:44 -08:00
Elliot Lee
e1630e1693 HISTORY - Add SHA checksums for 0.17.9 2017-12-29 01:52:24 -08:00
Elliot Lee
526d87c1fc Update HISTORY.md 2017-12-24 00:44:14 -08:00
Fred K. Schott
8204f6c648 Convert from Flow to Typescript (#816)
* convert to typescript
* add docs for custom node typing
* update webpack, gulpfile
2017-12-24 00:39:18 -08:00
Rome Reginelli
5979ff6197 Merge pull request #820 from mDuo13/fix-escrow-example
[Docs] Improve escrow creation example to have ExecuteAfter date
2017-12-20 12:15:24 -08:00
mDuo13
d22828b222 [Docs] Improve escrow creation example to have ExecuteAfter date 2017-12-18 10:23:54 -08:00
Fred K. Schott
7e5b9948a8 convert common.js modules to new standard esm module syntax (#815) 2017-12-04 11:21:56 -08:00
Fred K. Schott
7ece43e2e2 fix whitespace (lint errors) (#813) 2017-11-27 10:54:40 -08:00
Fred K. Schott
f90617eac4 fix flow type errors (#811) 2017-11-21 16:52:48 -08:00
Fred K. Schott
2469fb2307 Update package.json 2017-11-16 14:37:46 -08:00
Fred K. Schott
a051e6fd71 fix and update flow to get typechecker running again 2017-11-16 14:37:46 -08:00
217 changed files with 9511 additions and 4199 deletions

View File

@@ -1,4 +0,0 @@
{
"presets": ["es2015", "stage-1"],
"plugins": ["syntax-flow", "transform-flow-strip-types"]
}

View File

@@ -1,19 +0,0 @@
[ignore]
.*/ripple-lib/src/.*
.*/ripple-lib/dist/.*
.*/ripple-lib/test/fixtures/.*
.*/node_modules/flow-bin/.*
.*/node_modules/webpack/.*
.*/node_modules/babel-core/.*
.*/node_modules/babel-eslint/.*
.*/node_modules/babel-preset-es2015/.*
.*/node_modules/babel-preset-stage-1/.*
.*/node_modules/babel-register/.*
[include]
./node_modules/
[libs]
[options]
module.system=node

8
.gitignore vendored
View File

@@ -51,13 +51,13 @@ test/config.js
# Ignore npm-debug
npm-debug.log
# Ignore dist folder, build for bower
# Ignore dist folder, built from tsc
dist/
# Ignore flow output directory
out/
# Ignore perf test cache
scripts/cache
.eslintrc
# nyc (istanbul)
.nyc_output

10
.nycrc Normal file
View File

@@ -0,0 +1,10 @@
{
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.d.ts"],
"extension": [".ts"],
"require": ["ts-node/register"],
"reporter": ["text-summary", "html"],
"sourceMap": true,
"instrument": true,
"cache": true
}

10
.travis.yml Normal file
View File

@@ -0,0 +1,10 @@
language: node_js
node_js:
- 6
- 8
- 9
script:
- yarn compile
- yarn test
- yarn build
- yarn lint

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,25 @@ 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: [{
loader: 'ts-loader',
options: {
compilerOptions: {declaration: false}
},
}],
}, {
test: /\.json/,
loader: 'json-loader'
use: 'json-loader',
}]
}
},
resolve: {
extensions: [ '.ts', '.js' ]
},
};
return _.assign({}, defaults, overrides);
}
@@ -78,7 +86,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 +120,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 +152,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 +160,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() {

View File

@@ -1,5 +1,124 @@
# ripple-lib Release History
## 0.22.0 (2018-05-10)
+ [`getOrderbook` - return raw order data](https://github.com/ripple/ripple-lib/pull/886). The full `BookOffer` data is now provided under `data`.
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
33f71b55c4adec4452826e44fe7809377364df04222b60f0fce01e7de2daff33 ripple-0.22.0-debug.js
63232888a4ea77065e8e8eb8fdaa8ebfe3a785428fe935e2667c1ea54c837f29 ripple-0.22.0-min.js
ab98026fabe296bd938297c48cb58e01dfdbe90f3c66c9617d6a3e1efd4c6b93 ripple-0.22.0.js
```
## 0.21.0 (2018-04-11)
+ [Upgrade https-proxy-agent](https://github.com/ripple/ripple-lib/pull/883)
+ [Add getAccountObjects](https://github.com/ripple/ripple-lib/pull/881)
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
3ab52209ad4a80393c8c08ef3f4aa9cfb47bc76c0ede2ee9fa7f5ca180ba4d67 ripple-0.21.0-debug.js
3b1efccded347bed5f64757098a1ea6a513bb8932d922d00af47cd24e001dc14 ripple-0.21.0-min.js
db08e5a3eab1f659b4c803543374398004d950ba720adc4b9a7658817cb5c94b ripple-0.21.0.js
```
## 0.20.0 (2018-04-09)
+ [Add support for using a keypair with sign()](https://github.com/ripple/ripple-lib/pull/769)
+ [Fix a bug caused by jsonschema v1.2.3 by pinning to v1.2.2](https://github.com/ripple/ripple-lib/pull/882)
+ [Improve Payment Channel documentation](https://github.com/ripple/ripple-lib/pull/877)
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
389811a9baa72f77e2a43d0b48045762d29a6f616ed5fd2660ba76fc12a3ecc5 ripple-0.20.0-debug.js
c1746ea0dd55318cb4e1ef3955ef14759d9d70861437c69abafc10169916f068 ripple-0.20.0-min.js
17958b0e46395d2b2a35a003693c0babdfb5382513d3cc58a62f8648ad710b0e ripple-0.20.0.js
```
## 0.19.1 (2018-03-22)
+ [Fix: Include TypeScript declarations in npm package](https://github.com/ripple/ripple-lib/pull/863)
+ [Fix: Documentation link to checkCash](https://github.com/ripple/ripple-lib/pull/871)
+ [Internal: Clean up types and migrate more APIs to new request method](https://github.com/ripple/ripple-lib/pull/857)
+ [Internal: Fix Payment source and destination types](https://github.com/ripple/ripple-lib/pull/870)
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
3ed5332aa035c07bae6c1abfdfc8ca77cdbb05cc4b88878f544f1ea4cb793f4d ripple-0.19.1-debug.js
2f5507aa00a40ab6a94de1822af87db5e927edef3885aef5d9b39ccb623ccb54 ripple-0.19.1-min.js
1e439aee1b220242d56ea687a9b55a67b8614212c1ddbd70a4fcf34503fc487a ripple-0.19.1.js
```
## 0.19.0 (2018-03-02)
+ [Add support for Checks](https://github.com/ripple/ripple-lib/pull/853)
+ [Add support for the Deposit Authorization account root flag](https://github.com/ripple/ripple-lib/pull/852)
+ [Generate .ts.d TypeScript declaration files](https://github.com/ripple/ripple-lib/pull/851)
+ [Improve documentation of getTransactions params](https://github.com/ripple/ripple-lib/pull/856)
+ [Add new request interface](https://github.com/ripple/ripple-lib/pull/843) (private for now)
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
0e7ce4594b7e455fbc57ad81f6fddc391d1e1f349a49c96ad783be50f80fdc14 ripple-0.19.0-debug.js
6d716a0357929e51e476f22136880f7a0e5458fd396ac145ce9308f278ff7cc1 ripple-0.19.0-min.js
6715db1af638f99226ab7f8f244103306aa6e04d1b8c1da47a63431053bacb84 ripple-0.19.0.js
```
## 0.18.2 (2018-02-13)
+ [Fix: Publish updated browser builds to npm so that users can easily use
CDNs](https://github.com/ripple/ripple-lib/pull/849)
+ [Fix: Browserify fails due to dependency on `ws`](https://github.com/ripple/ripple-lib/pull/847)
+ [Fix: `build` script fails when `node_modules` is in path](https://github.com/ripple/ripple-lib/pull/846)
+ [Reduce size of published npm package](https://github.com/ripple/ripple-lib/commit/0c318816ccf25c4c3932934a35ef903cc552edc1)
+ Clean up files from Flow (we migrated to TypeScript)
+ Typos and code cleanup
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
f08ab61137255be3639e9d210ded2a182b6e0388f257a70d9b372ce7e7e518a6 ripple-0.18.2-debug.js
0604835b8421391167b4314ce93a76b5994780a08bd7edf36d91eb5e8f2643a2 ripple-0.18.2-min.js
fda56ab5c8256e04355e20064877ef4053f26c87f37cfcf861340f22bf89ee40 ripple-0.18.2.js
```
## 0.18.1 (2018-01-27)
Note: The package published to npm for this version did not include updated
browser builds. If you are using a CDN that pulls from npm, please use 0.18.2 or
later.
+ [Fix: isSameIssue() should check counterparty](https://github.com/ripple/ripple-lib/pull/836). This bug caused `getOrderbook()` to return incorrect values.
The SHA-256 checksums for the browser version of this release can be found below.
```
% shasum -a 256 *
6871855a2af1dc591ef557d442c11e8c60e01c5932054e13e8cbb84a182f45e0 ripple-0.18.1-debug.js
331f0baff46af44933a8fa31f128132945ff82a147acfff0a7315adb446e3de0 ripple-0.18.1-min.js
26324bb0725d2d484fe3b6086335d49734f45dc647b07c60746e0d8619f1ed3e ripple-0.18.1.js
```
## 0.18.0 (2018-01-25)
+ [Convert from Flow to TypeScript](https://github.com/ripple/ripple-lib/pull/816)
+ [Use ES Module syntax](https://github.com/ripple/ripple-lib/pull/815) (Babel still compiles these to common.js modules for
distribution)
+ Docs: [Improve escrow creation example/test](https://github.com/ripple/ripple-lib/pull/820)
+ [Fix type errors](https://github.com/ripple/ripple-lib/pull/811)
+ [Fix lint errors](https://github.com/ripple/ripple-lib/pull/813)
## 0.17.9 (2017-11-14)
+ [Update ws dependency to 3.3.1](https://github.com/ripple/ripple-lib/pull/804)
@@ -7,6 +126,22 @@
+ Fix lint errors ([#786](https://github.com/ripple/ripple-lib/pull/786), [#808](https://github.com/ripple/ripple-lib/pull/808))
+ [Update ripple-keypairs dependency to 0.10.1](https://github.com/ripple/ripple-lib/pull/805)
The SHA-256 checksums for the browser version of this release can be found below.
```
% shasum -a 256 *
b52f251eedac2509d72093eab1e8dba0d0f4a9fe6a28ec1cc90853cfb0fd7110 ripple-0.17.9-debug.js
d577a2bbdbdf7535c5365a1c52a2a31989d1b966e30abcba65c87133a536b9dc ripple-0.17.9-min.js
ff4c3002842fac72ec2ebbd081e9594b0de6050d4d051a8fd6c06adb9a351488 ripple-0.17.9.js
```
The SHA-1 checksums for the browser version of this release can be found below.
```
% shasum *
e1995afc34aef6accd269cfccc55a45619618a41 ripple-0.17.9-debug.js
e6ad9a9c111ab696f5637bfa372d80999e5ae362 ripple-0.17.9-min.js
4866494ec5f9095cc34bea142f1e2b8ac5f7fbf8 ripple-0.17.9.js
```
## 0.17.8 (2017-11-06)
+ Fix: Freezing in Safari 10.1 (updated bignumber.js) (closes #762)
@@ -100,7 +235,6 @@ __OTHER CHANGES__
__BREAKING CHANGES__
+ Add new RippleAPI interface and delete old API
- [RippleAPI README and samples](https://github.com/ripple/ripple-lib/tree/develop/docs/samples)
- [Method documentation](https://rawgit.com/ripple/ripple-lib/develop/docs/api.html)
__OTHER CHANGES__
+ [Removed timeout method of Request and added default timeout](https://github.com/ripple/ripple-lib/commit/634fe5683a9082e57682ff7d5c4fb9483b4af818)

View File

@@ -23,7 +23,7 @@ You can use `npm`, but we recommend using `yarn` for the added assurance provide
Install `ripple-lib`:
```
$ yarn install ripple-lib
$ yarn add ripple-lib
```
Then see the [documentation](https://github.com/ripple/ripple-lib/blob/develop/docs/index.md) and [code samples](https://github.com/ripple/ripple-lib/tree/develop/docs/samples)

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;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
## getAccountObjects
`getAccountObjects(address: string, options: object): Promise<AccountObjectsResponse>`
Returns objects owned by an account. For an account's trust lines and balances, see `getTrustlines` and `getBalances`.
### Parameters
<%- renderSchema('input/get-account-objects.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<%- renderSchema('output/get-account-objects.json') %>
The types of objects that may be returned include:
* Offer objects for orders that are currently live, unfunded, or expired but not yet removed.
* RippleState objects for trust lines where this account's side is not in the default state.
* A SignerList object if the account has multi-signing enabled.
* Escrow objects for held payments that have not yet been executed or canceled.
* PayChannel objects for open payment channels.
* Check objects for pending checks.
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
return api.getAccountObjects(address: address).then(objects =>
{/* ... */});
```
<%- renderFixture('responses/get-account-objects.json') %>

View File

@@ -1,6 +1,6 @@
## getFee
`getFee(): Promise<number>`
`getFee(): Promise<string>`
Returns the estimated transaction fee for the rippled server the RippleAPI instance is connected to.

View File

@@ -14,6 +14,12 @@ This method returns a promise that resolves with an object with the following st
<%- renderSchema('output/get-orderbook.json') %>
### New in ripple-lib 0.22.0 and higher
The response includes a `data` property containing the raw order data. This may include `owner_funds`, `Flags`, and other fields.
For details, see the rippled method [book_offers](https://ripple.com/build/rippled-apis/#book-offers).
### Example
```javascript

View File

@@ -21,6 +21,7 @@
<% include getOrderbook.md.ejs %>
<% include getSettings.md.ejs %>
<% include getAccountInfo.md.ejs %>
<% include getAccountObjects.md.ejs %>
<% include getPaymentChannel.md.ejs %>
<% include getLedger.md.ejs %>
<% include preparePayment.md.ejs %>
@@ -34,6 +35,9 @@
<% include preparePaymentChannelCreate.md.ejs %>
<% include preparePaymentChannelClaim.md.ejs %>
<% include preparePaymentChannelFund.md.ejs %>
<% include prepareCheckCreate.md.ejs %>
<% include prepareCheckCancel.md.ejs %>
<% include prepareCheckCash.md.ejs %>
<% include sign.md.ejs %>
<% include combine.md.ejs %>
<% include submit.md.ejs %>

View File

@@ -0,0 +1,30 @@
## prepareCheckCancel
`prepareCheckCancel(address: string, checkCancel: Object, instructions: Object): Promise<Object>`
Prepare a Check cancellation transaction. This cancels an unredeemed Check, removing it from the ledger without sending any money. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-check-cancel.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const checkCancel = <%- importFile('test/fixtures/requests/prepare-check-cancel.json') %>;
return api.prepareCheckCancel(address, checkCancel).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-check-cancel.json') %>

View File

@@ -0,0 +1,30 @@
## prepareCheckCash
`prepareCheckCash(address: string, checkCash: Object, instructions: Object): Promise<Object>`
Prepare a Check cashing transaction. This redeems a Check to receive up to the amount authorized by the corresponding CheckCreate transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-check-cash.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const checkCash = <%- importFile('test/fixtures/requests/prepare-check-cash-amount.json') %>;
return api.prepareCheckCash(address, checkCash).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-check-cash-amount.json') %>

View File

@@ -0,0 +1,30 @@
## prepareCheckCreate
`prepareCheckCreate(address: string, checkCreate: Object, instructions: Object): Promise<Object>`
Prepare a Check creation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
### Parameters
<%- renderSchema('input/prepare-check-create.json') %>
### Return Value
This method returns a promise that resolves with an object with the following structure:
<aside class="notice">
All "prepare*" methods have the same return type.
</aside>
<%- renderSchema('output/prepare.json') %>
### Example
```javascript
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
const checkCreate = <%- importFile('test/fixtures/requests/prepare-check-create.json') %>;
return api.prepareCheckCreate(address, checkCreate).then(prepared =>
{/* ... */});
```
<%- renderFixture('responses/prepare-check-create.json') %>

View File

@@ -1,6 +1,9 @@
## sign
`sign(txJSON: string, secret: string, options: Object): {signedTransaction: string, id: string}`
```
sign(txJSON: string, secret: string, options: Object): {signedTransaction: string, id: string}
sign(txJSON: string, keypair: Object, options: Object): {signedTransaction: string, id: string}
```
Sign a prepared transaction. The signed transaction must subsequently be [submitted](#submit).
@@ -19,7 +22,8 @@ This method returns an object with the following structure:
```javascript
const txJSON = '{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"726970706C652E636F6D","LastLedgerSequence":8820051,"Fee":"12","Sequence":23}';
const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV';
return api.sign(txJSON, secret);
const keypair = { privateKey: '00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A', publicKey: '02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8' };
return api.sign(txJSON, secret); // or: api.sign(txJSON, keypair);
```
<%- renderFixture("responses/sign.json") %>

View File

@@ -82,6 +82,36 @@ See [Transaction Types](#transaction-types) for a description.
<%- renderFixture('requests/prepare-escrow-execution.json') %>
## Check Create
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/check-create.json') %>
### Example
<%- renderFixture('requests/prepare-check-create.json') %>
## Check Cancel
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/check-cancel.json') %>
### Example
<%- renderFixture('requests/prepare-check-cancel.json') %>
## Check Cash
See [Transaction Types](#transaction-types) for a description.
<%- renderSchema('specifications/check-cash.json') %>
### Example
<%- renderFixture('requests/prepare-check-cash-amount.json') %>
## Payment Channel Create
See [Transaction Types](#transaction-types) for a description.

View File

@@ -14,6 +14,12 @@ Type | Description
[escrowCreation](#escrow-creation) | An `escrowCreation` transaction creates an escrow on the ledger, which locks XRP until a cryptographic condition is met or it expires. It is like an escrow service where the XRP Ledger acts as the escrow agent.
[escrowCancellation](#escrow-cancellation) | An `escrowCancellation` transaction unlocks the funds in an escrow and sends them back to the creator of the escrow, but it will only work after the escrow expires.
[escrowExecution](#escrow-execution) | An `escrowExecution` transaction unlocks the funds in an escrow and sends them to the destination of the escrow, but it will only work if the cryptographic condition is provided.
[checkCreate](#check-create) | A `checkCreate` transaction creates a check on the ledger, which is a deferred payment that can be cashed by its intended destination.
[checkCancel](#check-cancel) | A `checkCancel` transaction cancels an unreedemed Check, removing it from the ledger without sending any money.
[checkCash](#check-cash) | A `checkCash` transaction redeems a Check to receive up to the amount authorized by the corresponding `checkCreate` transaction. Only the `destination` address of a Check can cash it.
[paymentChannelCreate](#payment-channel-create) | A `paymentChannelCreate` transaction opens a payment channel between two addresses with XRP set aside for asynchronous payments.
[paymentChannelFund](#payment-channel-fund) | A `paymentChannelFund` transaction adds XRP to a payment channel and optionally sets a new expiration for the channel.
[paymentChannelClaim](#payment-channel-claim) | A `paymentChannelClaim` transaction withdraws XRP from a channel and optionally requests to close it.
## Transaction Flow
@@ -28,6 +34,9 @@ Executing a transaction with `RippleAPI` requires the following four steps:
* [prepareEscrowCreation](#prepareescrowcreation)
* [prepareEscrowCancellation](#prepareescrowcancellation)
* [prepareEscrowExecution](#prepareescrowexecution)
* [prepareCheckCreate](#preparecheckcreate)
* [prepareCheckCancel](#preparecheckcancel)
* [prepareCheckCash](#preparecheckcash)
2. [Sign](#sign) - Cryptographically sign the transaction locally and save the [transaction ID](#transaction-id). Signing is how the owner of an account authorizes a transaction to take place. For multisignature transactions, the `signedTransaction` fields returned by `sign` must be collected and passed to the [combine](#combine) method.
3. [Submit](#submit) - Submit the transaction to the connected server.
4. Verify - Verify that the transaction got validated by querying with [getTransaction](#gettransaction). This is necessary because transactions may fail even if they were successfully submitted.

View File

@@ -1,53 +1,45 @@
{
"name": "ripple-lib",
"version": "0.17.9",
"version": "0.22.0",
"license": "ISC",
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
"files": [
"dist/npm/*",
"bin/*",
"build/*",
"test/*",
"Gulpfile.js"
"build/*"
],
"main": "dist/npm/",
"types": "dist/npm/index.d.ts",
"browser": {
"ws": "./dist/npm/common/wswrapper.js"
},
"directories": {
"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",
"https-proxy-agent": "2.2.1",
"jsonschema": "1.2.2",
"lodash": "^4.17.4",
"ripple-address-codec": "^2.0.1",
"ripple-binary-codec": "^0.1.10",
"ripple-binary-codec": "^0.1.13",
"ripple-hashes": "^0.3.1",
"ripple-keypairs": "^0.10.1",
"ripple-lib-transactionparser": "^0.6.2",
"ws": "^3.3.1"
},
"devDependencies": {
"@types/node": "^8.0.53",
"assert-diff": "^1.0.1",
"babel-cli": "^6.4.0",
"babel-core": "^6.4.0",
"babel-eslint": "^6.0.4",
"babel-loader": "^6.2.1",
"babel-plugin-syntax-flow": "^6.3.13",
"babel-plugin-transform-flow-strip-types": "^6.4.0",
"babel-preset-es2015": "^6.3.13",
"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",
"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",
"json-loader": "^0.5.2",
"json-schema-to-markdown-table": "^0.4.0",
@@ -55,25 +47,31 @@
"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"
"nyc": "^11.3.0",
"source-map-support": "^0.5.0",
"ts-loader": "^3.2.0",
"ts-node": "^3.3.0",
"tslint": "^5.8.0",
"tslint-eslint-rules": "^4.1.1",
"typescript": "^2.6.1",
"uglifyjs-webpack-plugin": "^1.1.4",
"webpack": "^3.10.0",
"yargs": "^8.0.2"
},
"scripts": {
"build": "gulp",
"doctoc": "doctoc docs/index.md --title '# RippleAPI Reference' --github --maxlevel 2",
"docgen": "node --harmony scripts/build_docs.js",
"clean": "rm -rf dist/npm && rm -rf build/flow",
"typecheck": "babel --optional runtime --blacklist flow -d build/flow/ src/ && flow check",
"compile": "babel -D --optional runtime -d dist/npm/ src/",
"watch": "babel -w -D --optional runtime -d dist/npm/ src/",
"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",
"clean": "rm -rf dist/npm",
"compile": "mkdir -p dist/npm/common && cp -r src/common/schemas dist/npm/common/ && tsc",
"watch": "tsc -w",
"prepublish": "npm run clean && npm run compile && npm run build",
"test": "nyc 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/",
"lint": "tslint -p ./",
"perf": "./scripts/perf_test.sh",
"start": "babel-node scripts/http.js",
"sauce": "babel-node scripts/sauce-runner.js"
"start": "node scripts/http.js",
"sauce": "node scripts/sauce-runner.js"
},
"repository": {
"type": "git",
@@ -81,6 +79,6 @@
},
"readmeFilename": "README.md",
"engines": {
"node": ">=0.12.0"
"node": ">=6.12.3"
}
}

View File

@@ -7,19 +7,9 @@ function checkEOL {
./scripts/checkeol.sh
}
typecheck() {
yarn install -g flow-bin
flow --version
yarn run typecheck
}
lint() {
echo "eslint $(node_modules/.bin/eslint --version)"
yarn list babel-eslint
REPO_URL="https://raw.githubusercontent.com/ripple/javascript-style-guide"
curl "$REPO_URL/es6/eslintrc" > .eslintrc
echo "parser: babel-eslint" >> .eslintrc
node_modules/.bin/eslint -c .eslintrc $(git --no-pager diff --name-only -M100% --diff-filter=AM --relative $(git merge-base FETCH_HEAD origin/HEAD) FETCH_HEAD | grep "\.js$")
echo "tslint $(node_modules/.bin/tslint --version)"
yarn lint
}
unittest() {

View File

@@ -1,6 +1,6 @@
'use strict';
const createHTTPServer = require('../src/http').createHTTPServer;
const createHTTPServer = require('../dist/npm/http').createHTTPServer;
const port = 5990;
const serverUrl = 'wss://s1.ripple.com';

View File

@@ -1,159 +0,0 @@
/* @flow */
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const EventEmitter = require('events').EventEmitter
const common = require('./common')
const server = require('./server/server')
const connect = server.connect
const disconnect = server.disconnect
const getServerInfo = server.getServerInfo
const getFee = server.getFee
const isConnected = server.isConnected
const getLedgerVersion = server.getLedgerVersion
const getTransaction = require('./ledger/transaction')
const getTransactions = require('./ledger/transactions')
const getTrustlines = require('./ledger/trustlines')
const getBalances = require('./ledger/balances')
const getBalanceSheet = require('./ledger/balance-sheet')
const getPaths = require('./ledger/pathfind')
const getOrders = require('./ledger/orders')
const getOrderbook = require('./ledger/orderbook')
const getSettings = require('./ledger/settings')
const getAccountInfo = require('./ledger/accountinfo')
const getPaymentChannel = require('./ledger/payment-channel')
const preparePayment = require('./transaction/payment')
const prepareTrustline = require('./transaction/trustline')
const prepareOrder = require('./transaction/order')
const prepareOrderCancellation = require('./transaction/ordercancellation')
const prepareEscrowCreation =
require('./transaction/escrow-creation')
const prepareEscrowExecution =
require('./transaction/escrow-execution')
const prepareEscrowCancellation =
require('./transaction/escrow-cancellation')
const preparePaymentChannelCreate =
require('./transaction/payment-channel-create')
const preparePaymentChannelFund =
require('./transaction/payment-channel-fund')
const preparePaymentChannelClaim =
require('./transaction/payment-channel-claim')
const prepareSettings = require('./transaction/settings')
const sign = require('./transaction/sign')
const combine = require('./transaction/combine')
const submit = require('./transaction/submit')
const errors = require('./common').errors
const generateAddress =
require('./offline/generate-address').generateAddressAPI
const computeLedgerHash = require('./offline/ledgerhash')
const signPaymentChannelClaim =
require('./offline/sign-payment-channel-claim')
const verifyPaymentChannelClaim =
require('./offline/verify-payment-channel-claim')
const getLedger = require('./ledger/ledger')
type APIOptions = {
server?: string,
feeCushion?: number,
trace?: boolean,
proxy?: string,
timeout?: number
}
// prevent access to non-validated ledger versions
class RestrictedConnection extends common.Connection {
request(request, timeout) {
const ledger_index = request.ledger_index
if (ledger_index !== undefined && ledger_index !== 'validated') {
if (!_.isNumber(ledger_index) || ledger_index > this._ledgerVersion) {
return Promise.reject(new errors.LedgerVersionError(
`ledgerVersion ${ledger_index} is greater than server\'s ` +
`most recent validated ledger: ${this._ledgerVersion}`))
}
}
return super.request(request, timeout)
}
}
class RippleAPI extends EventEmitter {
constructor(options: APIOptions = {}) {
common.validate.apiOptions(options)
super()
this._feeCushion = options.feeCushion || 1.2
const serverURL = options.server
if (serverURL !== undefined) {
this.connection = new RestrictedConnection(serverURL, options)
this.connection.on('ledgerClosed', message => {
this.emit('ledger', server.formatLedgerClose(message))
})
this.connection.on('error', (errorCode, errorMessage, data) => {
this.emit('error', errorCode, errorMessage, data)
})
this.connection.on('connected', () => {
this.emit('connected')
})
this.connection.on('disconnected', code => {
this.emit('disconnected', code)
})
} else {
// use null object pattern to provide better error message if user
// tries to call a method that requires a connection
this.connection = new RestrictedConnection(null, options)
}
}
}
_.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,
computeLedgerHash,
signPaymentChannelClaim,
verifyPaymentChannelClaim,
errors
})
// these are exposed only for use by unit tests; they are not part of the API
RippleAPI._PRIVATE = {
validate: common.validate,
RangeSet: require('./common/rangeset').RangeSet,
ledgerUtils: require('./ledger/utils'),
schemaValidator: require('./common/schema-validator')
}
module.exports = {
RippleAPI
}

292
src/api.ts Normal file
View File

@@ -0,0 +1,292 @@
import * as _ from 'lodash'
import {EventEmitter} from 'events'
import {Connection, errors, validate} from './common'
import {
connect,
disconnect,
isConnected,
getServerInfo,
getFee,
getLedgerVersion,
formatLedgerClose
} from './server/server'
import getTransaction from './ledger/transaction'
import getTransactions from './ledger/transactions'
import getTrustlines from './ledger/trustlines'
import getBalances from './ledger/balances'
import getBalanceSheet from './ledger/balance-sheet'
import getPaths from './ledger/pathfind'
import getOrders from './ledger/orders'
import getOrderbook from './ledger/orderbook'
import getSettings from './ledger/settings'
import getAccountInfo from './ledger/accountinfo'
import getAccountObjects from './ledger/accountobjects'
import getPaymentChannel from './ledger/payment-channel'
import preparePayment from './transaction/payment'
import prepareTrustline from './transaction/trustline'
import prepareOrder from './transaction/order'
import prepareOrderCancellation from './transaction/ordercancellation'
import prepareEscrowCreation from './transaction/escrow-creation'
import prepareEscrowExecution from './transaction/escrow-execution'
import prepareEscrowCancellation from './transaction/escrow-cancellation'
import preparePaymentChannelCreate from './transaction/payment-channel-create'
import preparePaymentChannelFund from './transaction/payment-channel-fund'
import preparePaymentChannelClaim from './transaction/payment-channel-claim'
import prepareCheckCreate from './transaction/check-create'
import prepareCheckCancel from './transaction/check-cancel'
import prepareCheckCash from './transaction/check-cash'
import prepareSettings from './transaction/settings'
import sign from './transaction/sign'
import combine from './transaction/combine'
import submit from './transaction/submit'
import {generateAddressAPI} from './offline/generate-address'
import computeLedgerHash from './offline/ledgerhash'
import signPaymentChannelClaim from './offline/sign-payment-channel-claim'
import verifyPaymentChannelClaim from './offline/verify-payment-channel-claim'
import getLedger from './ledger/ledger'
import {
AccountObjectsRequest, AccountObjectsResponse,
AccountOffersRequest, AccountOffersResponse,
AccountInfoRequest, AccountInfoResponse,
AccountLinesRequest, AccountLinesResponse,
BookOffersRequest, BookOffersResponse,
GatewayBalancesRequest, GatewayBalancesResponse,
LedgerRequest, LedgerResponse,
LedgerEntryRequest, LedgerEntryResponse
} from './common/types/commands'
import RangeSet from './common/rangeset'
import * as ledgerUtils from './ledger/utils'
import * as schemaValidator from './common/schema-validator'
import {clamp} from './ledger/utils'
export type APIOptions = {
server?: string,
feeCushion?: number,
trace?: boolean,
proxy?: string,
timeout?: number
}
/**
* Get the response key / property name that contains the listed data for a
* command. This varies from command to command, but we need to know it to
* properly count across many requests.
*/
function getCollectKeyFromCommand(command: string): string|undefined {
switch (command) {
case 'account_offers':
case 'book_offers':
return 'offers'
case 'account_lines':
return 'lines'
default:
return undefined
}
}
// prevent access to non-validated ledger versions
export class RestrictedConnection extends Connection {
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) {
return Promise.reject(new errors.LedgerVersionError(
`ledgerVersion ${ledger_index} is greater than server\'s ` +
`most recent validated ledger: ${this._ledgerVersion}`))
}
}
return super.request(request, timeout)
}
}
class RippleAPI extends EventEmitter {
_feeCushion: number
connection: RestrictedConnection
// these are exposed only for use by unit tests; they are not part of the API.
static _PRIVATE = {
validate: validate,
RangeSet,
ledgerUtils,
schemaValidator
}
constructor(options: APIOptions = {}) {
super()
validate.apiOptions(options)
this._feeCushion = options.feeCushion || 1.2
const serverURL = options.server
if (serverURL !== undefined) {
this.connection = new RestrictedConnection(serverURL, options)
this.connection.on('ledgerClosed', message => {
this.emit('ledger', formatLedgerClose(message))
})
this.connection.on('error', (errorCode, errorMessage, data) => {
this.emit('error', errorCode, errorMessage, data)
})
this.connection.on('connected', () => {
this.emit('connected')
})
this.connection.on('disconnected', code => {
this.emit('disconnected', code)
})
} else {
// use null object pattern to provide better error message if user
// tries to call a method that requires a connection
this.connection = new RestrictedConnection(null, options)
}
}
async _request(command: 'account_info', params: AccountInfoRequest):
Promise<AccountInfoResponse>
async _request(command: 'account_lines', params: AccountLinesRequest):
Promise<AccountLinesResponse>
/**
* Returns objects owned by an account.
* For an account's trust lines and balances,
* see `getTrustlines` and `getBalances`.
*/
async _request(command: 'account_objects', params: AccountObjectsRequest):
Promise<AccountObjectsResponse>
async _request(command: 'account_offers', params: AccountOffersRequest):
Promise<AccountOffersResponse>
async _request(command: 'book_offers', params: BookOffersRequest):
Promise<BookOffersResponse>
async _request(command: 'gateway_balances', params: GatewayBalancesRequest):
Promise<GatewayBalancesResponse>
async _request(command: 'ledger', params: LedgerRequest):
Promise<LedgerResponse>
async _request(command: 'ledger_entry', params: LedgerEntryRequest):
Promise<LedgerEntryResponse>
/**
* Makes a request to the API with the given command and
* additional request body parameters.
*
* NOTE: This command is under development.
*/
async _request(command: string, params: object = {}) {
return this.connection.request({
...params,
command
})
}
/**
* Makes multiple paged requests to the API to return a given number of
* resources. _requestAll() will make multiple requests until the `limit`
* number of resources is reached (if no `limit` is provided, a single request
* will be made).
*
* If the command is unknown, an additional `collect` property is required to
* know which response key contains the array of resources.
*
* NOTE: This command is under development and should not yet be relied
* on by external consumers.
*/
async _requestAll(command: 'account_offers', params: AccountOffersRequest):
Promise<AccountOffersResponse[]>
async _requestAll(command: 'book_offers', params: BookOffersRequest):
Promise<BookOffersResponse[]>
async _requestAll(command: 'account_lines', params: AccountLinesRequest):
Promise<AccountLinesResponse[]>
async _requestAll(
command: string,
params: any = {},
options: {collect?: string} = {}): Promise<any[]> {
// The data under collection is keyed based on the command. Fail if command
// not recognized and collection key not provided.
const collectKey = options.collect || getCollectKeyFromCommand(command)
if (!collectKey) {
throw new errors.ValidationError(`no collect key for command ${command}`)
}
// If limit is not provided, fetches all data over multiple requests.
// NOTE: This may return much more than needed. Set limit when possible.
const countTo: number =
(params.limit !== undefined) ? params.limit : Infinity
let count: number = 0
let marker: string = params.marker
let lastBatchLength: number
const results = []
do {
const countRemaining = clamp(countTo - count, 10, 400)
const repeatProps = {
...params,
limit: countRemaining,
marker
}
// NOTE: We have to generalize the `this._request()` function signature
// here until we add support for unknown commands (since command is some
// unknown string).
const singleResult = await (<Function>this._request)(command, repeatProps)
const collectedData = singleResult[collectKey]
marker = singleResult.marker
results.push(singleResult)
// Make sure we handle when no data (not even an empty array) is returned.
const isExpectedFormat = Array.isArray(collectedData)
if (isExpectedFormat) {
count += collectedData.length
lastBatchLength = collectedData.length
} else {
lastBatchLength = 0
}
} while(!!marker && count < countTo && lastBatchLength !== 0)
return results
}
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
getAccountObjects = getAccountObjects
getPaymentChannel = getPaymentChannel
getLedger = getLedger
preparePayment = preparePayment
prepareTrustline = prepareTrustline
prepareOrder = prepareOrder
prepareOrderCancellation = prepareOrderCancellation
prepareEscrowCreation = prepareEscrowCreation
prepareEscrowExecution = prepareEscrowExecution
prepareEscrowCancellation = prepareEscrowCancellation
preparePaymentChannelCreate = preparePaymentChannelCreate
preparePaymentChannelFund = preparePaymentChannelFund
preparePaymentChannelClaim = preparePaymentChannelClaim
prepareCheckCreate = prepareCheckCreate
prepareCheckCash = prepareCheckCash
prepareCheckCancel = prepareCheckCancel
prepareSettings = prepareSettings
sign = sign
combine = combine
submit = submit
generateAddress = generateAddressAPI
computeLedgerHash = computeLedgerHash
signPaymentChannelClaim = signPaymentChannelClaim
verifyPaymentChannelClaim = verifyPaymentChannelClaim
errors = errors
}
export {
RippleAPI
}

View File

@@ -1,13 +1,16 @@
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const RippleAPI = require('./api').RippleAPI
import * as _ from 'lodash'
import {RippleAPI} from './api'
class RippleAPIBroadcast extends RippleAPI {
ledgerVersion: number | undefined = undefined
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 +24,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
@@ -46,25 +49,25 @@ class RippleAPIBroadcast extends RippleAPI {
}
onLedgerEvent(ledger) {
if (ledger.ledgerVersion > this.ledgerVersion) {
if (ledger.ledgerVersion > this.ledgerVersion ||
this.ledgerVersion === undefined) {
this.ledgerVersion = ledger.ledgerVersion
this.emit('ledger', ledger)
}
}
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
}
}
module.exports = {
export {
RippleAPIBroadcast
}

View File

@@ -1,21 +0,0 @@
'use strict' // eslint-disable-line strict
function setPrototypeOf(object, prototype) {
// Object.setPrototypeOf not supported on Internet Explorer 9
/* eslint-disable */
Object.setPrototypeOf ? Object.setPrototypeOf(object, prototype) :
object.__proto__ = prototype;
/* eslint-enable */
}
function getConstructorName(object) {
// hack for internet explorer
return process.browser ?
object.constructor.toString().match(/^function\s+([^(]*)/)[1] :
object.constructor.name
}
module.exports = {
getConstructorName,
setPrototypeOf
}

View File

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

View File

@@ -1,13 +1,11 @@
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const {EventEmitter} = require('events')
const WebSocket = require('ws')
const parseURL = require('url').parse
const RangeSet = require('./rangeset').RangeSet
const {RippledError, DisconnectedError, NotConnectedError,
import * as _ from 'lodash'
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,
RippledNotInitializedError} = require('./errors')
RippledNotInitializedError} from './errors'
function isStreamMessageType(type) {
return type === 'ledgerClosed' ||
@@ -15,12 +13,48 @@ function isStreamMessageType(type) {
type === 'path_find'
}
export interface ConnectionOptions {
trace?: boolean,
proxy?: string
proxyAuthorization?: string
authorization?: string
trustedCertificates?: string[]
key?: string
passphrase?: string
certificate?: string
timeout?: number
}
class Connection extends EventEmitter {
constructor(url, options = {}) {
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 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 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)) {
@@ -77,16 +100,16 @@ class Connection extends EventEmitter {
}
return [data.type, data]
} else if (data.type === undefined && data.error) {
return ['error', data.error, data.error_message, data] // e.g. slowDown
return ['error', data.error, data.error_message, data] // e.g. slowDown
}
throw new ResponseFormatError('unrecognized message type: ' + data.type)
}
_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 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 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 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 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 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 EventEmitter {
reject(new NotConnectedError(error && error.message))
}
_createWebSocket() {
const options = {}
_createWebSocket(): WebSocket {
const options: WebSocket.ClientOptions = {}
if (this._proxyURL !== undefined) {
const parsedURL = parseURL(this._url)
const parsedProxyURL = parseURL(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 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 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())
@@ -446,4 +472,4 @@ class Connection extends EventEmitter {
}
}
module.exports = Connection
export default Connection

View File

@@ -1,12 +1,13 @@
'use strict' // eslint-disable-line strict
const flagIndices = require('./txflags').txFlagIndices.AccountSet
import {txFlagIndices} from './txflags'
const accountRootFlags = {
PasswordSpent: 0x00010000, // password set fee is spent
RequireDestTag: 0x00020000, // require a DestinationTag for payments
RequireAuth: 0x00040000, // require a authorization to hold IOUs
RequireAuth: 0x00040000, // require authorization to hold IOUs
DepositAuth: 0x01000000, // require account to auth deposits
DisallowXRP: 0x00080000, // disallow sending XRP
DisableMaster: 0x00100000, // force regular key
DisableMaster: 0x00100000, // force regular key
NoFreeze: 0x00200000, // permanently disallowed freezing trustlines
GlobalFreeze: 0x00400000, // trustlines globally frozen
DefaultRipple: 0x00800000
@@ -16,6 +17,7 @@ const AccountFlags = {
passwordSpent: accountRootFlags.PasswordSpent,
requireDestinationTag: accountRootFlags.RequireDestTag,
requireAuthorization: accountRootFlags.RequireAuth,
depositAuth: accountRootFlags.DepositAuth,
disallowIncomingXRP: accountRootFlags.DisallowXRP,
disableMasterKey: accountRootFlags.DisableMaster,
noFreeze: accountRootFlags.NoFreeze,
@@ -24,25 +26,26 @@ const AccountFlags = {
}
const AccountFlagIndices = {
requireDestinationTag: flagIndices.asfRequireDest,
requireAuthorization: flagIndices.asfRequireAuth,
disallowIncomingXRP: flagIndices.asfDisallowXRP,
disableMasterKey: flagIndices.asfDisableMaster,
enableTransactionIDTracking: flagIndices.asfAccountTxnID,
noFreeze: flagIndices.asfNoFreeze,
globalFreeze: flagIndices.asfGlobalFreeze,
defaultRipple: flagIndices.asfDefaultRipple
requireDestinationTag: txFlagIndices.AccountSet.asfRequireDest,
requireAuthorization: txFlagIndices.AccountSet.asfRequireAuth,
depositAuth: txFlagIndices.AccountSet.asfDepositAuth,
disallowIncomingXRP: txFlagIndices.AccountSet.asfDisallowXRP,
disableMasterKey: txFlagIndices.AccountSet.asfDisableMaster,
enableTransactionIDTracking: txFlagIndices.AccountSet.asfAccountTxnID,
noFreeze: txFlagIndices.AccountSet.asfNoFreeze,
globalFreeze: txFlagIndices.AccountSet.asfGlobalFreeze,
defaultRipple: txFlagIndices.AccountSet.asfDefaultRipple
}
const AccountFields = {
EmailHash: {name: 'emailHash', encoding: 'hex',
length: 32, defaults: '0'},
length: 32, defaults: '0'},
MessageKey: {name: 'messageKey'},
Domain: {name: 'domain', encoding: 'hex'},
TransferRate: {name: 'transferRate', defaults: 0, shift: 9}
}
module.exports = {
export {
AccountFields,
AccountFlagIndices,
AccountFlags

View File

@@ -1,40 +1,35 @@
'use strict' // eslint-disable-line strict
const util = require('util')
const browserHacks = require('./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
}
import {inspect} from 'util'
import * as browserHacks from './browser-hacks'
class RippleError extends extendableBuiltin(Error) {
constructor(message, data) {
class RippleError extends Error {
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
}
/* console.log in node uses util.inspect on object, and util.inspect allows
us to cutomize its output:
us to customize its output:
https://nodejs.org/api/util.html#util_custom_inspect_function_on_objects */
inspect() {
return this.toString()
@@ -62,25 +57,25 @@ 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')
}
}
module.exports = {
export {
RippleError,
UnexpectedError,
ConnectionError,

View File

@@ -1,22 +0,0 @@
'use strict' // eslint-disable-line strict
const utils = require('./utils')
module.exports = {
Connection: require('./connection'),
constants: require('./constants'),
errors: require('./errors'),
validate: require('./validate'),
txFlags: require('./txflags').txFlags,
serverInfo: require('./serverinfo'),
dropsToXrp: utils.dropsToXrp,
xrpToDrops: utils.xrpToDrops,
toRippledAmount: utils.toRippledAmount,
generateAddress: utils.generateAddress,
generateAddressAPI: utils.generateAddressAPI,
removeUndefined: utils.removeUndefined,
convertKeysFromSnakeCaseToCamelCase:
utils.convertKeysFromSnakeCaseToCamelCase,
iso8601ToRippleTime: utils.iso8601ToRippleTime,
rippleTimeToISO8601: utils.rippleTimeToISO8601,
isValidSecret: utils.isValidSecret
}

23
src/common/index.ts Normal file
View File

@@ -0,0 +1,23 @@
import * as constants from './constants'
import * as errors from './errors'
import * as validate from './validate'
import * as serverInfo from './serverinfo'
export {
constants,
errors,
validate,
serverInfo
}
export {
dropsToXrp,
xrpToDrops,
toRippledAmount,
removeUndefined,
convertKeysFromSnakeCaseToCamelCase,
iso8601ToRippleTime,
rippleTimeToISO8601
} from './utils'
export {default as Connection} from './connection'
export {txFlags} from './txflags'

View File

@@ -1,13 +1,12 @@
/* @flow */
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const assert = require('assert')
const ranges = Symbol()
import * as _ from 'lodash'
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 {
@@ -19,22 +18,25 @@ function mergeIntervals(intervals: Array<[number, number]>) {
}
class RangeSet {
ranges: Array<[number, number]>
constructor() {
this.reset()
}
reset() {
this[ranges] = []
this.ranges = []
}
serialize() {
return this[ranges].map(range =>
return this.ranges.map(range =>
range[0].toString() + '-' + range[1].toString()).join(',')
}
addRange(start: number, end: number) {
assert(start <= end, 'invalid range')
this[ranges] = mergeIntervals(this[ranges].concat([[start, end]]))
this.ranges = mergeIntervals(this.ranges.concat([[start, end]]))
}
addValue(value: number) {
@@ -50,7 +52,7 @@ class RangeSet {
}
containsRange(start: number, end: number) {
return _.some(this[ranges], range => range[0] <= start && range[1] >= end)
return _.some(this.ranges, range => range[0] <= start && range[1] >= end)
}
containsValue(value: number) {
@@ -58,4 +60,4 @@ class RangeSet {
}
}
module.exports.RangeSet = RangeSet
export default RangeSet

View File

@@ -1,12 +1,9 @@
// flow is disabled for this file until support for requiring json is added:
// https://github.com/facebook/flow/issues/167
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const assert = require('assert')
const Validator = require('jsonschema').Validator
const ValidationError = require('./errors').ValidationError
const {isValidAddress} = require('ripple-address-codec')
const {isValidSecret} = require('./utils')
import * as _ from 'lodash'
import * as assert from 'assert'
const {Validator} = require('jsonschema')
import {ValidationError} from './errors'
import {isValidAddress} from 'ripple-address-codec'
import {isValidSecret} from './utils'
function loadSchemas() {
// listed explicitly for webpack (instead of scanning schemas directory)
@@ -23,6 +20,7 @@ function loadSchemas() {
require('./schemas/objects/memo.json'),
require('./schemas/objects/memos.json'),
require('./schemas/objects/public-key.json'),
require('./schemas/objects/private-key.json'),
require('./schemas/objects/uint32.json'),
require('./schemas/objects/value.json'),
require('./schemas/objects/source-adjustment.json'),
@@ -56,10 +54,14 @@ function loadSchemas() {
require('./schemas/specifications/payment-channel-create.json'),
require('./schemas/specifications/payment-channel-fund.json'),
require('./schemas/specifications/payment-channel-claim.json'),
require('./schemas/specifications/check-create.json'),
require('./schemas/specifications/check-cash.json'),
require('./schemas/specifications/check-cancel.json'),
require('./schemas/specifications/trustline.json'),
require('./schemas/output/sign.json'),
require('./schemas/output/submit.json'),
require('./schemas/output/get-account-info.json'),
require('./schemas/output/get-account-objects.json'),
require('./schemas/output/get-balances.json'),
require('./schemas/output/get-balance-sheet.json'),
require('./schemas/output/get-ledger.json'),
@@ -89,6 +91,7 @@ function loadSchemas() {
require('./schemas/input/api-options.json'),
require('./schemas/input/get-settings.json'),
require('./schemas/input/get-account-info.json'),
require('./schemas/input/get-account-objects.json'),
require('./schemas/input/get-transaction.json'),
require('./schemas/input/get-transactions.json'),
require('./schemas/input/get-trustlines.json'),
@@ -103,6 +106,9 @@ function loadSchemas() {
require('./schemas/input/prepare-payment-channel-create.json'),
require('./schemas/input/prepare-payment-channel-fund.json'),
require('./schemas/input/prepare-payment-channel-claim.json'),
require('./schemas/input/prepare-check-create.json'),
require('./schemas/input/prepare-check-cash.json'),
require('./schemas/input/prepare-check-cancel.json'),
require('./schemas/input/compute-ledger-hash.json'),
require('./schemas/input/sign.json'),
require('./schemas/input/submit.json'),
@@ -111,20 +117,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,25 +138,25 @@ 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())
}
}
module.exports = {
export {
schemaValidate,
isValidSecret
}

View File

@@ -0,0 +1,56 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "getAccountObjectsOptions",
"description": "Request options for getAccountObjects",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account to get the account objects of."
},
"options": {
"description": "Options that affect what to return.",
"properties": {
"type": {
"type": "string",
"enum": [
"check",
"escrow",
"offer",
"payment_channel",
"signer_list",
"state"
],
"description":
"(Optional) Filter results to include only this type of ledger object. The valid types are: `check`, `escrow`, `offer`, `payment_channel`, `signer_list`, and `state` (trust line)."
},
"ledgerHash": {
"type": "string",
"description":
"(Optional) A 20-byte hex string for the ledger version to use."
},
"ledgerIndex": {
"oneOf": [
{
"$ref": "ledgerVersion"
},
{
"type": "string"
}
],
"description":
"(Optional) The sequence number of the ledger to use, or a shortcut string to choose a ledger automatically."
},
"limit": {
"type": "integer",
"minimum": 1,
"description":
"(Optional) The maximum number of objects to include in the results."
}
},
"additionalProperties": false
}
},
"required": ["address"],
"additionalProperties": false
}

View File

@@ -13,7 +13,7 @@
"properties": {
"start": {
"$ref": "hash256",
"description": "If specified, this transaction will be the first transaction in the result."
"description": "If specified, this transaction will be the first transaction in the result. You cannot use `start` with `minLedgerVersion` or `maxLedgerVersion`. When `start` is specified, these ledger versions will be determined internally."
},
"limit": {
"type": "integer",

View File

@@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "prepareCheckCancelParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"checkCancel": {
"$ref": "checkCancel",
"description": "The specification of the Check cancellation to prepare."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "checkCancel"]
}

View File

@@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "prepareCheckCashParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"checkCash": {
"$ref": "checkCash",
"description": "The specification of the Check cash to prepare."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "checkCash"]
}

View File

@@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "prepareCheckCreateParameters",
"type": "object",
"properties": {
"address": {
"$ref": "address",
"description": "The address of the account that is creating the transaction."
},
"checkCreate": {
"$ref": "checkCreate",
"description": "The specification of the Check create creation to prepare."
},
"instructions": {"$ref": "instructions"}
},
"additionalProperties": false,
"required": ["address", "checkCreate"]
}

View File

@@ -10,7 +10,23 @@
"secret": {
"type": "string",
"format": "secret",
"description": "The secret of the account that is initiating the transaction."
"description": "The secret of the account that is initiating the transaction. (This field is exclusive with keypair)."
},
"keypair": {
"type": "object",
"properties": {
"privateKey": {
"type": "privateKey",
"description": "The uppercase hexadecimal representation of the secp256k1 or Ed25519 private key."
},
"publicKey": {
"type": "publicKey",
"description": "The uppercase hexadecimal representation of the secp256k1 or Ed25519 public key."
}
},
"description": "The private and public key of the account that is initiating the transaction. (This field is exclusive with secret).",
"required": ["privateKey", "publicKey"],
"additionalProperties": false
},
"options": {
"type": "object",
@@ -25,5 +41,15 @@
}
},
"additionalProperties": false,
"required": ["txJSON", "secret"]
"required": ["txJSON"],
"oneOf": [
{
"required": ["secret"],
"not": {"required": ["keypair"]}
},
{
"required": ["keypair"],
"not": {"required": ["secret"]}
}
]
}

View File

@@ -25,7 +25,7 @@
]
},
"maxLedgerVersionOffset": {
"description": "Offset from current validated legder version to highest ledger version that the transaction can be included in.",
"description": "Offset from current validated ledger version to highest ledger version that the transaction can be included in.",
"type": "integer",
"minimum": 0
},

View File

@@ -2,6 +2,14 @@
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "ledgerVersion",
"description": "A ledger version number",
"type": "integer",
"minimum": 1
"oneOf": [
{
"type": "integer",
"minimum": 1
},
{
"type": "string",
"enum": ["validated", "closed", "current"]
}
]
}

View File

@@ -0,0 +1,7 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "privateKey",
"description": "The hexadecimal representation of a secp256k1 or Ed25519 private key.",
"type": "string",
"pattern": "^[A-F0-9]+$"
}

View File

@@ -3,41 +3,25 @@
"title": "settingsPlusMemos",
"type": "object",
"properties": {
"passwordSpent": {
"defaultRipple": {
"type": "boolean",
"description": "Indicates that the account has used its free SetRegularKey transaction."
"description": "Enable [rippling](https://ripple.com/build/understanding-the-noripple-flag/) on this accounts trust lines by default. (New in [rippled 0.27.3](https://github.com/ripple/rippled/releases/tag/0.27.3))"
},
"requireDestinationTag": {
"depositAuth": {
"type": "boolean",
"description": "Requires incoming payments to specify a destination tag."
},
"requireAuthorization": {
"type": "boolean",
"description": "If set, this account must individually approve other users in order for those users to hold this accounts issuances."
},
"disallowIncomingXRP": {
"type": "boolean",
"description": "Indicates that client applications should not send XRP to this account. Not enforced by rippled."
"description": "Enable [Deposit Authorization](https://ripple.com/build/deposit-authorization/) on this account. If set, transactions cannot send value of any kind to this account unless the sender of those transactions is the account itself. (Requires the [DepositAuth amendment](https://ripple.com/build/known-amendments/#depositauth))"
},
"disableMasterKey": {
"type": "boolean",
"description": "Disallows use of the master key to sign transactions for this account."
},
"enableTransactionIDTracking": {
"disallowIncomingXRP": {
"type": "boolean",
"description": "Track the ID of this accounts most recent transaction."
"description": "Indicates that client applications should not send XRP to this account. Not enforced by rippled."
},
"noFreeze": {
"type": "boolean",
"description": "Permanently give up the ability to freeze individual trust lines. This flag can never be disabled after being enabled."
},
"globalFreeze": {
"type": "boolean",
"description": "Freeze all assets issued by this account."
},
"defaultRipple": {
"type": "boolean",
"description": "Enable [rippling](https://ripple.com/knowledge_center/understanding-the-noripple-flag/) on this accounts trust lines by default. (New in [rippled 0.27.3](https://github.com/ripple/rippled/releases/tag/0.27.3))"
"domain": {
"type": "string",
"description": " The domain that owns this account, as a hexadecimal string representing the ASCII for the domain in lowercase."
},
"emailHash": {
"description": "Hash of an email address to be used for generating an avatar image. Conventionally, clients use Gravatar to display this image. Use `null` to clear.",
@@ -46,20 +30,26 @@
{"$ref": "hash128"}
]
},
"enableTransactionIDTracking": {
"type": "boolean",
"description": "Track the ID of this accounts most recent transaction."
},
"globalFreeze": {
"type": "boolean",
"description": "Freeze all assets issued by this account."
},
"memos": {"$ref": "memos"},
"messageKey": {
"type": "string",
"description": "Public key for sending encrypted messages to this account. Conventionally, it should be a secp256k1 key, the same encryption that is used by the rest of Ripple."
},
"domain": {
"type": "string",
"description": " The domain that owns this account, as a hexadecimal string representing the ASCII for the domain in lowercase."
"noFreeze": {
"type": "boolean",
"description": "Permanently give up the ability to freeze individual trust lines. This flag can never be disabled after being enabled."
},
"transferRate": {
"description": " The fee to charge when users transfer this accounts issuances, as the decimal amount that must be sent to deliver 1 unit. Has precision up to 9 digits beyond the decimal point. Use `null` to set no fee.",
"oneOf": [
{"type": "null"},
{"type": "number", "minimum": 1, "maximum": 4.294967295}
]
"passwordSpent": {
"type": "boolean",
"description": "Indicates that the account has used its free SetRegularKey transaction."
},
"regularKey": {
"oneOf": [
@@ -68,6 +58,14 @@
],
"description": "The public key of a new keypair, to use as the regular key to this account, as a base-58-encoded string in the same format as an account address. Use `null` to remove the regular key."
},
"requireAuthorization": {
"type": "boolean",
"description": "If set, this account must individually approve other users in order for those users to hold this accounts issuances."
},
"requireDestinationTag": {
"type": "boolean",
"description": "Requires incoming payments to specify a destination tag."
},
"signers": {
"type": "object",
"description": "Settings that determine what sets of accounts can be used to sign a transaction on behalf of this account using multisigning.",
@@ -97,7 +95,13 @@
}
}
},
"memos": {"$ref": "memos"}
"transferRate": {
"description": " The fee to charge when users transfer this accounts issuances, as the decimal amount that must be sent to deliver 1 unit. Has precision up to 9 digits beyond the decimal point. Use `null` to set no fee.",
"oneOf": [
{"type": "null"},
{"type": "number", "minimum": 1, "maximum": 4.294967295}
]
}
},
"additionalProperties": false
}

View File

@@ -4,8 +4,20 @@
"link": "transaction-types",
"description": "The type of the transaction.",
"type": "string",
"enum": ["payment", "order", "orderCancellation", "trustline", "settings",
"escrowCreation", "escrowCancellation",
"escrowExecution", "paymentChannelCreate",
"paymentChannelFund", "paymentChannelClaim"]
"enum": [
"payment",
"order",
"orderCancellation",
"trustline",
"settings",
"escrowCreation",
"escrowCancellation",
"escrowExecution",
"paymentChannelCreate",
"paymentChannelFund",
"paymentChannelClaim",
"checkCreate",
"checkCancel",
"checkCash"
]
}

View File

@@ -0,0 +1,48 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "AccountObjectsResponse",
"description": "Response format for account_objects",
"type": "object",
"properties": {
"account": {
"$ref": "address",
"description":
"Unique address of the account this request corresponds to."
},
"account_objects": {
"type": "array",
"items": {
"type": "object"
},
"description":
"Array of objects owned by this account. Each object is in its raw ledger format."
},
"ledger_hash": {
"type": "string",
"description":
"(May be omitted) The identifying hash of the ledger that was used to generate this response."
},
"ledger_index": {
"$ref": "ledgerVersion",
"description":
"(May be omitted) The sequence number of the ledger that was used to generate this response."
},
"ledger_current_index": {
"$ref": "ledgerVersion",
"description":
"(May be omitted) The sequence number of the ledger that was used to generate this response."
},
"limit": {
"type": "integer",
"description":
"(May be omitted) The limit that was used in this request, if any."
},
"validated": {
"type": "boolean",
"description":
"If included and set to true, the information in this request comes from a validated ledger version. Otherwise, the information is subject to change."
}
},
"required": ["account", "account_objects"],
"additionalProperties": false
}

View File

@@ -3,7 +3,9 @@
"title": "getTransaction",
"link": "gettransaction",
"properties": {
"type": {"$ref": "transactionType"},
"type": {
"$ref": "transactionType"
},
"specification": {
"description": "A specification that would produce the same outcome as this transaction. The structure of the specification depends on the value of the `type` field (see [Transaction Types](#transaction-types) for details). *Note:* This is **not** necessarily the same as the original specification."
},
@@ -24,73 +26,182 @@
"description": "The account sequence number of the transaction for the account that initiated it."
}
},
"required": ["id", "address", "sequence", "type", "specification", "outcome"],
"required": [
"id",
"address",
"sequence",
"type",
"specification",
"outcome"
],
"additionalProperties": false,
"oneOf": [
{
"properties": {
"type": {"enum": ["payment"]},
"specification": {"$ref": "payment"}
"type": {
"enum": [
"payment"
]
},
"specification": {
"$ref": "payment"
}
}
},
{
"properties": {
"type": {"enum": ["order"]},
"specification": {"$ref": "order"}
"type": {
"enum": [
"order"
]
},
"specification": {
"$ref": "order"
}
}
},
{
"properties": {
"type": {"enum": ["orderCancellation"]},
"specification": {"$ref": "orderCancellation"}
"type": {
"enum": [
"orderCancellation"
]
},
"specification": {
"$ref": "orderCancellation"
}
}
},
{
"properties": {
"type": {"enum": ["trustline"]},
"specification": {"$ref": "trustline"}
"type": {
"enum": [
"trustline"
]
},
"specification": {
"$ref": "trustline"
}
}
},
{
"properties": {
"type": {"enum": ["settings"]},
"specification": {"$ref": "getSettings"}
"type": {
"enum": [
"settings"
]
},
"specification": {
"$ref": "getSettings"
}
}
},
{
"properties": {
"type": {"enum": ["escrowCreation"]},
"specification": {"$ref": "escrowCreation"}
"type": {
"enum": [
"checkCreate"
]
},
"specification": {
"$ref": "checkCreate"
}
}
},
{
"properties": {
"type": {"enum": ["escrowCancellation"]},
"specification": {"$ref": "escrowCancellation"}
"type": {
"enum": [
"checkCancel"
]
},
"specification": {
"$ref": "checkCancel"
}
}
},
{
"properties": {
"type": {"enum": ["escrowExecution"]},
"specification": {"$ref": "escrowExecution"}
"type": {
"enum": [
"checkCash"
]
},
"specification": {
"$ref": "checkCash"
}
}
},
{
"properties": {
"type": {"enum": ["paymentChannelCreate"]},
"specification": {"$ref": "paymentChannelCreate"}
"type": {
"enum": [
"escrowCreation"
]
},
"specification": {
"$ref": "escrowCreation"
}
}
},
{
"properties": {
"type": {"enum": ["paymentChannelFund"]},
"specification": {"$ref": "paymentChannelFund"}
"type": {
"enum": [
"escrowCancellation"
]
},
"specification": {
"$ref": "escrowCancellation"
}
}
},
{
"properties": {
"type": {"enum": ["paymentChannelClaim"]},
"specification": {"$ref": "paymentChannelClaim"}
"type": {
"enum": [
"escrowExecution"
]
},
"specification": {
"$ref": "escrowExecution"
}
}
},
{
"properties": {
"type": {
"enum": [
"paymentChannelCreate"
]
},
"specification": {
"$ref": "paymentChannelCreate"
}
}
},
{
"properties": {
"type": {
"enum": [
"paymentChannelFund"
]
},
"specification": {
"$ref": "paymentChannelFund"
}
}
},
{
"properties": {
"type": {
"enum": [
"paymentChannelClaim"
]
},
"specification": {
"$ref": "paymentChannelClaim"
}
}
}
]

View File

@@ -2,5 +2,7 @@
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "getTransactions",
"type": "array",
"items": {"$ref": "getTransaction"}
"items": {
"$ref": "getTransaction"
}
}

View File

@@ -45,9 +45,14 @@
},
"required": ["fundedAmount", "priceOfFundedAmount"],
"additionalProperties": false
},
"data": {
"description": "The raw order data. This may include `owner_funds`, `Flags`, and other fields.",
"type": "object",
"additionalProperties": true
}
},
"required": ["specification", "properties"],
"required": ["specification", "properties", "data"],
"additionalProperties": false
}
}

View File

@@ -0,0 +1,14 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "checkCancel",
"link": "check-cancel",
"type": "object",
"properties": {
"checkID": {
"$ref": "hash256",
"description": "The ID of the Check ledger object to cancel, as a 64-character hexadecimal string."
}
},
"required": ["checkID"],
"additionalProperties": false
}

View File

@@ -0,0 +1,26 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "checkCash",
"link": "check-cash",
"type": "object",
"properties": {
"checkID": {
"$ref": "hash256",
"description": "The ID of the Check ledger object to cash, as a 64-character hexadecimal string."
},
"amount": {
"$ref": "laxAmount",
"description": "Redeem the Check for exactly this amount, if possible. The currency must match that of the sendMax of the corresponding CheckCreate transaction. You must provide either this field or deliverMin."
},
"deliverMin": {
"$ref": "laxAmount",
"description": "Redeem the Check for at least this amount and for as much as possible. The currency must match that of the sendMax of the corresponding CheckCreate transaction. You must provide either this field or amount."
}
},
"required": ["checkID"],
"oneOf": [
{"required": ["amount"]},
{"required": ["deliverMin"]}
],
"additionalProperties": false
}

View File

@@ -0,0 +1,31 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "checkCreate",
"link": "check-create",
"type": "object",
"properties": {
"destination": {
"$ref": "address",
"description": "Address of the account that can cash the check."
},
"sendMax": {
"$ref": "laxAmount",
"description": "Amount of source currency the check is allowed to debit the sender, including transfer fees on non-XRP currencies."
},
"destinationTag": {
"$ref": "tag",
"description": "Destination tag that identifies the reason for the check, or a hosted recipient to pay."
},
"expiration": {
"type": "string",
"format": "date-time",
"description": "Time after which the check is no longer valid."
},
"invoiceID": {
"$ref": "hash256",
"description": "256-bit hash, as a 64-character hexadecimal string, representing a specific reason or identifier for this check."
}
},
"required": ["destination", "sendMax"],
"additionalProperties": false
}

View File

@@ -10,19 +10,19 @@
},
"amount": {
"$ref": "value",
"description": "XRP balance of this channel after claim is processed."
"description": "Amount of XRP authorized by this signature."
},
"balance": {
"$ref": "value",
"description": "Amount of XRP authorized by signature."
"description": "Total XRP balance delivered by this channel after claim is processed."
},
"signature": {
"$ref": "signature",
"description": "Signature of this claim."
"description": "Signed claim authorizing withdrawal of XRP from the channel. (Required except from the channel's source address.)"
},
"publicKey": {
"$ref": "publicKey",
"description": "Public key of the channel's sender"
"description": "Public key of the channel. (For verifying the signature.)"
},
"renew": {
"type": "boolean",
@@ -30,7 +30,7 @@
},
"close": {
"type": "boolean",
"description": "Request to close the channel."
"description": "Request to close the channel. If the channel has no XRP remaining or the destination address requests it, closes the channel immediately (returning unclaimed XRP to the source address). Otherwise, sets the channel to expire after settleDelay seconds have passed."
}
},
"required": ["channel"],

View File

@@ -18,12 +18,12 @@
},
"publicKey": {
"$ref": "publicKey",
"description": "Public key of the key pair the source will use to sign claims against this channel."
"description": "Public key of the key pair the source may use to sign claims against this channel."
},
"cancelAfter": {
"type": "string",
"format": "date-time",
"description": "Time when this channel expires."
"description": "Time when this channel expires. This expiration cannot be changed after creating the channel."
},
"sourceTag": {
"$ref": "tag",

View File

@@ -15,7 +15,7 @@
"expiration": {
"type": "string",
"format": "date-time",
"description": "New expiration for this channel."
"description": "New expiration for this channel. (This does not change the cancelAfter expiration, if the channel has one.) Cannot move the expiration sooner than settleDelay seconds from time of the request."
}
},
"required": ["amount", "channel"],

View File

@@ -22,11 +22,11 @@
"$ref": "hash256"
},
"allowPartialPayment": {
"description": "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",
"description": "If true, this payment should proceed even if the whole amount cannot be delivered due to a lack of liquidity or a lack of funds in the source account.",
"type": "boolean"
},
"noDirectRipple": {
"description": "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",
"description": "If true and paths are specified, the sender would like the XRP Ledger 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.",
"type": "boolean"
},
"limitQuality": {

View File

@@ -1,7 +1,7 @@
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const {convertKeysFromSnakeCaseToCamelCase} = require('./utils')
import type {Connection} from './connection'
import * as _ from 'lodash'
import {convertKeysFromSnakeCaseToCamelCase} from './utils'
import Connection from './connection'
import BigNumber from 'bignumber.js'
export type GetServerInfoResponse = {
buildVersion: string,
@@ -62,18 +62,20 @@ function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
}
function computeFeeFromServerInfo(cushion: number,
serverInfo: GetServerInfoResponse
): number {
return (Number(serverInfo.validatedLedger.baseFeeXRP)
* Number(serverInfo.loadFactor) * cushion).toString()
serverInfo: GetServerInfoResponse
): string {
return (new BigNumber(serverInfo.validatedLedger.baseFeeXRP)).
times(serverInfo.loadFactor).
times(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)
})
}
module.exports = {
export {
getServerInfo,
getFee
}

View File

@@ -1,4 +1,4 @@
'use strict' // eslint-disable-line strict
const txFlags = {
// Universal flags can apply to any transaction type
@@ -55,11 +55,12 @@ const txFlagIndices = {
asfAccountTxnID: 5,
asfNoFreeze: 6,
asfGlobalFreeze: 7,
asfDefaultRipple: 8
asfDefaultRipple: 8,
asfDepositAuth: 9
}
}
module.exports = {
export {
txFlags,
txFlagIndices
}

View File

@@ -1,55 +0,0 @@
/* @flow */
'use strict' // eslint-disable-line 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

@@ -0,0 +1,23 @@
import {
AccountRootLedgerEntry,
SignerListLedgerEntry,
QueueData
} from '../objects'
export interface AccountInfoRequest {
account: string,
strict?: boolean,
queue?: boolean,
ledger_hash?: string,
ledger_index?: number | ('validated' | 'closed' | 'current'),
signer_lists?: boolean
}
export interface AccountInfoResponse {
account_data: AccountRootLedgerEntry,
signer_lists?: SignerListLedgerEntry[],
ledger_current_index?: number,
ledger_index?: number,
queue_data?: QueueData,
validated?: boolean
}

View File

@@ -0,0 +1,19 @@
import {Trustline} from '../objects'
export interface AccountLinesRequest {
account: string,
ledger_hash?: string,
ledger_index?: number | ('validated' | 'closed' | 'current'),
peer?: string,
limit?: number,
marker?: any,
}
export interface AccountLinesResponse {
account: string,
lines: Trustline[],
ledger_current_index?: number,
ledger_index?: number,
ledger_hash?: string,
marker?: any,
}

View File

@@ -0,0 +1,72 @@
import {CheckLedgerEntry} from '../objects'
export interface GetAccountObjectsOptions {
type?: string | (
'check' |
'escrow' |
'offer' |
'payment_channel' |
'signer_list' |
'state'
),
ledgerHash?: string,
ledgerIndex?: number | ('validated' | 'closed' | 'current'),
limit?: number,
marker?: string
}
export interface AccountObjectsRequest {
account: string,
// (Optional) Filter results to include only this type of ledger object.
type?: string | (
'check' |
'escrow' |
'offer' |
'payment_channel' |
'signer_list' |
'state'
),
// (Optional) A 20-byte hex string for the ledger version to use.
ledger_hash?: string,
// (Optional) The sequence number of the ledger to use,
// or a shortcut string to choose a ledger automatically.
ledger_index?: number | ('validated' | 'closed' | 'current'),
limit?: number,
marker?: string
}
export interface AccountObjectsResponse {
account: string,
// Array of objects owned by this account.
account_objects: CheckLedgerEntry | object,
// (May be omitted) The identifying hash of the ledger
// that was used to generate this response.
ledger_hash?: string,
// (May be omitted) The sequence number of the ledger version
// that was used to generate this response.
ledger_index?: number,
// (May be omitted) The sequence number of the current in-progress ledger
// version that was used to generate this response.
ledger_current_index?: number,
// The limit that was used in this request, if any.
limit?: number,
// Server-defined value indicating the response is paginated. Pass this
// to the next call to resume where this call left off. Omitted when there
// are no additional pages after this one.
marker?: string,
// If true, this information comes from a ledger version
// that has been validated by consensus.
validated?: boolean
}

View File

@@ -0,0 +1,27 @@
import {RippledAmount} from '../objects'
export interface AccountOffersRequest {
account: string,
ledger_hash?: string,
ledger_index?: number | ('validated' | 'closed' | 'current'),
limit?: number,
marker?: any,
}
export interface AccountOffersResponse {
account: string,
ledger_hash?: string,
ledger_current_index?: number,
ledger_index?: number,
marker?: any,
offers?: AccountOffer[],
}
export interface AccountOffer {
seq: number,
flags: number,
taker_gets: RippledAmount,
taker_pays: RippledAmount,
quality: string,
expiration?: number
}

View File

@@ -0,0 +1,30 @@
import {
TakerRequestAmount,
RippledAmount,
OfferCreateTransaction
} from '../objects'
export interface BookOffersRequest {
taker?: string,
taker_gets: TakerRequestAmount,
taker_pays: TakerRequestAmount,
ledger_hash?: string,
ledger_index?: number | ('validated' | 'closed' | 'current'),
limit?: number,
marker?: any
}
export interface BookOffersResponse {
offers: BookOffer[],
ledger_hash?: string,
ledger_current_index?: number,
ledger_index?: number,
marker?: any
}
export interface BookOffer extends OfferCreateTransaction {
quality?: string
owner_funds?: string,
taker_gets_funded?: RippledAmount,
taker_pays_funded?: RippledAmount
}

View File

@@ -0,0 +1,19 @@
import {Amount} from '../objects'
export interface GatewayBalancesRequest {
account: string,
strict?: boolean,
hotwallet: string|Array<string>,
ledger_hash?: string,
ledger_index?: number | ('validated' | 'closed' | 'current')
}
export interface GatewayBalancesResponse {
account: string,
obligations?: {[currency: string]: string},
balances?: {[address: string]: Amount[]},
assets?: {[address: string]: Amount[]},
ledger_hash?: string,
ledger_current_index?: number,
ledger_index?: number
}

View File

@@ -0,0 +1,8 @@
export * from './account_info'
export * from './account_lines'
export * from './account_objects'
export * from './account_offers'
export * from './book_offers'
export * from './gateway_balances'
export * from './ledger'
export * from './ledger_entry'

View File

@@ -0,0 +1,20 @@
import {Ledger, QueueData} from '../objects'
export interface LedgerRequest {
ledger_hash?: string
ledger_index?: number | ('validated' | 'closed' | 'current')
full?: boolean
accounts?: boolean
transactions?: boolean
expand?: boolean
owner_funds?: boolean
binary?: boolean
queue?: boolean
}
export interface LedgerResponse {
ledger_index: number
ledger_hash: string
ledger: Ledger
queue_data?: QueueData
}

View File

@@ -0,0 +1,31 @@
import {LedgerEntry} from '../objects'
export interface LedgerEntryRequest {
ledger_hash?: string
ledger_index?: number | ('validated' | 'closed' | 'current')
index?: string,
account_root?: string,
directory?: string | {
sub_index?: number,
dir_root: string
} | {
sub_index?: number,
owner: string
},
offer?: string | {
account: string,
seq: number
},
ripple_state?: {
accounts: [string, string],
currency: string
},
binary?: boolean
}
export interface LedgerEntryResponse {
index: string,
ledger_index: number,
node_binary?: string,
node?: LedgerEntry,
}

View File

@@ -0,0 +1,19 @@
import {Amount} from './amounts'
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
}

View File

@@ -0,0 +1,28 @@
export type Amount = {
value: string,
currency: string,
issuer?: string,
counterparty?: string
}
export type RippledAmount = string | Amount
/**
* Specification of which currency the account taking the offer would pay/
* receive, as an object with currency and issuer fields (omit issuer for XRP).
* Similar to currency amounts.
*/
export interface TakerRequestAmount {
currency: string
issuer?: string
}
/**
* A currency-counterparty pair, or just currency if it's XRP.
*/
export type Issue = {
currency: string,
issuer?: string,
counterparty?: string
}

View File

@@ -0,0 +1,11 @@
export * from './adjustments'
export * from './amounts'
export * from './ledger'
export * from './ledger_entries'
export * from './memos'
export * from './orders'
export * from './queue_data'
export * from './settings'
export * from './signers'
export * from './transactions'
export * from './trustlines'

View File

@@ -0,0 +1,22 @@
export interface Ledger {
account_hash: string,
close_time: number,
close_time_human: string,
close_time_resolution: number,
closed: boolean,
ledger_hash: string,
ledger_index: string,
parent_hash: string,
total_coins: string,
transaction_hash: string,
transactions: string[] | object[],
// @deprecated
seqNum?: string,
// @deprecated
totalCoins?: string,
// @deprecated
hash?: string,
close_flags?: number,
parent_close_time?: number,
accountState?: any[]
}

View File

@@ -0,0 +1,83 @@
import {SignerEntry} from './index'
export interface AccountRootLedgerEntry {
LedgerEntryType: 'AccountRoot',
Account: string,
Balance: string,
Flags: number,
OwnerCount: number,
PreviousTxnID: string,
PreviousTxnLgrSeq: number,
Sequence: number,
AccountTxnID?: string,
Domain?: string,
EmailHash?: string,
MessageKey?: string
RegularKey?: string,
TickSize?: number,
TransferRate?: number,
WalletLocator?: string, // DEPRECATED
WalletSize?: number // DEPRECATED
}
export interface AmendmentsLedgerEntry {
LedgerEntryType: 'Amendments',
Amendments?: string[],
Majorities?: any[],
Flags: 0
}
export interface CheckLedgerEntry {
LedgerEntryType: 'Check',
Account: string,
Destination, string,
Flags: 0,
OwnerNode: string,
PreviousTxnID: string,
PreviousTxnLgrSeq: number,
SendMax: string | object,
Sequence: number,
DestinationNode: string,
DestinationTag: number,
Expiration: number,
InvoiceID: string,
SourceTag: number
}
export interface PayChannelLedgerEntry {
LedgerEntryType: 'PayChannel',
Sequence: number,
Account: string,
Amount: string,
Balance: string,
PublicKey: string,
Destination: string,
SettleDelay: number,
Expiration?: number,
CancelAfter?: number,
SourceTag?: number,
DestinationTag?: number,
OwnerNode: string,
PreviousTxnID: string,
PreviousTxnLgrSeq: number,
index: string
}
export interface SignerListLedgerEntry {
LedgerEntryType: 'SignerList',
OwnerNode: string,
SignerQuorum: number,
SignerEntries: SignerEntry[],
SignerListID: number,
PreviousTxnID: string,
PreviousTxnLgrSeq: number
}
// TODO: Add the other ledger entry types, then remove the `any` fallback
// see https://ripple.com/build/ledger-format/#ledger-object-types
export type LedgerEntry =
AccountRootLedgerEntry |
AmendmentsLedgerEntry |
PayChannelLedgerEntry |
SignerListLedgerEntry |
any

View File

@@ -0,0 +1,6 @@
export type Memo = {
type?: string,
format?: string,
data?: string
}

View File

@@ -0,0 +1,17 @@
import {Amount} from './amounts'
import {Memo} from './memos'
export type FormattedOrderSpecification = {
direction: string,
quantity: Amount,
totalPrice: Amount,
immediateOrCancel?: boolean,
fillOrKill?: boolean,
expirationTime?: string,
orderToReplace?: number,
memos?: Memo[],
// 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
}

View File

@@ -0,0 +1,16 @@
export interface QueueTransaction {
auth_change: boolean,
fee: string,
fee_level: string,
max_spend_drops: string,
seq: number
}
export interface QueueData {
txn_count: number,
auth_change_queued?: boolean,
lowest_sequence?: number,
highest_sequence?: number,
max_spend_drops_total?: string,
transactions?: QueueTransaction[]
}

View File

@@ -0,0 +1,30 @@
import {Memo} from './memos'
export type WeightedSigner = {
address: string,
weight: number
}
export type Signers = {
threshold?: number,
weights: WeightedSigner[]
}
export type FormattedSettings = {
passwordSpent?: boolean,
requireDestinationTag?: boolean,
requireAuthorization?: boolean,
disallowIncomingXRP?: boolean,
disableMasterKey?: boolean,
enableTransactionIDTracking?: boolean,
noFreeze?: boolean,
globalFreeze?: boolean,
defaultRipple?: boolean,
emailHash?: string|null,
messageKey?: string,
domain?: string,
transferRate?: number|null,
regularKey?: string,
signers?: Signers,
memos?: Memo[]
}

View File

@@ -0,0 +1,4 @@
export interface SignerEntry {
Account: string,
SignerWeight: number
}

View File

@@ -0,0 +1,22 @@
import {RippledAmount} from './amounts'
import {Memo} from './memos'
export interface OfferCreateTransaction {
TransactionType: 'OfferCreate',
Account: string,
AccountTxnID?: string,
Fee: string,
Field: any,
Flags: number,
LastLedgerSequence?: number,
Sequence: number,
Signers: any[],
SigningPubKey: string,
SourceTag?: number,
TakerGets: RippledAmount,
TakerPays: RippledAmount,
TxnSignature: string,
Expiration?: number,
Memos?: Memo[],
OfferSequence?: number,
}

View File

@@ -0,0 +1,42 @@
import {Memo} from './memos'
export interface Trustline {
account: string,
balance: string,
currency: string,
limit: string,
limit_peer: string,
quality_in: number,
quality_out: number,
no_ripple?: boolean,
no_ripple_peer?: boolean,
freeze?: boolean,
freeze_peer?: boolean,
authorized?: boolean,
peer_authorized?: boolean,
}
export type FormattedTrustlineSpecification = {
currency: string,
counterparty: string,
limit: string,
qualityIn?: number,
qualityOut?: number,
ripplingDisabled?: boolean,
authorized?: boolean,
frozen?: boolean,
memos?: Memo[]
}
export type FormattedTrustline = {
specification: FormattedTrustlineSpecification,
counterparty: {
limit: string,
ripplingDisabled?: boolean,
frozen?: boolean,
authorized?: boolean
},
state: {
balance: string
}
}

View File

@@ -1,10 +1,8 @@
/* @flow */
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const BigNumber = require('bignumber.js')
import * as _ from 'lodash'
import BigNumber from 'bignumber.js'
const {deriveKeypair} = require('ripple-keypairs')
import type {Amount, RippledAmount} from './types.js'
import {Amount, RippledAmount} from './types/objects'
function isValidSecret(secret: string): boolean {
try {
@@ -52,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
}
/**
@@ -81,7 +79,7 @@ function iso8601ToRippleTime(iso8601: string): number {
return unixToRippleTimestamp(Date.parse(iso8601))
}
module.exports = {
export {
dropsToXrp,
xrpToDrops,
toRippledAmount,
@@ -91,3 +89,4 @@ module.exports = {
iso8601ToRippleTime,
isValidSecret
}

View File

@@ -1,67 +0,0 @@
/* @flow */
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const ValidationError = require('./errors').ValidationError
const schemaValidate = require('./schema-validator').schemaValidate
function error(text) {
return new ValidationError(text)
}
function validateLedgerRange(options) {
if (!_.isUndefined(options) && !_.isUndefined(options.minLedgerVersion)
&& !_.isUndefined(options.maxLedgerVersion)) {
if (Number(options.minLedgerVersion) > Number(options.maxLedgerVersion)) {
throw error('minLedgerVersion must not be greater than maxLedgerVersion')
}
}
}
function validateOptions(schema, instance) {
schemaValidate(schema, instance)
validateLedgerRange(instance.options)
}
module.exports = {
getPaths: _.partial(schemaValidate, 'getPathsParameters'),
getTransactions: _.partial(validateOptions, 'getTransactionsParameters'),
getSettings: _.partial(validateOptions, 'getSettingsParameters'),
getAccountInfo: _.partial(validateOptions, 'getAccountInfoParameters'),
getTrustlines: _.partial(validateOptions, 'getTrustlinesParameters'),
getBalances: _.partial(validateOptions, 'getBalancesParameters'),
getBalanceSheet: _.partial(validateOptions, 'getBalanceSheetParameters'),
getOrders: _.partial(validateOptions, 'getOrdersParameters'),
getOrderbook: _.partial(validateOptions, 'getOrderbookParameters'),
getTransaction: _.partial(validateOptions, 'getTransactionParameters'),
getPaymentChannel: _.partial(validateOptions, 'getPaymentChannelParameters'),
getLedger: _.partial(validateOptions, 'getLedgerParameters'),
preparePayment: _.partial(schemaValidate, 'preparePaymentParameters'),
prepareOrder: _.partial(schemaValidate, 'prepareOrderParameters'),
prepareOrderCancellation:
_.partial(schemaValidate, 'prepareOrderCancellationParameters'),
prepareTrustline: _.partial(schemaValidate, 'prepareTrustlineParameters'),
prepareSettings: _.partial(schemaValidate, 'prepareSettingsParameters'),
prepareEscrowCreation: _.partial(schemaValidate,
'prepareEscrowCreationParameters'),
prepareEscrowCancellation: _.partial(schemaValidate,
'prepareEscrowCancellationParameters'),
prepareEscrowExecution: _.partial(schemaValidate,
'prepareEscrowExecutionParameters'),
preparePaymentChannelCreate: _.partial(schemaValidate,
'preparePaymentChannelCreateParameters'),
preparePaymentChannelFund: _.partial(schemaValidate,
'preparePaymentChannelFundParameters'),
preparePaymentChannelClaim: _.partial(schemaValidate,
'preparePaymentChannelClaimParameters'),
sign: _.partial(schemaValidate, 'signParameters'),
combine: _.partial(schemaValidate, 'combineParameters'),
submit: _.partial(schemaValidate, 'submitParameters'),
computeLedgerHash: _.partial(schemaValidate, 'computeLedgerHashParameters'),
generateAddress: _.partial(schemaValidate, 'generateAddressParameters'),
signPaymentChannelClaim: _.partial(schemaValidate,
'signPaymentChannelClaimParameters'),
verifyPaymentChannelClaim: _.partial(schemaValidate,
'verifyPaymentChannelClaimParameters'),
apiOptions: _.partial(schemaValidate, 'api-options'),
instructions: _.partial(schemaValidate, 'instructions')
}

126
src/common/validate.ts Normal file
View File

@@ -0,0 +1,126 @@
import * as _ from 'lodash'
import {ValidationError} from './errors'
import {schemaValidate} from './schema-validator'
function error(text) {
return new ValidationError(text)
}
function validateLedgerRange(options) {
if (!_.isUndefined(options) && !_.isUndefined(options.minLedgerVersion)
&& !_.isUndefined(options.maxLedgerVersion)) {
if (Number(options.minLedgerVersion) > Number(options.maxLedgerVersion)) {
throw error('minLedgerVersion must not be greater than maxLedgerVersion')
}
}
}
function validateOptions(schema, instance) {
schemaValidate(schema, instance)
validateLedgerRange(instance.options)
}
export const getPaths =
_.partial(schemaValidate, 'getPathsParameters')
export const getTransactions =
_.partial(validateOptions, 'getTransactionsParameters')
export const getSettings =
_.partial(validateOptions, 'getSettingsParameters')
export const getAccountInfo =
_.partial(validateOptions, 'getAccountInfoParameters')
export const getTrustlines =
_.partial(validateOptions, 'getTrustlinesParameters')
export const getBalances =
_.partial(validateOptions, 'getBalancesParameters')
export const getBalanceSheet =
_.partial(validateOptions, 'getBalanceSheetParameters')
export const getOrders =
_.partial(validateOptions, 'getOrdersParameters')
export const getOrderbook =
_.partial(validateOptions, 'getOrderbookParameters')
export const getTransaction =
_.partial(validateOptions, 'getTransactionParameters')
export const getPaymentChannel =
_.partial(validateOptions, 'getPaymentChannelParameters')
export const getLedger =
_.partial(validateOptions, 'getLedgerParameters')
export const preparePayment =
_.partial(schemaValidate, 'preparePaymentParameters')
export const prepareOrder =
_.partial(schemaValidate, 'prepareOrderParameters')
export const prepareOrderCancellation =
_.partial(schemaValidate, 'prepareOrderCancellationParameters')
export const prepareTrustline =
_.partial(schemaValidate, 'prepareTrustlineParameters')
export const prepareSettings =
_.partial(schemaValidate, 'prepareSettingsParameters')
export const prepareEscrowCreation =
_.partial(schemaValidate, 'prepareEscrowCreationParameters')
export const prepareEscrowCancellation =
_.partial(schemaValidate, 'prepareEscrowCancellationParameters')
export const prepareEscrowExecution =
_.partial(schemaValidate, 'prepareEscrowExecutionParameters')
export const preparePaymentChannelCreate =
_.partial(schemaValidate, 'preparePaymentChannelCreateParameters')
export const preparePaymentChannelFund =
_.partial(schemaValidate, 'preparePaymentChannelFundParameters')
export const preparePaymentChannelClaim =
_.partial(schemaValidate, 'preparePaymentChannelClaimParameters')
export const prepareCheckCreate =
_.partial(schemaValidate, 'prepareCheckCreateParameters')
export const prepareCheckCash =
_.partial(schemaValidate, 'prepareCheckCashParameters')
export const prepareCheckCancel =
_.partial(schemaValidate, 'prepareCheckCancelParameters')
export const sign =
_.partial(schemaValidate, 'signParameters')
export const combine =
_.partial(schemaValidate, 'combineParameters')
export const submit =
_.partial(schemaValidate, 'submitParameters')
export const computeLedgerHash =
_.partial(schemaValidate, 'computeLedgerHashParameters')
export const generateAddress =
_.partial(schemaValidate, 'generateAddressParameters')
export const signPaymentChannelClaim =
_.partial(schemaValidate, 'signPaymentChannelClaimParameters')
export const verifyPaymentChannelClaim =
_.partial(schemaValidate, 'verifyPaymentChannelClaimParameters')
export const apiOptions =
_.partial(schemaValidate, 'api-options')
export const instructions =
_.partial(schemaValidate, 'instructions')

View File

@@ -1,18 +1,31 @@
'use strict' // eslint-disable-line strict
import {EventEmitter} from 'events'
const {EventEmitter} = require('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 EventEmitter {
constructor(url, protocols = null, websocketOptions = {}) {
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 EventEmitter {
}
WSWrapper.CONNECTING = 0
WSWrapper.OPEN = 1
WSWrapper.CLOSING = 2
WSWrapper.CLOSED = 3
module.exports = WSWrapper
export = WSWrapper

View File

@@ -1,11 +1,9 @@
/* eslint-disable new-cap */
'use strict' // eslint-disable-line strict
const assert = require('assert')
const _ = require('lodash')
const jayson = require('jayson')
const RippleAPI = require('./api').RippleAPI
import * as assert from 'assert'
import * as _ from 'lodash'
import * as jayson from 'jayson'
import {RippleAPI} from './api'
/* istanbul ignore next */
@@ -81,6 +79,6 @@ function createHTTPServer(options, httpPort) {
}
}
module.exports = {
export {
createHTTPServer
}

View File

@@ -1,7 +0,0 @@
'use strict' // eslint-disable-line strict
module.exports = {
RippleAPI: require('./api').RippleAPI,
// Broadcast api is experimental
RippleAPIBroadcast: require('./broadcast').RippleAPIBroadcast
}

5
src/index.ts Normal file
View File

@@ -0,0 +1,5 @@
export {RippleAPI} from './api'
// Broadcast api is experimental
export {RippleAPIBroadcast} from './broadcast'

View File

@@ -1,66 +0,0 @@
/* @flow */
'use strict' // eslint-disable-line strict
const utils = require('./utils')
const {validate, removeUndefined} = utils.common
type AccountData = {
Sequence: number,
Account: string,
Balance: string,
Flags: number,
LedgerEntryType: string,
OwnerCount: number,
PreviousTxnID: string,
AccountTxnID?: string,
PreviousTxnLgrSeq: number,
index: string
}
type AccountDataResponse = {
account_data: AccountData,
ledger_current_index?: number,
ledger_hash?: string,
ledger_index: number,
validated: boolean
}
type AccountInfoOptions = {
ledgerVersion?: number
}
type AccountInfoResponse = {
sequence: number,
xrpBalance: string,
ownerCount: number,
previousInitiatedTransactionID: string,
previousAffectingTransactionID: string,
previousAffectingTransactionLedgerVersion: number
}
function formatAccountInfo(response: AccountDataResponse) {
const data = response.account_data
return removeUndefined({
sequence: data.Sequence,
xrpBalance: utils.common.dropsToXrp(data.Balance),
ownerCount: data.OwnerCount,
previousInitiatedTransactionID: data.AccountTxnID,
previousAffectingTransactionID: data.PreviousTxnID,
previousAffectingTransactionLedgerVersion: data.PreviousTxnLgrSeq
})
}
function getAccountInfo(address: string, options: AccountInfoOptions = {}
): Promise<AccountInfoResponse> {
validate.getAccountInfo({address, options})
const request = {
command: 'account_info',
account: address,
ledger_index: options.ledgerVersion || 'validated'
}
return this.connection.request(request).then(formatAccountInfo)
}
module.exports = getAccountInfo

44
src/ledger/accountinfo.ts Normal file
View File

@@ -0,0 +1,44 @@
import {validate, removeUndefined, dropsToXrp} from '../common'
import {RippleAPI} from '../api'
import {AccountInfoResponse} from '../common/types/commands/account_info'
export type GetAccountInfoOptions = {
ledgerVersion?: number
}
export type FormattedGetAccountInfoResponse = {
sequence: number,
xrpBalance: string,
ownerCount: number,
previousInitiatedTransactionID: string,
previousAffectingTransactionID: string,
previousAffectingTransactionLedgerVersion: number
}
function formatAccountInfo(
response: AccountInfoResponse
): FormattedGetAccountInfoResponse {
const data = response.account_data
return removeUndefined({
sequence: data.Sequence,
xrpBalance: dropsToXrp(data.Balance),
ownerCount: data.OwnerCount,
previousInitiatedTransactionID: data.AccountTxnID,
previousAffectingTransactionID: data.PreviousTxnID,
previousAffectingTransactionLedgerVersion: data.PreviousTxnLgrSeq
})
}
export default async function getAccountInfo(
this: RippleAPI, address: string, options: GetAccountInfoOptions = {}
): Promise<FormattedGetAccountInfoResponse> {
// 1. Validate
validate.getAccountInfo({address, options})
// 2. Make Request
const response = await this._request('account_info', {
account: address,
ledger_index: options.ledgerVersion || 'validated'
})
// 3. Return Formatted Response
return formatAccountInfo(response)
}

View File

@@ -0,0 +1,27 @@
import {removeUndefined} from '../common'
import {RippleAPI} from '../api'
import {
GetAccountObjectsOptions,
AccountObjectsResponse
} from '../common/types/commands/account_objects'
export default async function getAccountObjects(
this: RippleAPI,
address: string,
options: GetAccountObjectsOptions = {}
): Promise<AccountObjectsResponse> {
// Don't validate the options so that new types can be passed
// through to rippled. rippled validates requests.
// Make Request
const response = await this._request('account_objects', removeUndefined({
account: address,
type: options.type,
ledger_hash: options.ledgerHash,
ledger_index: options.ledgerIndex,
limit: options.limit,
marker: options.marker
}))
// Return Response
return response
}

View File

@@ -1,17 +1,15 @@
/* @flow */
'use strict' // eslint-disable-line strict
import * as _ from 'lodash'
import {validate} from '../common'
import {Amount} from '../common/types/objects'
import {ensureLedgerVersion} from './utils'
import {RippleAPI} from '../api'
const _ = require('lodash')
const utils = require('./utils')
const {validate} = utils.common
import type {Amount} from '../common/types.js'
type BalanceSheetOptions = {
export type BalanceSheetOptions = {
excludeAddresses?: Array<string>,
ledgerVersion?: number
}
type GetBalanceSheet = {
export type GetBalanceSheet = {
balances?: Array<Amount>,
assets?: Array<Amount>,
obligations?: Array<{
@@ -21,7 +19,7 @@ type GetBalanceSheet = {
}
function formatBalanceSheet(balanceSheet): GetBalanceSheet {
const result = {}
const result: GetBalanceSheet = {}
if (!_.isUndefined(balanceSheet.balances)) {
result.balances = []
@@ -40,28 +38,30 @@ 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
}
function getBalanceSheet(address: string, options: BalanceSheetOptions = {}
async function getBalanceSheet(
this: RippleAPI, address: string, options: BalanceSheetOptions = {}
): Promise<GetBalanceSheet> {
// 1. Validate
validate.getBalanceSheet({address, options})
return utils.ensureLedgerVersion.call(this, options).then(_options => {
const request = {
command: 'gateway_balances',
account: address,
strict: true,
hotwallet: _options.excludeAddresses,
ledger_index: _options.ledgerVersion
}
return this.connection.request(request).then(formatBalanceSheet)
options = await ensureLedgerVersion.call(this, options)
// 2. Make Request
const response = await this._request('gateway_balances', {
account: address,
strict: true,
hotwallet: options.excludeAddresses,
ledger_index: options.ledgerVersion
})
// 3. Return Formatted Response
return formatBalanceSheet(response)
}
module.exports = getBalanceSheet
export default getBalanceSheet

View File

@@ -1,20 +1,19 @@
/* @flow */
'use strict' // eslint-disable-line strict
const utils = require('./utils')
const {validate} = utils.common
import type {Connection} from '../common/connection.js'
import type {TrustlinesOptions, Trustline} from './trustlines-types.js'
import * as utils from './utils'
import {validate} from '../common'
import {Connection} from '../common'
import {GetTrustlinesOptions} from './trustlines'
import {FormattedTrustline} from '../common/types/objects/trustlines'
type Balance = {
export type Balance = {
value: string,
currency: string,
counterparty?: string
}
type GetBalances = Array<Balance>
export type GetBalances = Array<Balance>
function getTrustlineBalanceAmount(trustline: Trustline) {
function getTrustlineBalanceAmount(trustline: FormattedTrustline) {
return {
currency: trustline.specification.currency,
counterparty: trustline.specification.counterparty,
@@ -48,7 +47,7 @@ function getLedgerVersionHelper(connection: Connection, optionValue?: number
return connection.getLedgerVersion()
}
function getBalances(address: string, options: TrustlinesOptions = {}
function getBalances(address: string, options: GetTrustlinesOptions = {}
): Promise<GetBalances> {
validate.getTrustlines({address, options})
@@ -61,4 +60,4 @@ function getBalances(address: string, options: TrustlinesOptions = {}
formatBalances(options, {xrp: results[0], trustlines: results[1]}))
}
module.exports = getBalances
export default getBalances

View File

@@ -1,31 +0,0 @@
/* @flow */
'use strict' // eslint-disable-line strict
const utils = require('./utils')
const {validate} = utils.common
const parseLedger = require('./parse/ledger')
import type {GetLedger} from './types.js'
type LedgerOptions = {
ledgerVersion?: number,
includeAllData?: boolean,
includeTransactions?: boolean,
includeState?: boolean
}
function getLedger(options: LedgerOptions = {}): Promise<GetLedger> {
validate.getLedger({options})
const request = {
command: 'ledger',
ledger_index: options.ledgerVersion || 'validated',
expand: options.includeAllData,
transactions: options.includeTransactions,
accounts: options.includeState
}
return this.connection.request(request).then(response =>
parseLedger(response.ledger))
}
module.exports = getLedger

29
src/ledger/ledger.ts Normal file
View File

@@ -0,0 +1,29 @@
import {validate} from '../common'
import {FormattedLedger, parseLedger} from './parse/ledger'
import {RippleAPI} from '../api'
export type GetLedgerOptions = {
ledgerVersion?: number,
includeAllData?: boolean,
includeTransactions?: boolean,
includeState?: boolean
}
async function getLedger(
this: RippleAPI, options: GetLedgerOptions = {}
): Promise<FormattedLedger> {
// 1. Validate
validate.getLedger({options})
// 2. Make Request
const response = await this._request('ledger', {
ledger_index: options.ledgerVersion || 'validated',
expand: options.includeAllData,
transactions: options.includeTransactions,
accounts: options.includeState
})
// 3. Return Formatted Response
return parseLedger(response.ledger)
}
export default getLedger

View File

@@ -1,107 +0,0 @@
/* @flow */
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const utils = require('./utils')
const {validate} = utils.common
const parseOrderbookOrder = require('./parse/orderbook-order')
import type {Connection} from '../common/connection.js'
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
// are returned
function getBookOffers(connection: Connection, account: string,
ledgerVersion?: number, limit?: number, takerGets: Issue,
takerPays: Issue
): Promise {
return connection.request(utils.renameCounterpartyToIssuerInOrder({
command: 'book_offers',
taker_gets: takerGets,
taker_pays: takerPays,
ledger_index: ledgerVersion || 'validated',
limit: limit,
taker: account
})).then(data => data.offers)
}
function isSameIssue(a: Amount, b: Amount) {
return a.currency === b.currency && a.counterparty === b.counterparty
}
function directionFilter(direction: string, order: OrderbookItem) {
return order.specification.direction === direction
}
function flipOrder(order: OrderbookItem) {
const specification = order.specification
const flippedSpecification = {
quantity: specification.totalPrice,
totalPrice: specification.quantity,
direction: specification.direction === 'buy' ? 'sell' : 'buy'
}
const newSpecification = _.merge({}, specification, flippedSpecification)
return _.merge({}, order, {specification: newSpecification})
}
function alignOrder(base: Amount, order: OrderbookItem) {
const quantity = order.specification.quantity
return isSameIssue(quantity, base) ? order : flipOrder(order)
}
function formatBidsAndAsks(orderbook: Orderbook, offers) {
// the "base" currency is the currency that you are buying or selling
// the "counter" is the currency that the "base" is priced in
// a "bid"/"ask" is an order to buy/sell the base, respectively
// for bids: takerGets = totalPrice = counter, takerPays = quantity = base
// for asks: takerGets = quantity = base, takerPays = totalPrice = counter
// quality = takerPays / takerGets; price = totalPrice / quantity
// for bids: lowest quality => lowest quantity/totalPrice => highest price
// for asks: lowest quality => lowest totalPrice/quantity => lowest price
// for both bids and asks, lowest quality is closest to mid-market
// we sort the orders so that earlier orders are closer to mid-market
const orders = _.sortBy(offers, 'quality').map(parseOrderbookOrder)
const alignedOrders = orders.map(_.partial(alignOrder, orderbook.base))
const bids = alignedOrders.filter(_.partial(directionFilter, 'buy'))
const asks = alignedOrders.filter(_.partial(directionFilter, 'sell'))
return {bids, asks}
}
function getOrderbook(address: string, orderbook: Orderbook,
options: OrdersOptions = {}
): Promise<GetOrderbook> {
validate.getOrderbook({address, orderbook, options})
const getter = _.partial(getBookOffers, this.connection, address,
options.ledgerVersion, options.limit)
const getOffers = _.partial(getter, orderbook.base, orderbook.counter)
const getReverseOffers = _.partial(getter, orderbook.counter, orderbook.base)
return Promise.all([getOffers(), getReverseOffers()]).then(data =>
formatBidsAndAsks(orderbook, _.flatten(data)))
}
module.exports = getOrderbook

109
src/ledger/orderbook.ts Normal file
View File

@@ -0,0 +1,109 @@
import * as _ from 'lodash'
import * as utils from './utils'
import {
parseOrderbookOrder,
FormattedOrderbookOrder
} from './parse/orderbook-order'
import {validate} from '../common'
import {Amount, Issue} from '../common/types/objects'
import {BookOffer} from '../common/types/commands'
import {RippleAPI} from '../api'
export type FormattedOrderbook = {
bids: FormattedOrderbookOrder[],
asks: FormattedOrderbookOrder[]
}
function isSameIssue(a: Amount, b: Amount) {
return a.currency === b.currency && a.counterparty === b.counterparty
}
function directionFilter(direction: string, order: FormattedOrderbookOrder) {
return order.specification.direction === direction
}
function flipOrder(order: FormattedOrderbookOrder) {
const specification = order.specification
const flippedSpecification = {
quantity: specification.totalPrice,
totalPrice: specification.quantity,
direction: specification.direction === 'buy' ? 'sell' : 'buy'
}
const newSpecification = _.merge({}, specification, flippedSpecification)
return _.merge({}, order, {specification: newSpecification})
}
function alignOrder(base: Amount, order: FormattedOrderbookOrder) {
const quantity = order.specification.quantity
return isSameIssue(quantity, base) ? order : flipOrder(order)
}
function formatBidsAndAsks(
orderbook: OrderbookInfo, offers: BookOffer[]) {
// the "base" currency is the currency that you are buying or selling
// the "counter" is the currency that the "base" is priced in
// a "bid"/"ask" is an order to buy/sell the base, respectively
// for bids: takerGets = totalPrice = counter, takerPays = quantity = base
// for asks: takerGets = quantity = base, takerPays = totalPrice = counter
// quality = takerPays / takerGets; price = totalPrice / quantity
// for bids: lowest quality => lowest quantity/totalPrice => highest price
// for asks: lowest quality => lowest totalPrice/quantity => lowest price
// for both bids and asks, lowest quality is closest to mid-market
// we sort the orders so that earlier orders are closer to mid-market
const orders = _.sortBy(offers, 'quality').map(parseOrderbookOrder)
const alignedOrders = orders.map(_.partial(alignOrder, orderbook.base))
const bids = alignedOrders.filter(_.partial(directionFilter, 'buy'))
const asks = alignedOrders.filter(_.partial(directionFilter, 'sell'))
return {bids, asks}
}
// account is to specify a "perspective", which affects which unfunded offers
// are returned
async function makeRequest(
api: RippleAPI, taker: string, options: GetOrderbookOptions,
takerGets: Issue, takerPays: Issue
) {
const orderData = utils.renameCounterpartyToIssuerInOrder({
taker_gets: takerGets,
taker_pays: takerPays
})
return api._requestAll('book_offers', {
taker_gets: orderData.taker_gets,
taker_pays: orderData.taker_pays,
ledger_index: options.ledgerVersion || 'validated',
limit: options.limit,
taker
})
}
export type GetOrderbookOptions = {
limit?: number,
ledgerVersion?: number
}
export type OrderbookInfo = {
base: Issue,
counter: Issue
}
export default async function getOrderbook(
this: RippleAPI,
address: string,
orderbook: OrderbookInfo,
options: GetOrderbookOptions = {}
): Promise<FormattedOrderbook> {
// 1. Validate
validate.getOrderbook({address, orderbook, options})
// 2. Make Request
const [directOfferResults, reverseOfferResults] = await Promise.all([
makeRequest(this, address, options, orderbook.base, orderbook.counter),
makeRequest(this, address, options, orderbook.counter, orderbook.base)
])
// 3. Return Formatted Response
const directOffers = _.flatMap(directOfferResults,
directOfferResult => directOfferResult.offers)
const reverseOffers = _.flatMap(reverseOfferResults,
reverseOfferResult => reverseOfferResult.offers)
return formatBidsAndAsks(orderbook, [...directOffers, ...reverseOffers])
}

View File

@@ -1,41 +0,0 @@
/* @flow */
'use strict' // eslint-disable-line strict
const _ = require('lodash')
const utils = require('./utils')
const {validate} = utils.common
const parseAccountOrder = require('./parse/account-order')
import type {Connection} from '../common/connection.js'
import type {OrdersOptions, Order} from './types.js'
type GetOrders = Array<Order>
function requestAccountOffers(connection: Connection, address: string,
ledgerVersion: number, marker: string, limit: number
): Promise {
return connection.request({
command: 'account_offers',
account: address,
marker: marker,
limit: utils.clamp(limit, 10, 400),
ledger_index: ledgerVersion
}).then(data => {
return {
marker: data.marker,
results: data.offers.map(_.partial(parseAccountOrder, address))
}
})
}
function getOrders(address: string, options: OrdersOptions = {}
): Promise<GetOrders> {
validate.getOrders({address, options})
return utils.ensureLedgerVersion.call(this, options).then(_options => {
const getter = _.partial(requestAccountOffers, this.connection, address,
_options.ledgerVersion)
return utils.getRecursive(getter, _options.limit).then(orders =>
_.sortBy(orders, order => order.properties.sequence))
})
}
module.exports = getOrders

38
src/ledger/orders.ts Normal file
View File

@@ -0,0 +1,38 @@
import * as _ from 'lodash'
import {validate} from '../common'
import {FormattedAccountOrder, parseAccountOrder} from './parse/account-order'
import {RippleAPI} from '../api'
import {AccountOffersResponse} from '../common/types/commands'
export type GetOrdersOptions = {
limit?: number,
ledgerVersion?: number
}
function formatResponse(
address: string, responses: AccountOffersResponse[]
): FormattedAccountOrder[] {
let orders: FormattedAccountOrder[] = []
for (const response of responses) {
const offers = response.offers.map(offer => {
return parseAccountOrder(address, offer)
})
orders = orders.concat(offers)
}
return _.sortBy(orders, order => order.properties.sequence)
}
export default async function getOrders(
this: RippleAPI, address: string, options: GetOrdersOptions = {}
): Promise<FormattedAccountOrder[]> {
// 1. Validate
validate.getOrders({address, options})
// 2. Make Request
const responses = await this._requestAll('account_offers', {
account: address,
ledger_index: options.ledgerVersion || await this.getLedgerVersion(),
limit: options.limit
})
// 3. Return Formatted Response
return formatResponse(address, responses)
}

View File

@@ -1,9 +1,18 @@
/* @flow */
'use strict' // eslint-disable-line strict
const utils = require('./utils')
const flags = require('./flags').orderFlags
const parseAmount = require('./amount')
const BigNumber = require('bignumber.js')
import BigNumber from 'bignumber.js'
import parseAmount from './amount'
import {parseTimestamp, adjustQualityForXRP} from './utils'
import {removeUndefined} from '../../common'
import {orderFlags} from './flags'
import {FormattedOrderSpecification} from '../../common/types/objects'
export type FormattedAccountOrder = {
specification: FormattedOrderSpecification,
properties: {
maker: string,
sequence: number,
makerExchangeRate: string
}
}
// TODO: remove this function once rippled provides quality directly
function computeQuality(takerGets, takerPays) {
@@ -13,8 +22,10 @@ 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 {
const direction = (order.flags & flags.Sell) === 0 ? 'buy' : 'sell'
export function parseAccountOrder(
address: string, order: any
): FormattedAccountOrder {
const direction = (order.flags & orderFlags.Sell) === 0 ? 'buy' : 'sell'
const takerGetsAmount = parseAmount(order.taker_gets)
const takerPaysAmount = parseAmount(order.taker_pays)
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount
@@ -22,19 +33,19 @@ function parseAccountOrder(address: string, order: Object): Object {
// note: immediateOrCancel and fillOrKill orders cannot enter the order book
// so we can omit those flags here
const specification = utils.removeUndefined({
const specification = removeUndefined({
direction: direction,
quantity: quantity,
totalPrice: totalPrice,
passive: ((order.flags & flags.Passive) !== 0) || undefined,
passive: ((order.flags & orderFlags.Passive) !== 0) || undefined,
// rippled currently does not provide "expiration" in account_offers
expirationTime: utils.parseTimestamp(order.expiration)
expirationTime: parseTimestamp(order.expiration)
})
const makerExchangeRate = order.quality ?
utils.adjustQualityForXRP(order.quality.toString(),
takerGetsAmount.currency, takerPaysAmount.currency) :
computeQuality(takerGetsAmount, takerPaysAmount)
adjustQualityForXRP(order.quality.toString(),
takerGetsAmount.currency, takerPaysAmount.currency) :
computeQuality(takerGetsAmount, takerPaysAmount)
const properties = {
maker: address,
sequence: order.seq,
@@ -43,5 +54,3 @@ function parseAccountOrder(address: string, order: Object): Object {
return {specification, properties}
}
module.exports = parseAccountOrder

Some files were not shown because too many files have changed in this diff Show More