mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-05 05:15:48 +00:00
Compare commits
98 Commits
0.17.9
...
1.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2438295e70 | ||
|
|
f5e1a4a588 | ||
|
|
9e9a0a7d9b | ||
|
|
1c68283d1e | ||
|
|
28796d37cb | ||
|
|
067bc48d4e | ||
|
|
b94698df0b | ||
|
|
4f40b5cb6d | ||
|
|
14704eee6b | ||
|
|
860f6a6cd8 | ||
|
|
7a928804ec | ||
|
|
14444bea3f | ||
|
|
47a139fdff | ||
|
|
4e30b9b2fa | ||
|
|
2112d4c0b3 | ||
|
|
1d1132b7fa | ||
|
|
e07fa11923 | ||
|
|
7c92adbf45 | ||
|
|
d55aa2339f | ||
|
|
95e39153da | ||
|
|
65d8260908 | ||
|
|
1aa9feda71 | ||
|
|
2e5b435b11 | ||
|
|
54f12862dc | ||
|
|
226ef862ae | ||
|
|
4a0d675726 | ||
|
|
b2b6715ac0 | ||
|
|
823d93b86c | ||
|
|
7a42db99c9 | ||
|
|
f28ec27614 | ||
|
|
a36e23ebfa | ||
|
|
e978ef1888 | ||
|
|
9af3968508 | ||
|
|
86ce7b707c | ||
|
|
e0eb27ed8e | ||
|
|
2570e2a6d8 | ||
|
|
c71540e77a | ||
|
|
8eba827d11 | ||
|
|
90be539b09 | ||
|
|
43c08e5ea7 | ||
|
|
3f22b12216 | ||
|
|
a72041a321 | ||
|
|
71a0c16fec | ||
|
|
27ab98160a | ||
|
|
4eaaa8188d | ||
|
|
187154a2b0 | ||
|
|
c175e3f58e | ||
|
|
2ea22a099e | ||
|
|
c3aa062edd | ||
|
|
0ad8c577c0 | ||
|
|
facc513a52 | ||
|
|
df711ecb06 | ||
|
|
144be08af0 | ||
|
|
c53db4844a | ||
|
|
68b34f7532 | ||
|
|
3fe5d715a5 | ||
|
|
ca74cf1028 | ||
|
|
5b51ff6071 | ||
|
|
3cad4f4aa3 | ||
|
|
365de6d18a | ||
|
|
4a21360e37 | ||
|
|
43a3cfa010 | ||
|
|
b89eae5cb1 | ||
|
|
e311b74dac | ||
|
|
e3748e070b | ||
|
|
0c318816cc | ||
|
|
55e6801f4a | ||
|
|
4f60fc301f | ||
|
|
139159bf1a | ||
|
|
3ebbca0083 | ||
|
|
51aaa75a05 | ||
|
|
01a25f55f2 | ||
|
|
94196ab268 | ||
|
|
dc39343899 | ||
|
|
272eabd1cd | ||
|
|
7a653e6e63 | ||
|
|
994a6d5e76 | ||
|
|
3db72716b4 | ||
|
|
6d39e072f8 | ||
|
|
b7d636d157 | ||
|
|
e8ac4f3d40 | ||
|
|
ae2ccd9887 | ||
|
|
4fff85096c | ||
|
|
b4d8684740 | ||
|
|
d3fb4b6260 | ||
|
|
19eaedf50d | ||
|
|
c56e6a6c08 | ||
|
|
01ecfb0a07 | ||
|
|
e1630e1693 | ||
|
|
526d87c1fc | ||
|
|
8204f6c648 | ||
|
|
5979ff6197 | ||
|
|
d22828b222 | ||
|
|
7e5b9948a8 | ||
|
|
7ece43e2e2 | ||
|
|
f90617eac4 | ||
|
|
2469fb2307 | ||
|
|
a051e6fd71 |
4
.babelrc
4
.babelrc
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"presets": ["es2015", "stage-1"],
|
||||
"plugins": ["syntax-flow", "transform-flow-strip-types"]
|
||||
}
|
||||
19
.flowconfig
19
.flowconfig
@@ -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
8
.gitignore
vendored
@@ -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
10
.nycrc
Normal 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
10
.travis.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 6
|
||||
- 8
|
||||
- 9
|
||||
script:
|
||||
- yarn compile
|
||||
- yarn test
|
||||
- yarn build
|
||||
- yarn lint
|
||||
77
Gulpfile.js
77
Gulpfile.js
@@ -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() {
|
||||
|
||||
243
HISTORY.md
243
HISTORY.md
@@ -1,5 +1,231 @@
|
||||
# ripple-lib Release History
|
||||
|
||||
## 1.0.0-beta.4 (2018-08-10)
|
||||
|
||||
+ [Add `prepareTransaction()`](https://github.com/ripple/ripple-lib/pull/898)
|
||||
+ Internal improvements and cleanup
|
||||
|
||||
## 1.0.0-beta.3 (2018-07-17)
|
||||
|
||||
+ For payment channel transactions, `getTransaction` includes a new
|
||||
`channelChanges` property that describes the details of the payment channel.
|
||||
(#920)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
+ A bug caused calculated fees to use too many decimal places. This was fixed by
|
||||
rounding fees to 6 decimal places. (#912)
|
||||
+ When using the Settings transaction to set up a multi-signing list, the
|
||||
threshold and weights fields are required. (#909)
|
||||
+ Docs: Fix the MIMETYPE in examples with memos. (#914)
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found
|
||||
below.
|
||||
```
|
||||
% shasum -a 256 *
|
||||
460dbb521e24c44cb53dabc1a74feeca33d031b44d889dd5b51103ca92d51de6 ripple-1.0.0-beta.3-debug.js
|
||||
cccfd24973c6b7990d9e933a589175dae26249825737fff4f2f73d8558a3f186 ripple-1.0.0-beta.3-min.js
|
||||
0dc456a58fb078347d9920310621595905085595d73c2b8fe96bea73bcf35450 ripple-1.0.0-beta.3.js
|
||||
```
|
||||
|
||||
## 1.0.0-beta.2 (2018-06-08)
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
+ During transaction preparation, there is now a maximum fee. Also, when a transaction is signed, its fee is checked and an error is thrown if the fee exceeds the maximum. The default `maxFeeXRP` is `'2'` (2 XRP). Override this value in the RippleAPI constructor.
|
||||
+ Attempting to prepare a transaction with an exact `fee` higher than `maxFeeXRP` causes a `ValidationError` to be thrown.
|
||||
+ Attempting to sign a transaction with a fee higher than `maxFeeXRP` causes a `ValidationError` to be thrown.
|
||||
+ The value returned by `getFee()` is capped at `maxFeeXRP`.
|
||||
|
||||
### Other Changes
|
||||
|
||||
+ In Transaction Instructions, the `maxFee` parameter is deprecated. Use the `maxFeeXRP` parameter in the RippleAPI constructor.
|
||||
|
||||
#### Overview of new fee limit
|
||||
|
||||
Most users of ripple-lib do not need to make any code changes to accommodate the new soft limit on fees. The limit is designed to protect against the most severe cases where an unintentionally high fee may be used.
|
||||
|
||||
+ When having ripple-lib provide the fee with a `prepare*` method, a maximum fee of `maxFeeXRP` (default 2 XRP) applies. You can prepare more economical transactions by setting a lower `maxFeeXRP`, or support high-priority transactions by setting a higher `maxFeeXRP` in the RippleAPI constructor.
|
||||
+ When using `sign` with a Fee higher than `maxFeeXRP`, a `ValidationError` is thrown.
|
||||
|
||||
If you have any questions or concerns, please open an issue on GitHub.
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found
|
||||
below.
|
||||
```
|
||||
% shasum -a 256 *
|
||||
ef348a2805098e61395b689b410cbf4bfd35e4d72e38c89f4ab74ec5e19793f5 ripple-1.0.0-beta.2-debug.js
|
||||
ea33fd53df8c7176d5fbf52dae0b64aade7180860f26449062cdbefaf8bd4d9b ripple-1.0.0-beta.2-min.js
|
||||
fe5cc6e97c9b8a1470dacb34f16a64255cd639a25381abe9db1ba79e102456f2 ripple-1.0.0-beta.2.js
|
||||
```
|
||||
|
||||
## 1.0.0-beta.1 (2018-05-24)
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
+ Amounts in drops and XRP are checked for validity. Some
|
||||
methods may now throw a `BigNumber Error` or `ValidationError` if the amount
|
||||
is invalid. This may include methods that previously did not throw.
|
||||
+ Note that 1 drop is equivalent to 0.000001 XRP and 1 XRP is equivalent to 1,000,000 drops.
|
||||
+ Using drops is recommended. All rippled APIs require XRP amounts to be
|
||||
expressed in drops.
|
||||
|
||||
### Other Changes
|
||||
|
||||
+ Allow specifying amounts in drops for consistency with the `rippled`
|
||||
APIs.
|
||||
+ Export `xrpToDrops()` and `dropsToXrp()` functions.
|
||||
+ Potentially breaking change: Improve errors. For example, `RippledError` now includes the full response from
|
||||
the `rippled` server ([#687](https://github.com/ripple/ripple-lib/issues/687)). `NotConnectedError`
|
||||
may be thrown with a different message than before.
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found
|
||||
below.
|
||||
```
|
||||
% shasum -a 256 *
|
||||
a80ebb39e186640246306eadb2879147458c8271fd3c6cb32e6ef78d0b4b01a5 ripple-1.0.0-beta.1-debug.js
|
||||
81bcc4b5fd6fd52220ed151242eaddd63eb29c4078845edc68f65b769557d126 ripple-1.0.0-beta.1-min.js
|
||||
738b4d65b58cf4e3542fa396f8d319a24cd7d0b7aff5ff629a900e244f735ff4 ripple-1.0.0-beta.1.js
|
||||
```
|
||||
|
||||
## 1.0.0-beta.0 (2018-05-10)
|
||||
|
||||
+ [Add `request`, `hasNextPage`, and
|
||||
`requestNextPage`](https://github.com/ripple/ripple-lib/pull/887).
|
||||
+ This provides support for all rippled APIs, including subscriptions.
|
||||
|
||||
When using rippled APIs, you must:
|
||||
+ For all XRP amounts, use drops (1 drop = 0.000001 XRP).
|
||||
+ Instead of `counterparty`, use `issuer`.
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found
|
||||
below.
|
||||
```
|
||||
% shasum -a 256 *
|
||||
ab2094979a3d6b320c7bc22bc5946c50fa5e29af0976d352e7689b0a4d840c55 ripple-1.0.0-beta.0-debug.js
|
||||
0e7f7d740606c2866ebf63776b13b41a555848e1a1419e2c8058d2e6c562d7fd ripple-1.0.0-beta.0-min.js
|
||||
bd05e8806832ca4192aea7ba2d0362baa9f44605f8e8e6676acd25eb0b94b778 ripple-1.0.0-beta.0.js
|
||||
```
|
||||
|
||||
## 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 +233,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 +342,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)
|
||||
|
||||
32
README.md
32
README.md
@@ -23,10 +23,38 @@ 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)
|
||||
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).
|
||||
|
||||
### Mailing lists
|
||||
|
||||
We have a low-traffic mailing list for announcements of new ripple-lib releases. (About 1 email per week)
|
||||
|
||||
+ [Subscribe to ripple-lib-announce](https://groups.google.com/forum/#!forum/ripple-lib-announce)
|
||||
|
||||
If you're using the XRP Ledger in production, you should run a [rippled server](https://github.com/ripple/rippled) and subscribe to the ripple-server mailing list as well.
|
||||
|
||||
+ [Subscribe to ripple-server](https://groups.google.com/forum/#!forum/ripple-server)
|
||||
|
||||
## Development
|
||||
|
||||
To build the library for Node.js:
|
||||
```
|
||||
$ yarn compile
|
||||
```
|
||||
|
||||
The TypeScript compiler will [output](./tsconfig.json#L7) the resulting JS files in `./dist/npm/`.
|
||||
|
||||
To build the library for the browser:
|
||||
```
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
Gulp will [output](./Gulpfile.js) the resulting JS files in `./build/`.
|
||||
|
||||
For more details, see the `scripts` in `package.json`.
|
||||
|
||||
## Running tests
|
||||
|
||||
|
||||
9
custom_typings/node.d.ts
vendored
Normal file
9
custom_typings/node.d.ts
vendored
Normal 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;
|
||||
1478
docs/index.md
1478
docs/index.md
File diff suppressed because it is too large
Load Diff
@@ -19,14 +19,13 @@ Currencies are represented as either 3-character currency codes or 40-character
|
||||
## Value
|
||||
A *value* is a quantity of a currency represented as a decimal string. Be careful: JavaScript's native number format does not have sufficient precision to represent all values. XRP has different precision from other currencies.
|
||||
|
||||
**XRP** has 6 significant digits past the decimal point. In other words, XRP cannot be divided into positive values smaller than `0.000001` (1e-6). XRP has a maximum value of `100000000000` (1e11).
|
||||
**XRP** has 6 significant digits past the decimal point. In other words, XRP cannot be divided into positive values smaller than `0.000001` (1e-6). This smallest unit is called a "drop". XRP has a maximum value of `100000000000` (1e11). Some RippleAPI methods accept XRP in order to maintain compatibility with older versions of the API. For consistency with the `rippled` APIs, we recommend formally specifying XRP values in *drops* in all API requests, and converting them to XRP for display. This is similar to Bitcoin's *satoshis* and Ethereum's *wei*. 1 XRP = 1,000,000 drops.
|
||||
|
||||
**Non-XRP values** have 16 decimal digits of precision, with a maximum value of `9999999999999999e80`. The smallest positive non-XRP value is `1e-81`.
|
||||
|
||||
|
||||
## Amount
|
||||
|
||||
Example amount:
|
||||
Example 100.00 USD amount:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -36,15 +35,16 @@ Example amount:
|
||||
}
|
||||
```
|
||||
|
||||
Example XRP amount:
|
||||
Example 3.0 XRP amount, in drops:
|
||||
```json
|
||||
{
|
||||
"currency": "XRP",
|
||||
"value": "2000"
|
||||
"currency": "drops",
|
||||
"value": "3000000"
|
||||
}
|
||||
```
|
||||
(Requires `ripple-lib` version 1.0.0 or higher.)
|
||||
|
||||
An *amount* is data structure representing a currency, a quantity of that currency, and the counterparty on the trustline that holds the value. For XRP, there is no counterparty.
|
||||
An *amount* is an object specifying a currency, a quantity of that currency, and the counterparty (issuer) on the trustline that holds the value. For XRP, there is no counterparty.
|
||||
|
||||
A *lax amount* allows the counterparty to be omitted for all currencies. If the counterparty is not specified in an amount within a transaction specification, then any counterparty may be used for that amount.
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ If you omit the `server` parameter, RippleAPI operates [offline](#offline-functi
|
||||
|
||||
1. Install [Node.js](https://nodejs.org) and [Yarn](https://yarnpkg.com/en/docs/install). Most Linux distros have a package for Node.js; check that it's the version you want.
|
||||
2. Use yarn to install RippleAPI:
|
||||
`yarn install ripple-lib`
|
||||
`yarn add ripple-lib`
|
||||
|
||||
After you have installed ripple-lib, you can create scripts using the [boilerplate](#boilerplate) and run them using the Node.js executable, typically named `node`:
|
||||
|
||||
|
||||
33
docs/src/getAccountObjects.md.ejs
Normal file
33
docs/src/getAccountObjects.md.ejs
Normal 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') %>
|
||||
@@ -1,16 +1,18 @@
|
||||
## getFee
|
||||
|
||||
`getFee(): Promise<number>`
|
||||
`getFee(): Promise<string>`
|
||||
|
||||
Returns the estimated transaction fee for the rippled server the RippleAPI instance is connected to.
|
||||
|
||||
This will use the [feeCushion parameter](#parameters) provided to the RippleAPI constructor, or the default value of `1.2`.
|
||||
|
||||
### Parameters
|
||||
|
||||
This method has no parameters.
|
||||
<%- renderSchema('input/get-fee.json') %>
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with a string encoded floating point value representing the estimated fee to submit a transaction, expressed in XRP.
|
||||
This method returns a promise that resolves with a string-encoded floating point value representing the estimated fee to submit a transaction, expressed in XRP.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -19,5 +21,5 @@ return api.getFee().then(fee => {/* ... */});
|
||||
```
|
||||
|
||||
```json
|
||||
"0.012"
|
||||
"0.000012"
|
||||
```
|
||||
|
||||
@@ -14,6 +14,12 @@ This method returns a promise that resolves with an object with the following st
|
||||
|
||||
<%- renderSchema('output/get-orderbook.json') %>
|
||||
|
||||
### Raw order data
|
||||
|
||||
(Requires ripple-lib 0.22.0 or 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
|
||||
|
||||
27
docs/src/hasNextPage.md.ejs
Normal file
27
docs/src/hasNextPage.md.ejs
Normal file
@@ -0,0 +1,27 @@
|
||||
## hasNextPage
|
||||
|
||||
`hasNextPage(currentResponse): boolean`
|
||||
|
||||
Returns `true` when there are more pages available.
|
||||
|
||||
When there are more results than contained in the response, the response includes a `marker` field. You can use this convenience method, or check for `marker` yourself.
|
||||
|
||||
See [Markers and Pagination](https://ripple.com/build/rippled-apis/#markers-and-pagination).
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns `true` if `currentResponse` includes a `marker`.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
return api.request('ledger_data', {
|
||||
ledger_index: 'validated'
|
||||
}).then(response => {
|
||||
/* Do something useful with response */
|
||||
|
||||
if (api.hasNextPage(response)) {
|
||||
/* There are more pages available */
|
||||
}
|
||||
}).catch(console.error);
|
||||
```
|
||||
@@ -4,6 +4,10 @@
|
||||
<% include basictypes.md.ejs %>
|
||||
<% include transactions.md.ejs %>
|
||||
<% include specifications.md.ejs %>
|
||||
<% include rippledAPIs.md.ejs %>
|
||||
<% include request.md.ejs %>
|
||||
<% include hasNextPage.md.ejs %>
|
||||
<% include requestNextPage.md.ejs %>
|
||||
<% include methods.md.ejs %>
|
||||
<% include connect.md.ejs %>
|
||||
<% include disconnect.md.ejs %>
|
||||
@@ -21,6 +25,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 +39,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 %>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Introduction
|
||||
|
||||
RippleAPI is the official client library to the XRP Ledger. Currently, RippleAPI is only available in JavaScript.
|
||||
RippleAPI (ripple-lib) is the official client library to the XRP Ledger. Currently, RippleAPI is only available in JavaScript.
|
||||
Using RippleAPI, you can:
|
||||
|
||||
* [Query transactions from the XRP Ledger history](#gettransaction)
|
||||
@@ -8,5 +8,3 @@ Using RippleAPI, you can:
|
||||
* [Submit](#submit) transactions to the XRP Ledger, including [Payments](#payment), [Orders](#order), [Settings changes](#settings), and [other types](#transaction-types)
|
||||
* [Generate a new XRP Ledger Address](#generateaddress)
|
||||
* ... and [much more](#api-methods).
|
||||
|
||||
RippleAPI only provides access to *validated*, *immutable* transaction data.
|
||||
|
||||
30
docs/src/prepareCheckCancel.md.ejs
Normal file
30
docs/src/prepareCheckCancel.md.ejs
Normal 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') %>
|
||||
30
docs/src/prepareCheckCash.md.ejs
Normal file
30
docs/src/prepareCheckCash.md.ejs
Normal 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') %>
|
||||
30
docs/src/prepareCheckCreate.md.ejs
Normal file
30
docs/src/prepareCheckCreate.md.ejs
Normal 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') %>
|
||||
@@ -22,6 +22,8 @@ All "prepare*" methods have the same return type.
|
||||
|
||||
```javascript
|
||||
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
|
||||
|
||||
// Buy 10.10 USD (of the specified issuer) for 2.0 XRP (2000000 drops), fill or kill.
|
||||
const order = <%- importFile('test/fixtures/requests/prepare-order.json') %>;
|
||||
return api.prepareOrder(address, order)
|
||||
.then(prepared => {/* ... */});
|
||||
|
||||
27
docs/src/request.md.ejs
Normal file
27
docs/src/request.md.ejs
Normal file
@@ -0,0 +1,27 @@
|
||||
## request
|
||||
|
||||
`request(command: string, options: object): Promise<object>`
|
||||
|
||||
Returns the response from invoking the specified command, with the specified options, on the connected rippled server.
|
||||
|
||||
Refer to [rippled APIs](https://ripple.com/build/rippled-apis/) for commands and options. All XRP amounts must be specified in drops. One drop is equal to 0.000001 XRP. See [Specifying Currency Amounts](https://ripple.com/build/rippled-apis/#specifying-currency-amounts).
|
||||
|
||||
Most commands return data for the `current` (in-progress, open) ledger by default. Do not rely on this. Always specify a ledger version in your request. In the example below, the 'validated' ledger is requested, which is the most recent ledger that has been validated by the whole network. See [Specifying Ledgers](https://ripple.com/build/rippled-apis/#specifying-ledgers).
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with the response from rippled.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
// Replace 'ledger' with your desired rippled command
|
||||
return api.request('ledger', {
|
||||
ledger_index: 'validated'
|
||||
}).then(response => {
|
||||
/* Do something useful with response */
|
||||
console.log(JSON.stringify(response, null, 2))
|
||||
}).catch(console.error);
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/ledger.json') %>
|
||||
29
docs/src/requestNextPage.md.ejs
Normal file
29
docs/src/requestNextPage.md.ejs
Normal file
@@ -0,0 +1,29 @@
|
||||
## requestNextPage
|
||||
|
||||
`requestNextPage(command: string, params: object = {}, currentResponse: object): Promise<object>`
|
||||
|
||||
Requests the next page of data.
|
||||
|
||||
You can use this convenience method, or include `currentResponse.marker` in `params` yourself, when using `request`.
|
||||
|
||||
See [Markers and Pagination](https://ripple.com/build/rippled-apis/#markers-and-pagination).
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with the next page of data from rippled.
|
||||
|
||||
If the response does not have a next page, the promise will reject with `new errors.NotFoundError('response does not have a next page')`.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const command = 'ledger_data'
|
||||
const params = {
|
||||
ledger_index: 'validated'
|
||||
}
|
||||
return api.request(command, params).then(response => {
|
||||
return api.requestNextPage(command, params, response)
|
||||
}).then(response_page_2 => {
|
||||
/* Do something useful with second page of response */
|
||||
}).catch(console.error);
|
||||
```
|
||||
66
docs/src/rippledAPIs.md.ejs
Normal file
66
docs/src/rippledAPIs.md.ejs
Normal file
@@ -0,0 +1,66 @@
|
||||
# rippled APIs
|
||||
|
||||
ripple-lib relies on [rippled APIs](https://ripple.com/build/rippled-apis/) for all online functionality. With ripple-lib version 1.0.0 and higher, you can easily access rippled APIs through ripple-lib. Use the `request()`, `hasNextPage()`, and `requestNextPage()` methods:
|
||||
* Use `request()` to issue any `rippled` command, including `account_currencies`, `subscribe`, and `unsubscribe`. [Full list of API Methods](https://ripple.com/build/rippled-apis/#api-methods).
|
||||
* Use `hasNextPage()` to determine whether a response has more pages. This is true when the response includes a [`marker` field](https://ripple.com/build/rippled-apis/#markers-and-pagination).
|
||||
* Use `requestNextPage()` to request the next page of data.
|
||||
|
||||
When using rippled APIs, [specify XRP amounts in drops](https://ripple.com/build/rippled-apis/#specifying-currency-amounts). 1 XRP = 1000000 drops.
|
||||
|
||||
## Listening to streams
|
||||
|
||||
The `rippled` server can push updates to your client when various events happen. Refer to [Subscriptions in the `rippled` API docs](https://ripple.com/build/rippled-apis/#subscriptions) for details.
|
||||
|
||||
Note that the `streams` parameter for generic streams takes an array. For example, to subscribe to the `validations` stream, use `{ streams: [ 'validations' ] }`.
|
||||
|
||||
The string names of some generic streams to subscribe to are in the table below. (Refer to `rippled` for an up-to-date list of streams.)
|
||||
|
||||
Type | Description
|
||||
---- | -----------
|
||||
`server` | Sends a message whenever the status of the `rippled` server (for example, network connectivity) changes.
|
||||
`ledger` | Sends a message whenever the consensus process declares a new validated ledger.
|
||||
`transactions` | Sends a message whenever a transaction is included in a closed ledger.
|
||||
`transactions_proposed` | Sends a message whenever a transaction is included in a closed ledger, as well as some transactions that have not yet been included in a validated ledger and may never be. Not all proposed transactions appear before validation. Even some transactions that don't succeed are included in validated ledgers because they take the anti-spam transaction fee.
|
||||
`validations` | Sends a message whenever the server receives a validation message, also called a validation vote, regardless of whether the server trusts the validator.
|
||||
`manifests` | Sends a message whenever the server receives a manifest.
|
||||
`peer_status` | (Admin-only) Information about connected peer `rippled` servers, especially with regards to the consensus process.
|
||||
|
||||
When you subscribe to a stream, you must also listen to the relevant message type(s). Some of the available message types are in the table below. (Refer to `rippled` for an up-to-date list of message types.)
|
||||
|
||||
Type | Description
|
||||
---- | -----------
|
||||
`ledgerClosed` | Sent by the `ledger` stream when the consensus process declares a new fully validated ledger. The message identifies the ledger and provides some information about its contents.
|
||||
`validationReceived` | Sent by the `validations` stream when the server receives a validation message, also called a validation vote, regardless of whether the server trusts the validator.
|
||||
`manifestReceived` | Sent by the `manifests` stream when the server receives a manifest.
|
||||
`transaction` | Sent by many subscriptions including `transactions`, `transactions_proposed`, `accounts`, `accounts_proposed`, and `book` (Order Book). See [Transaction Streams](https://ripple.com/build/rippled-apis/#transaction-streams) for details.
|
||||
`peerStatusChange` | (Admin-only) Reports a large amount of information on the activities of other `rippled` servers to which the server is connected.
|
||||
|
||||
To register your listener function, use `connection.on(type, handler)`.
|
||||
|
||||
Here is an example of listening for transactions on given account(s):
|
||||
```
|
||||
const account = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn' // Replace with the account you want notifications for
|
||||
api.connect().then(() => { // Omit this if you are already connected
|
||||
|
||||
// 'transaction' can be replaced with the relevant `type` from the table above
|
||||
api.connection.on('transaction', (event) => {
|
||||
|
||||
// Do something useful with `event`
|
||||
console.log(JSON.stringify(event, null, 2))
|
||||
})
|
||||
|
||||
api.request('subscribe', {
|
||||
accounts: [ account ]
|
||||
}).then(response => {
|
||||
if (response.status === 'success') {
|
||||
console.log('Successfully subscribed')
|
||||
}
|
||||
}).catch(error => {
|
||||
// Handle `error`
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
The subscription ends when you unsubscribe or the WebSocket connection is closed.
|
||||
|
||||
For full details, see [rippled Subscriptions](https://ripple.com/build/rippled-apis/#subscriptions).
|
||||
@@ -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") %>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
@@ -44,7 +53,7 @@ Transaction instructions indicate how to execute a transaction, complementary wi
|
||||
|
||||
<%- renderSchema("objects/instructions.json") %>
|
||||
|
||||
We recommended that you specify a `maxLedgerVersion` so that you can quickly determine that a failed transaction will never succeeed in the future. It is impossible for a transaction to succeed after the XRP Ledger's consensus-validated ledger version exceeds the transaction's `maxLedgerVersion`. If you omit `maxLedgerVersion`, the "prepare*" method automatically supplies a `maxLedgerVersion` equal to the current ledger plus 3, which it includes in the return value from the "prepare*" method.
|
||||
We recommend that you specify a `maxLedgerVersion` so that you can quickly determine that a failed transaction will never succeeed in the future. It is impossible for a transaction to succeed after the XRP Ledger's consensus-validated ledger version exceeds the transaction's `maxLedgerVersion`. If you omit `maxLedgerVersion`, the "prepare\*" method automatically supplies a `maxLedgerVersion` equal to the current ledger plus 3, which it includes in the return value from the "prepare\*" method.
|
||||
|
||||
## Transaction ID
|
||||
|
||||
|
||||
66
package.json
66
package.json
@@ -1,53 +1,45 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.17.9",
|
||||
"version": "1.0.0-beta.4",
|
||||
"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",
|
||||
"ripple-lib-transactionparser": "0.7.1",
|
||||
"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.9.2",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
159
src/api.js
159
src/api.js
@@ -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
|
||||
}
|
||||
336
src/api.ts
Normal file
336
src/api.ts
Normal file
@@ -0,0 +1,336 @@
|
||||
import {EventEmitter} from 'events'
|
||||
import {
|
||||
Connection,
|
||||
errors,
|
||||
validate,
|
||||
xrpToDrops,
|
||||
dropsToXrp,
|
||||
iso8601ToRippleTime,
|
||||
txFlags
|
||||
} from './common'
|
||||
import {
|
||||
connect,
|
||||
disconnect,
|
||||
isConnected,
|
||||
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,
|
||||
ServerInfoRequest, ServerInfoResponse
|
||||
} from './common/types/commands'
|
||||
|
||||
|
||||
import RangeSet from './common/rangeset'
|
||||
import * as ledgerUtils from './ledger/utils'
|
||||
import * as transactionUtils from './transaction/utils'
|
||||
import * as schemaValidator from './common/schema-validator'
|
||||
import {getServerInfo, getFee} from './common/serverinfo'
|
||||
import {clamp} from './ledger/utils'
|
||||
import {Instructions} from './transaction/types'
|
||||
|
||||
export type APIOptions = {
|
||||
server?: string,
|
||||
feeCushion?: number,
|
||||
maxFeeXRP?: string,
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
class RippleAPI extends EventEmitter {
|
||||
_feeCushion: number
|
||||
_maxFeeXRP: string
|
||||
|
||||
// New in > 0.21.0
|
||||
// non-validated ledger versions are allowed, and passed to rippled as-is.
|
||||
connection: Connection
|
||||
|
||||
// these are exposed only for use by unit tests; they are not part of the API.
|
||||
static _PRIVATE = {
|
||||
validate,
|
||||
RangeSet,
|
||||
ledgerUtils,
|
||||
schemaValidator
|
||||
}
|
||||
|
||||
constructor(options: APIOptions = {}) {
|
||||
super()
|
||||
validate.apiOptions(options)
|
||||
this._feeCushion = options.feeCushion || 1.2
|
||||
this._maxFeeXRP = options.maxFeeXRP || '2'
|
||||
const serverURL = options.server
|
||||
if (serverURL !== undefined) {
|
||||
this.connection = new Connection(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 Connection(null, options)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a request to the API with the given command and
|
||||
* additional request body parameters.
|
||||
*/
|
||||
async request(command: 'account_info', params: AccountInfoRequest):
|
||||
Promise<AccountInfoResponse>
|
||||
async request(command: 'account_lines', params: AccountLinesRequest):
|
||||
Promise<AccountLinesResponse>
|
||||
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>
|
||||
async request(command: 'server_info', params?: ServerInfoRequest):
|
||||
Promise<ServerInfoResponse>
|
||||
async request(command: string, params: any):
|
||||
Promise<any>
|
||||
async request(command: string, params: any = {}): Promise<any> {
|
||||
return this.connection.request({
|
||||
...params,
|
||||
command
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are more pages of data.
|
||||
*
|
||||
* When there are more results than contained in the response, the response
|
||||
* includes a `marker` field.
|
||||
*
|
||||
* See https://ripple.com/build/rippled-apis/#markers-and-pagination
|
||||
*/
|
||||
hasNextPage<T extends {marker?: string}>(currentResponse: T): boolean {
|
||||
return !!currentResponse.marker
|
||||
}
|
||||
|
||||
async requestNextPage<T extends {marker?: string}>(
|
||||
command: string,
|
||||
params: object = {},
|
||||
currentResponse: T
|
||||
): Promise<object> {
|
||||
if (!currentResponse.marker) {
|
||||
return Promise.reject(
|
||||
new errors.NotFoundError('response does not have a next page')
|
||||
)
|
||||
}
|
||||
const nextPageParams = Object.assign({}, params, {
|
||||
marker: currentResponse.marker
|
||||
})
|
||||
return this.request(command, nextPageParams)
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a transaction.
|
||||
*
|
||||
* You can later submit the transaction with `submit()`.
|
||||
*/
|
||||
async prepareTransaction(txJSON: object, instructions: Instructions = {}) {
|
||||
return transactionUtils.prepareTransaction(txJSON, this, instructions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string to hex.
|
||||
*
|
||||
* This can be used to generate `MemoData`, `MemoType`, and `MemoFormat`.
|
||||
*
|
||||
* @param string string to convert to hex
|
||||
*/
|
||||
convertStringToHex(string: string): string {
|
||||
return transactionUtils.convertStringToHex(string)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 used by existing methods and is not recommended for
|
||||
* general use. Instead, use rippled's built-in pagination and make multiple
|
||||
* requests as needed.
|
||||
*/
|
||||
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
|
||||
}
|
||||
const singleResult = await 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
|
||||
|
||||
xrpToDrops = xrpToDrops
|
||||
dropsToXrp = dropsToXrp
|
||||
iso8601ToRippleTime = iso8601ToRippleTime
|
||||
txFlags = txFlags
|
||||
}
|
||||
|
||||
export {
|
||||
RippleAPI
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
20
src/common/browser-hacks.ts
Normal file
20
src/common/browser-hacks.ts
Normal 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
|
||||
}
|
||||
@@ -1,26 +1,54 @@
|
||||
'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' ||
|
||||
type === 'transaction' ||
|
||||
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 +61,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,30 +80,31 @@ 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)) {
|
||||
throw new ResponseFormatError('valid id not found in response')
|
||||
throw new ResponseFormatError('valid id not found in response', data)
|
||||
}
|
||||
return [data.id.toString(), data]
|
||||
} else if (isStreamMessageType(data.type)) {
|
||||
if (data.type === 'ledgerClosed') {
|
||||
this._updateLedgerVersions(data)
|
||||
this._updateFees(data)
|
||||
}
|
||||
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)
|
||||
|
||||
// Possible `data.type` values include 'ledgerClosed',
|
||||
// 'transaction', 'path_find', and many others.
|
||||
if (data.type === 'ledgerClosed') {
|
||||
this._updateLedgerVersions(data)
|
||||
this._updateFees(data)
|
||||
}
|
||||
return [data.type, data]
|
||||
}
|
||||
|
||||
_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 +113,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 +130,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 +173,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 +192,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 +206,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
|
||||
@@ -220,14 +241,14 @@ class Connection extends EventEmitter {
|
||||
_onOpenError(reject, error) {
|
||||
this._onOpenErrorBound = null
|
||||
this._unbindOnUnxpectedClose()
|
||||
reject(new NotConnectedError(error && error.message))
|
||||
reject(new NotConnectedError(error.message, error))
|
||||
}
|
||||
|
||||
_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 +358,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 +370,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))
|
||||
reject(new DisconnectedError(error.message, error))
|
||||
} else {
|
||||
resolve(result)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
request(request, timeout) {
|
||||
request(request, timeout?: number): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this._shouldBeConnected) {
|
||||
reject(new NotConnectedError())
|
||||
@@ -401,7 +422,7 @@ class Connection extends EventEmitter {
|
||||
function onDisconnect() {
|
||||
clearTimeout(timer)
|
||||
self.removeAllListeners(eventName)
|
||||
reject(new DisconnectedError())
|
||||
reject(new DisconnectedError('websocket was closed'))
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
@@ -424,12 +445,12 @@ class Connection extends EventEmitter {
|
||||
|
||||
this.once(eventName, response => {
|
||||
if (response.status === 'error') {
|
||||
_reject(new RippledError(response.error))
|
||||
_reject(new RippledError(response.error, response))
|
||||
} else if (response.status === 'success') {
|
||||
_resolve(response.result)
|
||||
} else {
|
||||
_reject(new ResponseFormatError(
|
||||
'unrecognized status: ' + response.status))
|
||||
'unrecognized status: ' + response.status, response))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -446,4 +467,4 @@ class Connection extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Connection
|
||||
export default Connection
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -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
23
src/common/index.ts
Normal 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'
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -12,6 +12,10 @@
|
||||
"minimum": 1,
|
||||
"description": "Factor to multiply estimated fee by to provide a cushion in case the required fee rises during submission of a transaction. Defaults to `1.2`."
|
||||
},
|
||||
"maxFeeXRP": {
|
||||
"type": "string",
|
||||
"description": "Maximum fee to use with transactions, in XRP. Must be a string-encoded number. Defaults to `'2'`."
|
||||
},
|
||||
"server": {
|
||||
"type": "string",
|
||||
"description": "URI for rippled websocket port to connect to. Must start with `wss://` or `ws://`.",
|
||||
|
||||
56
src/common/schemas/input/get-account-objects.json
Normal file
56
src/common/schemas/input/get-account-objects.json
Normal 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
|
||||
}
|
||||
13
src/common/schemas/input/get-fee.json
Normal file
13
src/common/schemas/input/get-fee.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getFeeParameters",
|
||||
"description": "Parameters for getFee",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cushion": {
|
||||
"type": "number",
|
||||
"description": "The fee is the product of the base fee, the `load_factor`, and this cushion. Default is provided by the `RippleAPI` constructor's `feeCushion`."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
18
src/common/schemas/input/prepare-check-cancel.json
Normal file
18
src/common/schemas/input/prepare-check-cancel.json
Normal 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"]
|
||||
}
|
||||
18
src/common/schemas/input/prepare-check-cash.json
Normal file
18
src/common/schemas/input/prepare-check-cash.json
Normal 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"]
|
||||
}
|
||||
18
src/common/schemas/input/prepare-check-create.json
Normal file
18
src/common/schemas/input/prepare-check-create.json
Normal 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"]
|
||||
}
|
||||
@@ -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"]}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
"$ref": "value"
|
||||
},
|
||||
"currency": {
|
||||
"description": "The three-character code or hexadecimal string used to denote currencies",
|
||||
"description": "The three-character code or hexadecimal string used to denote currencies, or \"drops\" for the smallest unit of XRP.",
|
||||
"$ref": "currency"
|
||||
},
|
||||
"counterparty": {
|
||||
"description": "The Ripple address of the account that owes or is owed the funds (omitted if `currency` is \"XRP\")",
|
||||
"description": "The Ripple address of the account that owes or is owed the funds (omitted if `currency` is \"XRP\" or \"drops\")",
|
||||
"$ref": "address"
|
||||
}
|
||||
},
|
||||
@@ -24,7 +24,7 @@
|
||||
"properties": {
|
||||
"currency": {
|
||||
"not": {
|
||||
"enum": ["XRP"]
|
||||
"enum": ["XRP", "drops"]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -33,7 +33,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"currency": {
|
||||
"enum": ["XRP"]
|
||||
"enum": ["XRP", "drops"]
|
||||
}
|
||||
},
|
||||
"not": {
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
"description": "The three-character code or hexadecimal string used to denote currencies",
|
||||
"type": "string",
|
||||
"link": "currency",
|
||||
"pattern": "^([a-zA-Z0-9<>(){}[\\]|?!@#$%^&*]{3}|[A-F0-9]{40})$"
|
||||
"pattern": "^([a-zA-Z0-9<>(){}[\\]|?!@#$%^&*]{3}|[A-F0-9]{40}|drops)$"
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"$ref": "value"
|
||||
},
|
||||
"maxFee": {
|
||||
"description": "The maximum fee to pay for the transaction. See [Transaction Fees](#transaction-fees) for more information.",
|
||||
"description": "Deprecated: Use `maxFeeXRP` in the RippleAPI constructor instead. The maximum fee to pay for this transaction. If this exceeds `maxFeeXRP`, `maxFeeXRP` will be used instead. See [Transaction Fees](#transaction-fees) for more information.",
|
||||
"$ref": "value"
|
||||
},
|
||||
"maxLedgerVersion": {
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
7
src/common/schemas/objects/private-key.json
Normal file
7
src/common/schemas/objects/private-key.json
Normal 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]+$"
|
||||
}
|
||||
@@ -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 account’s 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 account’s 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 account’s 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 account’s 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 account’s 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 account’s 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 account’s 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.",
|
||||
@@ -95,9 +93,17 @@
|
||||
"minItems": 1,
|
||||
"maxItems": 8
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["threshold", "weights"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"memos": {"$ref": "memos"}
|
||||
"transferRate": {
|
||||
"description": " The fee to charge when users transfer this account’s 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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
48
src/common/schemas/output/get-account-objects.json
Normal file
48
src/common/schemas/output/get-account-objects.json
Normal 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
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -2,5 +2,7 @@
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getTransactions",
|
||||
"type": "array",
|
||||
"items": {"$ref": "getTransaction"}
|
||||
"items": {
|
||||
"$ref": "getTransaction"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"description": "Key is the ripple address; value is an array of signed amounts representing changes of balances for that address.",
|
||||
"description": "Key is the XRP Ledger address; value is an array of signed amounts representing changes of balances for that address.",
|
||||
"items": {"$ref": "balance"}
|
||||
}
|
||||
},
|
||||
@@ -33,10 +33,14 @@
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"description": "Key is the maker's ripple address; value is an array of changes",
|
||||
"description": "Key is the maker's XRP Ledger address; value is an array of changes",
|
||||
"items": {"$ref": "orderChange"}
|
||||
}
|
||||
},
|
||||
"channelChanges": {
|
||||
"type": "object",
|
||||
"description": "Properties reflecting the details of the payment channel."
|
||||
},
|
||||
"ledgerVersion": {
|
||||
"$ref": "ledgerVersion",
|
||||
"description": "The ledger version that the transaction was validated in."
|
||||
|
||||
14
src/common/schemas/specifications/check-cancel.json
Normal file
14
src/common/schemas/specifications/check-cancel.json
Normal 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
|
||||
}
|
||||
26
src/common/schemas/specifications/check-cash.json
Normal file
26
src/common/schemas/specifications/check-cash.json
Normal 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
|
||||
}
|
||||
31
src/common/schemas/specifications/check-create.json
Normal file
31
src/common/schemas/specifications/check-create.json
Normal 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
|
||||
}
|
||||
@@ -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"],
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"],
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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 BigNumber from 'bignumber.js'
|
||||
import {RippleAPI} from '../index'
|
||||
|
||||
export type GetServerInfoResponse = {
|
||||
buildVersion: string,
|
||||
@@ -39,8 +39,8 @@ function renameKeys(object, mapping) {
|
||||
})
|
||||
}
|
||||
|
||||
function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
|
||||
return connection.request({command: 'server_info'}).then(response => {
|
||||
function getServerInfo(this: RippleAPI): Promise<GetServerInfoResponse> {
|
||||
return this.request('server_info').then(response => {
|
||||
const info = convertKeysFromSnakeCaseToCamelCase(response.info)
|
||||
renameKeys(info, {hostid: 'hostID'})
|
||||
if (info.validatedLedger) {
|
||||
@@ -61,19 +61,30 @@ function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
|
||||
})
|
||||
}
|
||||
|
||||
function computeFeeFromServerInfo(cushion: number,
|
||||
serverInfo: GetServerInfoResponse
|
||||
): number {
|
||||
return (Number(serverInfo.validatedLedger.baseFeeXRP)
|
||||
* Number(serverInfo.loadFactor) * cushion).toString()
|
||||
// This is a public API that can be called directly.
|
||||
// This is not used by the `prepare*` methods. See `src/transaction/utils.ts`
|
||||
async function getFee(
|
||||
this: RippleAPI,
|
||||
cushion?: number
|
||||
): Promise<string> {
|
||||
if (cushion === undefined) {
|
||||
cushion = this._feeCushion
|
||||
}
|
||||
if (cushion === undefined) {
|
||||
cushion = 1.2
|
||||
}
|
||||
|
||||
const serverInfo = (await this.request('server_info')).info
|
||||
const baseFeeXrp = new BigNumber(serverInfo.validated_ledger.base_fee_xrp)
|
||||
let fee = baseFeeXrp.times(serverInfo.load_factor).times(cushion)
|
||||
|
||||
// Cap fee to `this._maxFeeXRP`
|
||||
fee = BigNumber.min(fee, this._maxFeeXRP)
|
||||
// Round fee to 6 decimal places
|
||||
return (new BigNumber(fee.toFixed(6))).toString(10)
|
||||
}
|
||||
|
||||
function getFee(connection: Connection, cushion: number) {
|
||||
return getServerInfo(connection).then(
|
||||
_.partial(computeFeeFromServerInfo, cushion))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getServerInfo,
|
||||
getFee
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
23
src/common/types/commands/account_info.ts
Normal file
23
src/common/types/commands/account_info.ts
Normal 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
|
||||
}
|
||||
19
src/common/types/commands/account_lines.ts
Normal file
19
src/common/types/commands/account_lines.ts
Normal 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,
|
||||
}
|
||||
72
src/common/types/commands/account_objects.ts
Normal file
72
src/common/types/commands/account_objects.ts
Normal 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
|
||||
}
|
||||
27
src/common/types/commands/account_offers.ts
Normal file
27
src/common/types/commands/account_offers.ts
Normal 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
|
||||
}
|
||||
30
src/common/types/commands/book_offers.ts
Normal file
30
src/common/types/commands/book_offers.ts
Normal 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
|
||||
}
|
||||
19
src/common/types/commands/gateway_balances.ts
Normal file
19
src/common/types/commands/gateway_balances.ts
Normal 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
|
||||
}
|
||||
9
src/common/types/commands/index.ts
Normal file
9
src/common/types/commands/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
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'
|
||||
export * from './server_info'
|
||||
20
src/common/types/commands/ledger.ts
Normal file
20
src/common/types/commands/ledger.ts
Normal 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
|
||||
}
|
||||
31
src/common/types/commands/ledger_entry.ts
Normal file
31
src/common/types/commands/ledger_entry.ts
Normal 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,
|
||||
}
|
||||
51
src/common/types/commands/server_info.ts
Normal file
51
src/common/types/commands/server_info.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
export interface ServerInfoRequest {
|
||||
id?: number
|
||||
}
|
||||
|
||||
export interface ServerInfoResponse {
|
||||
info: {
|
||||
amendment_blocked?: boolean,
|
||||
build_version: string,
|
||||
closed_ledger?: LedgerInfo,
|
||||
complete_ledgers: string,
|
||||
hostid: string,
|
||||
io_latency_ms: number,
|
||||
last_close: {
|
||||
converge_time_s: number,
|
||||
proposers: number
|
||||
},
|
||||
load?: {
|
||||
job_types: {
|
||||
job_type: string,
|
||||
per_second: number,
|
||||
in_progress: number
|
||||
}[],
|
||||
threads: number
|
||||
},
|
||||
load_factor: number,
|
||||
load_factor_local?: number,
|
||||
load_factor_net?: number,
|
||||
load_factor_cluster?: number,
|
||||
load_factor_fee_escalation?: number,
|
||||
load_factor_fee_queue?: number,
|
||||
load_factor_server?: number,
|
||||
peers: number,
|
||||
pubkey_node: string,
|
||||
pubkey_validator: string,
|
||||
server_state: string,
|
||||
state_accounting: any,
|
||||
uptime: number,
|
||||
validated_ledger?: LedgerInfo,
|
||||
validation_quorum: number,
|
||||
validator_list_expires: string
|
||||
},
|
||||
}
|
||||
|
||||
export interface LedgerInfo {
|
||||
age: number,
|
||||
base_fee_xrp: number,
|
||||
hash: string,
|
||||
reserve_base_xrp: number,
|
||||
reserve_inc_xrp: number,
|
||||
seq: number,
|
||||
}
|
||||
19
src/common/types/objects/adjustments.ts
Normal file
19
src/common/types/objects/adjustments.ts
Normal 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
|
||||
}
|
||||
28
src/common/types/objects/amounts.ts
Normal file
28
src/common/types/objects/amounts.ts
Normal 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
|
||||
}
|
||||
11
src/common/types/objects/index.ts
Normal file
11
src/common/types/objects/index.ts
Normal 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'
|
||||
22
src/common/types/objects/ledger.ts
Normal file
22
src/common/types/objects/ledger.ts
Normal 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[]
|
||||
}
|
||||
83
src/common/types/objects/ledger_entries.ts
Normal file
83
src/common/types/objects/ledger_entries.ts
Normal 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
|
||||
6
src/common/types/objects/memos.ts
Normal file
6
src/common/types/objects/memos.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
export type Memo = {
|
||||
type?: string,
|
||||
format?: string,
|
||||
data?: string
|
||||
}
|
||||
17
src/common/types/objects/orders.ts
Normal file
17
src/common/types/objects/orders.ts
Normal 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
|
||||
}
|
||||
16
src/common/types/objects/queue_data.ts
Normal file
16
src/common/types/objects/queue_data.ts
Normal 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[]
|
||||
}
|
||||
30
src/common/types/objects/settings.ts
Normal file
30
src/common/types/objects/settings.ts
Normal 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[]
|
||||
}
|
||||
4
src/common/types/objects/signers.ts
Normal file
4
src/common/types/objects/signers.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface SignerEntry {
|
||||
Account: string,
|
||||
SignerWeight: number
|
||||
}
|
||||
22
src/common/types/objects/transactions.ts
Normal file
22
src/common/types/objects/transactions.ts
Normal 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,
|
||||
}
|
||||
42
src/common/types/objects/trustlines.ts
Normal file
42
src/common/types/objects/trustlines.ts
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/* @flow */
|
||||
'use strict' // eslint-disable-line strict
|
||||
const _ = require('lodash')
|
||||
const BigNumber = require('bignumber.js')
|
||||
const {deriveKeypair} = require('ripple-keypairs')
|
||||
|
||||
import type {Amount, RippledAmount} from './types.js'
|
||||
|
||||
function isValidSecret(secret: string): boolean {
|
||||
try {
|
||||
deriveKeypair(secret)
|
||||
return true
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function dropsToXrp(drops: string): string {
|
||||
return (new BigNumber(drops)).dividedBy(1000000.0).toString()
|
||||
}
|
||||
|
||||
function xrpToDrops(xrp: string): string {
|
||||
return (new BigNumber(xrp)).times(1000000.0).floor().toString()
|
||||
}
|
||||
|
||||
function toRippledAmount(amount: Amount): RippledAmount {
|
||||
if (amount.currency === 'XRP') {
|
||||
return xrpToDrops(amount.value)
|
||||
}
|
||||
return {
|
||||
currency: amount.currency,
|
||||
issuer: amount.counterparty ? amount.counterparty :
|
||||
(amount.issuer ? amount.issuer : undefined),
|
||||
value: amount.value
|
||||
}
|
||||
}
|
||||
|
||||
function convertKeysFromSnakeCaseToCamelCase(obj: any): any {
|
||||
if (typeof obj === 'object') {
|
||||
let newKey
|
||||
return _.reduce(obj, (result, value, key) => {
|
||||
newKey = key
|
||||
// taking this out of function leads to error in PhantomJS
|
||||
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g
|
||||
if (FINDSNAKE.test(key)) {
|
||||
newKey = key.replace(FINDSNAKE, r => r[0] + r[2].toUpperCase())
|
||||
}
|
||||
result[newKey] = convertKeysFromSnakeCaseToCamelCase(value)
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
function removeUndefined(obj: Object): Object {
|
||||
return _.omitBy(obj, _.isUndefined)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} rpepoch (seconds since 1/1/2000 GMT)
|
||||
* @return {Number} ms since unix epoch
|
||||
*
|
||||
*/
|
||||
function rippleToUnixTimestamp(rpepoch: number): number {
|
||||
return (rpepoch + 0x386D4380) * 1000
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number|Date} timestamp (ms since unix epoch)
|
||||
* @return {Number} seconds since ripple epoch ( 1/1/2000 GMT)
|
||||
*/
|
||||
function unixToRippleTimestamp(timestamp: number): number {
|
||||
return Math.round(timestamp / 1000) - 0x386D4380
|
||||
}
|
||||
|
||||
function rippleTimeToISO8601(rippleTime: number): string {
|
||||
return new Date(rippleToUnixTimestamp(rippleTime)).toISOString()
|
||||
}
|
||||
|
||||
function iso8601ToRippleTime(iso8601: string): number {
|
||||
return unixToRippleTimestamp(Date.parse(iso8601))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
dropsToXrp,
|
||||
xrpToDrops,
|
||||
toRippledAmount,
|
||||
convertKeysFromSnakeCaseToCamelCase,
|
||||
removeUndefined,
|
||||
rippleTimeToISO8601,
|
||||
iso8601ToRippleTime,
|
||||
isValidSecret
|
||||
}
|
||||
160
src/common/utils.ts
Normal file
160
src/common/utils.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import * as _ from 'lodash'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import {deriveKeypair} from 'ripple-keypairs'
|
||||
import {Amount, RippledAmount} from './types/objects'
|
||||
import {ValidationError} from './errors'
|
||||
|
||||
function isValidSecret(secret: string): boolean {
|
||||
try {
|
||||
deriveKeypair(secret)
|
||||
return true
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function dropsToXrp(drops: string | BigNumber): string {
|
||||
if (typeof drops === 'string') {
|
||||
if (!drops.match(/^-?[0-9]*\.?[0-9]*$/)) {
|
||||
throw new ValidationError(`dropsToXrp: invalid value '${drops}',` +
|
||||
` should be a number matching (^-?[0-9]*\.?[0-9]*$).`)
|
||||
} else if (drops === '.') {
|
||||
throw new ValidationError(`dropsToXrp: invalid value '${drops}',` +
|
||||
` should be a BigNumber or string-encoded number.`)
|
||||
}
|
||||
}
|
||||
|
||||
// Converting to BigNumber and then back to string should remove any
|
||||
// decimal point followed by zeros, e.g. '1.00'.
|
||||
// Important: specify base 10 to avoid exponential notation, e.g. '1e-7'.
|
||||
drops = (new BigNumber(drops)).toString(10)
|
||||
|
||||
// drops are only whole units
|
||||
if (drops.includes('.')) {
|
||||
throw new ValidationError(`dropsToXrp: value '${drops}' has` +
|
||||
` too many decimal places.`)
|
||||
}
|
||||
|
||||
// This should never happen; the value has already been
|
||||
// validated above. This just ensures BigNumber did not do
|
||||
// something unexpected.
|
||||
if (!drops.match(/^-?[0-9]+$/)) {
|
||||
throw new ValidationError(`dropsToXrp: failed sanity check -` +
|
||||
` value '${drops}',` +
|
||||
` does not match (^-?[0-9]+$).`)
|
||||
}
|
||||
|
||||
return (new BigNumber(drops)).dividedBy(1000000.0).toString(10)
|
||||
}
|
||||
|
||||
function xrpToDrops(xrp: string | BigNumber): string {
|
||||
if (typeof xrp === 'string') {
|
||||
if (!xrp.match(/^-?[0-9]*\.?[0-9]*$/)) {
|
||||
throw new ValidationError(`xrpToDrops: invalid value '${xrp}',` +
|
||||
` should be a number matching (^-?[0-9]*\.?[0-9]*$).`)
|
||||
} else if (xrp === '.') {
|
||||
throw new ValidationError(`xrpToDrops: invalid value '${xrp}',` +
|
||||
` should be a BigNumber or string-encoded number.`)
|
||||
}
|
||||
}
|
||||
|
||||
// Important: specify base 10 to avoid exponential notation, e.g. '1e-7'.
|
||||
xrp = (new BigNumber(xrp)).toString(10)
|
||||
|
||||
// This should never happen; the value has already been
|
||||
// validated above. This just ensures BigNumber did not do
|
||||
// something unexpected.
|
||||
if (!xrp.match(/^-?[0-9.]+$/)) {
|
||||
throw new ValidationError(`xrpToDrops: failed sanity check -` +
|
||||
` value '${xrp}',` +
|
||||
` does not match (^-?[0-9.]+$).`)
|
||||
}
|
||||
|
||||
const components = xrp.split('.')
|
||||
if (components.length > 2) {
|
||||
throw new ValidationError(`xrpToDrops: failed sanity check -` +
|
||||
` value '${xrp}' has` +
|
||||
` too many decimal points.`)
|
||||
}
|
||||
|
||||
const fraction = components[1] || '0'
|
||||
if (fraction.length > 6) {
|
||||
throw new ValidationError(`xrpToDrops: value '${xrp}' has` +
|
||||
` too many decimal places.`)
|
||||
}
|
||||
|
||||
return (new BigNumber(xrp)).times(1000000.0).floor().toString(10)
|
||||
}
|
||||
|
||||
function toRippledAmount(amount: Amount): RippledAmount {
|
||||
if (amount.currency === 'XRP') {
|
||||
return xrpToDrops(amount.value)
|
||||
}
|
||||
if (amount.currency === 'drops') {
|
||||
return amount.value
|
||||
}
|
||||
return {
|
||||
currency: amount.currency,
|
||||
issuer: amount.counterparty ? amount.counterparty :
|
||||
(amount.issuer ? amount.issuer : undefined),
|
||||
value: amount.value
|
||||
}
|
||||
}
|
||||
|
||||
function convertKeysFromSnakeCaseToCamelCase(obj: any): any {
|
||||
if (typeof obj === 'object') {
|
||||
let newKey
|
||||
return _.reduce(obj, (result, value, key) => {
|
||||
newKey = key
|
||||
// taking this out of function leads to error in PhantomJS
|
||||
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g
|
||||
if (FINDSNAKE.test(key)) {
|
||||
newKey = key.replace(FINDSNAKE, r => r[0] + r[2].toUpperCase())
|
||||
}
|
||||
result[newKey] = convertKeysFromSnakeCaseToCamelCase(value)
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
function removeUndefined<T extends object>(obj: T): T {
|
||||
return _.omitBy(obj, _.isUndefined) as T
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} rpepoch (seconds since 1/1/2000 GMT)
|
||||
* @return {Number} ms since unix epoch
|
||||
*
|
||||
*/
|
||||
function rippleToUnixTimestamp(rpepoch: number): number {
|
||||
return (rpepoch + 0x386D4380) * 1000
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number|Date} timestamp (ms since unix epoch)
|
||||
* @return {Number} seconds since ripple epoch ( 1/1/2000 GMT)
|
||||
*/
|
||||
function unixToRippleTimestamp(timestamp: number): number {
|
||||
return Math.round(timestamp / 1000) - 0x386D4380
|
||||
}
|
||||
|
||||
function rippleTimeToISO8601(rippleTime: number): string {
|
||||
return new Date(rippleToUnixTimestamp(rippleTime)).toISOString()
|
||||
}
|
||||
|
||||
function iso8601ToRippleTime(iso8601: string): number {
|
||||
return unixToRippleTimestamp(Date.parse(iso8601))
|
||||
}
|
||||
|
||||
export {
|
||||
dropsToXrp,
|
||||
xrpToDrops,
|
||||
toRippledAmount,
|
||||
convertKeysFromSnakeCaseToCamelCase,
|
||||
removeUndefined,
|
||||
rippleTimeToISO8601,
|
||||
iso8601ToRippleTime,
|
||||
isValidSecret
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user