mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-14 01:25:48 +00:00
Compare commits
165 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de47263087 | ||
|
|
3b9679a673 | ||
|
|
f175966816 | ||
|
|
f1f5364d07 | ||
|
|
1b8b0c76ac | ||
|
|
1a8096ab18 | ||
|
|
f177771c67 | ||
|
|
081fcbfa32 | ||
|
|
0a5e4e2155 | ||
|
|
19eb88a00e | ||
|
|
c8f2967de0 | ||
|
|
b5564330f6 | ||
|
|
43ccb83f73 | ||
|
|
e2d92126c0 | ||
|
|
8c8eef45d5 | ||
|
|
a574e1158a | ||
|
|
af687a6aed | ||
|
|
016e82ab5d | ||
|
|
f300a412d7 | ||
|
|
75e2249cf3 | ||
|
|
1942bcb971 | ||
|
|
9393adf66f | ||
|
|
917aae9bf3 | ||
|
|
da36457d5c | ||
|
|
15a0ededc8 | ||
|
|
68d7864f93 | ||
|
|
1eddbf995f | ||
|
|
592385ac73 | ||
|
|
56d626f5b1 | ||
|
|
7a14300409 | ||
|
|
30fa8d658e | ||
|
|
c0101cb5e7 | ||
|
|
fd640cd65e | ||
|
|
11528eff92 | ||
|
|
3c9175459d | ||
|
|
bd4e0e01e2 | ||
|
|
cfcf6e473c | ||
|
|
50c6af3158 | ||
|
|
1d4310cd3a | ||
|
|
2191596e68 | ||
|
|
acf8f87a88 | ||
|
|
cfac146620 | ||
|
|
f3234ad853 | ||
|
|
b65fee3d85 | ||
|
|
82b294bc7d | ||
|
|
2a58573823 | ||
|
|
a96f71b7fd | ||
|
|
077f4a4c79 | ||
|
|
9a495467fb | ||
|
|
db2e62b219 | ||
|
|
2fafa493a2 | ||
|
|
7617c3005c | ||
|
|
5cdbb71277 | ||
|
|
f9339c36bf | ||
|
|
67dc57e9d0 | ||
|
|
757f3190d1 | ||
|
|
0d94a15ee7 | ||
|
|
7f1c80da1b | ||
|
|
f74e11bce0 | ||
|
|
d4c843e8e3 | ||
|
|
bae190b282 | ||
|
|
d2cbd70da8 | ||
|
|
5da78ce583 | ||
|
|
14bbe3e30b | ||
|
|
e52e2bbc68 | ||
|
|
b56752e45b | ||
|
|
4632f511ab | ||
|
|
e17b6f172d | ||
|
|
eb04e878ba | ||
|
|
c71febd116 | ||
|
|
69c1ccbb6b | ||
|
|
499b8c8d8b | ||
|
|
ea009f9a84 | ||
|
|
dc784d4567 | ||
|
|
9ffc8a2c0b | ||
|
|
5b20fe573e | ||
|
|
7e466bb80f | ||
|
|
1f8418b447 | ||
|
|
ccfc57fc62 | ||
|
|
1d31fccd72 | ||
|
|
9ac1a89e48 | ||
|
|
bfc0696324 | ||
|
|
e33e782f9e | ||
|
|
f2b591d1b2 | ||
|
|
fe9af5153d | ||
|
|
0dfdd0a601 | ||
|
|
4acc42e1b6 | ||
|
|
7c9a179865 | ||
|
|
c6296a4918 | ||
|
|
cc399f1164 | ||
|
|
e4ffb96646 | ||
|
|
8d34428dac | ||
|
|
353637a0c0 | ||
|
|
00713d8ec1 | ||
|
|
d949881e9f | ||
|
|
5075441a69 | ||
|
|
94a852cb8b | ||
|
|
06f847c2d0 | ||
|
|
0c2f9d0e62 | ||
|
|
11ed6b124f | ||
|
|
8767fc0068 | ||
|
|
66b07623b0 | ||
|
|
4f3635eef0 | ||
|
|
f638833759 | ||
|
|
ab9d1936d9 | ||
|
|
0fefb2bd2c | ||
|
|
6740eee495 | ||
|
|
aa6020e00d | ||
|
|
7bfe4a6cd8 | ||
|
|
aa467681e4 | ||
|
|
6b8cd6151d | ||
|
|
0d6aaee12a | ||
|
|
dc03c6e0ac | ||
|
|
0f4d957d14 | ||
|
|
71a13224a1 | ||
|
|
8097ed60ba | ||
|
|
408bb74214 | ||
|
|
9433b43873 | ||
|
|
896bf48c79 | ||
|
|
3dd21a7e11 | ||
|
|
ed79a04018 | ||
|
|
ebfe20defb | ||
|
|
28b148348d | ||
|
|
fe099f2c8b | ||
|
|
107c8c9f0f | ||
|
|
39e818b3e5 | ||
|
|
588ffa3d5c | ||
|
|
691e4dd114 | ||
|
|
55bc42725f | ||
|
|
cce55b9361 | ||
|
|
c23c6e4fc9 | ||
|
|
afdd60efe8 | ||
|
|
8f6ea573ff | ||
|
|
3271b544ef | ||
|
|
6e83130754 | ||
|
|
f6ebe32519 | ||
|
|
3caed3c761 | ||
|
|
ce1c55427a | ||
|
|
9cd72595f0 | ||
|
|
ad1d3e135f | ||
|
|
76866ab901 | ||
|
|
20b647dfbf | ||
|
|
99d08065e4 | ||
|
|
261fba3d21 | ||
|
|
e1d9de7b1f | ||
|
|
391b2f3622 | ||
|
|
86ff315ef2 | ||
|
|
8d8a850864 | ||
|
|
7bf2da6014 | ||
|
|
7eae3ce709 | ||
|
|
5f5e48e414 | ||
|
|
4f6a37f7b1 | ||
|
|
82613e7e8b | ||
|
|
588aa382a1 | ||
|
|
809d981987 | ||
|
|
cfc21fde8c | ||
|
|
5c06ef547b | ||
|
|
0990ad4a6f | ||
|
|
d8f967d2b8 | ||
|
|
fe1c3e7130 | ||
|
|
062148674c | ||
|
|
11320693fd | ||
|
|
7af7eaccb4 | ||
|
|
5d5cf868a2 | ||
|
|
ddf8fe5b1a |
4
.babelrc
Normal file
4
.babelrc
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": ["es2015", "stage-1"],
|
||||
"plugins": ["syntax-flow", "transform-flow-strip-types"]
|
||||
}
|
||||
@@ -4,6 +4,11 @@
|
||||
.*/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/
|
||||
|
||||
90
Gulpfile.js
90
Gulpfile.js
@@ -8,24 +8,49 @@ 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');
|
||||
|
||||
var pkg = require('./package.json');
|
||||
|
||||
var uglifyOptions = {
|
||||
mangle: {
|
||||
except: ['_', 'RippleError', 'RippledError', 'UnexpectedError',
|
||||
'LedgerVersionError', 'ConnectionError', 'NotConnectedError',
|
||||
'DisconnectedError', 'TimeoutError', 'ResponseFormatError',
|
||||
'ValidationError', 'NotFoundError', 'MissingLedgerHistoryError',
|
||||
'PendingLedgerVersionError'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
function webpackConfig(extension, overrides) {
|
||||
overrides = overrides || {};
|
||||
var defaults = {
|
||||
cache: true,
|
||||
externals: [{
|
||||
'lodash': '_'
|
||||
}],
|
||||
entry: './src/index.js',
|
||||
output: {
|
||||
library: 'ripple',
|
||||
path: './build/',
|
||||
filename: ['ripple-', extension].join(pkg.version)
|
||||
},
|
||||
plugins: [
|
||||
new webpack.NormalModuleReplacementPlugin(/^ws$/, './wswrapper'),
|
||||
new webpack.NormalModuleReplacementPlugin(/^\.\/wallet$/, './wallet-web'),
|
||||
new webpack.NormalModuleReplacementPlugin(/^.*setup-api$/,
|
||||
'./setup-api-web')
|
||||
],
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /jayson/,
|
||||
loader: 'null'
|
||||
}, {
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader?optional=runtime'
|
||||
exclude: [/node_modules/],
|
||||
loader: 'babel-loader'
|
||||
}, {
|
||||
test: /\.json/,
|
||||
loader: 'json-loader'
|
||||
@@ -35,15 +60,70 @@ function webpackConfig(extension, overrides) {
|
||||
return _.assign({}, defaults, overrides);
|
||||
}
|
||||
|
||||
function webpackConfigForWebTest(testFileName, path) {
|
||||
var match = testFileName.match(/\/?([^\/]*)-test.js$/);
|
||||
if (!match) {
|
||||
assert(false, 'wrong filename:' + testFileName);
|
||||
}
|
||||
var configOverrides = {
|
||||
externals: [{
|
||||
'lodash': '_',
|
||||
'ripple-api': 'ripple',
|
||||
'net': 'null'
|
||||
}],
|
||||
entry: testFileName,
|
||||
output: {
|
||||
library: match[1].replace(/-/g, '_'),
|
||||
path: './test-compiled-for-web/' + (path ? path : ''),
|
||||
filename: match[1] + '-test.js'
|
||||
}
|
||||
};
|
||||
return webpackConfig('.js', configOverrides);
|
||||
}
|
||||
|
||||
gulp.task('build-tests', function(callback) {
|
||||
var times = 0;
|
||||
function done() {
|
||||
if (++times >= 5) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
webpack(webpackConfigForWebTest('./test/rangeset-test.js'), done);
|
||||
webpack(webpackConfigForWebTest('./test/connection-test.js'), done);
|
||||
webpack(webpackConfigForWebTest('./test/api-test.js'), done);
|
||||
webpack(webpackConfigForWebTest('./test/broadcast-api-test.js'), done);
|
||||
webpack(webpackConfigForWebTest('./test/integration/integration-test.js',
|
||||
'integration/'), done);
|
||||
});
|
||||
|
||||
function createLink(from, to) {
|
||||
if (fs.existsSync(to)) {
|
||||
fs.unlinkSync(to);
|
||||
}
|
||||
fs.linkSync(from, to);
|
||||
}
|
||||
|
||||
function createBuildLink(callback) {
|
||||
return function(err, res) {
|
||||
createLink('./build/ripple-' + pkg.version + '.js',
|
||||
'./build/ripple-latest.js');
|
||||
callback(err, res);
|
||||
};
|
||||
}
|
||||
|
||||
gulp.task('build', function(callback) {
|
||||
webpack(webpackConfig('.js'), callback);
|
||||
webpack(webpackConfig('.js'), createBuildLink(callback));
|
||||
});
|
||||
|
||||
gulp.task('build-min', ['build'], function() {
|
||||
return gulp.src(['./build/ripple-', '.js'].join(pkg.version))
|
||||
.pipe(uglify())
|
||||
.pipe(uglify(uglifyOptions))
|
||||
.pipe(rename(['ripple-', '-min.js'].join(pkg.version)))
|
||||
.pipe(gulp.dest('./build/'));
|
||||
.pipe(gulp.dest('./build/'))
|
||||
.on('end', function() {
|
||||
createLink('./build/ripple-' + pkg.version + '-min.js',
|
||||
'./build/ripple-latest-min.js');
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('build-debug', function(callback) {
|
||||
|
||||
41
HISTORY.md
41
HISTORY.md
@@ -1,3 +1,44 @@
|
||||
##0.16.5
|
||||
**Changes**
|
||||
+ [Filter insufficient source funds paths from pathfind results](https://github.com/ripple/ripple-lib/pull/688)
|
||||
|
||||
##0.16.4
|
||||
**Changes**
|
||||
+ [Update ws to 1.0.1](https://github.com/ripple/ripple-lib/pull/682)
|
||||
|
||||
##0.16.2
|
||||
**Changes**
|
||||
+ [Bump ripple-binary-codec dependency version to 0.1.1 to fix issue with computeLedgerHash for transactions with DeliverMin]
|
||||
|
||||
##0.16.1
|
||||
**Changes**
|
||||
+ [FIX: Use assert not assert-diff](https://github.com/ripple/ripple-lib/commit/f6ebe325193e7208c5ee8d8e84a7504714f0009e)
|
||||
|
||||
##0.16.0
|
||||
**Breaking Changes**
|
||||
+ [Fix types of XRP values in getServerInfo response](https://github.com/ripple/ripple-lib/commit/99d08065e4bda3dda6ae1f183adbd11abc70a9b7)
|
||||
+ [Change error event format and fix crash due to error event on webscocket](https://github.com/ripple/ripple-lib/commit/9cd72595f0efc062d77b9d625695d6030c524cc6)
|
||||
|
||||
**Changes**
|
||||
+ [Fix generateAddress docs and add error event listener to boilerplate](https://github.com/ripple/ripple-lib/commit/809d981987a2890fac3a73a40a05c598b9040334)
|
||||
+ [Allow setting maxLedgerVersion to null to specify no maximum](https://github.com/ripple/ripple-lib/commit/82613e7e8b360d1ae1552eab4559ab4763c06d7e)
|
||||
+ [Add support for client certificates](https://github.com/ripple/ripple-lib/commit/5f5e48e4140345d166b8c1a3ee0847b0d9e2d893)
|
||||
+ [getFee returns a string not float](https://github.com/ripple/ripple-lib/commit/7bf2da6014c87e164542e69356efeaabb575a157)
|
||||
+ [Fix parsing of quality for getTrustlines](https://github.com/ripple/ripple-lib/commit/86ff315ef2a39dfdc2ce97e0e1c4aa73f04e363b)
|
||||
+ [Fix DeliverMin value when specifying minAmount](Fix DeliverMin value when specifying minAmount)
|
||||
+ [http server example](https://github.com/ripple/ripple-lib/commit/76866ab901ea46a2dd73181605e0f7f4220043d4)
|
||||
|
||||
|
||||
##0.15.2
|
||||
**Changes**
|
||||
+ [Fix support for proxy credentials in proxy URL and fix error when there are more than 10 outstanding requests](https://github.com/ripple/ripple-lib/commit/0990ad4a6f1d59ca9d2cb859b4e2d71693f3fc4b)
|
||||
|
||||
##0.15.1
|
||||
**Changes**
|
||||
+ [Fix babel-polyfill require](https://github.com/ripple/ripple-lib/commit/062148674c3b1293ab82c28e25615ddd530339fa)
|
||||
+ [Fix samples](https://github.com/ripple/ripple-lib/commit/5d5cf868a2ddb1b1cd40e4a4f0a782d0066c2055)
|
||||
+ [add unit tests for RippleAPIBroadcast](https://github.com/ripple/ripple-lib/commit/ddf8fe5b1a9c750490dca98fb9ffaaf8017f87e0)
|
||||
|
||||
##0.15.0
|
||||
**Breaking Changes**
|
||||
+ ["servers" parameter changed to single "server"](https://github.com/ripple/ripple-lib/commit/7061e9afe46f0682254d098adeff3dd7157521a1)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ripple-lib
|
||||
|
||||
A JavaScript API for interacting with Ripple in Node.js and the browser
|
||||
A JavaScript API for interacting with Ripple in Node.js
|
||||
|
||||
[](https://circleci.com/gh/ripple/ripple-lib/tree/develop) [](https://coveralls.io/r/ripple/ripple-lib?branch=develop)
|
||||
|
||||
@@ -8,7 +8,7 @@ A JavaScript API for interacting with Ripple in Node.js and the browser
|
||||
|
||||
###Features
|
||||
|
||||
+ Connect to a rippled server in JavaScript (Node.js or browser)
|
||||
+ Connect to a rippled server in Node.js
|
||||
+ Issue [rippled API](https://ripple.com/build/rippled-apis/) requests
|
||||
+ Listen to events on the Ripple network (transaction, ledger, etc.)
|
||||
+ Sign and submit transactions to the Ripple network
|
||||
@@ -30,7 +30,7 @@ Then see the [documentation](https://github.com/ripple/ripple-lib/blob/develop/d
|
||||
|
||||
##Generating Documentation
|
||||
|
||||
The continuous integration tests require that the documentation stays up-to-date. If you make changes the the JSON schemas, fixtures, or documentation sources, you must update the documentation by running `npm run docgen`.
|
||||
The continuous integration tests require that the documentation stays up-to-date. If you make changes to the JSON schemas, fixtures, or documentation sources, you must update the documentation by running `npm run docgen`.
|
||||
|
||||
##More Information
|
||||
|
||||
|
||||
12
circle.yml
12
circle.yml
@@ -1,7 +1,19 @@
|
||||
machine:
|
||||
node:
|
||||
version: 0.12.0
|
||||
hosts:
|
||||
testripple.circleci.com: 127.0.0.1
|
||||
dependencies:
|
||||
pre:
|
||||
- npm -g install npm@latest-2
|
||||
- wget https://s3-us-west-2.amazonaws.com/ripple-debs/rippled_0.30.1-b11-1.deb
|
||||
- sudo dpkg -i rippled_0.30.1-b11-1.deb
|
||||
test:
|
||||
pre:
|
||||
- rippled -a --start --conf "$HOME/$CIRCLE_PROJECT_REPONAME/test/integration/rippled.cfg":
|
||||
background: true
|
||||
override:
|
||||
- scripts/ci.sh "$CIRCLE_NODE_INDEX" "$CIRCLE_NODE_TOTAL":
|
||||
parallel: true
|
||||
post:
|
||||
- killall /usr/bin/rippled
|
||||
|
||||
783
docs/index.md
783
docs/index.md
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
const RippleAPI = require('../../src').RippleAPI; // require('ripple-lib')
|
||||
|
||||
const api = new RippleAPI({servers: ['wss://s1.ripple.com:443']});
|
||||
const api = new RippleAPI({server: 'wss://s1.ripple.com:443'});
|
||||
const address = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV';
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
38
docs/samples/cancelall.js
Normal file
38
docs/samples/cancelall.js
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
const RippleAPI = require('../../dist/npm').RippleAPI; // require('ripple-lib')
|
||||
|
||||
const address = 'rLDYrujdKUfVx28T9vRDAbyJ7G2WVXKo4K';
|
||||
const secret = '';
|
||||
|
||||
const api = new RippleAPI({server: 'wss://s1.ripple.com:443'});
|
||||
const instructions = {maxLedgerVersionOffset: 5};
|
||||
|
||||
function fail(message) {
|
||||
console.error(message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function cancelOrder(orderSequence) {
|
||||
console.log('Cancelling order: ' + orderSequence.toString());
|
||||
return api.prepareOrderCancellation(address, {orderSequence}, instructions)
|
||||
.then(prepared => {
|
||||
const signing = api.sign(prepared.txJSON, secret);
|
||||
return api.submit(signing.signedTransaction);
|
||||
});
|
||||
}
|
||||
|
||||
function cancelAllOrders(orderSequences) {
|
||||
if (orderSequences.length === 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const orderSequence = orderSequences.pop();
|
||||
return cancelOrder(orderSequence).then(() => cancelAllOrders(orderSequences));
|
||||
}
|
||||
|
||||
api.connect().then(() => {
|
||||
console.log('Connected...');
|
||||
return api.getOrders(address).then(orders => {
|
||||
const orderSequences = orders.map(order => order.properties.sequence);
|
||||
return cancelAllOrders(orderSequences);
|
||||
}).then(() => process.exit(0));
|
||||
}).catch(fail);
|
||||
@@ -4,13 +4,13 @@ const RippleAPI = require('../../src').RippleAPI; // require('ripple-lib')
|
||||
const address = 'INSERT ADDRESS HERE';
|
||||
const secret = 'INSERT SECRET HERE';
|
||||
|
||||
const api = new RippleAPI({servers: ['wss://s1.ripple.com:443']});
|
||||
const api = new RippleAPI({server: 'wss://s1.ripple.com:443'});
|
||||
const instructions = {maxLedgerVersionOffset: 5};
|
||||
|
||||
const payment = {
|
||||
source: {
|
||||
address: address,
|
||||
amount: {
|
||||
maxAmount: {
|
||||
value: '0.01',
|
||||
currency: 'XRP'
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ A *value* is a quantity of a currency represented as a decimal string. Be carefu
|
||||
|
||||
**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).
|
||||
|
||||
**Non-XRP values** have 15 decimal digits of precision, with a maximum value of `9999999999999999e80`. The smallest positive non-XRP value is `1e-81`.
|
||||
**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
|
||||
|
||||
@@ -8,6 +8,17 @@ const {RippleAPI} = require('ripple-lib');
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server hosted by Ripple, Inc.
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
api.on('connected', () => {
|
||||
console.log('connected');
|
||||
});
|
||||
api.on('disconnected', (code) => {
|
||||
// code - [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) sent by the server
|
||||
// will be 1000 if this was normal closure
|
||||
console.log('disconnected, code:', code);
|
||||
});
|
||||
api.connect().then(() => {
|
||||
/* insert code here */
|
||||
}).then(() => {
|
||||
@@ -27,6 +38,10 @@ All the code snippets in this documentation assume that you have surrounded them
|
||||
If you omit the "catch" section, errors may not be visible.
|
||||
</aside>
|
||||
|
||||
<aside class="notice">
|
||||
The "error" event is emitted whenever an error occurs that cannot be associated with a specific request. If the listener is not registered, an exception will be thrown whenever the event is emitted.
|
||||
</aside>
|
||||
|
||||
### Parameters
|
||||
|
||||
The RippleAPI constructor optionally takes one argument, an object with the following options:
|
||||
@@ -40,7 +55,7 @@ If you omit the `server` parameter, RippleAPI operates [offline](#offline-functi
|
||||
|
||||
1. Install [NodeJS](https://nodejs.org) and the Node Package Manager (npm). Most Linux distros have a package for NodeJS, but make sure you have version `0.12.0` or higher.
|
||||
2. Use npm to install [Babel](https://babeljs.io/) globally:
|
||||
`npm install -g babel`
|
||||
`npm install -g babel-cli`
|
||||
3. Use npm to install RippleAPI:
|
||||
`npm install ripple-lib`
|
||||
|
||||
|
||||
24
docs/src/combine.md.ejs
Normal file
24
docs/src/combine.md.ejs
Normal file
@@ -0,0 +1,24 @@
|
||||
## combine
|
||||
|
||||
`combine(signedTransactions: Array<string>): {signedTransaction: string, id: string}`
|
||||
|
||||
Combines signed transactions from multiple accounts for a multisignature transaction. The signed transaction must subsequently be [submitted](#submit).
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema("input/combine.json") %>
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns an object with the following structure:
|
||||
|
||||
<%- renderSchema("output/sign.json") %>
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const signedTransactions = <%- importFile('test/fixtures/requests/combine.json') %>;
|
||||
return api.combine(signedTransactions);
|
||||
```
|
||||
|
||||
<%- renderFixture("responses/combine.json") %>
|
||||
@@ -20,16 +20,26 @@ api.on('ledger', ledger => {
|
||||
|
||||
## error
|
||||
|
||||
This event is emitted when there is an error on the connection to the server.
|
||||
This event is emitted when there is an error on the connection to the server that cannot be associated to a specific request.
|
||||
|
||||
### Return Value
|
||||
|
||||
The first parameter is a string indicating the error type, which may be `badMessage` (meaning that rippled returned a malformed message), or one of the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors). The second parameter is a message explaining the error, or the message that caused the error in the case of `badMessage`.
|
||||
The first parameter is a string indicating the error type:
|
||||
* `badMessage` - rippled returned a malformed message
|
||||
* `websocket` - the websocket library emitted an error
|
||||
* one of the error codes found in the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors).
|
||||
|
||||
The second parameter is a message explaining the error.
|
||||
|
||||
The third parameter is:
|
||||
* the message that caused the error for `badMessage`
|
||||
* the error object emitted for `websocket`
|
||||
* the parsed response for rippled errors
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
api.on('error', (errorCode, errorMessage, data) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
```
|
||||
@@ -37,3 +47,35 @@ api.on('error', (errorCode, errorMessage) => {
|
||||
```
|
||||
tooBusy: The server is too busy to help you now.
|
||||
```
|
||||
|
||||
## connected
|
||||
|
||||
This event is emitted after connection successfully opened.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('connected', () => {
|
||||
console.log('Connection is open now.');
|
||||
});
|
||||
```
|
||||
|
||||
## disconnected
|
||||
|
||||
This event is emitted when connection is closed.
|
||||
|
||||
### Return Value
|
||||
|
||||
The only parameter is a number containing the [close code](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) send by the server.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.on('disconnected', (code) => {
|
||||
if (code !== 1000) {
|
||||
console.log('Connection is closed due to error.');
|
||||
} else {
|
||||
console.log('Connection is closed normally.');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
@@ -6,7 +6,7 @@ Generate a new Ripple address and corresponding secret.
|
||||
|
||||
### Parameters
|
||||
|
||||
This method has no parameters.
|
||||
<%- renderSchema('input/generate-address.json') %>
|
||||
|
||||
### Return Value
|
||||
|
||||
@@ -17,8 +17,7 @@ This method returns an object with the following structure:
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
return api.generateAddress()
|
||||
.then(result => {/* ... */});
|
||||
return api.generateAddress();
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/generate-address.json') %>
|
||||
|
||||
@@ -10,7 +10,7 @@ Returns aggregate balances by currency plus a breakdown of assets and obligation
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with an array of objects with the following structure:
|
||||
This method returns a promise that resolves with an object with the following structure:
|
||||
|
||||
<%- renderSchema('output/get-balance-sheet.json') %>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ This method has no parameters.
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with a 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 +19,5 @@ return api.getFee().then(fee => {/* ... */});
|
||||
```
|
||||
|
||||
```json
|
||||
0.012
|
||||
"0.012"
|
||||
```
|
||||
|
||||
26
docs/src/getPaymentChannel.md.ejs
Normal file
26
docs/src/getPaymentChannel.md.ejs
Normal file
@@ -0,0 +1,26 @@
|
||||
## getPaymentChannel
|
||||
|
||||
`getPaymentChannel(id: string): Promise<Object>`
|
||||
|
||||
Returns specified payment channel.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/get-payment-channel.json') %>
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with an object with the following structure:
|
||||
|
||||
<%- renderSchema('output/get-payment-channel.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const channelId =
|
||||
'E30E709CF009A1F26E0E5C48F7AA1BFB79393764F15FB108BDC6E06D3CBD8415';
|
||||
return api.getPaymentChannel(channelId).then(channel =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/get-payment-channel.json') %>
|
||||
@@ -21,17 +21,24 @@
|
||||
<% include getOrderbook.md.ejs %>
|
||||
<% include getSettings.md.ejs %>
|
||||
<% include getAccountInfo.md.ejs %>
|
||||
<% include getPaymentChannel.md.ejs %>
|
||||
<% include getLedger.md.ejs %>
|
||||
<% include preparePayment.md.ejs %>
|
||||
<% include prepareTrustline.md.ejs %>
|
||||
<% include prepareOrder.md.ejs %>
|
||||
<% include prepareOrderCancellation.md.ejs %>
|
||||
<% include prepareSettings.md.ejs %>
|
||||
<% include prepareSuspendedPaymentCreation.md.ejs %>
|
||||
<% include prepareSuspendedPaymentCancellation.md.ejs %>
|
||||
<% include prepareSuspendedPaymentExecution.md.ejs %>
|
||||
<% include prepareEscrowCreation.md.ejs %>
|
||||
<% include prepareEscrowCancellation.md.ejs %>
|
||||
<% include prepareEscrowExecution.md.ejs %>
|
||||
<% include preparePaymentChannelCreate.md.ejs %>
|
||||
<% include preparePaymentChannelClaim.md.ejs %>
|
||||
<% include preparePaymentChannelFund.md.ejs %>
|
||||
<% include sign.md.ejs %>
|
||||
<% include combine.md.ejs %>
|
||||
<% include submit.md.ejs %>
|
||||
<% include generateAddress.md.ejs %>
|
||||
<% include signPaymentChannelClaim.md.ejs %>
|
||||
<% include verifyPaymentChannelClaim.md.ejs %>
|
||||
<% include computeLedgerHash.md.ejs %>
|
||||
<% include events.md.ejs %>
|
||||
|
||||
@@ -18,9 +18,9 @@ Methods that depend on the state of the Ripple Consensus Ledger are unavailable
|
||||
* [prepareOrder](#prepareorder)
|
||||
* [prepareOrderCancellation](#prepareordercancellation)
|
||||
* [prepareSettings](#preparesettings)
|
||||
* [prepareSuspendedPaymentCreation](#preparesuspendedpaymentcreation)
|
||||
* [prepareSuspendedPaymentCancellation](#preparesuspendedpaymentcancellation)
|
||||
* [prepareSuspendedPaymentExecution](#preparesuspendedpaymentexecution)
|
||||
* [prepareEscrowCreation](#prepareescrowcreation)
|
||||
* [prepareEscrowCancellation](#prepareescrowcancellation)
|
||||
* [prepareEscrowExecution](#prepareescrowexecution)
|
||||
* [sign](#sign)
|
||||
* [generateAddress](#generateaddress)
|
||||
* [computeLedgerHash](#computeledgerhash)
|
||||
|
||||
30
docs/src/prepareEscrowCancellation.md.ejs
Normal file
30
docs/src/prepareEscrowCancellation.md.ejs
Normal file
@@ -0,0 +1,30 @@
|
||||
## prepareEscrowCancellation
|
||||
|
||||
`prepareEscrowCancellation(address: string, escrowCancellation: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare an escrow cancellation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-escrow-cancellation.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 escrowCancellation = <%- importFile('test/fixtures/requests/prepare-escrow-cancellation.json') %>;
|
||||
return api.prepareEscrowCancellation(address, escrowCancellation).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-escrow-cancellation.json') %>
|
||||
30
docs/src/prepareEscrowCreation.md.ejs
Normal file
30
docs/src/prepareEscrowCreation.md.ejs
Normal file
@@ -0,0 +1,30 @@
|
||||
## prepareEscrowCreation
|
||||
|
||||
`prepareEscrowCreation(address: string, escrowCreation: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare an escrow creation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-escrow-creation.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 escrowCreation = <%- importFile('test/fixtures/requests/prepare-escrow-creation.json') %>;
|
||||
return api.prepareEscrowCreation(address, escrowCreation).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-escrow-creation.json') %>
|
||||
30
docs/src/prepareEscrowExecution.md.ejs
Normal file
30
docs/src/prepareEscrowExecution.md.ejs
Normal file
@@ -0,0 +1,30 @@
|
||||
## prepareEscrowExecution
|
||||
|
||||
`prepareEscrowExecution(address: string, escrowExecution: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare an escrow execution transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-escrow-execution.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 escrowExecution = <%- importFile('test/fixtures/requests/prepare-escrow-execution.json') %>;
|
||||
return api.prepareEscrowExecution(address, escrowExecution).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-escrow-execution.json') %>
|
||||
@@ -23,7 +23,7 @@ All "prepare*" methods have the same return type.
|
||||
```javascript
|
||||
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
|
||||
const orderCancellation = {orderSequence: 123};
|
||||
return api.prepareOrderCancellation(address, sequence)
|
||||
return api.prepareOrderCancellation(address, orderCancellation)
|
||||
.then(prepared => {/* ... */});
|
||||
```
|
||||
|
||||
|
||||
30
docs/src/preparePaymentChannelClaim.md.ejs
Normal file
30
docs/src/preparePaymentChannelClaim.md.ejs
Normal file
@@ -0,0 +1,30 @@
|
||||
## preparePaymentChannelClaim
|
||||
|
||||
`preparePaymentChannelClaim(address: string, paymentChannelClaim: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare a payment channel claim transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-payment-channel-claim.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 paymentChannelClaim = <%- importFile('test/fixtures/requests/prepare-payment-channel-claim.json') %>;
|
||||
return api.preparePaymentChannelClaim(address, paymentChannelClaim).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-payment-channel-claim.json') %>
|
||||
30
docs/src/preparePaymentChannelCreate.md.ejs
Normal file
30
docs/src/preparePaymentChannelCreate.md.ejs
Normal file
@@ -0,0 +1,30 @@
|
||||
## preparePaymentChannelCreate
|
||||
|
||||
`preparePaymentChannelCreate(address: string, paymentChannelCreate: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare a payment channel creation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-payment-channel-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 paymentChannelCreate = <%- importFile('test/fixtures/requests/prepare-payment-channel-create.json') %>;
|
||||
return api.preparePaymentChannelCreate(address, paymentChannelCreate).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-payment-channel-create.json') %>
|
||||
30
docs/src/preparePaymentChannelFund.md.ejs
Normal file
30
docs/src/preparePaymentChannelFund.md.ejs
Normal file
@@ -0,0 +1,30 @@
|
||||
## preparePaymentChannelFund
|
||||
|
||||
`preparePaymentChannelFund(address: string, paymentChannelFund: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare a payment channel fund transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-payment-channel-fund.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 paymentChannelFund = <%- importFile('test/fixtures/requests/prepare-payment-channel-fund.json') %>;
|
||||
return api.preparePaymentChannelFund(address, paymentChannelFund).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-payment-channel-fund.json') %>
|
||||
@@ -1,32 +0,0 @@
|
||||
## prepareSuspendedPaymentCancellation
|
||||
|
||||
`prepareSuspendedPaymentCancellation(address: string, suspendedPaymentCancellation: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare a suspended payment cancellation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
**Caution:** Suspended Payments are currently available on the [Ripple Test Net](https://ripple.com/build/ripple-test-net/) only.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-suspended-payment-cancellation.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 suspendedPaymentCancellation = <%- importFile('test/fixtures/requests/prepare-suspended-payment-cancellation.json') %>;
|
||||
return api.prepareSuspendedPaymentCancellation(address, suspendedPaymentCancellation).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-suspended-payment-cancellation.json') %>
|
||||
@@ -1,32 +0,0 @@
|
||||
## prepareSuspendedPaymentCreation
|
||||
|
||||
`prepareSuspendedPaymentCreation(address: string, suspendedPaymentCreation: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare a suspended payment creation transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
**Caution:** Suspended Payments are currently available on the [Ripple Test Net](https://ripple.com/build/ripple-test-net/) only.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-suspended-payment-creation.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 suspendedPaymentCreation = <%- importFile('test/fixtures/requests/prepare-suspended-payment-creation.json') %>;
|
||||
return api.prepareSuspendedPaymentCreation(address, suspendedPaymentCreation).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-suspended-payment-creation.json') %>
|
||||
@@ -1,32 +0,0 @@
|
||||
## prepareSuspendedPaymentExecution
|
||||
|
||||
`prepareSuspendedPaymentExecution(address: string, suspendedPaymentExecution: Object, instructions: Object): Promise<Object>`
|
||||
|
||||
Prepare a suspended payment execution transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
**Caution:** Suspended Payments are currently available on the [Ripple Test Net](https://ripple.com/build/ripple-test-net/) only.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/prepare-suspended-payment-execution.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 suspendedPaymentExecution = <%- importFile('test/fixtures/requests/prepare-suspended-payment-execution.json') %>;
|
||||
return api.prepareSuspendedPaymentExecution(address, suspendedPaymentExecution).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/prepare-suspended-payment-execution.json') %>
|
||||
@@ -23,7 +23,7 @@ All "prepare*" methods have the same return type.
|
||||
```javascript
|
||||
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
|
||||
const trustline = <%- importFile('test/fixtures/requests/prepare-trustline.json') %>;
|
||||
return api.preparePayment(address, trustline).then(prepared =>
|
||||
return api.prepareTrustline(address, trustline).then(prepared =>
|
||||
{/* ... */});
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## sign
|
||||
|
||||
`sign(txJSON: string, secret: string): {signedTransaction: string, id: string}`
|
||||
`sign(txJSON: string, secret: string, options: Object): {signedTransaction: string, id: string}`
|
||||
|
||||
Sign a prepared transaction. The signed transaction must subsequently be [submitted](#submit).
|
||||
|
||||
|
||||
28
docs/src/signPaymentChannelClaim.md.ejs
Normal file
28
docs/src/signPaymentChannelClaim.md.ejs
Normal file
@@ -0,0 +1,28 @@
|
||||
## signPaymentChannelClaim
|
||||
|
||||
`signPaymentChannelClaim(channel: string, amount: string, privateKey: string): string`
|
||||
|
||||
Sign a payment channel claim. The signature can be submitted in a subsequent [PaymentChannelClaim](#preparePaymmentChannelClaim) transaction.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema("input/sign-payment-channel-claim.json") %>
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a signature string:
|
||||
|
||||
<%- renderSchema("output/sign-payment-channel-claim.json") %>
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const channel =
|
||||
'3E18C05AD40319B809520F1A136370C4075321B285217323396D6FD9EE1E9037';
|
||||
const amount = '.00001';
|
||||
const privateKey =
|
||||
'ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A';
|
||||
return api.signPaymentChannelClaim(channel, amount, privateKey);
|
||||
```
|
||||
|
||||
<%- renderFixture("responses/sign-payment-channel-claim.json") %>
|
||||
@@ -52,32 +52,62 @@ See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderFixture('requests/prepare-settings.json') %>
|
||||
|
||||
## Suspended Payment Creation
|
||||
## Escrow Creation
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/suspended-payment-creation.json') %>
|
||||
<%- renderSchema('specifications/escrow-creation.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-suspended-payment-creation.json') %>
|
||||
<%- renderFixture('requests/prepare-escrow-creation.json') %>
|
||||
|
||||
## Suspended Payment Cancellation
|
||||
## Escrow Cancellation
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/suspended-payment-cancellation.json') %>
|
||||
<%- renderSchema('specifications/escrow-cancellation.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-suspended-payment-cancellation.json') %>
|
||||
<%- renderFixture('requests/prepare-escrow-cancellation.json') %>
|
||||
|
||||
## Suspended Payment Execution
|
||||
## Escrow Execution
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/suspended-payment-execution.json') %>
|
||||
<%- renderSchema('specifications/escrow-execution.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-suspended-payment-execution.json') %>
|
||||
<%- renderFixture('requests/prepare-escrow-execution.json') %>
|
||||
|
||||
## Payment Channel Create
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/payment-channel-create.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-payment-channel-create.json') %>
|
||||
|
||||
## Payment Channel Fund
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/payment-channel-fund.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-payment-channel-fund.json') %>
|
||||
|
||||
## Payment Channel Claim
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/payment-channel-claim.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-payment-channel-claim.json') %>
|
||||
|
||||
@@ -11,11 +11,9 @@ Type | Description
|
||||
[orderCancellation](#order-cancellation) | An `orderCancellation` transaction cancels an order in the Ripple Consensus Ledger's order book.
|
||||
[trustline](#trustline) | A `trustline` transactions creates or modifies a trust line between two accounts.
|
||||
[settings](#settings) | A `settings` transaction modifies the settings of an account in the Ripple Consensus Ledger.
|
||||
[suspendedPaymentCreation](#suspended-payment-creation) | A `suspendedPaymentCreation` transaction creates a suspended payment on the ledger, which locks XRP until a cryptographic condition is met or it expires. It is like an escrow service where the Ripple network acts as the escrow agent.
|
||||
[suspendedPaymentCancellation](#suspended-payment-cancellation) | A `suspendedPaymentCancellation` transaction unlocks the funds in a suspended payment and sends them back to the creator of the suspended payment, but it will only work after the suspended payment expires.
|
||||
[suspendedPaymentExecution](#suspended-payment-execution) | A `suspendedPaymentExecution` transaction unlocks the funds in a suspended payment and sends them to the destination of the suspended payment, but it will only work if the cryptographic condition is provided.
|
||||
|
||||
The three "suspended payment" transaction types are not supported by the production Ripple peer-to-peer network at this time. They are available for testing purposes if you [configure RippleAPI](#boilerplate) to connect to the [Ripple Test Net](https://ripple.com/build/ripple-test-net/) instead.
|
||||
[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 Ripple network 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.
|
||||
|
||||
## Transaction Flow
|
||||
|
||||
@@ -27,10 +25,10 @@ Executing a transaction with `RippleAPI` requires the following four steps:
|
||||
* [prepareOrder](#prepareorder)
|
||||
* [prepareOrderCancellation](#prepareordercancellation)
|
||||
* [prepareSettings](#preparesettings)
|
||||
* [prepareSuspendedPaymentCreation](#preparesuspendedpaymentcreation)
|
||||
* [prepareSuspendedPaymentCancellation](#preparesuspendedpaymentcancellation)
|
||||
* [prepareSuspendedPaymentExecution](#preparesuspendedpaymentexecution)
|
||||
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.
|
||||
* [prepareEscrowCreation](#prepareescrowcreation)
|
||||
* [prepareEscrowCancellation](#prepareescrowcancellation)
|
||||
* [prepareEscrowExecution](#prepareescrowexecution)
|
||||
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.
|
||||
|
||||
|
||||
31
docs/src/verifyPaymentChannelClaim.md.ejs
Normal file
31
docs/src/verifyPaymentChannelClaim.md.ejs
Normal file
@@ -0,0 +1,31 @@
|
||||
## verifyPaymentChannelClaim
|
||||
|
||||
`verifyPaymentChannelClaim(channel: string, amount: string, signature: string, publicKey: string): boolean`
|
||||
|
||||
Verify a payment channel claim signature.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema("input/verify-payment-channel-claim.json") %>
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns `true` if the claim signature is valid.
|
||||
|
||||
<%- renderSchema("output/verify-payment-channel-claim.json") %>
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const channel =
|
||||
'3E18C05AD40319B809520F1A136370C4075321B285217323396D6FD9EE1E9037';
|
||||
const amount = '.00001';
|
||||
const signature = <%- importFile("test/fixtures/responses/sign-payment-channel-claim.json") %>;
|
||||
const publicKey =
|
||||
'02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8';
|
||||
return api.verifyPaymentChannelClaim(channel, amount, signature, publicKey);
|
||||
```
|
||||
|
||||
```json
|
||||
true
|
||||
```
|
||||
398
npm-shrinkwrap.json
generated
398
npm-shrinkwrap.json
generated
@@ -1,248 +1,170 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.15.0",
|
||||
"version": "0.17.6",
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "1.4.8",
|
||||
"from": "https://registry.npmjs.org/ajv/-/ajv-1.4.8.tgz",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-1.4.8.tgz",
|
||||
"dependencies": {
|
||||
"json-stable-stringify": {
|
||||
"version": "1.0.0",
|
||||
"from": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.0.tgz",
|
||||
"dependencies": {
|
||||
"jsonify": {
|
||||
"version": "0.0.0",
|
||||
"from": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"agent-base": {
|
||||
"version": "2.0.1",
|
||||
"from": "agent-base@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.0.1.tgz"
|
||||
},
|
||||
"babel-polyfill": {
|
||||
"version": "6.2.0",
|
||||
"from": "babel-polyfill@*",
|
||||
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.2.0.tgz",
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "1.2.6",
|
||||
"from": "core-js@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz"
|
||||
},
|
||||
"babel-regenerator-runtime": {
|
||||
"version": "6.2.0",
|
||||
"from": "babel-regenerator-runtime@>=6.2.0 <7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-regenerator-runtime/-/babel-regenerator-runtime-6.2.0.tgz"
|
||||
}
|
||||
}
|
||||
"version": "6.9.1",
|
||||
"from": "babel-polyfill@>=6.3.14 <7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.9.1.tgz"
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "5.8.29",
|
||||
"from": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.29.tgz",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.29.tgz",
|
||||
"version": "6.9.2",
|
||||
"from": "babel-runtime@>=6.3.19 <7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.9.2.tgz"
|
||||
},
|
||||
"base-x": {
|
||||
"version": "1.0.4",
|
||||
"from": "base-x@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-1.0.4.tgz"
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "2.3.0",
|
||||
"from": "bignumber.js@>=2.0.3 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.3.0.tgz"
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "4.11.6",
|
||||
"from": "bn.js@>=4.11.3 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz"
|
||||
},
|
||||
"brorand": {
|
||||
"version": "1.0.5",
|
||||
"from": "brorand@>=1.0.5 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz"
|
||||
},
|
||||
"cipher-base": {
|
||||
"version": "1.0.2",
|
||||
"from": "cipher-base@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz"
|
||||
},
|
||||
"core-js": {
|
||||
"version": "2.4.0",
|
||||
"from": "core-js@>=2.4.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.0.tgz"
|
||||
},
|
||||
"create-hash": {
|
||||
"version": "1.1.2",
|
||||
"from": "create-hash@>=1.1.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz"
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.2.0",
|
||||
"from": "debug@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz"
|
||||
},
|
||||
"decimal.js": {
|
||||
"version": "5.0.8",
|
||||
"from": "decimal.js@>=5.0.8 <6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-5.0.8.tgz"
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "5.2.1",
|
||||
"from": "elliptic@>=5.1.0 <6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-5.2.1.tgz",
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "1.2.3",
|
||||
"from": "https://registry.npmjs.org/core-js/-/core-js-1.2.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.3.tgz"
|
||||
"bn.js": {
|
||||
"version": "3.3.0",
|
||||
"from": "bn.js@>=3.1.1 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.3.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "2.1.0",
|
||||
"from": "bignumber.js@>=2.0.3 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.1.0.tgz"
|
||||
"extend": {
|
||||
"version": "3.0.0",
|
||||
"from": "extend@>=3.0.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
|
||||
},
|
||||
"hash.js": {
|
||||
"version": "1.0.3",
|
||||
"from": "hash.js@>=1.0.3 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz"
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "1.0.0",
|
||||
"from": "https-proxy-agent@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
|
||||
"dependencies": {
|
||||
"agent-base": {
|
||||
"version": "2.0.1",
|
||||
"from": "agent-base@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.0.1.tgz",
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "5.0.3",
|
||||
"from": "semver@>=5.0.1 <5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.2.0",
|
||||
"from": "debug@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "0.7.1",
|
||||
"from": "ms@0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.0",
|
||||
"from": "extend@>=3.0.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
|
||||
}
|
||||
}
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz"
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
},
|
||||
"jsonschema": {
|
||||
"version": "1.1.1",
|
||||
"from": "jsonschema@latest",
|
||||
"resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.1.1.tgz"
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.10.1",
|
||||
"from": "lodash@>=3.1.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz"
|
||||
},
|
||||
"ms": {
|
||||
"version": "0.7.1",
|
||||
"from": "ms@0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
|
||||
},
|
||||
"options": {
|
||||
"version": "0.0.6",
|
||||
"from": "options@>=0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz"
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.9.5",
|
||||
"from": "regenerator-runtime@>=0.9.5 <0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz"
|
||||
},
|
||||
"ripemd160": {
|
||||
"version": "1.0.1",
|
||||
"from": "ripemd160@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz"
|
||||
},
|
||||
"ripple-address-codec": {
|
||||
"version": "2.0.1",
|
||||
"from": "ripple-address-codec@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-2.0.1.tgz",
|
||||
"dependencies": {
|
||||
"hash.js": {
|
||||
"version": "1.0.3",
|
||||
"from": "hash.js@>=1.0.3 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz",
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-address-codec": {
|
||||
"version": "0.7.2",
|
||||
"from": "x-address-codec@>=0.7.0 <0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.7.2.tgz",
|
||||
"dependencies": {
|
||||
"base-x": {
|
||||
"version": "1.0.1",
|
||||
"from": "base-x@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-1.0.1.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-2.0.1.tgz"
|
||||
},
|
||||
"ripple-binary-codec": {
|
||||
"version": "0.1.0",
|
||||
"from": "ripple-binary-codec@0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-0.1.0.tgz",
|
||||
"version": "0.1.10",
|
||||
"from": "ripple-binary-codec@>=0.1.10 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-0.1.10.tgz",
|
||||
"dependencies": {
|
||||
"bn.js": {
|
||||
"version": "3.3.0",
|
||||
"from": "bn.js@>=3.2.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.3.0.tgz"
|
||||
},
|
||||
"create-hash": {
|
||||
"version": "1.1.2",
|
||||
"from": "create-hash@>=1.1.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
|
||||
"dependencies": {
|
||||
"cipher-base": {
|
||||
"version": "1.0.2",
|
||||
"from": "cipher-base@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz"
|
||||
},
|
||||
"ripemd160": {
|
||||
"version": "1.0.1",
|
||||
"from": "ripemd160@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz"
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.4.4",
|
||||
"from": "sha.js@>=2.3.6 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"decimal.js": {
|
||||
"version": "4.0.3",
|
||||
"from": "decimal.js@>=4.0.2 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-4.0.3.tgz"
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
"lodash": {
|
||||
"version": "4.17.4",
|
||||
"from": "lodash@>=4.12.0 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ripple-hashes": {
|
||||
"version": "0.1.0",
|
||||
"from": "ripple-hashes@0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-hashes/-/ripple-hashes-0.1.0.tgz",
|
||||
"dependencies": {
|
||||
"create-hash": {
|
||||
"version": "1.1.2",
|
||||
"from": "create-hash@>=1.1.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz",
|
||||
"dependencies": {
|
||||
"cipher-base": {
|
||||
"version": "1.0.2",
|
||||
"from": "cipher-base@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.2.tgz"
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
},
|
||||
"ripemd160": {
|
||||
"version": "1.0.1",
|
||||
"from": "ripemd160@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz"
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.4.4",
|
||||
"from": "sha.js@>=2.3.6 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.4.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"version": "0.3.0",
|
||||
"from": "ripple-hashes@>=0.3.0 <0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-hashes/-/ripple-hashes-0.3.0.tgz"
|
||||
},
|
||||
"ripple-keypairs": {
|
||||
"version": "0.10.0",
|
||||
"from": "ripple-keypairs@>=0.10.0 <0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-0.10.0.tgz",
|
||||
"dependencies": {
|
||||
"babel-runtime": {
|
||||
"version": "5.8.38",
|
||||
"from": "babel-runtime@>=5.8.20 <6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz"
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "3.3.0",
|
||||
"from": "bn.js@>=3.1.1 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.3.0.tgz"
|
||||
},
|
||||
"brorand": {
|
||||
"version": "1.0.5",
|
||||
"from": "brorand@>=1.0.5 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz"
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "5.2.1",
|
||||
"from": "elliptic@>=5.1.0 <6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-5.2.1.tgz",
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"hash.js": {
|
||||
"version": "1.0.3",
|
||||
"from": "hash.js@>=1.0.3 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz",
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
}
|
||||
}
|
||||
"core-js": {
|
||||
"version": "1.2.6",
|
||||
"from": "core-js@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -251,56 +173,30 @@
|
||||
"from": "ripple-lib-transactionparser@>=0.6.0 <0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-lib-transactionparser/-/ripple-lib-transactionparser-0.6.0.tgz"
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.0.3",
|
||||
"from": "semver@>=5.0.1 <5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz"
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.4.5",
|
||||
"from": "sha.js@>=2.3.6 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.5.tgz"
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.0.2",
|
||||
"from": "ultron@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
|
||||
},
|
||||
"ws": {
|
||||
"version": "1.1.1",
|
||||
"from": "ws@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-1.1.1.tgz"
|
||||
},
|
||||
"x-address-codec": {
|
||||
"version": "0.7.2",
|
||||
"from": "ws@>=0.7.1 <0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-0.7.2.tgz",
|
||||
"dependencies": {
|
||||
"options": {
|
||||
"version": "0.0.6",
|
||||
"from": "options@>=0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz"
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.0.2",
|
||||
"from": "ultron@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
|
||||
},
|
||||
"bufferutil": {
|
||||
"version": "1.1.0",
|
||||
"from": "bufferutil@>=1.1.0 <1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.1.0.tgz",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1",
|
||||
"from": "bindings@>=1.2.0 <1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.8.4",
|
||||
"from": "nan@>=1.8.0 <1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"version": "1.1.0",
|
||||
"from": "utf-8-validate@>=1.1.0 <1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-1.1.0.tgz",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1",
|
||||
"from": "bindings@>=1.2.0 <1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.8.4",
|
||||
"from": "nan@>=1.8.0 <1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"from": "x-address-codec@>=0.7.0 <0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/x-address-codec/-/x-address-codec-0.7.2.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
46
package.json
46
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.15.0",
|
||||
"version": "0.17.7",
|
||||
"license": "ISC",
|
||||
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
|
||||
"files": [
|
||||
@@ -15,40 +15,48 @@
|
||||
"test": "test"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": "^1.4.8",
|
||||
"babel-polyfill": "^6.2.0",
|
||||
"babel-runtime": "^5.5.4",
|
||||
"babel-polyfill": "^6.3.14",
|
||||
"babel-runtime": "^6.3.19",
|
||||
"bignumber.js": "^2.0.3",
|
||||
"https-proxy-agent": "^1.0.0",
|
||||
"jsonschema": "^1.1.1",
|
||||
"lodash": "^3.1.0",
|
||||
"ripple-address-codec": "^2.0.1",
|
||||
"ripple-binary-codec": "^0.1.0",
|
||||
"ripple-hashes": "^0.1.0",
|
||||
"ripple-binary-codec": "^0.1.10",
|
||||
"ripple-hashes": "^0.3.0",
|
||||
"ripple-keypairs": "^0.10.0",
|
||||
"ripple-lib-transactionparser": "^0.6.0",
|
||||
"ws": "^0.7.1"
|
||||
"ws": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"assert-diff": "^1.0.1",
|
||||
"babel": "^5.8.21",
|
||||
"babel-core": "^5.8.22",
|
||||
"babel-eslint": "^4.1.3",
|
||||
"babel-loader": "^5.3.2",
|
||||
"coveralls": "^2.10.0",
|
||||
"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.11.9",
|
||||
"doctoc": "^0.15.0",
|
||||
"ejs": "^2.3.4",
|
||||
"eslint": "^1.3.0",
|
||||
"eslint-plugin-flowtype": "^1.0.0",
|
||||
"eslint": "^2.9.0",
|
||||
"eventemitter2": "^0.4.14",
|
||||
"flow-bin": "^0.14",
|
||||
"gulp": "^3.8.10",
|
||||
"gulp-bump": "^0.1.13",
|
||||
"gulp-rename": "^1.2.0",
|
||||
"gulp-uglify": "^1.1.0",
|
||||
"istanbul": "^0.3.5",
|
||||
"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",
|
||||
"mocha": "^2.1.0",
|
||||
"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"
|
||||
},
|
||||
@@ -62,10 +70,12 @@
|
||||
"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": "istanbul test _mocha",
|
||||
"test": "babel-node ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha",
|
||||
"coveralls": "cat ./coverage/lcov.info | coveralls",
|
||||
"lint": "if ! [ -f eslintrc ]; then curl -o eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; echo 'parser: babel-eslint' >> eslintrc; fi; eslint -c eslintrc src/",
|
||||
"perf": "./scripts/perf_test.sh"
|
||||
"perf": "./scripts/perf_test.sh",
|
||||
"start": "babel-node scripts/http.js",
|
||||
"sauce": "babel-node scripts/sauce-runner.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
18
scripts/checkeol.sh
Executable file
18
scripts/checkeol.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
function checkEOL {
|
||||
local changedFiles=$(git --no-pager diff --name-only -M100% --diff-filter=AM --relative $(git merge-base FETCH_HEAD origin/HEAD) FETCH_HEAD)
|
||||
local result=0
|
||||
for name in $changedFiles; do
|
||||
grep -c -U -q $'\r' $name
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "windows eol found in $name" >&2
|
||||
result=1
|
||||
fi
|
||||
done
|
||||
if [ $result -eq 1 ]; then
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
checkEOL
|
||||
@@ -3,6 +3,10 @@
|
||||
NODE_INDEX="$1"
|
||||
TOTAL_NODES="$2"
|
||||
|
||||
function checkEOL {
|
||||
./scripts/checkeol.sh
|
||||
}
|
||||
|
||||
typecheck() {
|
||||
npm install -g flow-bin
|
||||
flow --version
|
||||
@@ -11,7 +15,7 @@ typecheck() {
|
||||
|
||||
lint() {
|
||||
echo "eslint $(node_modules/.bin/eslint --version)"
|
||||
npm list babel-eslint | grep babel-eslint
|
||||
npm list babel-eslint
|
||||
REPO_URL="https://raw.githubusercontent.com/ripple/javascript-style-guide"
|
||||
curl "$REPO_URL/es6/eslintrc" > ./eslintrc
|
||||
echo "parser: babel-eslint" >> ./eslintrc
|
||||
@@ -20,6 +24,7 @@ lint() {
|
||||
|
||||
unittest() {
|
||||
# test "src"
|
||||
mocha test --reporter mocha-junit-reporter --reporter-options mochaFile=$CIRCLE_TEST_REPORTS/test-results.xml
|
||||
npm test --coverage
|
||||
npm run coveralls
|
||||
|
||||
@@ -29,11 +34,33 @@ unittest() {
|
||||
mkdir -p test-compiled/node_modules
|
||||
ln -nfs ../../dist/npm test-compiled/node_modules/ripple-api
|
||||
mocha --opts test-compiled/mocha.opts test-compiled
|
||||
|
||||
#compile tests for browser testing
|
||||
#gulp build-min build-tests
|
||||
#node --harmony test-compiled/mocked-server.js > /dev/null &
|
||||
|
||||
#echo "Running tests in PhantomJS"
|
||||
#mocha-phantomjs test/localrunner.html
|
||||
#echo "Running tests using minified version in PhantomJS"
|
||||
#mocha-phantomjs test/localrunnermin.html
|
||||
|
||||
#echo "Running tests in SauceLabs"
|
||||
#http-server &
|
||||
#npm run sauce
|
||||
|
||||
#pkill -f mocked-server.js
|
||||
#pkill -f http-server
|
||||
rm -rf test-compiled
|
||||
}
|
||||
|
||||
integrationtest() {
|
||||
mocha test/integration/integration-test.js
|
||||
mocha test/integration/http-integration-test.js
|
||||
|
||||
# run integration tests in PhantomJS
|
||||
#gulp build-tests build-min
|
||||
#echo "Running integragtion tests in PhantomJS"
|
||||
#mocha-phantomjs test/localintegrationrunner.html
|
||||
}
|
||||
|
||||
doctest() {
|
||||
@@ -46,9 +73,9 @@ doctest() {
|
||||
}
|
||||
|
||||
oneNode() {
|
||||
checkEOL
|
||||
doctest
|
||||
lint
|
||||
typecheck
|
||||
unittest
|
||||
integrationtest
|
||||
}
|
||||
@@ -56,7 +83,7 @@ oneNode() {
|
||||
twoNodes() {
|
||||
case "$NODE_INDEX" in
|
||||
0) doctest; lint; integrationtest;;
|
||||
1) typecheck; unittest;;
|
||||
1) checkEOL; unittest;;
|
||||
*) echo "ERROR: invalid usage"; exit 2;;
|
||||
esac
|
||||
}
|
||||
@@ -64,7 +91,7 @@ twoNodes() {
|
||||
threeNodes() {
|
||||
case "$NODE_INDEX" in
|
||||
0) doctest; lint; integrationtest;;
|
||||
1) typecheck;;
|
||||
1) checkEOL;;
|
||||
2) unittest;;
|
||||
*) echo "ERROR: invalid usage"; exit 2;;
|
||||
esac
|
||||
|
||||
16
scripts/http.js
Normal file
16
scripts/http.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const createHTTPServer = require('../src/http').createHTTPServer;
|
||||
const port = 5990;
|
||||
const serverUrl = 'wss://s1.ripple.com';
|
||||
|
||||
|
||||
function main() {
|
||||
const server = createHTTPServer({server: serverUrl}, port);
|
||||
server.start().then(() => {
|
||||
console.log('Server started on port ' + String(port));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
@@ -16,28 +16,3 @@ echo ""
|
||||
echo "publish to npm"
|
||||
npm publish
|
||||
exit_on_error
|
||||
|
||||
rm -rf dist/bower
|
||||
echo ""
|
||||
echo "publish to bower"
|
||||
|
||||
git clone git@github.com:ripple/bower-ripple.git dist/bower
|
||||
gulp bower
|
||||
exit_on_error
|
||||
|
||||
cd dist/bower
|
||||
version=$(cat bower.json | grep -Eo '([0-9]\.?)+(-rc([0-9])+)?')
|
||||
echo "version: $version"
|
||||
git add ripple.js ripple-debug.js ripple-min.js bower.json
|
||||
exit_on_error
|
||||
|
||||
git commit -m "[TASK] add v$version"
|
||||
exit_on_error
|
||||
|
||||
git tag "v$version"
|
||||
exit_on_error
|
||||
|
||||
git push origin master
|
||||
git push --tags origin master
|
||||
|
||||
cd ../..
|
||||
|
||||
@@ -16,28 +16,3 @@ echo ""
|
||||
echo "publish rc to npm"
|
||||
npm publish --tag beta
|
||||
exit_on_error
|
||||
|
||||
rm -rf dist/bower
|
||||
echo ""
|
||||
echo "publish to bower"
|
||||
|
||||
git clone git@github.com:ripple/bower-ripple.git dist/bower
|
||||
gulp bower
|
||||
exit_on_error
|
||||
|
||||
cd dist/bower
|
||||
version=$(cat bower.json | grep -Eo '([0-9]\.?)+(-rc([0-9])+)?')
|
||||
echo "version: $version"
|
||||
git add ripple.js ripple-debug.js ripple-min.js bower.json
|
||||
exit_on_error
|
||||
|
||||
git commit -m "[TASK] add v$version"
|
||||
exit_on_error
|
||||
|
||||
git tag "v$version"
|
||||
exit_on_error
|
||||
|
||||
git push origin master
|
||||
git push --tags origin master
|
||||
|
||||
cd ../..
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
rm -rf dist/bower
|
||||
git clone git@github.com:ripple/bower-ripple.git dist/bower
|
||||
gulp bower
|
||||
cd dist/bower
|
||||
version=$(cat bower.json | grep -Eo '([0-9]\.?)+(-rc[0-9])?')
|
||||
echo "version: $version"
|
||||
git add ripple.js ripple-debug.js ripple-min.js bower.json
|
||||
git commit -m "[TASK] add v$version"
|
||||
git tag "v$version"
|
||||
git push origin master
|
||||
git push --tags origin master
|
||||
cd ..
|
||||
100
scripts/sauce-runner.js
Normal file
100
scripts/sauce-runner.js
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
const _ = require('lodash');
|
||||
const MochaSauce = require('mocha-in-sauce');
|
||||
|
||||
const testUrl = 'http://testripple.circleci.com:8080/test/saucerunner.html';
|
||||
|
||||
|
||||
function main() {
|
||||
// uncomment for more debug info
|
||||
// process.env.DEBUG = '*';
|
||||
|
||||
// configure
|
||||
const config = {
|
||||
name: 'RippleAPI',
|
||||
host: 'localhost',
|
||||
port: 4445,
|
||||
maxDuration: 180000,
|
||||
// the current build name (optional)
|
||||
build: Date.now(),
|
||||
url: testUrl,
|
||||
runSauceConnect: true
|
||||
};
|
||||
|
||||
if (process.env.CIRCLE_BUILD_NUM) {
|
||||
config.build = process.env.CIRCLE_BUILD_NUM;
|
||||
config.tags = [process.env.CIRCLE_BRANCH, process.env.CIRCLE_SHA1];
|
||||
config.tunnelIdentifier = process.env.CIRCLE_BUILD_NUM;
|
||||
}
|
||||
|
||||
const sauce = new MochaSauce(config);
|
||||
|
||||
sauce.concurrency(5);
|
||||
|
||||
// setup what browsers to test with
|
||||
sauce.browser({browserName: 'firefox', platform: 'Linux',
|
||||
version: '43'});
|
||||
sauce.browser({browserName: 'firefox', platform: 'Windows 8.1',
|
||||
version: '43'});
|
||||
sauce.browser({browserName: 'firefox', platform: 'OS X 10.11',
|
||||
version: '43'});
|
||||
sauce.browser({browserName: 'safari', platform: 'OS X 10.11',
|
||||
version: '9'});
|
||||
sauce.browser({browserName: 'safari', platform: 'OS X 10.10',
|
||||
version: '8'});
|
||||
sauce.browser({browserName: 'safari', platform: 'OS X 10.9',
|
||||
version: '7'});
|
||||
sauce.browser({browserName: 'chrome', platform: 'OS X 10.11',
|
||||
version: '47'});
|
||||
sauce.browser({browserName: 'chrome', platform: 'Linux',
|
||||
version: '47'});
|
||||
sauce.browser({browserName: 'chrome', platform: 'Windows 8.1',
|
||||
version: '47'});
|
||||
sauce.browser({browserName: 'internet explorer', platform: 'Windows 10',
|
||||
version: '11'});
|
||||
sauce.browser({browserName: 'MicrosoftEdge', platform: 'Windows 10',
|
||||
version: '20'});
|
||||
|
||||
sauce.on('init', function(browser) {
|
||||
console.log(' init : %s %s', browser.browserName, browser.platform);
|
||||
});
|
||||
|
||||
sauce.on('start', function(browser) {
|
||||
console.log(' start : %s %s', browser.browserName, browser.platform);
|
||||
});
|
||||
|
||||
sauce.on('end', function(browser, res) {
|
||||
console.log(' end : %s %s : %d failures', browser.browserName,
|
||||
browser.platform, res && res.failures);
|
||||
});
|
||||
|
||||
sauce.on('connected', sauceConnectProcess => {
|
||||
sauceConnectProcess.on('exit', function(code, /* signal */) {
|
||||
if (code > 0) {
|
||||
console.log('something wrong - exiting');
|
||||
process.exit();
|
||||
} else {
|
||||
console.log('normal tunnel exit');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
sauce.start(function(err, res) {
|
||||
let failure = false;
|
||||
if (err) {
|
||||
console.log('Error starting Sauce');
|
||||
console.error(err);
|
||||
process.exitCode = 2;
|
||||
} else {
|
||||
console.log('-------------- done --------------');
|
||||
failure = _.some(res, 'failures');
|
||||
console.log('Tests are failed:', failure);
|
||||
if (failure) {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
||||
144
src/api.js
144
src/api.js
@@ -1,5 +1,5 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
'use strict' // eslint-disable-line strict
|
||||
|
||||
/* eslint-disable max-len */
|
||||
// Enable core-js polyfills. This allows use of ES6/7 extensions listed here:
|
||||
@@ -9,46 +9,59 @@
|
||||
// In node.js env, polyfill might be already loaded (from any npm package),
|
||||
// that's why we do this check.
|
||||
if (!global._babelPolyfill) {
|
||||
require('babel-core/polyfill');
|
||||
require('babel-polyfill')
|
||||
}
|
||||
|
||||
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 preparePayment = require('./transaction/payment');
|
||||
const prepareTrustline = require('./transaction/trustline');
|
||||
const prepareOrder = require('./transaction/order');
|
||||
const prepareOrderCancellation = require('./transaction/ordercancellation');
|
||||
const prepareSuspendedPaymentCreation =
|
||||
require('./transaction/suspended-payment-creation');
|
||||
const prepareSuspendedPaymentExecution =
|
||||
require('./transaction/suspended-payment-execution');
|
||||
const prepareSuspendedPaymentCancellation =
|
||||
require('./transaction/suspended-payment-cancellation');
|
||||
const prepareSettings = require('./transaction/settings');
|
||||
const sign = require('./transaction/sign');
|
||||
const submit = require('./transaction/submit');
|
||||
const errors = require('./common').errors;
|
||||
const generateAddress = common.generateAddressAPI;
|
||||
const computeLedgerHash = require('./offline/ledgerhash');
|
||||
const getLedger = require('./ledger/ledger');
|
||||
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,
|
||||
@@ -61,36 +74,42 @@ type APIOptions = {
|
||||
// prevent access to non-validated ledger versions
|
||||
class RestrictedConnection extends common.Connection {
|
||||
request(request, timeout) {
|
||||
const ledger_index = request.ledger_index;
|
||||
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}`));
|
||||
`most recent validated ledger: ${this._ledgerVersion}`))
|
||||
}
|
||||
}
|
||||
return super.request(request, timeout);
|
||||
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;
|
||||
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 = new RestrictedConnection(serverURL, options)
|
||||
this.connection.on('ledgerClosed', message => {
|
||||
this.emit('ledger', server.formatLedgerClose(message));
|
||||
});
|
||||
this.connection.on('error', (type, info) => {
|
||||
this.emit('error', type, info);
|
||||
});
|
||||
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);
|
||||
this.connection = new RestrictedConnection(null, options)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,23 +132,30 @@ _.assign(RippleAPI.prototype, {
|
||||
getOrderbook,
|
||||
getSettings,
|
||||
getAccountInfo,
|
||||
getPaymentChannel,
|
||||
getLedger,
|
||||
|
||||
preparePayment,
|
||||
prepareTrustline,
|
||||
prepareOrder,
|
||||
prepareOrderCancellation,
|
||||
prepareSuspendedPaymentCreation,
|
||||
prepareSuspendedPaymentExecution,
|
||||
prepareSuspendedPaymentCancellation,
|
||||
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 = {
|
||||
@@ -137,8 +163,8 @@ RippleAPI._PRIVATE = {
|
||||
RangeSet: require('./common/rangeset').RangeSet,
|
||||
ledgerUtils: require('./ledger/utils'),
|
||||
schemaValidator: require('./common/schema-validator')
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
RippleAPI
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,66 +1,70 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const RippleAPI = require('./api').RippleAPI;
|
||||
'use strict' // eslint-disable-line strict
|
||||
const _ = require('lodash')
|
||||
const RippleAPI = require('./api').RippleAPI
|
||||
|
||||
class RippleAPIBroadcast extends RippleAPI {
|
||||
constructor(servers, options) {
|
||||
super(options);
|
||||
this.ledgerVersion = 0;
|
||||
super(options)
|
||||
this.ledgerVersion = 0
|
||||
|
||||
const apis = servers.map(server => new RippleAPI(
|
||||
_.assign({}, options, {server})
|
||||
));
|
||||
))
|
||||
|
||||
// exposed for testing
|
||||
this._apis = apis
|
||||
|
||||
this.getMethodNames().forEach(name => {
|
||||
this[name] = function() { // eslint-disable-line no-loop-func
|
||||
return Promise.race(apis.map(api => api[name].apply(api, arguments)));
|
||||
};
|
||||
});
|
||||
return Promise.race(apis.map(api => api[name](...arguments)))
|
||||
}
|
||||
})
|
||||
|
||||
// connection methods must be overridden to apply to all api instances
|
||||
this.connect = function() {
|
||||
return Promise.all(apis.map(api => api.connect()));
|
||||
};
|
||||
return Promise.all(apis.map(api => api.connect()))
|
||||
}
|
||||
this.disconnect = function() {
|
||||
return Promise.all(apis.map(api => api.disconnect()));
|
||||
};
|
||||
return Promise.all(apis.map(api => api.disconnect()))
|
||||
}
|
||||
this.isConnected = function() {
|
||||
return _.every(apis.map(api => api.isConnected()));
|
||||
};
|
||||
return _.every(apis.map(api => api.isConnected()))
|
||||
}
|
||||
|
||||
// synchronous methods are all passed directly to the first api instance
|
||||
const defaultAPI = apis[0];
|
||||
const syncMethods = ['sign', 'generateAddress', 'computeLedgerHash'];
|
||||
const defaultAPI = apis[0]
|
||||
const syncMethods = ['sign', 'generateAddress', 'computeLedgerHash']
|
||||
syncMethods.forEach(name => {
|
||||
this[name] = defaultAPI[name].bind(defaultAPI);
|
||||
});
|
||||
this[name] = defaultAPI[name].bind(defaultAPI)
|
||||
})
|
||||
|
||||
apis.forEach(api => {
|
||||
api.on('ledger', this.onLedgerEvent.bind(this));
|
||||
api.on('error', (type, info) => this.emit('error', type, info));
|
||||
});
|
||||
api.on('ledger', this.onLedgerEvent.bind(this))
|
||||
api.on('error', (errorCode, errorMessage, data) =>
|
||||
this.emit('error', errorCode, errorMessage, data))
|
||||
})
|
||||
}
|
||||
|
||||
onLedgerEvent(ledger) {
|
||||
if (ledger.ledgerVersion > this.ledgerVersion) {
|
||||
this.ledgerVersion = ledger.ledgerVersion;
|
||||
this.emit('ledger', ledger);
|
||||
this.ledgerVersion = ledger.ledgerVersion
|
||||
this.emit('ledger', ledger)
|
||||
}
|
||||
}
|
||||
|
||||
getMethodNames() {
|
||||
const methodNames = [];
|
||||
const methodNames = []
|
||||
for (const name in RippleAPI.prototype) {
|
||||
if (RippleAPI.prototype.hasOwnProperty(name)) {
|
||||
if (typeof RippleAPI.prototype[name] === 'function') {
|
||||
methodNames.push(name);
|
||||
methodNames.push(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return methodNames;
|
||||
return methodNames
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
RippleAPIBroadcast
|
||||
};
|
||||
}
|
||||
|
||||
21
src/common/browser-hacks.js
Normal file
21
src/common/browser-hacks.js
Normal file
@@ -0,0 +1,21 @@
|
||||
'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
|
||||
}
|
||||
@@ -1,278 +1,449 @@
|
||||
'use strict';
|
||||
const {EventEmitter} = require('events');
|
||||
const WebSocket = require('ws');
|
||||
const parseURL = require('url').parse;
|
||||
const RangeSet = require('./rangeset').RangeSet;
|
||||
'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,
|
||||
TimeoutError, ResponseFormatError, ConnectionError} = require('./errors');
|
||||
TimeoutError, ResponseFormatError, ConnectionError,
|
||||
RippledNotInitializedError} = require('./errors')
|
||||
|
||||
function isStreamMessageType(type) {
|
||||
return type === 'ledgerClosed' ||
|
||||
type === 'transaction' ||
|
||||
type === 'path_find';
|
||||
type === 'path_find'
|
||||
}
|
||||
|
||||
class Connection extends EventEmitter {
|
||||
constructor(url, options = {}) {
|
||||
super();
|
||||
this._url = url;
|
||||
this._trace = options.trace;
|
||||
super()
|
||||
this.setMaxListeners(Infinity)
|
||||
this._url = url
|
||||
this._trace = options.trace
|
||||
if (this._trace) {
|
||||
// for easier unit testing
|
||||
this._console = console;
|
||||
this._console = console
|
||||
}
|
||||
this._proxyURL = options.proxy;
|
||||
this._proxyAuthorization = options.proxyAuthorization;
|
||||
this._authorization = options.authorization;
|
||||
this._trustedCertificates = options.trustedCertificates;
|
||||
this._timeout = options.timeout || (20 * 1000);
|
||||
this._isReady = false;
|
||||
this._ws = null;
|
||||
this._ledgerVersion = null;
|
||||
this._availableLedgerVersions = new RangeSet();
|
||||
this._nextRequestID = 1;
|
||||
this._proxyURL = options.proxy
|
||||
this._proxyAuthorization = options.proxyAuthorization
|
||||
this._authorization = options.authorization
|
||||
this._trustedCertificates = options.trustedCertificates
|
||||
this._key = options.key
|
||||
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) {
|
||||
this._ledgerVersion = Number(data.ledger_index)
|
||||
if (data.validated_ledgers) {
|
||||
this._availableLedgerVersions.reset()
|
||||
this._availableLedgerVersions.parseAndAddRanges(
|
||||
data.validated_ledgers)
|
||||
} else {
|
||||
this._availableLedgerVersions.addValue(this._ledgerVersion)
|
||||
}
|
||||
}
|
||||
|
||||
_updateFees(data) {
|
||||
this._fee_base = Number(data.fee_base)
|
||||
this._fee_ref = Number(data.fee_ref)
|
||||
}
|
||||
|
||||
// return value is array of arguments to Connection.emit
|
||||
_parseMessage(message) {
|
||||
const data = JSON.parse(message);
|
||||
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')
|
||||
}
|
||||
return [data.id.toString(), data];
|
||||
return [data.id.toString(), data]
|
||||
} else if (isStreamMessageType(data.type)) {
|
||||
if (data.type === 'ledgerClosed') {
|
||||
this._ledgerVersion = Number(data.ledger_index);
|
||||
this._availableLedgerVersions.reset();
|
||||
this._availableLedgerVersions.parseAndAddRanges(
|
||||
data.validated_ledgers);
|
||||
this._updateLedgerVersions(data)
|
||||
this._updateFees(data)
|
||||
}
|
||||
return [data.type, data];
|
||||
return [data.type, data]
|
||||
} else if (data.type === undefined && data.error) {
|
||||
return ['error', data.error, data.error_message]; // e.g. slowDown
|
||||
return ['error', data.error, data.error_message, data] // e.g. slowDown
|
||||
}
|
||||
throw new ResponseFormatError('unrecognized message type: ' + data.type);
|
||||
throw new ResponseFormatError('unrecognized message type: ' + data.type)
|
||||
}
|
||||
|
||||
_onMessage(message) {
|
||||
let parameters;
|
||||
let parameters
|
||||
if (this._trace) {
|
||||
this._console.log(message);
|
||||
this._console.log(message)
|
||||
}
|
||||
try {
|
||||
parameters = this._parseMessage(message);
|
||||
parameters = this._parseMessage(message)
|
||||
} catch (error) {
|
||||
this.emit('error', 'badMessage', message);
|
||||
return;
|
||||
this.emit('error', 'badMessage', error.message, message)
|
||||
return
|
||||
}
|
||||
// we don't want this inside the try/catch or exceptions in listener
|
||||
// will be caught
|
||||
this.emit.apply(this, parameters);
|
||||
this.emit(...parameters)
|
||||
}
|
||||
|
||||
get _state() {
|
||||
return this._ws ? this._ws.readyState : WebSocket.CLOSED;
|
||||
return this._ws ? this._ws.readyState : WebSocket.CLOSED
|
||||
}
|
||||
|
||||
get _shouldBeConnected() {
|
||||
return this._ws !== null;
|
||||
return this._ws !== null
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
return this._state === WebSocket.OPEN && this._isReady;
|
||||
return this._state === WebSocket.OPEN && this._isReady
|
||||
}
|
||||
|
||||
_onUnexpectedClose() {
|
||||
this._ws = null;
|
||||
this._isReady = false;
|
||||
this.connect().then();
|
||||
_onUnexpectedClose(beforeOpen, resolve, reject, code) {
|
||||
if (this._onOpenErrorBound) {
|
||||
this._ws.removeListener('error', this._onOpenErrorBound)
|
||||
this._onOpenErrorBound = null
|
||||
}
|
||||
// just in case
|
||||
this._ws.removeAllListeners('open')
|
||||
this._ws = null
|
||||
this._isReady = false
|
||||
if (beforeOpen) {
|
||||
// connection was closed before it was properly opened, so we must return
|
||||
// error to connect's caller
|
||||
this.connect().then(resolve, reject)
|
||||
} else {
|
||||
// if first parameter ws lib sends close code,
|
||||
// but sometimes it forgots about it, so default to 1006 - CLOSE_ABNORMAL
|
||||
this.emit('disconnected', code || 1006)
|
||||
this._retryConnect()
|
||||
}
|
||||
}
|
||||
|
||||
_calculateTimeout(retriesCount) {
|
||||
return (retriesCount < 40)
|
||||
// First, for 2 seconds: 20 times per second
|
||||
? (1000 / 20)
|
||||
: (retriesCount < 40 + 60)
|
||||
// Then, for 1 minute: once per second
|
||||
? (1000)
|
||||
: (retriesCount < 40 + 60 + 60)
|
||||
// Then, for 10 minutes: once every 10 seconds
|
||||
? (10 * 1000)
|
||||
// Then: once every 30 seconds
|
||||
: (30 * 1000)
|
||||
}
|
||||
|
||||
_retryConnect() {
|
||||
this._retry += 1
|
||||
const retryTimeout = this._calculateTimeout(this._retry)
|
||||
this._retryTimer = setTimeout(() => {
|
||||
this.emit('reconnecting', this._retry)
|
||||
this.connect().catch(this._retryConnect.bind(this))
|
||||
}, retryTimeout)
|
||||
}
|
||||
|
||||
_clearReconnectTimer() {
|
||||
clearTimeout(this._retryTimer)
|
||||
this._retryTimer = null
|
||||
}
|
||||
|
||||
_onOpen() {
|
||||
if (!this._ws) {
|
||||
return Promise.reject(new DisconnectedError())
|
||||
}
|
||||
if (this._onOpenErrorBound) {
|
||||
this._ws.removeListener('error', this._onOpenErrorBound)
|
||||
this._onOpenErrorBound = null
|
||||
}
|
||||
|
||||
const request = {
|
||||
command: 'subscribe',
|
||||
streams: ['ledger']
|
||||
};
|
||||
return this.request(request).then(response => {
|
||||
this._ledgerVersion = Number(response.ledger_index);
|
||||
this._availableLedgerVersions.parseAndAddRanges(
|
||||
response.validated_ledgers);
|
||||
this._isReady = true;
|
||||
this.emit('connected');
|
||||
});
|
||||
}
|
||||
return this.request(request).then(data => {
|
||||
if (_.isEmpty(data) || !data.ledger_index) {
|
||||
// rippled instance doesn't have validated ledgers
|
||||
return this._disconnect(false).then(() => {
|
||||
throw new RippledNotInitializedError('Rippled not initialized')
|
||||
})
|
||||
}
|
||||
|
||||
this._updateLedgerVersions(data)
|
||||
this._updateFees(data)
|
||||
this._rebindOnUnxpectedClose()
|
||||
|
||||
this._retry = 0
|
||||
this._ws.on('error', error => {
|
||||
if (process.browser && error && error.type === 'error') {
|
||||
// we are in browser, ignore error - `close` event will be fired
|
||||
// after error
|
||||
return
|
||||
}
|
||||
this.emit('error', 'websocket', error.message, error)
|
||||
})
|
||||
|
||||
this._isReady = true
|
||||
this.emit('connected')
|
||||
|
||||
return undefined
|
||||
})
|
||||
}
|
||||
|
||||
_createWebSocket(url, proxyURL, proxyAuthorization, authorization,
|
||||
trustedCertificates) {
|
||||
const options = {};
|
||||
if (proxyURL !== undefined) {
|
||||
const parsedURL = parseURL(url);
|
||||
const proxyOptions = parseURL(proxyURL);
|
||||
proxyOptions.secureEndpoint = (parsedURL.protocol === 'wss:');
|
||||
proxyOptions.secureProxy = (proxyOptions.protocol === 'https:');
|
||||
proxyOptions.auth = proxyAuthorization;
|
||||
if (trustedCertificates) {
|
||||
proxyOptions.ca = trustedCertificates;
|
||||
}
|
||||
let HttpsProxyAgent;
|
||||
_rebindOnUnxpectedClose() {
|
||||
if (this._onUnexpectedCloseBound) {
|
||||
this._ws.removeListener('close', this._onUnexpectedCloseBound)
|
||||
}
|
||||
this._onUnexpectedCloseBound =
|
||||
this._onUnexpectedClose.bind(this, false, null, null)
|
||||
this._ws.once('close', this._onUnexpectedCloseBound)
|
||||
}
|
||||
|
||||
_unbindOnUnxpectedClose() {
|
||||
if (this._onUnexpectedCloseBound) {
|
||||
this._ws.removeListener('close', this._onUnexpectedCloseBound)
|
||||
}
|
||||
this._onUnexpectedCloseBound = null
|
||||
}
|
||||
|
||||
_onOpenError(reject, error) {
|
||||
this._onOpenErrorBound = null
|
||||
this._unbindOnUnxpectedClose()
|
||||
reject(new NotConnectedError(error && error.message))
|
||||
}
|
||||
|
||||
_createWebSocket() {
|
||||
const options = {}
|
||||
if (this._proxyURL !== undefined) {
|
||||
const parsedURL = parseURL(this._url)
|
||||
const parsedProxyURL = parseURL(this._proxyURL)
|
||||
const proxyOverrides = _.omit({
|
||||
secureEndpoint: (parsedURL.protocol === 'wss:'),
|
||||
secureProxy: (parsedProxyURL.protocol === 'https:'),
|
||||
auth: this._proxyAuthorization,
|
||||
ca: this._trustedCertificates,
|
||||
key: this._key,
|
||||
passphrase: this._passphrase,
|
||||
cert: this._certificate
|
||||
}, _.isUndefined)
|
||||
const proxyOptions = _.assign({}, parsedProxyURL, proxyOverrides)
|
||||
let HttpsProxyAgent
|
||||
try {
|
||||
HttpsProxyAgent = require('https-proxy-agent');
|
||||
HttpsProxyAgent = require('https-proxy-agent')
|
||||
} catch (error) {
|
||||
throw new Error('"proxy" option is not supported in the browser');
|
||||
throw new Error('"proxy" option is not supported in the browser')
|
||||
}
|
||||
options.agent = new HttpsProxyAgent(proxyOptions);
|
||||
options.agent = new HttpsProxyAgent(proxyOptions)
|
||||
}
|
||||
if (authorization !== undefined) {
|
||||
const base64 = new Buffer(authorization).toString('base64');
|
||||
options.headers = {Authorization: `Basic ${base64}`};
|
||||
if (this._authorization !== undefined) {
|
||||
const base64 = new Buffer(this._authorization).toString('base64')
|
||||
options.headers = {Authorization: `Basic ${base64}`}
|
||||
}
|
||||
return new WebSocket(url, options);
|
||||
const optionsOverrides = _.omit({
|
||||
ca: this._trustedCertificates,
|
||||
key: this._key,
|
||||
passphrase: this._passphrase,
|
||||
cert: this._certificate
|
||||
}, _.isUndefined)
|
||||
const websocketOptions = _.assign({}, options, optionsOverrides)
|
||||
const websocket = new WebSocket(this._url, null, websocketOptions)
|
||||
// we will have a listener for each outstanding request,
|
||||
// so we have to raise the limit (the default is 10)
|
||||
if (typeof websocket.setMaxListeners === 'function') {
|
||||
websocket.setMaxListeners(Infinity)
|
||||
}
|
||||
return websocket
|
||||
}
|
||||
|
||||
connect() {
|
||||
this._clearReconnectTimer()
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this._url) {
|
||||
reject(new ConnectionError(
|
||||
'Cannot connect because no server was specified'));
|
||||
'Cannot connect because no server was specified'))
|
||||
}
|
||||
if (this._state === WebSocket.OPEN) {
|
||||
resolve();
|
||||
resolve()
|
||||
} else if (this._state === WebSocket.CONNECTING) {
|
||||
this._ws.once('open', resolve);
|
||||
this._ws.once('open', resolve)
|
||||
} else {
|
||||
this._ws = this._createWebSocket(this._url, this._proxyURL,
|
||||
this._proxyAuthorization, this._authorization,
|
||||
this._trustedCertificates);
|
||||
this._ws.on('message', this._onMessage.bind(this));
|
||||
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this);
|
||||
this._ws.once('close', this._onUnexpectedCloseBound);
|
||||
this._ws.once('open', () => this._onOpen().then(resolve, reject));
|
||||
this._ws = this._createWebSocket()
|
||||
// when an error causes the connection to close, the close event
|
||||
// should still be emitted; the "ws" documentation says: "The close
|
||||
// event is also emitted when then underlying net.Socket closes the
|
||||
// connection (end or close)."
|
||||
// In case if there is connection error (say, server is not responding)
|
||||
// we must return this error to connection's caller. After successful
|
||||
// opening, we will forward all errors to main api object.
|
||||
this._onOpenErrorBound = this._onOpenError.bind(this, reject)
|
||||
this._ws.once('error', this._onOpenErrorBound)
|
||||
this._ws.on('message', this._onMessage.bind(this))
|
||||
// in browser close event can came before open event, so we must
|
||||
// resolve connect's promise after reconnect in that case.
|
||||
// after open event we will rebound _onUnexpectedCloseBound
|
||||
// without resolve and reject functions
|
||||
this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this, true,
|
||||
resolve, reject)
|
||||
this._ws.once('close', this._onUnexpectedCloseBound)
|
||||
this._ws.once('open', () => this._onOpen().then(resolve, reject))
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
return this._disconnect(true)
|
||||
}
|
||||
|
||||
_disconnect(calledByUser) {
|
||||
if (calledByUser) {
|
||||
this._clearReconnectTimer()
|
||||
this._retry = 0
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
if (this._state === WebSocket.CLOSED) {
|
||||
resolve();
|
||||
resolve()
|
||||
} else if (this._state === WebSocket.CLOSING) {
|
||||
this._ws.once('close', resolve);
|
||||
this._ws.once('close', resolve)
|
||||
} else {
|
||||
this._ws.removeListener('close', this._onUnexpectedCloseBound);
|
||||
this._ws.once('close', () => {
|
||||
this._ws = null;
|
||||
this._isReady = false;
|
||||
resolve();
|
||||
});
|
||||
this._ws.close();
|
||||
if (this._onUnexpectedCloseBound) {
|
||||
this._ws.removeListener('close', this._onUnexpectedCloseBound)
|
||||
this._onUnexpectedCloseBound = null
|
||||
}
|
||||
this._ws.once('close', code => {
|
||||
this._ws = null
|
||||
this._isReady = false
|
||||
if (calledByUser) {
|
||||
this.emit('disconnected', code || 1000) // 1000 - CLOSE_NORMAL
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
this._ws.close()
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
reconnect() {
|
||||
return this.disconnect().then(() => this.connect());
|
||||
return this.disconnect().then(() => this.connect())
|
||||
}
|
||||
|
||||
_whenReady(promise) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this._shouldBeConnected) {
|
||||
reject(new NotConnectedError());
|
||||
reject(new NotConnectedError())
|
||||
} else if (this._state === WebSocket.OPEN && this._isReady) {
|
||||
promise.then(resolve, reject);
|
||||
promise.then(resolve, reject)
|
||||
} else {
|
||||
this.once('connected', () => promise.then(resolve, reject));
|
||||
this.once('connected', () => promise.then(resolve, reject))
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
getLedgerVersion() {
|
||||
return this._whenReady(Promise.resolve(this._ledgerVersion));
|
||||
return this._whenReady(Promise.resolve(this._ledgerVersion))
|
||||
}
|
||||
|
||||
hasLedgerVersions(lowLedgerVersion, highLedgerVersion) {
|
||||
return this._whenReady(Promise.resolve(
|
||||
this._availableLedgerVersions.containsRange(
|
||||
lowLedgerVersion, highLedgerVersion || this._ledgerVersion)));
|
||||
lowLedgerVersion, highLedgerVersion || this._ledgerVersion)))
|
||||
}
|
||||
|
||||
hasLedgerVersion(ledgerVersion) {
|
||||
return this.hasLedgerVersions(ledgerVersion, ledgerVersion);
|
||||
return this.hasLedgerVersions(ledgerVersion, ledgerVersion)
|
||||
}
|
||||
|
||||
getFeeBase() {
|
||||
return this._whenReady(Promise.resolve(Number(this._fee_base)))
|
||||
}
|
||||
|
||||
getFeeRef() {
|
||||
return this._whenReady(Promise.resolve(Number(this._fee_ref)))
|
||||
}
|
||||
|
||||
_send(message) {
|
||||
if (this._trace) {
|
||||
this._console.log(message);
|
||||
this._console.log(message)
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._ws.send(message, undefined, (error, result) => {
|
||||
if (error) {
|
||||
reject(new DisconnectedError(error.message));
|
||||
reject(new DisconnectedError(error.message))
|
||||
} else {
|
||||
resolve(result);
|
||||
resolve(result)
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
request(request, timeout) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this._shouldBeConnected) {
|
||||
reject(new NotConnectedError());
|
||||
reject(new NotConnectedError())
|
||||
}
|
||||
|
||||
let timer = null;
|
||||
const self = this;
|
||||
const id = this._nextRequestID;
|
||||
this._nextRequestID += 1;
|
||||
const eventName = id.toString();
|
||||
let timer = null
|
||||
const self = this
|
||||
const id = this._nextRequestID
|
||||
this._nextRequestID += 1
|
||||
const eventName = id.toString()
|
||||
|
||||
function onDisconnect() {
|
||||
clearTimeout(timer);
|
||||
self.removeAllListeners(eventName);
|
||||
reject(new DisconnectedError());
|
||||
clearTimeout(timer)
|
||||
self.removeAllListeners(eventName)
|
||||
reject(new DisconnectedError())
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
clearTimeout(timer);
|
||||
self.removeAllListeners(eventName);
|
||||
clearTimeout(timer)
|
||||
self.removeAllListeners(eventName)
|
||||
if (self._ws !== null) {
|
||||
self._ws.removeListener('close', onDisconnect);
|
||||
self._ws.removeListener('close', onDisconnect)
|
||||
}
|
||||
}
|
||||
|
||||
function _resolve(response) {
|
||||
cleanup();
|
||||
resolve(response);
|
||||
cleanup()
|
||||
resolve(response)
|
||||
}
|
||||
|
||||
function _reject(error) {
|
||||
cleanup();
|
||||
reject(error);
|
||||
cleanup()
|
||||
reject(error)
|
||||
}
|
||||
|
||||
this.once(eventName, response => {
|
||||
if (response.status === 'error') {
|
||||
_reject(new RippledError(response.error));
|
||||
_reject(new RippledError(response.error))
|
||||
} else if (response.status === 'success') {
|
||||
_resolve(response.result);
|
||||
_resolve(response.result)
|
||||
} else {
|
||||
_reject(new ResponseFormatError(
|
||||
'unrecognized status: ' + response.status));
|
||||
'unrecognized status: ' + response.status))
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
this._ws.once('close', onDisconnect);
|
||||
this._ws.once('close', onDisconnect)
|
||||
|
||||
// JSON.stringify automatically removes keys with value of 'undefined'
|
||||
const message = JSON.stringify(Object.assign({}, request, {id}));
|
||||
const message = JSON.stringify(Object.assign({}, request, {id}))
|
||||
|
||||
this._whenReady(this._send(message)).then(() => {
|
||||
const delay = timeout || this._timeout;
|
||||
timer = setTimeout(() => _reject(new TimeoutError()), delay);
|
||||
}).catch(_reject);
|
||||
});
|
||||
const delay = timeout || this._timeout
|
||||
timer = setTimeout(() => _reject(new TimeoutError()), delay)
|
||||
}).catch(_reject)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Connection;
|
||||
module.exports = Connection
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
const flagIndices = require('./txflags').txFlagIndices.AccountSet;
|
||||
'use strict' // eslint-disable-line strict
|
||||
const flagIndices = require('./txflags').txFlagIndices.AccountSet
|
||||
|
||||
const accountRootFlags = {
|
||||
PasswordSpent: 0x00010000, // password set fee is spent
|
||||
@@ -10,7 +10,7 @@ const accountRootFlags = {
|
||||
NoFreeze: 0x00200000, // permanently disallowed freezing trustlines
|
||||
GlobalFreeze: 0x00400000, // trustlines globally frozen
|
||||
DefaultRipple: 0x00800000
|
||||
};
|
||||
}
|
||||
|
||||
const AccountFlags = {
|
||||
passwordSpent: accountRootFlags.PasswordSpent,
|
||||
@@ -21,7 +21,7 @@ const AccountFlags = {
|
||||
noFreeze: accountRootFlags.NoFreeze,
|
||||
globalFreeze: accountRootFlags.GlobalFreeze,
|
||||
defaultRipple: accountRootFlags.DefaultRipple
|
||||
};
|
||||
}
|
||||
|
||||
const AccountFlagIndices = {
|
||||
requireDestinationTag: flagIndices.asfRequireDest,
|
||||
@@ -32,7 +32,7 @@ const AccountFlagIndices = {
|
||||
noFreeze: flagIndices.asfNoFreeze,
|
||||
globalFreeze: flagIndices.asfGlobalFreeze,
|
||||
defaultRipple: flagIndices.asfDefaultRipple
|
||||
};
|
||||
}
|
||||
|
||||
const AccountFields = {
|
||||
EmailHash: {name: 'emailHash', encoding: 'hex',
|
||||
@@ -40,10 +40,10 @@ const AccountFields = {
|
||||
MessageKey: {name: 'messageKey'},
|
||||
Domain: {name: 'domain', encoding: 'hex'},
|
||||
TransferRate: {name: 'transferRate', defaults: 0, shift: 9}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
AccountFields,
|
||||
AccountFlagIndices,
|
||||
AccountFlags
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,29 +1,43 @@
|
||||
'use strict';
|
||||
const util = require('util');
|
||||
'use strict' // eslint-disable-line strict
|
||||
const util = require('util')
|
||||
const browserHacks = require('./browser-hacks')
|
||||
|
||||
class RippleError extends Error {
|
||||
// this is needed because extending builtins doesn't work in babel 6.x
|
||||
function extendableBuiltin(cls) {
|
||||
function ExtendableBuiltin() {
|
||||
cls.apply(this, arguments)
|
||||
}
|
||||
ExtendableBuiltin.prototype = Object.create(cls.prototype)
|
||||
browserHacks.setPrototypeOf(ExtendableBuiltin, cls)
|
||||
return ExtendableBuiltin
|
||||
}
|
||||
|
||||
class RippleError extends extendableBuiltin(Error) {
|
||||
constructor(message, data) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
Error.captureStackTrace(this, this.constructor.name);
|
||||
super(message)
|
||||
|
||||
this.name = browserHacks.getConstructorName(this)
|
||||
this.message = message
|
||||
this.data = data
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, this.constructor.name)
|
||||
}
|
||||
}
|
||||
|
||||
toString() {
|
||||
let result = '[' + this.name + '(' + this.message;
|
||||
let result = '[' + this.name + '(' + this.message
|
||||
if (this.data) {
|
||||
result += ', ' + util.inspect(this.data);
|
||||
result += ', ' + util.inspect(this.data)
|
||||
}
|
||||
result += ')]';
|
||||
return result;
|
||||
result += ')]'
|
||||
return result
|
||||
}
|
||||
|
||||
/* console.log in node uses util.inspect on object, and util.inspect allows
|
||||
us to cutomize its output:
|
||||
https://nodejs.org/api/util.html#util_custom_inspect_function_on_objects */
|
||||
inspect() {
|
||||
return this.toString();
|
||||
return this.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +53,8 @@ class NotConnectedError extends ConnectionError {}
|
||||
|
||||
class DisconnectedError extends ConnectionError {}
|
||||
|
||||
class RippledNotInitializedError extends ConnectionError {}
|
||||
|
||||
class TimeoutError extends ConnectionError {}
|
||||
|
||||
class ResponseFormatError extends ConnectionError {}
|
||||
@@ -47,20 +63,20 @@ class ValidationError extends RippleError {}
|
||||
|
||||
class NotFoundError extends RippleError {
|
||||
constructor(message) {
|
||||
super(message || 'Not found');
|
||||
super(message || 'Not found')
|
||||
}
|
||||
}
|
||||
|
||||
class MissingLedgerHistoryError extends RippleError {
|
||||
constructor(message) {
|
||||
super(message || 'Server is missing ledger history in the specified range');
|
||||
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');
|
||||
+ ' most recent validated ledger')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +87,7 @@ module.exports = {
|
||||
RippledError,
|
||||
NotConnectedError,
|
||||
DisconnectedError,
|
||||
RippledNotInitializedError,
|
||||
TimeoutError,
|
||||
ResponseFormatError,
|
||||
ValidationError,
|
||||
@@ -78,4 +95,4 @@ module.exports = {
|
||||
PendingLedgerVersionError,
|
||||
MissingLedgerHistoryError,
|
||||
LedgerVersionError
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
'use strict' // eslint-disable-line strict
|
||||
const utils = require('./utils')
|
||||
|
||||
module.exports = {
|
||||
Connection: require('./connection'),
|
||||
@@ -19,4 +19,4 @@ module.exports = {
|
||||
iso8601ToRippleTime: utils.iso8601ToRippleTime,
|
||||
rippleTimeToISO8601: utils.rippleTimeToISO8601,
|
||||
isValidSecret: utils.isValidSecret
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const ranges = Symbol();
|
||||
'use strict' // eslint-disable-line strict
|
||||
const _ = require('lodash')
|
||||
const assert = require('assert')
|
||||
const ranges = Symbol()
|
||||
|
||||
function mergeIntervals(intervals: Array<[number, number]>) {
|
||||
const stack = [[-Infinity, -Infinity]];
|
||||
const stack = [[-Infinity, -Infinity]]
|
||||
_.forEach(_.sortBy(intervals, x => x[0]), interval => {
|
||||
const lastInterval = stack.pop();
|
||||
const lastInterval = stack.pop()
|
||||
if (interval[0] <= lastInterval[1] + 1) {
|
||||
stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])]);
|
||||
stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])])
|
||||
} else {
|
||||
stack.push(lastInterval);
|
||||
stack.push(interval);
|
||||
stack.push(lastInterval)
|
||||
stack.push(interval)
|
||||
}
|
||||
});
|
||||
return stack.slice(1);
|
||||
})
|
||||
return stack.slice(1)
|
||||
}
|
||||
|
||||
class RangeSet {
|
||||
constructor() {
|
||||
this.reset();
|
||||
this.reset()
|
||||
}
|
||||
|
||||
reset() {
|
||||
this[ranges] = [];
|
||||
this[ranges] = []
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return this[ranges].map(range =>
|
||||
range[0].toString() + '-' + range[1].toString()).join(',');
|
||||
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]]));
|
||||
assert(start <= end, 'invalid range')
|
||||
this[ranges] = mergeIntervals(this[ranges].concat([[start, end]]))
|
||||
}
|
||||
|
||||
addValue(value: number) {
|
||||
this.addRange(value, value);
|
||||
this.addRange(value, value)
|
||||
}
|
||||
|
||||
parseAndAddRanges(rangesString: string) {
|
||||
const rangeStrings = rangesString.split(',');
|
||||
const rangeStrings = rangesString.split(',')
|
||||
_.forEach(rangeStrings, rangeString => {
|
||||
const range = rangeString.split('-').map(Number);
|
||||
this.addRange(range[0], range.length === 1 ? range[0] : range[1]);
|
||||
});
|
||||
const range = rangeString.split('-').map(Number)
|
||||
this.addRange(range[0], range.length === 1 ? range[0] : range[1])
|
||||
})
|
||||
}
|
||||
|
||||
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) {
|
||||
return this.containsRange(value, value);
|
||||
return this.containsRange(value, value)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.RangeSet = RangeSet;
|
||||
module.exports.RangeSet = RangeSet
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// flow is disabled for this file until support for requiring json is added:
|
||||
// https://github.com/facebook/flow/issues/167
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const Ajv = require('ajv');
|
||||
const ValidationError = require('./errors').ValidationError;
|
||||
const {isValidAddress} = require('ripple-address-codec');
|
||||
const {isValidSecret} = require('./utils');
|
||||
'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')
|
||||
|
||||
function loadSchemas() {
|
||||
// listed explicitly for webpack (instead of scanning schemas directory)
|
||||
@@ -16,11 +16,13 @@ function loadSchemas() {
|
||||
require('./schemas/objects/hash128.json'),
|
||||
require('./schemas/objects/hash256.json'),
|
||||
require('./schemas/objects/sequence.json'),
|
||||
require('./schemas/objects/signature.json'),
|
||||
require('./schemas/objects/issue.json'),
|
||||
require('./schemas/objects/ledgerversion.json'),
|
||||
require('./schemas/objects/max-adjustment.json'),
|
||||
require('./schemas/objects/memo.json'),
|
||||
require('./schemas/objects/memos.json'),
|
||||
require('./schemas/objects/public-key.json'),
|
||||
require('./schemas/objects/uint32.json'),
|
||||
require('./schemas/objects/value.json'),
|
||||
require('./schemas/objects/source-adjustment.json'),
|
||||
@@ -46,21 +48,25 @@ function loadSchemas() {
|
||||
require('./schemas/objects/settings.json'),
|
||||
require('./schemas/specifications/settings.json'),
|
||||
require('./schemas/specifications/payment.json'),
|
||||
require('./schemas/specifications/suspended-payment-cancellation.json'),
|
||||
require('./schemas/specifications/escrow-cancellation.json'),
|
||||
require('./schemas/specifications/order-cancellation.json'),
|
||||
require('./schemas/specifications/order.json'),
|
||||
require('./schemas/specifications/suspended-payment-execution.json'),
|
||||
require('./schemas/specifications/suspended-payment-creation.json'),
|
||||
require('./schemas/specifications/escrow-execution.json'),
|
||||
require('./schemas/specifications/escrow-creation.json'),
|
||||
require('./schemas/specifications/payment-channel-create.json'),
|
||||
require('./schemas/specifications/payment-channel-fund.json'),
|
||||
require('./schemas/specifications/payment-channel-claim.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-balances.json'),
|
||||
require('./schemas/output/get-balance-sheet'),
|
||||
require('./schemas/output/get-balance-sheet.json'),
|
||||
require('./schemas/output/get-ledger.json'),
|
||||
require('./schemas/output/get-orderbook.json'),
|
||||
require('./schemas/output/get-orders.json'),
|
||||
require('./schemas/output/order-change.json'),
|
||||
require('./schemas/output/get-payment-channel.json'),
|
||||
require('./schemas/output/prepare.json'),
|
||||
require('./schemas/output/ledger-event.json'),
|
||||
require('./schemas/output/get-paths.json'),
|
||||
@@ -71,12 +77,15 @@ function loadSchemas() {
|
||||
require('./schemas/output/get-transaction.json'),
|
||||
require('./schemas/output/get-transactions.json'),
|
||||
require('./schemas/output/get-trustlines.json'),
|
||||
require('./schemas/output/sign-payment-channel-claim.json'),
|
||||
require('./schemas/output/verify-payment-channel-claim.json'),
|
||||
require('./schemas/input/get-balances.json'),
|
||||
require('./schemas/input/get-balance-sheet.json'),
|
||||
require('./schemas/input/get-ledger.json'),
|
||||
require('./schemas/input/get-orders.json'),
|
||||
require('./schemas/input/get-orderbook.json'),
|
||||
require('./schemas/input/get-paths.json'),
|
||||
require('./schemas/input/get-payment-channel.json'),
|
||||
require('./schemas/input/api-options.json'),
|
||||
require('./schemas/input/get-settings.json'),
|
||||
require('./schemas/input/get-account-info.json'),
|
||||
@@ -88,33 +97,60 @@ function loadSchemas() {
|
||||
require('./schemas/input/prepare-trustline.json'),
|
||||
require('./schemas/input/prepare-order-cancellation.json'),
|
||||
require('./schemas/input/prepare-settings.json'),
|
||||
require('./schemas/input/prepare-suspended-payment-creation.json'),
|
||||
require('./schemas/input/prepare-suspended-payment-cancellation.json'),
|
||||
require('./schemas/input/prepare-suspended-payment-execution.json'),
|
||||
require('./schemas/input/compute-ledger-hash'),
|
||||
require('./schemas/input/sign'),
|
||||
require('./schemas/input/submit')
|
||||
];
|
||||
const titles = _.map(schemas, schema => schema.title);
|
||||
const duplicates = _.keys(_.pick(_.countBy(titles), count => count > 1));
|
||||
assert(duplicates.length === 0, 'Duplicate schemas for: ' + duplicates);
|
||||
const ajv = new Ajv();
|
||||
_.forEach(schemas, schema => ajv.addSchema(schema, schema.title));
|
||||
ajv.addFormat('address', isValidAddress);
|
||||
ajv.addFormat('secret', isValidSecret);
|
||||
return ajv;
|
||||
require('./schemas/input/prepare-escrow-creation.json'),
|
||||
require('./schemas/input/prepare-escrow-cancellation.json'),
|
||||
require('./schemas/input/prepare-escrow-execution.json'),
|
||||
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/compute-ledger-hash.json'),
|
||||
require('./schemas/input/sign.json'),
|
||||
require('./schemas/input/submit.json'),
|
||||
require('./schemas/input/generate-address.json'),
|
||||
require('./schemas/input/sign-payment-channel-claim.json'),
|
||||
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))
|
||||
assert(duplicates.length === 0, 'Duplicate schemas for: ' + duplicates)
|
||||
const v = 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) {
|
||||
if (instance === undefined) {
|
||||
return true
|
||||
}
|
||||
return isValidAddress(instance)
|
||||
}
|
||||
v.customFormats.secret = function(instance) {
|
||||
if (instance === undefined) {
|
||||
return true
|
||||
}
|
||||
return isValidSecret(instance)
|
||||
}
|
||||
|
||||
// Register under the root URI '/'
|
||||
_.forEach(schemas, schema => v.addSchema(schema, '/' + schema.title))
|
||||
return v
|
||||
}
|
||||
|
||||
const ajv = loadSchemas();
|
||||
const v = loadSchemas()
|
||||
|
||||
function schemaValidate(schemaName: string, object: any): void {
|
||||
const isValid = ajv.validate(schemaName, object);
|
||||
if (!isValid) {
|
||||
throw new ValidationError(ajv.errorsText());
|
||||
// Lookup under the root URI '/'
|
||||
const schema = v.getSchema('/' + schemaName)
|
||||
if (schema === undefined) {
|
||||
throw new ValidationError('no schema for ' + schemaName)
|
||||
}
|
||||
const result = v.validate(object, schema)
|
||||
if (!result.valid) {
|
||||
throw new ValidationError(result.errors.join())
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
schemaValidate,
|
||||
isValidSecret
|
||||
};
|
||||
}
|
||||
|
||||
@@ -42,6 +42,18 @@
|
||||
"type": "string",
|
||||
"description": "A PEM-formatted SSL certificate to trust when connecting to a proxy."
|
||||
}
|
||||
},
|
||||
"key": {
|
||||
"type": "string",
|
||||
"description": "A string containing the private key of the client in PEM format. (Can be an array of keys)."
|
||||
},
|
||||
"passphrase": {
|
||||
"type": "string",
|
||||
"description": "The passphrase for the private key of the client."
|
||||
},
|
||||
"certificate": {
|
||||
"type": "string",
|
||||
"description": "A string containing the certificate key of the client in PEM format. (Can be an array of certificates)."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
19
src/common/schemas/input/combine.json
Normal file
19
src/common/schemas/input/combine.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "combineParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"signedTransactions": {
|
||||
"type": "array",
|
||||
"description": "An array of signed transactions (from the output of [sign](#sign)) to combine.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-F0-9]+$",
|
||||
"description": "A single-signed transaction represented as an uppercase hexadecimal string (from the output of [sign](#sign))"
|
||||
},
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["signedTransactions"]
|
||||
}
|
||||
29
src/common/schemas/input/generate-address.json
Normal file
29
src/common/schemas/input/generate-address.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "generateAddressParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"options": {
|
||||
"type": "object",
|
||||
"description": "Options to control how the address and secret are generated.",
|
||||
"properties": {
|
||||
"entropy": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"description": "The entropy to use to generate the seed."
|
||||
},
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"enum": ["ecdsa-secp256k1", "ed25519"],
|
||||
"description": "The digital signature algorithm to generate an address for. Can be `ecdsa-secp256k1` (default) or `ed25519`."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
14
src/common/schemas/input/get-payment-channel.json
Normal file
14
src/common/schemas/input/get-payment-channel.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getPaymentChannelParameters",
|
||||
"description": "Parameters for getPaymentChannel",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "hash256",
|
||||
"description": "256-bit hexadecimal channel identifier."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["id"]
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "prepareSuspendedPaymentCreationParameters",
|
||||
"title": "prepareEscrowCancellationParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the account that is creating the transaction."
|
||||
},
|
||||
"suspendedPaymentCreation": {
|
||||
"$ref": "suspendedPaymentCreation",
|
||||
"description": "The specification of the suspended payment creation to prepare."
|
||||
"escrowCancellation": {
|
||||
"$ref": "escrowCancellation",
|
||||
"description": "The specification of the escrow cancellation to prepare."
|
||||
},
|
||||
"instructions": {"$ref": "instructions"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["address", "suspendedPaymentCreation"]
|
||||
"required": ["address", "escrowCancellation"]
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "prepareSuspendedPaymentExecutionParameters",
|
||||
"title": "prepareEscrowCreationParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the account that is creating the transaction."
|
||||
},
|
||||
"suspendedPaymentExecution": {
|
||||
"$ref": "suspendedPaymentExecution",
|
||||
"description": "The specification of the suspended payment execution to prepare."
|
||||
"escrowCreation": {
|
||||
"$ref": "escrowCreation",
|
||||
"description": "The specification of the escrow creation to prepare."
|
||||
},
|
||||
"instructions": {"$ref": "instructions"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["address", "suspendedPaymentExecution"]
|
||||
"required": ["address", "escrowCreation"]
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "prepareSuspendedPaymentCancellationParameters",
|
||||
"title": "prepareEscrowExecutionParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the account that is creating the transaction."
|
||||
},
|
||||
"suspendedPaymentCancellation": {
|
||||
"$ref": "suspendedPaymentCancellation",
|
||||
"description": "The specification of the suspended payment cancellation to prepare."
|
||||
"escrowExecution": {
|
||||
"$ref": "escrowExecution",
|
||||
"description": "The specification of the escrow execution to prepare."
|
||||
},
|
||||
"instructions": {"$ref": "instructions"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["address", "suspendedPaymentCancellation"]
|
||||
"required": ["address", "escrowExecution"]
|
||||
}
|
||||
18
src/common/schemas/input/prepare-payment-channel-claim.json
Normal file
18
src/common/schemas/input/prepare-payment-channel-claim.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "preparePaymentChannelClaimParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the account that is creating the transaction."
|
||||
},
|
||||
"paymentChannelClaim": {
|
||||
"$ref": "paymentChannelClaim",
|
||||
"description": "Details of the channel and claim."
|
||||
},
|
||||
"instructions": {"$ref": "instructions"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["address", "paymentChannelClaim"]
|
||||
}
|
||||
18
src/common/schemas/input/prepare-payment-channel-create.json
Normal file
18
src/common/schemas/input/prepare-payment-channel-create.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "preparePaymentChannelCreateParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the account that is creating the transaction."
|
||||
},
|
||||
"paymentChannelCreate": {
|
||||
"$ref": "paymentChannelCreate",
|
||||
"description": "The specification of the payment channel to create."
|
||||
},
|
||||
"instructions": {"$ref": "instructions"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["address", "paymentChannelCreate"]
|
||||
}
|
||||
18
src/common/schemas/input/prepare-payment-channel-fund.json
Normal file
18
src/common/schemas/input/prepare-payment-channel-fund.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "preparePaymentChannelFundParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the account that is creating the transaction."
|
||||
},
|
||||
"paymentChannelFund": {
|
||||
"$ref": "paymentChannelFund",
|
||||
"description": "The channel to fund, and the details of how to fund it."
|
||||
},
|
||||
"instructions": {"$ref": "instructions"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["address", "paymentChannelFund"]
|
||||
}
|
||||
21
src/common/schemas/input/sign-payment-channel-claim.json
Normal file
21
src/common/schemas/input/sign-payment-channel-claim.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "signPaymentChannelClaimParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"channel": {
|
||||
"$ref": "hash256",
|
||||
"description": "256-bit hexadecimal channel identifier."
|
||||
},
|
||||
"amount": {
|
||||
"$ref": "value",
|
||||
"description": "Amount of XRP authorized by the claim."
|
||||
},
|
||||
"privateKey": {
|
||||
"$ref": "publicKey",
|
||||
"description": "The private key to sign the payment channel claim."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["channel", "amount", "privateKey"]
|
||||
}
|
||||
@@ -11,6 +11,17 @@
|
||||
"type": "string",
|
||||
"format": "secret",
|
||||
"description": "The secret of the account that is initiating the transaction."
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"description": "Options that control the type of signature that will be generated.",
|
||||
"properties": {
|
||||
"signAs": {
|
||||
"$ref": "address",
|
||||
"description": "The account that the signature should count for in multisigning."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
25
src/common/schemas/input/verify-payment-channel-claim.json
Normal file
25
src/common/schemas/input/verify-payment-channel-claim.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "verifyPaymentChannelClaimParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"channel": {
|
||||
"$ref": "hash256",
|
||||
"description": "256-bit hexadecimal channel identifier."
|
||||
},
|
||||
"amount": {
|
||||
"$ref": "value",
|
||||
"description": "Amount of XRP authorized by the claim."
|
||||
},
|
||||
"signature": {
|
||||
"$ref": "signature",
|
||||
"description": "Signature of this claim."
|
||||
},
|
||||
"publicKey": {
|
||||
"$ref": "publicKey",
|
||||
"description": "Public key of the channel's sender"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["channel", "amount", "signature", "publicKey"]
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "amount",
|
||||
"link": "amount",
|
||||
"description": "An Amount on the Ripple Protocol, used also for XRP in the ripple-rest API",
|
||||
"description": "An Amount on the Ripple Protocol",
|
||||
"allOf": [
|
||||
{"$ref": "amountbase"},
|
||||
{"required": ["value"]}
|
||||
|
||||
@@ -18,13 +18,21 @@
|
||||
"$ref": "value"
|
||||
},
|
||||
"maxLedgerVersion": {
|
||||
"description": "The highest ledger version that the transaction can be included in.",
|
||||
"$ref": "ledgerVersion"
|
||||
"description": "The highest ledger version that the transaction can be included in. If this option and `maxLedgerVersionOffset` are both omitted, the `maxLedgerVersion` option will default to 3 greater than the current validated ledger version (equivalent to `maxLedgerVersionOffset=3`). Use `null` to not set a maximum ledger version.",
|
||||
"oneOf": [
|
||||
{"$ref": "ledgerVersion"},
|
||||
{"type": "null"}
|
||||
]
|
||||
},
|
||||
"maxLedgerVersionOffset": {
|
||||
"description": "Offset from current legder version to highest ledger version that the transaction can be included in.",
|
||||
"description": "Offset from current validated legder version to highest ledger version that the transaction can be included in.",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"signersCount": {
|
||||
"description": "Number of signers that will be signing this transaction.",
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
7
src/common/schemas/objects/public-key.json
Normal file
7
src/common/schemas/objects/public-key.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "publicKey",
|
||||
"description": "The hexadecimal representation of a secp256k1 or Ed25519 public key.",
|
||||
"type": "string",
|
||||
"pattern": "^[A-F0-9]+$"
|
||||
}
|
||||
@@ -55,7 +55,7 @@
|
||||
"description": " The domain that owns this account, as a hexadecimal string representing the ASCII for the domain in lowercase."
|
||||
},
|
||||
"transferRate": {
|
||||
"description": " The fee to charge when users transfer this account’s issuances, represented as billionths of a unit. Use `null` to set no fee.",
|
||||
"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}
|
||||
@@ -68,6 +68,35 @@
|
||||
],
|
||||
"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."
|
||||
},
|
||||
"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.",
|
||||
"properties": {
|
||||
"threshold": {
|
||||
"$ref": "uint32",
|
||||
"description": "A target number for the signer weights. A multi-signature from this list is valid only if the sum weights of the signatures provided is equal or greater than this value. To delete the signers setting, use the value `0`."
|
||||
},
|
||||
"weights": {
|
||||
"type": "array",
|
||||
"description": "Weights of signatures for each signer.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "An association of an address and a weight.",
|
||||
"properties": {
|
||||
"address": {"$ref": "address"},
|
||||
"weight": {
|
||||
"$ref": "uint32",
|
||||
"description": "The weight that the signature of this account counts as towards the threshold."
|
||||
}
|
||||
},
|
||||
"required": ["address", "weight"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 1,
|
||||
"maxItems": 8
|
||||
}
|
||||
}
|
||||
},
|
||||
"memos": {"$ref": "memos"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
7
src/common/schemas/objects/signature.json
Normal file
7
src/common/schemas/objects/signature.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "signature",
|
||||
"description": "The hexadecimal representation of a signature.",
|
||||
"type": "string",
|
||||
"pattern": "^[A-F0-9]+$"
|
||||
}
|
||||
@@ -2,9 +2,10 @@
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "transactionType",
|
||||
"link": "transaction-types",
|
||||
"description": "The type of the tranasction.",
|
||||
"description": "The type of the transaction.",
|
||||
"type": "string",
|
||||
"enum": ["payment", "order", "orderCancellation", "trustline", "settings",
|
||||
"suspendedPaymentCreation", "suspendedPaymentCancellation",
|
||||
"suspendedPaymentExecution"]
|
||||
"escrowCreation", "escrowCancellation",
|
||||
"escrowExecution", "paymentChannelCreate",
|
||||
"paymentChannelFund", "paymentChannelClaim"]
|
||||
}
|
||||
|
||||
67
src/common/schemas/output/get-payment-channel.json
Normal file
67
src/common/schemas/output/get-payment-channel.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getPaymentChannel",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"account": {
|
||||
"$ref": "address",
|
||||
"description": "Address that created the payment channel."
|
||||
},
|
||||
"destination": {
|
||||
"$ref": "address",
|
||||
"description": "Address to receive XRP claims against this channel."
|
||||
},
|
||||
"amount": {
|
||||
"$ref": "value",
|
||||
"description": "The total amount of XRP funded in this channel."
|
||||
},
|
||||
"balance": {
|
||||
"$ref": "value",
|
||||
"description": "The total amount of XRP delivered by this channel."
|
||||
},
|
||||
"settleDelay": {
|
||||
"type": "number",
|
||||
"description": "Amount of seconds the source address must wait before closing the channel if it has unclaimed XRP."
|
||||
},
|
||||
"expiration": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Time when this channel expires."
|
||||
},
|
||||
"publicKey": {
|
||||
"$ref": "publicKey",
|
||||
"description": "Public key of the key pair the source will use to sign claims against this channel."
|
||||
},
|
||||
"cancelAfter": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Time when this channel expires as specified at creation."
|
||||
},
|
||||
"sourceTag": {
|
||||
"$ref": "tag",
|
||||
"description": "Source tag."
|
||||
},
|
||||
"destinationTag": {
|
||||
"$ref": "tag",
|
||||
"description": "Destination tag."
|
||||
},
|
||||
"previousAffectingTransactionID": {
|
||||
"$ref": "hash256",
|
||||
"description": "Hash value representing the most recent transaction that affected this payment channel."
|
||||
},
|
||||
"previousAffectingTransactionLedgerVersion": {
|
||||
"$ref": "ledgerVersion",
|
||||
"description": "The ledger version that the transaction identified by the `previousAffectingTransactionID` was validated in."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"account",
|
||||
"destination",
|
||||
"amount",
|
||||
"balance",
|
||||
"settleDelay",
|
||||
"previousAffectingTransactionID",
|
||||
"previousAffectingTransactionLedgerVersion"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -83,7 +83,7 @@
|
||||
"description": "The time since the ledger was closed, in seconds."
|
||||
},
|
||||
"baseFeeXRP": {
|
||||
"type": "number",
|
||||
"$ref": "value",
|
||||
"description": "Base fee, in XRP. This may be represented in scientific notation such as 1e-05 for 0.00005."
|
||||
},
|
||||
"hash": {
|
||||
@@ -91,13 +91,11 @@
|
||||
"description": "Unique hash for the ledger, as an uppercase hexadecimal string."
|
||||
},
|
||||
"reserveBaseXRP": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"$ref": "value",
|
||||
"description": "Minimum amount of XRP necessary for every account to keep in reserve."
|
||||
},
|
||||
"reserveIncrementXRP": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"$ref": "value",
|
||||
"description": "Amount of XRP added to the account reserve for each object an account is responsible for in the ledger."
|
||||
},
|
||||
"ledgerVersion": {
|
||||
|
||||
@@ -59,20 +59,38 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {"enum": ["suspendedPaymentCreation"]},
|
||||
"specification": {"$ref": "suspendedPaymentCreation"}
|
||||
"type": {"enum": ["escrowCreation"]},
|
||||
"specification": {"$ref": "escrowCreation"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {"enum": ["suspendedPaymentCancellation"]},
|
||||
"specification": {"$ref": "suspendedPaymentCancellation"}
|
||||
"type": {"enum": ["escrowCancellation"]},
|
||||
"specification": {"$ref": "escrowCancellation"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {"enum": ["suspendedPaymentExecution"]},
|
||||
"specification": {"$ref": "suspendedPaymentExecution"}
|
||||
"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"}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"reserveBaseXRP": {
|
||||
"$ref": "value",
|
||||
"description": "The minimum reserve, in drops of XRP, that is required for an account."
|
||||
"description": "The minimum reserve, in XRP, that is required for an account."
|
||||
},
|
||||
"reserveIncrementXRP": {
|
||||
"$ref": "value",
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
"$ref": "value",
|
||||
"description": "The XRP fee that was charged for the transaction."
|
||||
},
|
||||
"deliveredAmount": {
|
||||
"$ref": "amount",
|
||||
"description": "For payment transactions, it is impossible to reliably compute the actual delivered amount from the balanceChanges due to fixed precision. If the payment is not a partial payment and the transaction succeeded, the deliveredAmount should always be considered to be the amount specified in the transaction."
|
||||
},
|
||||
"balanceChanges": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
|
||||
@@ -21,12 +21,15 @@
|
||||
"description": "The initiating account's sequence number for this transaction."
|
||||
},
|
||||
"maxLedgerVersion": {
|
||||
"$ref": "ledgerVersion",
|
||||
"description": "The highest ledger version that the transaction can be included in."
|
||||
"oneOf": [
|
||||
{"$ref": "ledgerVersion"},
|
||||
{"type": "null"}
|
||||
],
|
||||
"description": "The highest ledger version that the transaction can be included in. Set to `null` if there is no maximum."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["fee", "sequence"]
|
||||
"required": ["fee", "sequence", "maxLedgerVersion"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "signPaymentChannelClaim",
|
||||
"type": "string",
|
||||
"$ref": "signature",
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"properties": {
|
||||
"resultCode": {
|
||||
"type": "string",
|
||||
"description": "The result code returned by rippled. [List of tranasction responses](http://pages.lightthenight.org/gba/SanFran15/ripple)"
|
||||
"description": "The result code returned by rippled. [List of transaction responses](https://ripple.com/build/transactions/#full-transaction-response-list)"
|
||||
},
|
||||
"resultMessage": {
|
||||
"type": "string",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "verifyPaymentChannelClaim",
|
||||
"type": "boolean",
|
||||
"additionalProperties": false
|
||||
}
|
||||
19
src/common/schemas/specifications/escrow-cancellation.json
Normal file
19
src/common/schemas/specifications/escrow-cancellation.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "escrowCancellation",
|
||||
"link": "escrow-cancellation",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memos": {"$ref": "memos"},
|
||||
"owner": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the owner of the escrow to cancel."
|
||||
},
|
||||
"escrowSequence": {
|
||||
"$ref": "sequence",
|
||||
"description": "The [account sequence number](#account-sequence-number) of the [Escrow Creation](#escrow-creation) transaction for the escrow to cancel."
|
||||
}
|
||||
},
|
||||
"required": ["owner", "escrowSequence"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
42
src/common/schemas/specifications/escrow-creation.json
Normal file
42
src/common/schemas/specifications/escrow-creation.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "escrowCreation",
|
||||
"link": "escrow-creation",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"$ref": "value",
|
||||
"description": "Amount of XRP for sender to escrow."
|
||||
},
|
||||
"destination": {
|
||||
"$ref": "address",
|
||||
"description": "Address to receive escrowed XRP."
|
||||
},
|
||||
"memos": {"$ref": "memos"},
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"description": "A hex value representing a [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1). If present, `fulfillment` is required upon execution.",
|
||||
"pattern": "^[A-F0-9]{0,256}$"
|
||||
},
|
||||
"allowCancelAfter": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "If present, the escrow may be cancelled after this time."
|
||||
},
|
||||
"allowExecuteAfter": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "If present, the escrow can not be executed before this time."
|
||||
},
|
||||
"sourceTag": {
|
||||
"$ref": "tag",
|
||||
"description": "Source tag."
|
||||
},
|
||||
"destinationTag": {
|
||||
"$ref": "tag",
|
||||
"description": "Destination tag."
|
||||
}
|
||||
},
|
||||
"required": ["amount", "destination"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
29
src/common/schemas/specifications/escrow-execution.json
Normal file
29
src/common/schemas/specifications/escrow-execution.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "escrowExecution",
|
||||
"link": "escrow-execution",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memos": {"$ref": "memos"},
|
||||
"owner": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the owner of the escrow to execute."
|
||||
},
|
||||
"escrowSequence": {
|
||||
"$ref": "sequence",
|
||||
"description": "The [account sequence number](#account-sequence-number) of the [Escrow Creation](#escrow-creation) transaction for the escrow to execute."
|
||||
},
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"description": "A hex value representing a [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1). This must match the original `condition` from the escrow creation transaction.",
|
||||
"pattern": "^[A-F0-9]{0,256}$"
|
||||
},
|
||||
"fulfillment": {
|
||||
"type": "string",
|
||||
"description": "A hex value representing the [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1) fulfillment for `condition`.",
|
||||
"pattern": "^[A-F0-9]+$"
|
||||
}
|
||||
},
|
||||
"required": ["owner", "escrowSequence"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -34,6 +34,10 @@
|
||||
"format": "date-time",
|
||||
"description": "Time after which the offer is no longer active, as an [ISO 8601 date-time](https://en.wikipedia.org/wiki/ISO_8601)."
|
||||
},
|
||||
"orderToReplace": {
|
||||
"$ref": "sequence",
|
||||
"description": "The [account sequence number](#account-sequence-number) of an order to cancel before the new order is created, effectively replacing the old order."
|
||||
},
|
||||
"memos": {"$ref": "memos"}
|
||||
},
|
||||
"required": ["direction", "quantity", "totalPrice"],
|
||||
|
||||
38
src/common/schemas/specifications/payment-channel-claim.json
Normal file
38
src/common/schemas/specifications/payment-channel-claim.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "paymentChannelClaim",
|
||||
"link": "payment-channel-claim",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"channel": {
|
||||
"$ref": "hash256",
|
||||
"description": "256-bit hexadecimal channel identifier."
|
||||
},
|
||||
"amount": {
|
||||
"$ref": "value",
|
||||
"description": "XRP balance of this channel after claim is processed."
|
||||
},
|
||||
"balance": {
|
||||
"$ref": "value",
|
||||
"description": "Amount of XRP authorized by signature."
|
||||
},
|
||||
"signature": {
|
||||
"$ref": "signature",
|
||||
"description": "Signature of this claim."
|
||||
},
|
||||
"publicKey": {
|
||||
"$ref": "publicKey",
|
||||
"description": "Public key of the channel's sender"
|
||||
},
|
||||
"renew": {
|
||||
"type": "boolean",
|
||||
"description": "Clear the channel's expiration time."
|
||||
},
|
||||
"close": {
|
||||
"type": "boolean",
|
||||
"description": "Request to close the channel."
|
||||
}
|
||||
},
|
||||
"required": ["channel"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "paymentChannelCreate",
|
||||
"link": "payment-channel-create",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"$ref": "value",
|
||||
"description": "Amount of XRP for sender to set aside in this channel."
|
||||
},
|
||||
"destination": {
|
||||
"$ref": "address",
|
||||
"description": "Address to receive XRP claims against this channel."
|
||||
},
|
||||
"settleDelay": {
|
||||
"type": "number",
|
||||
"description": "Amount of seconds the source address must wait before closing the channel if it has unclaimed XRP."
|
||||
},
|
||||
"publicKey": {
|
||||
"$ref": "publicKey",
|
||||
"description": "Public key of the key pair the source will use to sign claims against this channel."
|
||||
},
|
||||
"cancelAfter": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Time when this channel expires."
|
||||
},
|
||||
"sourceTag": {
|
||||
"$ref": "tag",
|
||||
"description": "Source tag."
|
||||
},
|
||||
"destinationTag": {
|
||||
"$ref": "tag",
|
||||
"description": "Destination tag."
|
||||
}
|
||||
},
|
||||
"required": ["amount", "destination", "settleDelay", "publicKey"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
23
src/common/schemas/specifications/payment-channel-fund.json
Normal file
23
src/common/schemas/specifications/payment-channel-fund.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "paymentChannelFund",
|
||||
"link": "payment-channel-fund",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"$ref": "value",
|
||||
"description": "Amount of XRP to fund the channel with."
|
||||
},
|
||||
"channel": {
|
||||
"$ref": "hash256",
|
||||
"description": "256-bit hexadecimal channel identifier."
|
||||
},
|
||||
"expiration": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "New expiration for this channel."
|
||||
}
|
||||
},
|
||||
"required": ["amount", "channel"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "suspendedPaymentCancellation",
|
||||
"link": "suspended-payment-cancellation",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memos": {"$ref": "memos"},
|
||||
"owner": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the owner of the suspended payment to cancel."
|
||||
},
|
||||
"suspensionSequence": {
|
||||
"$ref": "sequence",
|
||||
"description": "The [account sequence number](#account-sequence-number) of the [Suspended Payment Creation](#suspended-payment-creation) transaction for the suspended payment to cancel."
|
||||
}
|
||||
},
|
||||
"required": ["owner", "suspensionSequence"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "suspendedPaymentCreation",
|
||||
"link": "suspended-payment-creation",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {
|
||||
"$ref": "maxAdjustment",
|
||||
"description": "Fields pertaining to the source of the payment."
|
||||
},
|
||||
"destination": {
|
||||
"$ref": "destinationExactAdjustment",
|
||||
"description": "Fields pertaining to the destination of the payment."
|
||||
},
|
||||
"memos": {"$ref": "memos"},
|
||||
"digest": {
|
||||
"$ref": "hash256",
|
||||
"description": "If present, proof is required upon execution."
|
||||
},
|
||||
"allowCancelAfter": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "If present, the suspended payment may be cancelled after this time."
|
||||
},
|
||||
"allowExecuteAfter": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "If present, the suspended payment can not be executed before this time."
|
||||
}
|
||||
},
|
||||
"required": ["source", "destination"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "suspendedPaymentExecution",
|
||||
"link": "suspended-payment-execution",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memos": {"$ref": "memos"},
|
||||
"owner": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the owner of the suspended payment to execute."
|
||||
},
|
||||
"suspensionSequence": {
|
||||
"$ref": "sequence",
|
||||
"description": "The [account sequence number](#account-sequence-number) of the [Suspended Payment Creation](#suspended-payment-creation) transaction for the suspended payment to execute."
|
||||
},
|
||||
"method": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255,
|
||||
"description": "The method for verifying the proof; only method `1` is supported."
|
||||
},
|
||||
"digest": {
|
||||
"$ref": "hash256",
|
||||
"description": "The original `digest` from the suspended payment creation transaction. This is sha256 hash of `proof` string. It is replicated here so that the relatively expensive hashing operation can be delegated to a server without ledger history and the server with ledger history only has to do a quick comparison of the old digest with the new digest."
|
||||
},
|
||||
"proof": {
|
||||
"type": "string",
|
||||
"description": "A value that produces the digest when hashed. It must be 32 charaters long and contain only 8-bit characters.",
|
||||
"pattern": "^[\\x00-\\xFF]{32}$"
|
||||
}
|
||||
},
|
||||
"required": ["owner", "suspensionSequence"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const {convertKeysFromSnakeCaseToCamelCase} = require('./utils');
|
||||
import type {Connection} from './connection';
|
||||
'use strict' // eslint-disable-line strict
|
||||
const _ = require('lodash')
|
||||
const {convertKeysFromSnakeCaseToCamelCase} = require('./utils')
|
||||
import type {Connection} from './connection'
|
||||
|
||||
export type GetServerInfoResponse = {
|
||||
buildVersion: string,
|
||||
completeLedgers: string,
|
||||
hostid: string,
|
||||
hostID: string,
|
||||
ioLatencyMs: number,
|
||||
load?: {
|
||||
jobTypes: Array<Object>,
|
||||
@@ -23,49 +23,57 @@ export type GetServerInfoResponse = {
|
||||
serverState: string,
|
||||
validatedLedger: {
|
||||
age: number,
|
||||
baseFeeXrp: number,
|
||||
baseFeeXRP: string,
|
||||
hash: string,
|
||||
reserveBaseXrp: number,
|
||||
reserveIncXrp: number,
|
||||
seq: number
|
||||
reserveBaseXRP: string,
|
||||
reserveIncrementXRP: string,
|
||||
ledgerVersion: number
|
||||
},
|
||||
validationQuorum: number
|
||||
}
|
||||
|
||||
function renameKeys(object, mapping) {
|
||||
_.forEach(mapping, (to, from) => {
|
||||
object[to] = object[from];
|
||||
delete object[from];
|
||||
});
|
||||
object[to] = object[from]
|
||||
delete object[from]
|
||||
})
|
||||
}
|
||||
|
||||
function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> {
|
||||
return connection.request({command: 'server_info'}).then(response => {
|
||||
const info = convertKeysFromSnakeCaseToCamelCase(response.info);
|
||||
renameKeys(info, {hostid: 'hostID'});
|
||||
renameKeys(info.validatedLedger, {
|
||||
baseFeeXrp: 'baseFeeXRP',
|
||||
reserveBaseXrp: 'reserveBaseXRP',
|
||||
reserveIncXrp: 'reserveIncrementXRP',
|
||||
seq: 'ledgerVersion'
|
||||
});
|
||||
return info;
|
||||
});
|
||||
const info = convertKeysFromSnakeCaseToCamelCase(response.info)
|
||||
renameKeys(info, {hostid: 'hostID'})
|
||||
if (info.validatedLedger) {
|
||||
renameKeys(info.validatedLedger, {
|
||||
baseFeeXrp: 'baseFeeXRP',
|
||||
reserveBaseXrp: 'reserveBaseXRP',
|
||||
reserveIncXrp: 'reserveIncrementXRP',
|
||||
seq: 'ledgerVersion'
|
||||
})
|
||||
info.validatedLedger.baseFeeXRP =
|
||||
info.validatedLedger.baseFeeXRP.toString()
|
||||
info.validatedLedger.reserveBaseXRP =
|
||||
info.validatedLedger.reserveBaseXRP.toString()
|
||||
info.validatedLedger.reserveIncrementXRP =
|
||||
info.validatedLedger.reserveIncrementXRP.toString()
|
||||
}
|
||||
return info
|
||||
})
|
||||
}
|
||||
|
||||
function computeFeeFromServerInfo(cushion: number,
|
||||
serverInfo: GetServerInfoResponse
|
||||
): number {
|
||||
return (Number(serverInfo.validatedLedger.baseFeeXRP)
|
||||
* Number(serverInfo.loadFactor) * cushion).toString();
|
||||
* Number(serverInfo.loadFactor) * cushion).toString()
|
||||
}
|
||||
|
||||
function getFee(connection: Connection, cushion: number) {
|
||||
return getServerInfo(connection).then(
|
||||
_.partial(computeFeeFromServerInfo, cushion));
|
||||
_.partial(computeFeeFromServerInfo, cushion))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getServerInfo,
|
||||
getFee
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
'use strict' // eslint-disable-line strict
|
||||
|
||||
const txFlags = {
|
||||
// Universal flags can apply to any transaction type
|
||||
@@ -35,8 +35,13 @@ const txFlags = {
|
||||
NoRippleDirect: 0x00010000,
|
||||
PartialPayment: 0x00020000,
|
||||
LimitQuality: 0x00040000
|
||||
},
|
||||
|
||||
PaymentChannelClaim: {
|
||||
Renew: 0x00010000,
|
||||
Close: 0x00020000
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// The following are integer (as opposed to bit) flags
|
||||
// that can be set for particular transactions in the
|
||||
@@ -52,9 +57,9 @@ const txFlagIndices = {
|
||||
asfGlobalFreeze: 7,
|
||||
asfDefaultRipple: 8
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
txFlags,
|
||||
txFlagIndices
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
export type RippledAmountIOU = {
|
||||
currency: string,
|
||||
value: string,
|
||||
issuer?: string
|
||||
}
|
||||
|
||||
export type RippledAmount = string | RippledAmountIOU
|
||||
|
||||
|
||||
export type Amount = {
|
||||
value: string,
|
||||
currency: string,
|
||||
counterparty?: string
|
||||
}
|
||||
|
||||
|
||||
// Amount where counterparty and value are optional
|
||||
export type LaxLaxAmount = {
|
||||
currency: string,
|
||||
value?: string,
|
||||
counterparty?: string
|
||||
}
|
||||
|
||||
// A currency-counterparty pair, or just currency if it's XRP
|
||||
export type Issue = {
|
||||
currency: string,
|
||||
counterparty?: string
|
||||
}
|
||||
|
||||
export type Adjustment = {
|
||||
address: string,
|
||||
amount: Amount,
|
||||
tag?: number
|
||||
}
|
||||
|
||||
export type MaxAdjustment = {
|
||||
address: string,
|
||||
maxAmount: Amount,
|
||||
tag?: number
|
||||
}
|
||||
|
||||
export type MinAdjustment = {
|
||||
address: string,
|
||||
minAmount: Amount,
|
||||
tag?: number
|
||||
}
|
||||
|
||||
export type Memo = {
|
||||
type?: string,
|
||||
format?: string,
|
||||
data?: string
|
||||
}
|
||||
/* @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
|
||||
}
|
||||
|
||||
@@ -1,75 +1,59 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const BigNumber = require('bignumber.js');
|
||||
const errors = require('./errors');
|
||||
const keypairs = require('ripple-keypairs');
|
||||
const {deriveKeypair} = require('ripple-keypairs');
|
||||
'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';
|
||||
import type {Amount, RippledAmount} from './types.js'
|
||||
|
||||
function isValidSecret(secret: string): boolean {
|
||||
try {
|
||||
deriveKeypair(secret);
|
||||
return true;
|
||||
deriveKeypair(secret)
|
||||
return true
|
||||
} catch (err) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function dropsToXrp(drops: string): string {
|
||||
return (new BigNumber(drops)).dividedBy(1000000.0).toString();
|
||||
return (new BigNumber(drops)).dividedBy(1000000.0).toString()
|
||||
}
|
||||
|
||||
function xrpToDrops(xrp: string): string {
|
||||
return (new BigNumber(xrp)).times(1000000.0).floor().toString();
|
||||
return (new BigNumber(xrp)).times(1000000.0).floor().toString()
|
||||
}
|
||||
|
||||
function toRippledAmount(amount: Amount): RippledAmount {
|
||||
if (amount.currency === 'XRP') {
|
||||
return xrpToDrops(amount.value);
|
||||
return xrpToDrops(amount.value)
|
||||
}
|
||||
return {
|
||||
currency: amount.currency,
|
||||
issuer: amount.counterparty ? amount.counterparty :
|
||||
(amount.issuer ? amount.issuer : undefined),
|
||||
value: amount.value
|
||||
};
|
||||
}
|
||||
|
||||
function generateAddress(options?: Object): Object {
|
||||
const secret = keypairs.generateSeed(options);
|
||||
const keypair = keypairs.deriveKeypair(secret);
|
||||
const address = keypairs.deriveAddress(keypair.publicKey);
|
||||
return {secret, address};
|
||||
}
|
||||
|
||||
function generateAddressAPI(options?: Object): Object {
|
||||
try {
|
||||
return generateAddress(options);
|
||||
} catch (error) {
|
||||
throw new errors.UnexpectedError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g;
|
||||
function convertKeysFromSnakeCaseToCamelCase(obj: any): any {
|
||||
if (typeof obj === 'object') {
|
||||
let newKey;
|
||||
let newKey
|
||||
return _.reduce(obj, (result, value, key) => {
|
||||
newKey = 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());
|
||||
newKey = key.replace(FINDSNAKE, r => r[0] + r[2].toUpperCase())
|
||||
}
|
||||
result[newKey] = convertKeysFromSnakeCaseToCamelCase(value);
|
||||
return result;
|
||||
}, {});
|
||||
result[newKey] = convertKeysFromSnakeCaseToCamelCase(value)
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
return obj;
|
||||
return obj
|
||||
}
|
||||
|
||||
function removeUndefined(obj: Object): Object {
|
||||
return _.omit(obj, _.isUndefined);
|
||||
return _.omit(obj, _.isUndefined)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +62,7 @@ function removeUndefined(obj: Object): Object {
|
||||
*
|
||||
*/
|
||||
function rippleToUnixTimestamp(rpepoch: number): number {
|
||||
return (rpepoch + 0x386D4380) * 1000;
|
||||
return (rpepoch + 0x386D4380) * 1000
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,26 +70,24 @@ function rippleToUnixTimestamp(rpepoch: number): number {
|
||||
* @return {Number} seconds since ripple epoch ( 1/1/2000 GMT)
|
||||
*/
|
||||
function unixToRippleTimestamp(timestamp: number): number {
|
||||
return Math.round(timestamp / 1000) - 0x386D4380;
|
||||
return Math.round(timestamp / 1000) - 0x386D4380
|
||||
}
|
||||
|
||||
function rippleTimeToISO8601(rippleTime: number): string {
|
||||
return new Date(rippleToUnixTimestamp(rippleTime)).toISOString();
|
||||
return new Date(rippleToUnixTimestamp(rippleTime)).toISOString()
|
||||
}
|
||||
|
||||
function iso8601ToRippleTime(iso8601: string): number {
|
||||
return unixToRippleTimestamp(Date.parse(iso8601));
|
||||
return unixToRippleTimestamp(Date.parse(iso8601))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
dropsToXrp,
|
||||
xrpToDrops,
|
||||
toRippledAmount,
|
||||
generateAddress,
|
||||
generateAddressAPI,
|
||||
convertKeysFromSnakeCaseToCamelCase,
|
||||
removeUndefined,
|
||||
rippleTimeToISO8601,
|
||||
iso8601ToRippleTime,
|
||||
isValidSecret
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const ValidationError = require('./errors').ValidationError;
|
||||
const schemaValidate = require('./schema-validator').schemaValidate;
|
||||
'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);
|
||||
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');
|
||||
throw error('minLedgerVersion must not be greater than maxLedgerVersion')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateOptions(schema, instance) {
|
||||
schemaValidate(schema, instance);
|
||||
validateLedgerRange(instance.options);
|
||||
schemaValidate(schema, instance)
|
||||
validateLedgerRange(instance.options)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@@ -33,6 +33,7 @@ module.exports = {
|
||||
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'),
|
||||
@@ -40,15 +41,27 @@ module.exports = {
|
||||
_.partial(schemaValidate, 'prepareOrderCancellationParameters'),
|
||||
prepareTrustline: _.partial(schemaValidate, 'prepareTrustlineParameters'),
|
||||
prepareSettings: _.partial(schemaValidate, 'prepareSettingsParameters'),
|
||||
prepareSuspendedPaymentCreation: _.partial(schemaValidate,
|
||||
'prepareSuspendedPaymentCreationParameters'),
|
||||
prepareSuspendedPaymentCancellation: _.partial(schemaValidate,
|
||||
'prepareSuspendedPaymentCancellationParameters'),
|
||||
prepareSuspendedPaymentExecution: _.partial(schemaValidate,
|
||||
'prepareSuspendedPaymentExecutionParameters'),
|
||||
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')
|
||||
};
|
||||
}
|
||||
|
||||
59
src/common/wswrapper.js
Normal file
59
src/common/wswrapper.js
Normal file
@@ -0,0 +1,59 @@
|
||||
'use strict' // eslint-disable-line strict
|
||||
|
||||
const {EventEmitter} = require('events')
|
||||
|
||||
function unsused() {}
|
||||
|
||||
/**
|
||||
* Provides `EventEmitter` interface for native browser `WebSocket`,
|
||||
* same, as `ws` package provides.
|
||||
*/
|
||||
class WSWrapper extends EventEmitter {
|
||||
constructor(url, protocols = null, websocketOptions = {}) {
|
||||
super()
|
||||
unsused(protocols)
|
||||
unsused(websocketOptions)
|
||||
this.setMaxListeners(Infinity)
|
||||
|
||||
this._ws = new WebSocket(url)
|
||||
|
||||
this._ws.onclose = () => {
|
||||
this.emit('close')
|
||||
}
|
||||
|
||||
this._ws.onopen = () => {
|
||||
this.emit('open')
|
||||
}
|
||||
|
||||
this._ws.onerror = error => {
|
||||
this.emit('error', error)
|
||||
}
|
||||
|
||||
this._ws.onmessage = message => {
|
||||
this.emit('message', message.data)
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.readyState === 1) {
|
||||
this._ws.close()
|
||||
}
|
||||
}
|
||||
|
||||
send(message) {
|
||||
this._ws.send(message)
|
||||
}
|
||||
|
||||
get readyState() {
|
||||
return this._ws.readyState
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WSWrapper.CONNECTING = 0
|
||||
WSWrapper.OPEN = 1
|
||||
WSWrapper.CLOSING = 2
|
||||
WSWrapper.CLOSED = 3
|
||||
|
||||
module.exports = WSWrapper
|
||||
|
||||
86
src/http.js
Normal file
86
src/http.js
Normal file
@@ -0,0 +1,86 @@
|
||||
/* eslint-disable new-cap */
|
||||
'use strict' // eslint-disable-line strict
|
||||
|
||||
const assert = require('assert')
|
||||
const _ = require('lodash')
|
||||
const jayson = require('jayson')
|
||||
|
||||
const RippleAPI = require('./api').RippleAPI
|
||||
|
||||
|
||||
/* istanbul ignore next */
|
||||
function createHTTPServer(options, httpPort) {
|
||||
const rippleAPI = new RippleAPI(options)
|
||||
|
||||
const methodNames = _.filter(_.keys(RippleAPI.prototype), k => {
|
||||
return typeof RippleAPI.prototype[k] === 'function'
|
||||
&& k !== 'connect'
|
||||
&& k !== 'disconnect'
|
||||
&& k !== 'constructor'
|
||||
&& k !== 'RippleAPI'
|
||||
})
|
||||
|
||||
function applyPromiseWithCallback(fnName, callback, args_) {
|
||||
try {
|
||||
let args = args_
|
||||
if (!_.isArray(args_)) {
|
||||
const fnParameters = jayson.Utils.getParameterNames(rippleAPI[fnName])
|
||||
args = fnParameters.map(name => args_[name])
|
||||
const defaultArgs = _.omit(args_, fnParameters)
|
||||
assert(_.size(defaultArgs) <= 1,
|
||||
'Function must have no more than one default argument')
|
||||
if (_.size(defaultArgs) > 0) {
|
||||
args.push(defaultArgs[_.keys(defaultArgs)[0]])
|
||||
}
|
||||
}
|
||||
Promise.resolve(rippleAPI[fnName](...args))
|
||||
.then(res => callback(null, res))
|
||||
.catch(err => {
|
||||
callback({code: 99, message: err.message, data: {name: err.name}})
|
||||
})
|
||||
} catch (err) {
|
||||
callback({code: 99, message: err.message, data: {name: err.name}})
|
||||
}
|
||||
}
|
||||
|
||||
const methods = {}
|
||||
_.forEach(methodNames, fn => {
|
||||
methods[fn] = jayson.Method((args, cb) => {
|
||||
applyPromiseWithCallback(fn, cb, args)
|
||||
}, {collect: true})
|
||||
})
|
||||
|
||||
const server = jayson.server(methods)
|
||||
let httpServer = null
|
||||
|
||||
return {
|
||||
server: server,
|
||||
start: function() {
|
||||
if (httpServer !== null) {
|
||||
return Promise.reject('Already started')
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
rippleAPI.connect().then(() => {
|
||||
httpServer = server.http()
|
||||
httpServer.listen(httpPort, resolve)
|
||||
})
|
||||
})
|
||||
},
|
||||
stop: function() {
|
||||
if (httpServer === null) {
|
||||
return Promise.reject('Not started')
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
rippleAPI.disconnect()
|
||||
httpServer.close(() => {
|
||||
httpServer = null
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createHTTPServer
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
'use strict' // eslint-disable-line strict
|
||||
|
||||
module.exports = {
|
||||
RippleAPI: require('./api').RippleAPI,
|
||||
// Broadcast api is experimental
|
||||
RippleAPIBroadcast: require('./broadcast').RippleAPIBroadcast
|
||||
};
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user