mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-12 00:35:47 +00:00
Compare commits
279 Commits
0.12.6
...
0.13.0-rc4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37198bde66 | ||
|
|
281c056f6c | ||
|
|
49a513cd07 | ||
|
|
7a95aabbf4 | ||
|
|
83874ec096 | ||
|
|
9270d0a33d | ||
|
|
30295efdb4 | ||
|
|
f1342c1456 | ||
|
|
194b73c293 | ||
|
|
89e5f79bbb | ||
|
|
82d7ce7ac2 | ||
|
|
0cc4c704f8 | ||
|
|
dde762a1d6 | ||
|
|
1c86e246c7 | ||
|
|
2d173c8e69 | ||
|
|
600fd34d30 | ||
|
|
4cb9cf801c | ||
|
|
50fb8789b4 | ||
|
|
fb8dc44ec1 | ||
|
|
0781caa8bc | ||
|
|
2cdb23f0dd | ||
|
|
8e536c00b9 | ||
|
|
8ff154cc2d | ||
|
|
daaae6e01e | ||
|
|
a64a4e697a | ||
|
|
3f51d8cc12 | ||
|
|
9f9e76f8b9 | ||
|
|
5b51db158d | ||
|
|
a4d1509448 | ||
|
|
bbd51a03b6 | ||
|
|
b55b82b2fd | ||
|
|
fdb0f101bd | ||
|
|
0afca5633d | ||
|
|
7c0d9a7172 | ||
|
|
f6b7e27c67 | ||
|
|
b8624bc55f | ||
|
|
2eec30756d | ||
|
|
6b44ce8973 | ||
|
|
ed0b501716 | ||
|
|
0fd391af72 | ||
|
|
fe9c1ada88 | ||
|
|
4c1f4ef58c | ||
|
|
10afc770ff | ||
|
|
8543e60f86 | ||
|
|
116d7e0f29 | ||
|
|
68adaec55b | ||
|
|
03640efef5 | ||
|
|
c6f450842e | ||
|
|
e583eb4592 | ||
|
|
7fffbe0c64 | ||
|
|
63e3b71eb5 | ||
|
|
823ef738fe | ||
|
|
0977ef0ec2 | ||
|
|
cecf3f3d22 | ||
|
|
472fbce23a | ||
|
|
e44aea1767 | ||
|
|
d682d90d86 | ||
|
|
141aa17dfc | ||
|
|
0b09e53479 | ||
|
|
528d8bf25d | ||
|
|
03a2109e24 | ||
|
|
b38b9bced6 | ||
|
|
ea063d0c95 | ||
|
|
7f93929014 | ||
|
|
4cd10ecb87 | ||
|
|
6ef30debd2 | ||
|
|
4766bace4e | ||
|
|
261500a3a4 | ||
|
|
fae22b7023 | ||
|
|
4568b39997 | ||
|
|
4a218cacfa | ||
|
|
34a4dd3077 | ||
|
|
a383bd7e52 | ||
|
|
e76e693bdb | ||
|
|
2c52e4aa69 | ||
|
|
13dee36e93 | ||
|
|
6e180439d1 | ||
|
|
e8d0c1ae95 | ||
|
|
068bda0c95 | ||
|
|
ab694381d5 | ||
|
|
dc2a6c75cf | ||
|
|
98dbba8f27 | ||
|
|
9a1b80d77a | ||
|
|
a655be30d6 | ||
|
|
e5aabc3072 | ||
|
|
2cd32d58ad | ||
|
|
0c02b92717 | ||
|
|
c58a077a2f | ||
|
|
6e7dc9d7d3 | ||
|
|
2695f4302a | ||
|
|
9a533ab807 | ||
|
|
a037952493 | ||
|
|
dc96795a02 | ||
|
|
8d9746d7b1 | ||
|
|
00342c4239 | ||
|
|
e48df2c1fd | ||
|
|
6ade0f6554 | ||
|
|
a88157bb92 | ||
|
|
00f318284f | ||
|
|
2e12dc6d53 | ||
|
|
34435d4d05 | ||
|
|
a99452b773 | ||
|
|
a05cb39ab0 | ||
|
|
0c69f7f10e | ||
|
|
8d50034265 | ||
|
|
64f451e904 | ||
|
|
4787e5d29a | ||
|
|
194f76d57f | ||
|
|
d2ee5cb0bc | ||
|
|
040298db2c | ||
|
|
b4e6d4b98c | ||
|
|
a2b31e2677 | ||
|
|
e997c44a18 | ||
|
|
b27011fb38 | ||
|
|
b477eb238b | ||
|
|
02bc256225 | ||
|
|
9f7293127c | ||
|
|
61a0ea7eac | ||
|
|
51ef93e23b | ||
|
|
ab11220e27 | ||
|
|
b23d588747 | ||
|
|
a71dc28523 | ||
|
|
2de0e13ec5 | ||
|
|
d0c922ed13 | ||
|
|
8c82ebec79 | ||
|
|
ddd83d10fa | ||
|
|
031375e701 | ||
|
|
4bc285313c | ||
|
|
f42dd69b53 | ||
|
|
1dae06fdd8 | ||
|
|
ff29247b9e | ||
|
|
d9eca203ed | ||
|
|
4a85182a79 | ||
|
|
055d275f0a | ||
|
|
eb7bbe5715 | ||
|
|
8d5752883f | ||
|
|
2b5f356de8 | ||
|
|
c9610900fd | ||
|
|
79b1a65a7b | ||
|
|
df21b9453f | ||
|
|
22257bdd2b | ||
|
|
aa3767b180 | ||
|
|
c073c2b7de | ||
|
|
529a55efb0 | ||
|
|
c36567e062 | ||
|
|
f7873f3b41 | ||
|
|
6b54f1c1eb | ||
|
|
1fb1bc7404 | ||
|
|
aa646a3acf | ||
|
|
18ac8a9d03 | ||
|
|
7c357c5d52 | ||
|
|
816db9e0dc | ||
|
|
fa9e1de4df | ||
|
|
137d947606 | ||
|
|
77a05c1881 | ||
|
|
ab13e3fe18 | ||
|
|
fc4b085026 | ||
|
|
67e8f6ab65 | ||
|
|
792b30c8b5 | ||
|
|
3407aadfb8 | ||
|
|
29e59ebfd2 | ||
|
|
286a684963 | ||
|
|
3ef586d2d3 | ||
|
|
5889037a71 | ||
|
|
5e3f3969f5 | ||
|
|
eecf45918b | ||
|
|
6d91e6e6b2 | ||
|
|
7808f87060 | ||
|
|
6c48b22eea | ||
|
|
7344f1178b | ||
|
|
5a6a3ce6e0 | ||
|
|
f3a54bf02a | ||
|
|
766dc5d0ce | ||
|
|
f8f196903a | ||
|
|
337c41fe10 | ||
|
|
fb8eefd00d | ||
|
|
3082b959f6 | ||
|
|
487371737c | ||
|
|
14ccc9359d | ||
|
|
665b76271c | ||
|
|
11ca00bb45 | ||
|
|
046d397dfb | ||
|
|
58cc01b6d3 | ||
|
|
6a3eb7b9b9 | ||
|
|
935a463d3b | ||
|
|
f2f4173d7b | ||
|
|
941aaf6d8b | ||
|
|
1068b68568 | ||
|
|
e76b9a9051 | ||
|
|
410ac117f6 | ||
|
|
fa89c4dee8 | ||
|
|
a464ca2368 | ||
|
|
befd89c3d7 | ||
|
|
49640cf282 | ||
|
|
2ac4549712 | ||
|
|
6bffe06c3b | ||
|
|
13e9ad45f9 | ||
|
|
193fcc9014 | ||
|
|
30529b7a04 | ||
|
|
38b254e7f0 | ||
|
|
c4b98d2139 | ||
|
|
1309b58592 | ||
|
|
9b9d2dc32b | ||
|
|
73020fb8ae | ||
|
|
8221db833f | ||
|
|
09b10d3f2c | ||
|
|
c31798c7f8 | ||
|
|
064c5e9e50 | ||
|
|
077a53475d | ||
|
|
32ca23a00b | ||
|
|
1a7cdd7d04 | ||
|
|
85befa467b | ||
|
|
9b956e57ac | ||
|
|
93c0c49002 | ||
|
|
44954621e0 | ||
|
|
96e5d484da | ||
|
|
4efe0b920e | ||
|
|
d158cc7fc1 | ||
|
|
034cd4eaf6 | ||
|
|
d5f3d90486 | ||
|
|
99e076b7dd | ||
|
|
8f9aec83f2 | ||
|
|
87a8745a64 | ||
|
|
2ab51d7a8a | ||
|
|
3e0f43e44e | ||
|
|
6a763fab18 | ||
|
|
3fe6726789 | ||
|
|
5b4deabd90 | ||
|
|
84bc7dd4aa | ||
|
|
3960b4e11f | ||
|
|
141215fc38 | ||
|
|
2446e2f6da | ||
|
|
81a9bc0739 | ||
|
|
64e86f403e | ||
|
|
77f1351e5b | ||
|
|
47a87f3a92 | ||
|
|
d2df75dc25 | ||
|
|
d92fbfb7aa | ||
|
|
1b3be55711 | ||
|
|
8d98e443c5 | ||
|
|
46121edd62 | ||
|
|
1a32536ac8 | ||
|
|
85bf6891f9 | ||
|
|
1ccca1c4ec | ||
|
|
22cd70e53f | ||
|
|
d8aad1444e | ||
|
|
621dfd9ca5 | ||
|
|
2ad6a1a77e | ||
|
|
8f37438a08 | ||
|
|
ff6ac0333c | ||
|
|
1b936d2aa2 | ||
|
|
df0cff969c | ||
|
|
46e2598499 | ||
|
|
0b32378ab5 | ||
|
|
bf25eb350f | ||
|
|
97cea2ce4d | ||
|
|
82ed402b16 | ||
|
|
ca7b69a2a0 | ||
|
|
d9c61a9431 | ||
|
|
3b636ce2d1 | ||
|
|
2196352335 | ||
|
|
823d7048ba | ||
|
|
d066e1145d | ||
|
|
fb7021abcc | ||
|
|
9c14fb2379 | ||
|
|
a114bf42c4 | ||
|
|
87b6c09de3 | ||
|
|
f1c95112bd | ||
|
|
76d8c8b061 | ||
|
|
7cbcb9a220 | ||
|
|
4433ac57bd | ||
|
|
5379da4874 | ||
|
|
d488ce55b3 | ||
|
|
908e306f04 | ||
|
|
62b5953abe | ||
|
|
35ae968d9f | ||
|
|
22dc39b920 | ||
|
|
278331cc4a | ||
|
|
16e3541a10 |
@@ -1,7 +1,14 @@
|
||||
[ignore]
|
||||
.*/src/api/.*
|
||||
.*/src/core/.*
|
||||
.*/dist/.*
|
||||
.*/test/fixtures/.*
|
||||
.*/node_modules/flow-bin/.*
|
||||
|
||||
[include]
|
||||
./node_modules/
|
||||
|
||||
[libs]
|
||||
|
||||
[options]
|
||||
module.system=node
|
||||
|
||||
15
.travis.yml
15
.travis.yml
@@ -1,18 +1,9 @@
|
||||
sudo: false # use faster docker containers
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.12"
|
||||
before_script:
|
||||
- npm install -g eslint
|
||||
- curl 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc' > ./eslintrc
|
||||
- eslint --reset -c ./eslintrc $(git --no-pager diff --name-only -M100% --diff-filter=AM --relative $(git merge-base FETCH_HEAD origin/HEAD) FETCH_HEAD | grep "\.js$")
|
||||
script: MOCHA_REPORTER=tap npm test --coverage
|
||||
after_success:
|
||||
- npm run coveralls
|
||||
- sh -c "git log | head -12"
|
||||
script: bin/ci.sh
|
||||
notifications:
|
||||
email: false
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/d1ec4245f90231619d30
|
||||
on_success: change # options: [always|never|change] default: always
|
||||
on_failure: always # options: [always|never|change] default: always
|
||||
on_start: false # default: false
|
||||
|
||||
30
Gulpfile.js
30
Gulpfile.js
@@ -3,17 +3,10 @@
|
||||
'use strict';
|
||||
var _ = require('lodash');
|
||||
var gulp = require('gulp');
|
||||
var gutil = require('gulp-util');
|
||||
var watch = require('gulp-watch');
|
||||
var plumber = require('gulp-plumber');
|
||||
var filelog = require('gulp-filelog');
|
||||
var cleanDest = require('gulp-clean-dest');
|
||||
var uglify = require('gulp-uglify');
|
||||
var rename = require('gulp-rename');
|
||||
var webpack = require('webpack');
|
||||
var bump = require('gulp-bump');
|
||||
var react = require('gulp-react');
|
||||
var flow = require('gulp-flowtype');
|
||||
var argv = require('yargs').argv;
|
||||
|
||||
var pkg = require('./package.json');
|
||||
@@ -39,10 +32,6 @@ function webpackConfig(extension, overrides) {
|
||||
return _.assign({}, defaults, overrides);
|
||||
}
|
||||
|
||||
function logPluginError(error) {
|
||||
gutil.log(error.toString());
|
||||
}
|
||||
|
||||
gulp.task('build', function(callback) {
|
||||
webpack(webpackConfig('.js'), callback);
|
||||
});
|
||||
@@ -118,25 +107,6 @@ gulp.task('watch', function() {
|
||||
gulp.watch('src/*', ['build-debug']);
|
||||
});
|
||||
|
||||
// To use this, each javascript file must have /* @flow */ on the first line
|
||||
gulp.task('typecheck', function() {
|
||||
return gulp.src('src/*.js')
|
||||
.pipe(flow({ // note: do not set the 'all' option, it is broken
|
||||
weak: true, // remove this after all errors are addressed
|
||||
killFlow: true
|
||||
}));
|
||||
});
|
||||
|
||||
gulp.task('strip', function() {
|
||||
return gulp.src('src/*.js')
|
||||
.pipe(watch('src/*.js'))
|
||||
.pipe(cleanDest('out')) // delete outdated output file before stripping
|
||||
.pipe(plumber()) // prevent an error in one file from ending build
|
||||
.pipe(react({stripTypes: true}).on('error', logPluginError))
|
||||
.pipe(filelog())
|
||||
.pipe(gulp.dest('out'));
|
||||
});
|
||||
|
||||
gulp.task('version-bump', function() {
|
||||
if (!argv.type) {
|
||||
throw new Error('No type found, pass it in using the --type argument');
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
##0.13.0
|
||||
|
||||
+ Added experimental version of RippleAPI
|
||||
- [RippleAPI README and samples](https://github.com/ripple/ripple-lib/tree/develop/docs/samples)
|
||||
- [Method documentation](https://rawgit.com/ripple/ripple-lib/develop/docs/api.html)
|
||||
+ [Fix bug where the paths would be set with an empty array](https://github.com/ripple/ripple-lib/commit/83874ec0962da311b76f2385623e51c68bc39035)
|
||||
|
||||
##0.12.6
|
||||
|
||||
+ [Fix webpack require failure due to "./" notation](https://github.com/ripple/ripple-lib/commit/8d9746d7b10be203ee613df523c2522012ff1baf)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
A JavaScript API for interacting with Ripple in Node.js and the browser
|
||||
|
||||
[](https://travis-ci.org/ripple/ripple-lib) [](https://coveralls.io/r/ripple/ripple-lib?branch=develop)
|
||||
[](https://circleci.com/gh/ripple/ripple-lib/tree/develop) [](https://coveralls.io/r/ripple/ripple-lib?branch=develop)
|
||||
|
||||
[](https://www.npmjs.org/package/ripple-lib)
|
||||
|
||||
@@ -44,7 +44,7 @@ A JavaScript API for interacting with Ripple in Node.js and the browser
|
||||
$ bower install ripple
|
||||
```
|
||||
|
||||
See the [bower-ripple repo](https://github.com/ripple/bower-ripple) for additional bower instructions
|
||||
See the [bower-ripple repo](https://github.com/ripple/bower-ripple) for additional bower instructions.
|
||||
|
||||
|
||||
**Building ripple-lib for browser environments**
|
||||
|
||||
58
bin/ci.sh
Executable file
58
bin/ci.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
NODE_INDEX="$1"
|
||||
TOTAL_NODES="$2"
|
||||
|
||||
typecheck() {
|
||||
npm install -g flow-bin
|
||||
npm run typecheck
|
||||
}
|
||||
|
||||
lint() {
|
||||
REPO_URL="https://raw.githubusercontent.com/ripple/javascript-style-guide"
|
||||
curl "$REPO_URL/es6/eslintrc" > ./eslintrc
|
||||
echo "plugins: [flowtype]" >> ./eslintrc
|
||||
node_modules/.bin/eslint -c ./eslintrc $(git --no-pager diff --name-only -M100% --diff-filter=AM --relative $(git merge-base FETCH_HEAD origin/HEAD) FETCH_HEAD | grep "\.js$")
|
||||
}
|
||||
|
||||
unittest() {
|
||||
# test "src"
|
||||
npm test --coverage
|
||||
npm run coveralls
|
||||
|
||||
# test compiled version in "dist/npm"
|
||||
ln -nfs ../../dist/npm/core test/node_modules/ripple-lib
|
||||
ln -nfs ../../dist/npm test/node_modules/ripple-api
|
||||
npm test
|
||||
}
|
||||
|
||||
oneNode() {
|
||||
lint
|
||||
typecheck
|
||||
unittest
|
||||
}
|
||||
|
||||
twoNodes() {
|
||||
case "$NODE_INDEX" in
|
||||
0) lint && unittest;;
|
||||
1) typecheck;;
|
||||
*) echo "ERROR: invalid usage"; exit 2;;
|
||||
esac
|
||||
}
|
||||
|
||||
threeNodes() {
|
||||
case "$NODE_INDEX" in
|
||||
0) lint;;
|
||||
1) typecheck;;
|
||||
2) unittest;;
|
||||
*) echo "ERROR: invalid usage"; exit 2;;
|
||||
esac
|
||||
}
|
||||
|
||||
case "$TOTAL_NODES" in
|
||||
"") oneNode;;
|
||||
1) oneNode;;
|
||||
2) twoNodes;;
|
||||
3) threeNodes;;
|
||||
*) echo "ERROR: invalid usage"; exit 2;;
|
||||
esac
|
||||
7
circle.yml
Normal file
7
circle.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
machine:
|
||||
node:
|
||||
version: 0.12.0
|
||||
test:
|
||||
override:
|
||||
- bin/ci.sh "$CIRCLE_NODE_INDEX" "$CIRCLE_NODE_TOTAL":
|
||||
parallel: true
|
||||
@@ -173,7 +173,7 @@ See the [wiki](https://ripple.com/wiki/JSON_Messages#subscribe) for details on s
|
||||
|
||||
##Submitting a payment to the network
|
||||
|
||||
Submitting a payment transaction to the Ripple network involves connecting to a `Remote`, creating a transaction, signing it with the user's secret, and submitting it to the `rippled` server. Note that the `Amount` module is used to convert human-readable amounts like '1XRP' or '10.50USD' to the type of Amount object used by the Ripple network.
|
||||
Submitting a payment transaction to the Ripple network involves connecting to a `Remote`, creating a transaction, signing it with the user's secret, and submitting it to the `rippled` server. Note that the `Amount` module is used to convert human-readable amounts like '1 XRP' or '10.50 USD' to the type of Amount object used by the Ripple network.
|
||||
|
||||
```js
|
||||
/* Loading ripple-lib Remote and Amount modules in Node.js */
|
||||
@@ -187,7 +187,7 @@ var Amount = require('ripple-lib').Amount;
|
||||
var MY_ADDRESS = 'rrrMyAddress';
|
||||
var MY_SECRET = 'secret';
|
||||
var RECIPIENT = 'rrrRecipient';
|
||||
var AMOUNT = Amount.from_human('1XRP');
|
||||
var AMOUNT = Amount.from_human('1 USD').set_issuer('rrrIssuer');
|
||||
|
||||
var remote = new Remote({ /* Remote options */ });
|
||||
|
||||
|
||||
358
docs/api.html
Normal file
358
docs/api.html
Normal file
@@ -0,0 +1,358 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.method {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.details {
|
||||
font-family: "Courier New", monospace;
|
||||
white-space: pre;
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function toggle(element) {
|
||||
var results = element.parentElement.getElementsByClassName('details');
|
||||
if (results.length > 0) {
|
||||
var style = results[0].style;
|
||||
style.display = (style.display === 'block') ? 'none' : 'block';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2><a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/index.js">RippleAPI</a></h2>
|
||||
|
||||
<div class="method">
|
||||
connect()
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
disconnect()
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
isConnected()
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
getServerInfo()
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
getFee()
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
getLedgerVersion()
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-transaction.json">getTransaction</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/hash256.json">identifier</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/transaction-options.json">options</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
identifier: txhash
|
||||
options: {minLedgerVersion: int, maxLedgerVersion: int}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-transactions.json">getTransactions</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/transactions-options.json">options</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
options: {
|
||||
start: txhash,
|
||||
limit: int,
|
||||
minLedgerVersion: int,
|
||||
maxLedgerVersion: int,
|
||||
earliestFirst: bool,
|
||||
excludeFailures: bool,
|
||||
initiated: bool,
|
||||
counterparty: address,
|
||||
types: [string],
|
||||
binary: bool
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-trustlines.json">getTrustlines</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/trustlines-options.json">options</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
options: {counterparty: address, currency: string, limit: int, ledgerVersion: int}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-balances.json">getBalances</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/trustlines-options.json">options</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
options: {counterparty: address, currency: string, limit: int, ledgerVersion: int}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-paths.json">getPaths</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/pathfind.json">pathfind</a>
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
pathfind: {
|
||||
source: {
|
||||
address: address,
|
||||
currencies: [{
|
||||
currency: string,
|
||||
counterparty: address
|
||||
}]
|
||||
},
|
||||
destination: adjustment
|
||||
}
|
||||
|
||||
adjustment = {address: address, amount: amount, tag?: int}
|
||||
amount = {currency: string, counterparty: address, value: floatstr}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-orders.json">getOrders</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/orders-options.json">options</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
options: {limit: int, ledverVersion: int}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-orderbook.json">getOrderbook</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/orderbook.json">orderbook</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/orders-options.json">options</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
orderbook: {
|
||||
base: {
|
||||
currency,
|
||||
counterparty
|
||||
},
|
||||
counter: {
|
||||
currency,
|
||||
counterparty
|
||||
}
|
||||
}
|
||||
options: {limit: int, ledverVersion: int}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-settings.json">getSettings</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/settings-options.json">options</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
options: {ledgerVersion: int}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/get-account-info.json">getAccountInfo</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/settings-options.json">options</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
options: {ledgerVersion: int}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/tx.json">preparePayment</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/payment.json">payment</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/instructions.json">instructions</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
payment: {
|
||||
source: adjustment,
|
||||
destination: adjustment,
|
||||
paths?: string,
|
||||
slippage?: strfloat,
|
||||
memos?: [{
|
||||
type: string,
|
||||
format: string,
|
||||
data: string
|
||||
}],
|
||||
invoiceID?: hash256,
|
||||
allowPartialPayment?: bool,
|
||||
noDirectRipple?: bool,
|
||||
limitQuality?: bool
|
||||
}
|
||||
|
||||
adjustment = {address: address, amount: amount, tag?: int}
|
||||
amount = {currency: string, counterparty: address, value: floatstr}
|
||||
|
||||
instructions: {
|
||||
sequence: int,
|
||||
fee: floatstr,
|
||||
maxFee: floatstr,
|
||||
maxLedgerVersion: int,
|
||||
maxLedgerVersionOffset: int
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/tx.json">prepareTrustline</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/trustline.json">trustline</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/instructions.json">instructions</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
trustline: {
|
||||
currency: string,
|
||||
counterparty: address,
|
||||
limit: strfloat,
|
||||
qualityIn?: float,
|
||||
qualityOut?: float,
|
||||
allowRippling?: bool,
|
||||
authorized?: bool,
|
||||
frozen?: bool
|
||||
}
|
||||
|
||||
instructions: {
|
||||
sequence: int,
|
||||
fee: floatstr,
|
||||
maxFee: floatstr,
|
||||
maxLedgerVersion: int,
|
||||
maxLedgerVersionOffset: int
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/tx.json">prepareOrder</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/order.json">order</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/instructions.json">instructions</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
order: {
|
||||
direction: ("buy"|"sell"),
|
||||
quantity: amount,
|
||||
totalPrice: amount,
|
||||
immediateOrCancel?: bool,
|
||||
fillOrKill?: bool,
|
||||
passive?: bool
|
||||
}
|
||||
|
||||
amount = {currency: string, counterparty: address, value: floatstr}
|
||||
|
||||
instructions: {
|
||||
sequence: int,
|
||||
fee: floatstr,
|
||||
maxFee: floatstr,
|
||||
maxLedgerVersion: int,
|
||||
maxLedgerVersionOffset: int
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/tx.json">prepareOrderCancellation</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/sequence.json">sequence</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/instructions.json">instructions</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
sequence: int
|
||||
|
||||
instructions: {
|
||||
sequence: int,
|
||||
fee: floatstr,
|
||||
maxFee: floatstr,
|
||||
maxLedgerVersion: int,
|
||||
maxLedgerVersionOffset: int
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/tx.json">prepareSettings</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/address.json">account</a>,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/settings.json">settings</a>[,
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/instructions.json">instructions</a>]
|
||||
)
|
||||
<a href="#" onclick="javascript:toggle(this)">+</a>
|
||||
<div class="details">
|
||||
settings: {
|
||||
passwordSpent: bool,
|
||||
requireDestinationTag: bool,
|
||||
requireAuthorization: bool,
|
||||
disallowIncomingXRP: bool,
|
||||
disableMasterKey: bool,
|
||||
enableTransactionIDTracking: bool,
|
||||
noFreeze: bool,
|
||||
globalFreeze: bool,
|
||||
defaultRipple: bool,
|
||||
emailHash: hash128,
|
||||
walletLocator: hash256,
|
||||
walletSize: int,
|
||||
messageKey: string,
|
||||
domain: string,
|
||||
transferRate: float,
|
||||
signers: string,
|
||||
regularKey: address
|
||||
}
|
||||
|
||||
instructions: {
|
||||
sequence: int,
|
||||
fee: floatstr,
|
||||
maxFee: floatstr,
|
||||
maxLedgerVersion: int,
|
||||
maxLedgerVersionOffset: int
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/sign.json">sign</a>(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/tx.json">txJSON</a>,
|
||||
secret)
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
submit(
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/schemas/blob.json">txBlob</a>
|
||||
)
|
||||
</div>
|
||||
|
||||
<div class="method">
|
||||
generateWallet()
|
||||
</div>
|
||||
|
||||
<a href="https://github.com/ripple/ripple-lib/blob/develop/src/api/common/errors.js">errors</a>
|
||||
</body>
|
||||
</html>
|
||||
3
docs/samples/README
Normal file
3
docs/samples/README
Normal file
@@ -0,0 +1,3 @@
|
||||
Usage:
|
||||
babel-node balances.js
|
||||
babel-node payment.js (requires setting address and secret in source file first)
|
||||
12
docs/samples/balances.js
Normal file
12
docs/samples/balances.js
Normal file
@@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
const RippleAPI = require('../../src').RippleAPI; // require('ripple-lib')
|
||||
|
||||
const api = new RippleAPI({servers: ['wss://s1.ripple.com:443']});
|
||||
const address = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV';
|
||||
|
||||
api.connect().then(() => {
|
||||
api.getBalances(address).then(balances => {
|
||||
console.log(JSON.stringify(balances, null, 2));
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
41
docs/samples/payment.js
Normal file
41
docs/samples/payment.js
Normal file
@@ -0,0 +1,41 @@
|
||||
'use strict';
|
||||
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 instructions = {maxLedgerVersionOffset: 5};
|
||||
|
||||
const payment = {
|
||||
source: {
|
||||
address: address,
|
||||
amount: {
|
||||
value: '0.01',
|
||||
currency: 'XRP'
|
||||
}
|
||||
},
|
||||
destination: {
|
||||
address: 'rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc',
|
||||
amount: {
|
||||
value: '0.01',
|
||||
currency: 'XRP'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
api.connect().then(() => {
|
||||
console.log('Connected...');
|
||||
api.preparePayment(address, payment, instructions).then(txJSON => {
|
||||
console.log('Payment transaction prepared...');
|
||||
const signedTransaction = api.sign(txJSON, secret).signedTransaction;
|
||||
console.log('Payment transaction signed...');
|
||||
api.submit(signedTransaction).then(response => {
|
||||
console.log(response);
|
||||
process.exit(0);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
process.exit(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
104
npm-shrinkwrap.json
generated
104
npm-shrinkwrap.json
generated
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.12.6",
|
||||
"version": "0.13.0-rc4",
|
||||
"npm-shrinkwrap-version": "5.4.0",
|
||||
"node-version": "v0.12.6",
|
||||
"node-version": "v0.12.7",
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz"
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.3.tgz",
|
||||
"version": "5.8.20",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.20.tgz",
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "0.9.18",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-0.9.18.tgz"
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.0.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -22,25 +22,109 @@
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.0.7.tgz"
|
||||
},
|
||||
"es6-promisify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-2.0.0.tgz",
|
||||
"dependencies": {
|
||||
"es6-promise": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz"
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
|
||||
"dependencies": {
|
||||
"agent-base": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.0.0.tgz",
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "4.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-my-json-valid": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.12.1.tgz",
|
||||
"dependencies": {
|
||||
"generate-function": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz"
|
||||
},
|
||||
"generate-object-property": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
|
||||
"dependencies": {
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jsonpointer": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-1.1.0.tgz"
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.0.tgz"
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz"
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.2.tgz"
|
||||
},
|
||||
"ripple-lib-transactionparser": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/ripple-lib-transactionparser/-/ripple-lib-transactionparser-0.5.0.tgz",
|
||||
"dependencies": {
|
||||
"bignumber.js": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-1.4.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ripple-wallet-generator": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ripple-wallet-generator/-/ripple-wallet-generator-1.0.3.tgz"
|
||||
},
|
||||
"sjcl": {
|
||||
"sjcl-extended": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sjcl/-/sjcl-1.0.3.tgz"
|
||||
"resolved": "git://github.com/ripple/sjcl-extended.git#d8cf8b22e7d97193c54e1f65113e3edcf200ca17",
|
||||
"dependencies": {
|
||||
"sjcl": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sjcl/-/sjcl-1.0.3.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "0.7.2",
|
||||
|
||||
44
package.json
44
package.json
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "0.12.6",
|
||||
"version": "0.13.0-rc4",
|
||||
"license": "ISC",
|
||||
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
|
||||
"files": [
|
||||
"dist/npm/*",
|
||||
@@ -15,49 +16,50 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "~0.9.0",
|
||||
"babel-runtime": "^5.3.2",
|
||||
"babel-runtime": "^5.5.4",
|
||||
"bignumber.js": "^2.0.3",
|
||||
"es6-promisify": "^2.0.0",
|
||||
"extend": "~1.2.1",
|
||||
"https-proxy-agent": "^1.0.0",
|
||||
"is-my-json-valid": "^2.12.0",
|
||||
"lodash": "^3.1.0",
|
||||
"lru-cache": "~2.5.0",
|
||||
"ripple-lib-transactionparser": "^0.5.0",
|
||||
"ripple-wallet-generator": "^1.0.3",
|
||||
"sjcl": "^1.0.3",
|
||||
"sjcl-extended": "ripple/sjcl-extended#1.0.3",
|
||||
"ws": "~0.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"assert-diff": "^1.0.1",
|
||||
"babel": "^5.3.3",
|
||||
"babel-core": "^5.3.2",
|
||||
"babel": "^5.5.4",
|
||||
"babel-core": "^5.5.4",
|
||||
"babel-eslint": "^3.1.23",
|
||||
"babel-loader": "^5.0.0",
|
||||
"coveralls": "~2.10.0",
|
||||
"eslint": "^0.18.0",
|
||||
"eslint": "^1.0.0",
|
||||
"eslint-plugin-flowtype": "^1.0.0",
|
||||
"eventemitter2": "^0.4.14",
|
||||
"flow-bin": "^0.14",
|
||||
"gulp": "~3.8.10",
|
||||
"gulp-bump": "~0.1.13",
|
||||
"gulp-clean-dest": "^0.1.0",
|
||||
"gulp-filelog": "^0.4.1",
|
||||
"gulp-flowtype": "^0.4.1",
|
||||
"gulp-plumber": "^0.6.6",
|
||||
"gulp-react": "^2.0.0",
|
||||
"gulp-rename": "~1.2.0",
|
||||
"gulp-uglify": "~1.1.0",
|
||||
"gulp-util": "^3.0.3",
|
||||
"gulp-watch": "^4.1.0",
|
||||
"istanbul": "~0.3.5",
|
||||
"map-stream": "~0.1.0",
|
||||
"mocha": "~2.1.0",
|
||||
"nock": "^0.34.1",
|
||||
"webpack": "~1.5.3",
|
||||
"yargs": "~1.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp",
|
||||
"compile": "babel -i runtime -d dist/npm/ src/",
|
||||
"compile-with-source-maps": "babel -i runtime -s -t -d dist/npm/ src/",
|
||||
"prepublish": "npm run compile",
|
||||
"postinstall": "cd node_modules/sjcl; ./configure --with-all --compress=none; make",
|
||||
"clean": "rm -rf dist/npm && rm -rf build/flow",
|
||||
"typecheck": "babel --optional runtime --blacklist flow -d build/flow/ src/ && flow check",
|
||||
"compile": "babel -D --optional runtime -d dist/npm/ src/",
|
||||
"watch": "babel -w -D --optional runtime -d dist/npm/ src/",
|
||||
"compile-with-source-maps": "babel -D --optional runtime -s -t -d dist/npm/ src/",
|
||||
"prepublish": "npm run clean && npm run compile",
|
||||
"test": "istanbul test _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'; fi; eslint --reset -c eslintrc src/*.js",
|
||||
"lint": "if ! [ -f eslintrc ]; then curl -o eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; echo 'plugins:\n - flowtype' >> eslintrc; fi; eslint --reset -c eslintrc src/",
|
||||
"perf": "./scripts/perf_test.sh"
|
||||
},
|
||||
"repository": {
|
||||
@@ -66,6 +68,6 @@
|
||||
},
|
||||
"readmeFilename": "README.md",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
var fs = require('fs');
|
||||
var Amount = require('../dist/npm').Amount;
|
||||
var Ledger = require('../dist/npm/ledger').Ledger;
|
||||
var Ledger = require('../dist/npm').Ledger;
|
||||
|
||||
function parse_options(from, flags) {
|
||||
var argv = from.slice(),
|
||||
|
||||
44
src/api/common/constants.js
Normal file
44
src/api/common/constants.js
Normal file
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
const core = require('./utils').core;
|
||||
const flagIndices = core.Transaction.set_clear_flags.AccountSet;
|
||||
const flags = core.Remote.flags.account_root;
|
||||
|
||||
const AccountFlags = {
|
||||
passwordSpent: flags.PasswordSpent,
|
||||
requireDestinationTag: flags.RequireDestTag,
|
||||
requireAuthorization: flags.RequireAuth,
|
||||
disallowIncomingXRP: flags.DisallowXRP,
|
||||
disableMasterKey: flags.DisableMaster,
|
||||
noFreeze: flags.NoFreeze,
|
||||
globalFreeze: flags.GlobalFreeze,
|
||||
defaultRipple: flags.DefaultRipple
|
||||
};
|
||||
|
||||
const AccountFlagIndices = {
|
||||
requireDestinationTag: flagIndices.asfRequireDest,
|
||||
requireAuthorization: flagIndices.asfRequireAuth,
|
||||
disallowIncomingXRP: flagIndices.asfDisallowXRP,
|
||||
disableMasterKey: flagIndices.asfDisableMaster,
|
||||
enableTransactionIDTracking: flagIndices.asfAccountTxnID,
|
||||
noFreeze: flagIndices.asfNoFreeze,
|
||||
globalFreeze: flagIndices.asfGlobalFreeze,
|
||||
defaultRipple: flagIndices.asfDefaultRipple
|
||||
};
|
||||
|
||||
const AccountFields = {
|
||||
EmailHash: {name: 'emailHash', encoding: 'hex',
|
||||
length: 32, defaults: '0'},
|
||||
WalletLocator: {name: 'walletLocator', encoding: 'hex',
|
||||
length: 64, defaults: '0'},
|
||||
WalletSize: {name: 'walletSize', defaults: 0},
|
||||
MessageKey: {name: 'messageKey'},
|
||||
Domain: {name: 'domain', encoding: 'hex'},
|
||||
TransferRate: {name: 'transferRate', defaults: 0, shift: 9},
|
||||
Signers: {name: 'signers'}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
AccountFields,
|
||||
AccountFlagIndices,
|
||||
AccountFlags
|
||||
};
|
||||
89
src/api/common/errors.js
Normal file
89
src/api/common/errors.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/* eslint-disable valid-jsdoc */
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Base class for all errors
|
||||
*/
|
||||
function RippleError(message) {
|
||||
this.message = message;
|
||||
}
|
||||
RippleError.prototype = new Error();
|
||||
RippleError.prototype.name = 'RippleError';
|
||||
|
||||
function ValidationError(message) {
|
||||
this.message = message;
|
||||
}
|
||||
ValidationError.prototype = new RippleError();
|
||||
ValidationError.prototype.name = 'ValidationError';
|
||||
|
||||
/**
|
||||
* Timeout, disconnects and too busy
|
||||
*/
|
||||
function NetworkError(message) {
|
||||
this.message = message;
|
||||
}
|
||||
NetworkError.prototype = new RippleError();
|
||||
NetworkError.prototype.name = 'NetworkError';
|
||||
|
||||
/**
|
||||
* Failed transactions, no paths found, not enough balance, etc.
|
||||
*/
|
||||
function RippledNetworkError(message) {
|
||||
this.message = message !== undefined ? message : 'Cannot connect to rippled';
|
||||
}
|
||||
RippledNetworkError.prototype = new NetworkError();
|
||||
|
||||
/**
|
||||
* Failed transactions, no paths found, not enough balance, etc.
|
||||
*/
|
||||
function TransactionError(message) {
|
||||
this.message = message;
|
||||
}
|
||||
TransactionError.prototype = new RippleError();
|
||||
TransactionError.prototype.name = 'TransactionError';
|
||||
|
||||
/**
|
||||
* Asset could not be found
|
||||
*/
|
||||
function NotFoundError(message) {
|
||||
this.message = message;
|
||||
}
|
||||
NotFoundError.prototype = new RippleError();
|
||||
NotFoundError.prototype.name = 'NotFoundError';
|
||||
|
||||
function MissingLedgerHistoryError(message) {
|
||||
this.message = message ||
|
||||
'Server is missing ledger history in the specified range';
|
||||
}
|
||||
MissingLedgerHistoryError.prototype = new RippleError();
|
||||
MissingLedgerHistoryError.prototype.name = 'MissingLedgerHistoryError';
|
||||
|
||||
/**
|
||||
* Request timed out
|
||||
*/
|
||||
function TimeOutError(message) {
|
||||
this.message = message;
|
||||
}
|
||||
TimeOutError.prototype = new RippleError();
|
||||
TimeOutError.prototype.name = 'TimeOutError';
|
||||
|
||||
/**
|
||||
* API logic failed to do what it intended
|
||||
*/
|
||||
function ApiError(message) {
|
||||
this.message = message;
|
||||
}
|
||||
ApiError.prototype = new RippleError();
|
||||
ApiError.prototype.name = 'ApiError';
|
||||
|
||||
module.exports = {
|
||||
ValidationError: ValidationError,
|
||||
NetworkError: NetworkError,
|
||||
TransactionError: TransactionError,
|
||||
RippledNetworkError: RippledNetworkError,
|
||||
NotFoundError: NotFoundError,
|
||||
MissingLedgerHistoryError: MissingLedgerHistoryError,
|
||||
TimeOutError: TimeOutError,
|
||||
ApiError: ApiError,
|
||||
RippleError: RippleError
|
||||
};
|
||||
18
src/api/common/index.js
Normal file
18
src/api/common/index.js
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = {
|
||||
core: utils.core,
|
||||
constants: require('./constants'),
|
||||
errors: require('./errors'),
|
||||
validate: require('./validate'),
|
||||
dropsToXrp: utils.dropsToXrp,
|
||||
xrpToDrops: utils.xrpToDrops,
|
||||
toRippledAmount: utils.toRippledAmount,
|
||||
composeAsync: utils.composeAsync,
|
||||
wrapCatch: utils.wrapCatch,
|
||||
convertExceptions: utils.convertExceptions,
|
||||
convertKeysFromSnakeCaseToCamelCase:
|
||||
utils.convertKeysFromSnakeCaseToCamelCase,
|
||||
promisify: utils.promisify
|
||||
};
|
||||
69
src/api/common/schema-validator.js
Normal file
69
src/api/common/schema-validator.js
Normal file
@@ -0,0 +1,69 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const validator = require('is-my-json-valid');
|
||||
const core = require('./utils').core;
|
||||
const ValidationError = require('./errors').ValidationError;
|
||||
|
||||
let SCHEMAS = {};
|
||||
|
||||
function isValidAddress(address) {
|
||||
return core.UInt160.is_valid(address);
|
||||
}
|
||||
|
||||
function isValidLedgerHash(ledgerHash) {
|
||||
return core.UInt256.is_valid(ledgerHash);
|
||||
}
|
||||
|
||||
function loadSchema(filepath: string): {} {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(filepath, 'utf8'));
|
||||
} catch (e) {
|
||||
throw new Error('Failed to parse schema: ' + filepath);
|
||||
}
|
||||
}
|
||||
|
||||
function endsWith(str, suffix) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
|
||||
function loadSchemas(dir) {
|
||||
const filenames = fs.readdirSync(dir).filter(name => endsWith(name, '.json'));
|
||||
const schemas = filenames.map(name => loadSchema(path.join(dir, name)));
|
||||
return _.indexBy(schemas, 'title');
|
||||
}
|
||||
|
||||
function formatSchemaError(error) {
|
||||
return error.field + ' ' + error.message
|
||||
+ (error.value ? ' (' + JSON.stringify(error.value) + ')' : '');
|
||||
}
|
||||
|
||||
function formatSchemaErrors(errors) {
|
||||
return errors.map(formatSchemaError).join(', ');
|
||||
}
|
||||
|
||||
function schemaValidate(schemaName: string, object: any): void {
|
||||
const formats = {address: isValidAddress,
|
||||
ledgerHash: isValidLedgerHash};
|
||||
const options = {schemas: SCHEMAS, formats: formats,
|
||||
verbose: true, greedy: true};
|
||||
const schema = SCHEMAS[schemaName];
|
||||
if (schema === undefined) {
|
||||
throw new Error('schema not found for: ' + schemaName);
|
||||
}
|
||||
const validate = validator(schema, options);
|
||||
const isValid = validate(object);
|
||||
if (!isValid) {
|
||||
throw new ValidationError(formatSchemaErrors(validate.errors));
|
||||
}
|
||||
}
|
||||
|
||||
SCHEMAS = loadSchemas(path.join(__dirname, './schemas'));
|
||||
module.exports = {
|
||||
schemaValidate: schemaValidate,
|
||||
loadSchema: loadSchema,
|
||||
SCHEMAS: SCHEMAS
|
||||
};
|
||||
8
src/api/common/schemas/address.json
Normal file
8
src/api/common/schemas/address.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "address",
|
||||
"description": "A Ripple account address",
|
||||
"type": "string",
|
||||
"format": "address",
|
||||
"pattern": "^r[1-9A-HJ-NP-Za-km-z]{25,34}$"
|
||||
}
|
||||
24
src/api/common/schemas/adjustment.json
Normal file
24
src/api/common/schemas/adjustment.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "adjustment",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {"$ref": "address"},
|
||||
"amount": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"currency": {"$ref": "currency"},
|
||||
"counterparty": {"$ref": "address"},
|
||||
"value": {"$ref": "value"}
|
||||
},
|
||||
"required": ["currency", "value"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"tag": {
|
||||
"description": "A string representing an unsigned 32-bit integer most commonly used to refer to a sender's hosted account at a Ripple gateway",
|
||||
"$ref": "uint32"
|
||||
}
|
||||
},
|
||||
"required": ["address", "amount"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
9
src/api/common/schemas/amount.json
Normal file
9
src/api/common/schemas/amount.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "amount",
|
||||
"description": "An Amount on the Ripple Protocol, used also for XRP in the ripple-rest API",
|
||||
"allOf": [
|
||||
{"$ref": "amountbase"},
|
||||
{"required": ["value"]}
|
||||
]
|
||||
}
|
||||
44
src/api/common/schemas/amountbase.json
Normal file
44
src/api/common/schemas/amountbase.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "amountbase",
|
||||
"description": "Base class for amount and issue",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"value": {
|
||||
"description": "The quantity of the currency, denoted as a string to retain floating point precision",
|
||||
"$ref": "value"
|
||||
},
|
||||
"currency": {
|
||||
"description": "The three-character code or hex string used to denote currencies",
|
||||
"$ref": "currency"
|
||||
},
|
||||
"counterparty": {
|
||||
"description": "The Ripple account address of the currency's issuer or gateway",
|
||||
"$ref": "address"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["currency"],
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"currency": {
|
||||
"not": {
|
||||
"enum": ["XRP"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["counterparty"]
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"currency": {
|
||||
"enum": ["XRP"]
|
||||
}
|
||||
},
|
||||
"not": {
|
||||
"required": ["counterparty"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
44
src/api/common/schemas/balance.json
Normal file
44
src/api/common/schemas/balance.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "balance",
|
||||
"description": "Balance amount",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"value": {
|
||||
"description": "The balance on the trustline",
|
||||
"$ref": "signed-value"
|
||||
},
|
||||
"currency": {
|
||||
"description": "The three-character code or hex string used to denote currencies",
|
||||
"$ref": "currency"
|
||||
},
|
||||
"counterparty": {
|
||||
"description": "The Ripple account address of the currency's issuer or gateway",
|
||||
"$ref": "address"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["currency", "value"],
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"currency": {
|
||||
"not": {
|
||||
"enum": ["XRP"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["counterparty"]
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"currency": {
|
||||
"enum": ["XRP"]
|
||||
}
|
||||
},
|
||||
"not": {
|
||||
"required": ["counterparty"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
8
src/api/common/schemas/blob.json
Normal file
8
src/api/common/schemas/blob.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "blob",
|
||||
"description": "An uppercase hex string representation of a transaction",
|
||||
"type": "string",
|
||||
"minLength": "1",
|
||||
"pattern": "^[0-9A-F]*$"
|
||||
}
|
||||
7
src/api/common/schemas/currency.json
Normal file
7
src/api/common/schemas/currency.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "currency",
|
||||
"description": "The three-character code or hex string used to denote currencies",
|
||||
"type": "string",
|
||||
"pattern": "^([a-zA-Z0-9<>(){}[\\]|?!@#$%^&*]{3}|[A-F0-9]{40})$"
|
||||
}
|
||||
21
src/api/common/schemas/get-account-info.json
Normal file
21
src/api/common/schemas/get-account-info.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getAccountInfo",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sequence": {"$ref": "sequence"},
|
||||
"xrpBalance": {"$ref": "value"},
|
||||
"ownerCount": {"type": "integer", "minimum": 0},
|
||||
"previousInitiatedTransactionID": {"$ref": "hash256"},
|
||||
"previousAffectingTransactionID": {"$ref": "hash256"},
|
||||
"previousAffectingTransactionLedgerVersion": {"$ref": "ledgerVersion"}
|
||||
},
|
||||
"required": [
|
||||
"sequence",
|
||||
"xrpBalance",
|
||||
"ownerCount",
|
||||
"previousAffectingTransactionID",
|
||||
"previousAffectingTransactionLedgerVersion"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
6
src/api/common/schemas/get-balances.json
Normal file
6
src/api/common/schemas/get-balances.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getBalances",
|
||||
"type": "array",
|
||||
"items": {"$ref": "balance"}
|
||||
}
|
||||
11
src/api/common/schemas/get-orderbook.json
Normal file
11
src/api/common/schemas/get-orderbook.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getOrderbook",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bids": {"$ref": "orderbookOrders"},
|
||||
"asks": {"$ref": "orderbookOrders"}
|
||||
},
|
||||
"required": ["bids", "asks"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
23
src/api/common/schemas/get-orders.json
Normal file
23
src/api/common/schemas/get-orders.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getOrders",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"specification": {"$ref": "order"},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"maker": {"$ref": "address"},
|
||||
"sequence": {"$ref": "sequence"},
|
||||
"makerExchangeRate": {"$ref": "value"}
|
||||
},
|
||||
"required": ["maker", "sequence", "makerExchangeRate"],
|
||||
"addtionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["specification", "properties"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
15
src/api/common/schemas/get-paths.json
Normal file
15
src/api/common/schemas/get-paths.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getPaths",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"$ref": "adjustment"},
|
||||
"destination": {"$ref": "adjustment"},
|
||||
"paths": {"type": "string"}
|
||||
},
|
||||
"required": ["source", "destination", "paths"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
49
src/api/common/schemas/get-server-info.json
Normal file
49
src/api/common/schemas/get-server-info.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getServerInfo",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"buildVersion": {"type": "string"},
|
||||
"completeLedgers": {"type": "string", "pattern": "[0-9,-]+"},
|
||||
"hostid": {"type": "string"},
|
||||
"ioLatencyMs": {"type": "number"},
|
||||
"load": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"job_types": {
|
||||
"type": "array",
|
||||
"items": {"type": "object"}
|
||||
},
|
||||
"threads": {"type": "number"}
|
||||
}
|
||||
},
|
||||
"lastClose": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"convergeTimeS": {"type": "number"},
|
||||
"proposers": {"type": "integer", "minimum": 0}
|
||||
}
|
||||
},
|
||||
"loadFactor": {"type": "number"},
|
||||
"peers": {"type": "integer", "minimum": 0},
|
||||
"pubkeyNode": {"type": "string"},
|
||||
"pubkeyValidator": {"type": "string"},
|
||||
"serverState": {
|
||||
"type": "string",
|
||||
"enum": ["disconnected", "connected", "syncing", "tracking", "full", "validating", "proposing"]
|
||||
},
|
||||
"validatedLedger": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"age": {"type": "integer", "minimum": 0},
|
||||
"baseFeeXrp": {"type": "number"},
|
||||
"hash": {"$ref": "hash256"},
|
||||
"reserveBaseXrp": {"type": "integer", "minimum": 0},
|
||||
"reserveIncXrp": {"type": "integer", "minimum": 0},
|
||||
"seq": {"type": "integer", "minimum": 0}
|
||||
}
|
||||
},
|
||||
"validationQuorum": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
40
src/api/common/schemas/get-settings.json
Normal file
40
src/api/common/schemas/get-settings.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getSettings",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"passwordSpent": {"type": "boolean"},
|
||||
"requireDestinationTag": {"type": "boolean"},
|
||||
"requireAuthorization": {"type": "boolean"},
|
||||
"disallowIncomingXRP": {"type": "boolean"},
|
||||
"disableMasterKey": {"type": "boolean"},
|
||||
"enableTransactionIDTracking": {"type": "boolean"},
|
||||
"noFreeze": {"type": "boolean"},
|
||||
"globalFreeze": {"type": "boolean"},
|
||||
"defaultRipple": {"type": "boolean"},
|
||||
"emailHash": {
|
||||
"oneOf": [
|
||||
{"type": "null"},
|
||||
{"$ref": "hash128"}
|
||||
]
|
||||
},
|
||||
"walletLocator": {
|
||||
"oneOf": [
|
||||
{"type": "null"},
|
||||
{"$ref": "hash256"}
|
||||
]
|
||||
},
|
||||
"walletSize": {"type": ["integer", "null"]},
|
||||
"messageKey": {"type": "string"},
|
||||
"domain": {"type": "string"},
|
||||
"transferRate": {
|
||||
"oneOf": [
|
||||
{"type": "null"},
|
||||
{"type": "number", "minimum": 1, "maximum": 4.294967295}
|
||||
]
|
||||
},
|
||||
"signers": {"type": "string"},
|
||||
"regularKey": {"$ref": "address"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
11
src/api/common/schemas/get-transaction.json
Normal file
11
src/api/common/schemas/get-transaction.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getTransaction",
|
||||
"oneOf": [
|
||||
{"$ref": "paymentTransaction"},
|
||||
{"$ref": "orderTransaction"},
|
||||
{"$ref": "orderCancellationTransaction"},
|
||||
{"$ref": "trustlineTransaction"},
|
||||
{"$ref": "settingsTransaction"}
|
||||
]
|
||||
}
|
||||
6
src/api/common/schemas/get-transactions.json
Normal file
6
src/api/common/schemas/get-transactions.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getTransactions",
|
||||
"type": "array",
|
||||
"items": {"$ref": "getTransaction"}
|
||||
}
|
||||
29
src/api/common/schemas/get-trustlines.json
Normal file
29
src/api/common/schemas/get-trustlines.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "getTrustlines",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"properties": {
|
||||
"specification": {"$ref": "trustline"},
|
||||
"counterparty": {
|
||||
"properties": {
|
||||
"limit": {"$ref": "value"},
|
||||
"ripplingDisabled": {"type": "boolean"},
|
||||
"frozen": {"type": "boolean"},
|
||||
"authorized": {"type": "boolean"}
|
||||
},
|
||||
"required": ["limit"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"balance": {"$ref": "value"}
|
||||
},
|
||||
"required": ["balance"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["specification", "counterparty", "state"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
7
src/api/common/schemas/hash128.json
Normal file
7
src/api/common/schemas/hash128.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "hash128",
|
||||
"description": "The hex representation of a 128-bit hash",
|
||||
"type": "string",
|
||||
"pattern": "^[A-F0-9]{32}$"
|
||||
}
|
||||
7
src/api/common/schemas/hash256.json
Normal file
7
src/api/common/schemas/hash256.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "hash256",
|
||||
"description": "The hex representation of a 256-bit hash",
|
||||
"type": "string",
|
||||
"pattern": "^[A-F0-9]{64}$"
|
||||
}
|
||||
42
src/api/common/schemas/instructions.json
Normal file
42
src/api/common/schemas/instructions.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "instructions",
|
||||
"description": "Instructions for executing a transaction",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sequence": {
|
||||
"description": "The sequence number, relative to the initiating account, of this transaction.",
|
||||
"$ref": "sequence"
|
||||
},
|
||||
"fee": {
|
||||
"description": "Fixed Fee",
|
||||
"$ref": "value"
|
||||
},
|
||||
"maxFee": {
|
||||
"description": "Max Fee",
|
||||
"$ref": "value"
|
||||
},
|
||||
"maxLedgerVersion": {
|
||||
"description": "Highest ledger version number that a transaction can appear in.",
|
||||
"$ref": "ledgerVersion"
|
||||
},
|
||||
"maxLedgerVersionOffset": {
|
||||
"description": "Offset from current legder version to highest ledger version that a transaction can appear in.",
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "fee and maxFee are mutually exclusive",
|
||||
"required": ["fee", "maxFee"]
|
||||
},
|
||||
{
|
||||
"description": "maxLedgerVersion and maxLedgerVersionOffset are mutually exclusive",
|
||||
"required": ["maxLedgerVersion", "maxLedgerVersionOffset"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
9
src/api/common/schemas/issue.json
Normal file
9
src/api/common/schemas/issue.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "issue",
|
||||
"description": "A currency-counterparty pair, or just currency if it's XRP",
|
||||
"allOf": [
|
||||
{"$ref": "amountbase"},
|
||||
{"not": {"required": ["value"]}}
|
||||
]
|
||||
}
|
||||
7
src/api/common/schemas/ledgerversion.json
Normal file
7
src/api/common/schemas/ledgerversion.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "ledgerVersion",
|
||||
"description": "A ledger version number",
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
}
|
||||
22
src/api/common/schemas/memo.json
Normal file
22
src/api/common/schemas/memo.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "memo",
|
||||
"description": "Memo objects represent arbitrary data that can be included in a transaction",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"pattern": "^[A-Za-z0-9\\-._~:/?#[\\]@!$&'()*+,;=%]*$"
|
||||
},
|
||||
"format": {
|
||||
"pattern": "^[A-Za-z0-9\\-._~:/?#[\\]@!$&'()*+,;=%]*$"
|
||||
},
|
||||
"data": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"anyOf": [
|
||||
{"required": ["data"]},
|
||||
{"required": ["type"]}
|
||||
]
|
||||
}
|
||||
15
src/api/common/schemas/order-cancellation-transaction.json
Normal file
15
src/api/common/schemas/order-cancellation-transaction.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "orderCancellationTransaction",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"enum": ["orderCancellation"]},
|
||||
"specification": {"$ref": "orderCancellation"},
|
||||
"outcome": {"$ref": "outcome"},
|
||||
"id": {"$ref": "hash256"},
|
||||
"address": {"$ref": "address"},
|
||||
"sequence": {"$ref": "sequence"}
|
||||
},
|
||||
"required": ["type", "id", "address", "sequence", "specification", "outcome"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
10
src/api/common/schemas/order-cancellation.json
Normal file
10
src/api/common/schemas/order-cancellation.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "orderCancellation",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"orderSequence": {"$ref": "sequence"}
|
||||
},
|
||||
"required": ["orderSequence"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
17
src/api/common/schemas/order-change.json
Normal file
17
src/api/common/schemas/order-change.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "order-change",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"direction": {
|
||||
"type": "string",
|
||||
"enum": ["buy", "sell"]
|
||||
},
|
||||
"quantity": {"$ref": "balance"},
|
||||
"totalPrice": {"$ref": "balance"},
|
||||
"sequence": {"$ref": "sequence"},
|
||||
"status": {"enum": ["created", "open", "closed", "canceled"]}
|
||||
},
|
||||
"required": ["direction", "quantity", "totalPrice", "sequence", "status"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
15
src/api/common/schemas/order-transaction.json
Normal file
15
src/api/common/schemas/order-transaction.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "orderTransaction",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"enum": ["order"]},
|
||||
"specification": {"$ref": "order"},
|
||||
"outcome": {"$ref": "outcome"},
|
||||
"id": {"$ref": "hash256"},
|
||||
"address": {"$ref": "address"},
|
||||
"sequence": {"$ref": "sequence"}
|
||||
},
|
||||
"required": ["type", "id", "address", "sequence", "specification", "outcome"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
25
src/api/common/schemas/order.json
Normal file
25
src/api/common/schemas/order.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "order",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"direction": {
|
||||
"type": "string",
|
||||
"enum": ["buy", "sell"]
|
||||
},
|
||||
"quantity": {"$ref": "amount"},
|
||||
"totalPrice": {"$ref": "amount"},
|
||||
"immediateOrCancel": {"type": "boolean"},
|
||||
"fillOrKill": {"type": "boolean"},
|
||||
"passive": {
|
||||
"description": "If enabled, the offer will not consume offers that exactly match it, and instead becomes an Offer node in the ledger. It will still consume offers that cross it.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": ["direction", "quantity", "totalPrice"],
|
||||
"additionalProperties": false,
|
||||
"not": {
|
||||
"description": "immediateOrCancel and fillOrKill are mutually exclusive",
|
||||
"required": ["immediateOrCancel", "fillOrKill"]
|
||||
}
|
||||
}
|
||||
32
src/api/common/schemas/orderbook-orders.json
Normal file
32
src/api/common/schemas/orderbook-orders.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "orderbookOrders",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"specification": {"$ref": "order"},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"maker": {"$ref": "address"},
|
||||
"sequence": {"$ref": "sequence"},
|
||||
"makerExchangeRate": {"$ref": "value"}
|
||||
},
|
||||
"required": ["maker", "sequence", "makerExchangeRate"],
|
||||
"addtionalProperties": false
|
||||
},
|
||||
"state": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fundedAmount": {"$ref": "amount"},
|
||||
"priceOfFundedAmount": {"$ref": "amount"}
|
||||
},
|
||||
"required": ["fundedAmount", "priceOfFundedAmount"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["specification", "properties"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
11
src/api/common/schemas/orderbook.json
Normal file
11
src/api/common/schemas/orderbook.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "orderbook",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"base": {"$ref": "issue"},
|
||||
"counter": {"$ref": "issue"}
|
||||
},
|
||||
"required": ["base", "counter"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
14
src/api/common/schemas/orders-options.json
Normal file
14
src/api/common/schemas/orders-options.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "orders-options",
|
||||
"description": "Options for getOrders and getOrderbook",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"ledgerVersion": {"$ref": "ledgerVersion"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
31
src/api/common/schemas/outcome.json
Normal file
31
src/api/common/schemas/outcome.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "outcome",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {"type": "string"},
|
||||
"timestamp": {"type": "string"},
|
||||
"fee": {"$ref": "value"},
|
||||
"balanceChanges": {
|
||||
"type": "object",
|
||||
"description": "Key is the ripple address; value is an array of changes",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "balance"}
|
||||
}
|
||||
},
|
||||
"orderbookChanges": {
|
||||
"type": "object",
|
||||
"description": "Key is the maker's ripple address; value is an array of changes",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "order-change"}
|
||||
}
|
||||
},
|
||||
"ledgerVersion": {"$ref": "ledgerVersion"},
|
||||
"indexInLedger": {"type": "integer", "minimum": 0}
|
||||
},
|
||||
"required": ["result", "fee", "balanceChanges",
|
||||
"orderbookChanges", "ledgerVersion", "indexInLedger"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
31
src/api/common/schemas/pathfind.json
Normal file
31
src/api/common/schemas/pathfind.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "pathfind",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {"$ref": "address"},
|
||||
"currencies": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"currency": {"$ref": "currency"},
|
||||
"counterparty": {"$ref": "address"}
|
||||
},
|
||||
"required": ["currency"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["address"]
|
||||
},
|
||||
"destination": {"$ref": "adjustment"}
|
||||
},
|
||||
"required": ["source", "destination"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
15
src/api/common/schemas/payment-transaction.json
Normal file
15
src/api/common/schemas/payment-transaction.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "paymentTransaction",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"enum": ["payment"]},
|
||||
"specification": {"$ref": "payment"},
|
||||
"outcome": {"$ref": "outcome"},
|
||||
"id": {"$ref": "hash256"},
|
||||
"address": {"$ref": "address"},
|
||||
"sequence": {"$ref": "sequence"}
|
||||
},
|
||||
"required": ["type", "id", "address", "sequence", "specification", "outcome"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
31
src/api/common/schemas/payment.json
Normal file
31
src/api/common/schemas/payment.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "payment",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"$ref": "adjustment"},
|
||||
"destination": {"$ref": "adjustment"},
|
||||
"paths": {"type": "string"},
|
||||
"memos": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "memo"
|
||||
}
|
||||
},
|
||||
"invoiceID": {
|
||||
"description": "A 256-bit hash that can be used to identify a particular payment",
|
||||
"$ref": "hash256"
|
||||
},
|
||||
"allowPartialPayment": {
|
||||
"description": "A boolean that, if set to true, indicates that this payment should go through even if the whole amount cannot be delivered because of a lack of liquidity or funds in the source_account account",
|
||||
"type": "boolean"
|
||||
},
|
||||
"noDirectRipple": {
|
||||
"description": "A boolean that can be set to true if paths are specified and the sender would like the Ripple Network to disregard any direct paths from the source_account to the destination_account. This may be used to take advantage of an arbitrage opportunity or by gateways wishing to issue balances from a hot wallet to a user who has mistakenly set a trustline directly to the hot wallet",
|
||||
"type": "boolean"
|
||||
},
|
||||
"limitQuality": {"type": "boolean"}
|
||||
},
|
||||
"required": ["source", "destination"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
8
src/api/common/schemas/quality.json
Normal file
8
src/api/common/schemas/quality.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "quality",
|
||||
"description": "Ratio for incoming/outgoing transit fees.",
|
||||
"type": "number",
|
||||
"minimum": 0.000000001,
|
||||
"maximum": 4.294967295
|
||||
}
|
||||
7
src/api/common/schemas/sequence.json
Normal file
7
src/api/common/schemas/sequence.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "sequence",
|
||||
"description": "An account transaction sequence number",
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
}
|
||||
10
src/api/common/schemas/settings-options.json
Normal file
10
src/api/common/schemas/settings-options.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "settings-options",
|
||||
"description": "Options for getSettings and getAccountInfo",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ledgerVersion": {"$ref": "ledgerVersion"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
15
src/api/common/schemas/settings-transaction.json
Normal file
15
src/api/common/schemas/settings-transaction.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "settingsTransaction",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"enum": ["settings"]},
|
||||
"specification": {"$ref": "getSettings"},
|
||||
"outcome": {"$ref": "outcome"},
|
||||
"id": {"$ref": "hash256"},
|
||||
"address": {"$ref": "address"},
|
||||
"sequence": {"$ref": "sequence"}
|
||||
},
|
||||
"required": ["type", "id", "address", "sequence", "specification"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
13
src/api/common/schemas/settings.json
Normal file
13
src/api/common/schemas/settings.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "settings",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "getSettings"
|
||||
},
|
||||
{
|
||||
"minProperties": 1,
|
||||
"maxProperties": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
14
src/api/common/schemas/sign.json
Normal file
14
src/api/common/schemas/sign.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "sign",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"signedTransaction": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-F0-9]+$"
|
||||
},
|
||||
"id": {"$ref": "hash256"}
|
||||
},
|
||||
"required": ["signedTransaction", "id"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
7
src/api/common/schemas/signed-value.json
Normal file
7
src/api/common/schemas/signed-value.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "value",
|
||||
"description": "A string representation of a floating point number",
|
||||
"type": "string",
|
||||
"pattern": "[-]?^[0-9]*[.]?[0-9]+([eE][-+]?[0-9]+)?$"
|
||||
}
|
||||
15
src/api/common/schemas/submit.json
Normal file
15
src/api/common/schemas/submit.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "submit",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": {"type": "boolean"},
|
||||
"engineResult": {"type": "string"},
|
||||
"engineResultCode": {"type": "integer"},
|
||||
"engineResultMessage": {"type": "string"},
|
||||
"txBlob": {"type": "string"},
|
||||
"txJson": {"type": "object"}
|
||||
},
|
||||
"required": ["success", "engineResult", "engineResultCode"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
7
src/api/common/schemas/timestamp.json
Normal file
7
src/api/common/schemas/timestamp.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "timestamp",
|
||||
"description": "An ISO 8601 combined date and time timestamp",
|
||||
"type": "string",
|
||||
"pattern": "^$|^[0-9]{4}-[0-1][0-9]-[0-3][0-9]T(2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9](Z|[+](2[0-3]|[01][0-9]):[0-5][0-9])$"
|
||||
}
|
||||
11
src/api/common/schemas/transaction-options.json
Normal file
11
src/api/common/schemas/transaction-options.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "transaction-options",
|
||||
"description": "Options for getTransaction",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"minLedgerVersion": {"$ref": "ledgerVersion"},
|
||||
"maxLedgerVersion": {"$ref": "ledgerVersion"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
40
src/api/common/schemas/transactions-options.json
Normal file
40
src/api/common/schemas/transactions-options.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "transactions-options",
|
||||
"description": "Options for getTransactions",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"start": {"$ref": "hash256"},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"minLedgerVersion": {"$ref": "ledgerVersion"},
|
||||
"maxLedgerVersion": {"$ref": "ledgerVersion"},
|
||||
"earliestFirst": {"type": "boolean"},
|
||||
"excludeFailures": {"type": "boolean"},
|
||||
"initiated": {"type": "boolean"},
|
||||
"counterparty": {"$ref": "address"},
|
||||
"types": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"enum": [
|
||||
"payment",
|
||||
"trustline",
|
||||
"order",
|
||||
"orderCancellation",
|
||||
"settings"
|
||||
]
|
||||
}
|
||||
},
|
||||
"binary": {"type": "boolean"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{"required": ["incoming", "outgoing"]},
|
||||
{"required": ["start", "minLedgerVersion"]},
|
||||
{"required": ["start", "maxLedgerVersion"]}
|
||||
]
|
||||
}
|
||||
}
|
||||
15
src/api/common/schemas/trustline-transaction.json
Normal file
15
src/api/common/schemas/trustline-transaction.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "trustlineTransaction",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"enum": ["trustline"]},
|
||||
"specification": {"$ref": "trustline"},
|
||||
"outcome": {"$ref": "outcome"},
|
||||
"id": {"$ref": "hash256"},
|
||||
"address": {"$ref": "address"},
|
||||
"sequence": {"$ref": "sequence"}
|
||||
},
|
||||
"required": ["type", "id", "address", "sequence", "specification", "outcome"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
17
src/api/common/schemas/trustline.json
Normal file
17
src/api/common/schemas/trustline.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "trustline",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"currency": {"$ref": "currency"},
|
||||
"counterparty": {"$ref": "address"},
|
||||
"limit": {"$ref": "value"},
|
||||
"qualityIn": {"$ref": "quality"},
|
||||
"qualityOut": {"$ref": "quality"},
|
||||
"ripplingDisabled": {"type": "boolean"},
|
||||
"authorized": {"type": "boolean"},
|
||||
"frozen": {"type": "boolean"}
|
||||
},
|
||||
"required": ["currency", "counterparty", "limit"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
16
src/api/common/schemas/trustlines-options.json
Normal file
16
src/api/common/schemas/trustlines-options.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "trustlines-options",
|
||||
"description": "Options for getTrustlines and getBalances",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"counterparty": {"$ref": "address"},
|
||||
"currency": {"$ref": "currency"},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"ledgerVersion": {"$ref": "ledgerVersion"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
10
src/api/common/schemas/tx.json
Normal file
10
src/api/common/schemas/tx.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "tx",
|
||||
"description": "An object in rippled txJSON format",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Account": {"$ref": "address"}
|
||||
},
|
||||
"required": ["Account"]
|
||||
}
|
||||
8
src/api/common/schemas/uint32.json
Normal file
8
src/api/common/schemas/uint32.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "uint32",
|
||||
"description": "A 32-bit unsigned integer",
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
}
|
||||
7
src/api/common/schemas/value.json
Normal file
7
src/api/common/schemas/value.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "value",
|
||||
"description": "A string representation of a non-negative floating point number",
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]*[.]?[0-9]+([eE][-+]?[0-9]+)?$"
|
||||
}
|
||||
103
src/api/common/utils.js
Normal file
103
src/api/common/utils.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const BigNumber = require('bignumber.js');
|
||||
const core = require('../../core');
|
||||
const errors = require('./errors');
|
||||
const es6promisify = require('es6-promisify');
|
||||
|
||||
type Amount = {currency: string, issuer: string, value: string}
|
||||
|
||||
function dropsToXrp(drops: string): string {
|
||||
return (new BigNumber(drops)).dividedBy(1000000.0).toString();
|
||||
}
|
||||
|
||||
function xrpToDrops(xrp: string): string {
|
||||
return (new BigNumber(xrp)).times(1000000.0).floor().toString();
|
||||
}
|
||||
|
||||
function toRippledAmount(amount: Amount): string|Amount {
|
||||
if (amount.currency === 'XRP') {
|
||||
return xrpToDrops(amount.value);
|
||||
}
|
||||
return {
|
||||
currency: amount.currency,
|
||||
issuer: amount.counterparty ? amount.counterparty : amount.issuer,
|
||||
value: amount.value
|
||||
};
|
||||
}
|
||||
|
||||
type AsyncFunction = (...x: any) => void
|
||||
|
||||
function wrapCatch(asyncFunction: AsyncFunction): AsyncFunction {
|
||||
return function() {
|
||||
try {
|
||||
asyncFunction.apply(this, arguments);
|
||||
} catch (error) {
|
||||
const callback = arguments[arguments.length - 1];
|
||||
callback(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
type Callback = (err: any, data: any) => void
|
||||
type Wrapper = (data: any) => any
|
||||
|
||||
function composeAsync(wrapper: Wrapper, callback: Callback): Callback {
|
||||
return function(error, data) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
let result;
|
||||
try {
|
||||
result = wrapper(data);
|
||||
} catch (exception) {
|
||||
callback(exception);
|
||||
return;
|
||||
}
|
||||
callback(null, result);
|
||||
};
|
||||
}
|
||||
|
||||
function convertExceptions<T>(f: () => T): () => T {
|
||||
return function() {
|
||||
try {
|
||||
return f.apply(this, arguments);
|
||||
} catch (error) {
|
||||
throw new errors.ApiError(error.message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g;
|
||||
function convertKeysFromSnakeCaseToCamelCase(obj: any): any {
|
||||
if (typeof obj === 'object') {
|
||||
let newKey;
|
||||
return _.reduce(obj, (result, value, key) => {
|
||||
newKey = key;
|
||||
if (FINDSNAKE.test(key)) {
|
||||
newKey = key.replace(FINDSNAKE, r => r[0] + r[2].toUpperCase());
|
||||
}
|
||||
result[newKey] = convertKeysFromSnakeCaseToCamelCase(value);
|
||||
return result;
|
||||
}, {});
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function promisify<T>(asyncFunction: AsyncFunction): Function {
|
||||
return es6promisify(wrapCatch(asyncFunction));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
core,
|
||||
dropsToXrp,
|
||||
xrpToDrops,
|
||||
toRippledAmount,
|
||||
composeAsync,
|
||||
wrapCatch,
|
||||
convertExceptions,
|
||||
convertKeysFromSnakeCaseToCamelCase,
|
||||
promisify
|
||||
};
|
||||
79
src/api/common/validate.js
Normal file
79
src/api/common/validate.js
Normal file
@@ -0,0 +1,79 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const core = require('./utils').core;
|
||||
const ValidationError = require('./errors').ValidationError;
|
||||
const schemaValidate = require('./schema-validator').schemaValidate;
|
||||
|
||||
function error(text) {
|
||||
return new ValidationError(text);
|
||||
}
|
||||
|
||||
function validateAddressAndSecret(obj: {address: string, secret: string}): void {
|
||||
const address = obj.address;
|
||||
const secret = obj.secret;
|
||||
schemaValidate('address', address);
|
||||
if (!secret) {
|
||||
throw error('Parameter missing: secret');
|
||||
}
|
||||
try {
|
||||
core.Seed.from_json(secret).get_key(address);
|
||||
} catch (exception) {
|
||||
throw error('secret does not match address');
|
||||
}
|
||||
}
|
||||
|
||||
function validateSecret(secret: string): void {
|
||||
if (!secret) {
|
||||
throw error('Parameter missing: secret');
|
||||
}
|
||||
if (typeof secret !== 'string' || secret[0] !== 's') {
|
||||
throw error('Invalid parameter');
|
||||
}
|
||||
|
||||
const seed = new core.Seed().parse_base58(secret);
|
||||
if (!seed.is_valid()) {
|
||||
throw error('invalid seed');
|
||||
}
|
||||
}
|
||||
|
||||
function validateLedgerRange(options) {
|
||||
if (!_.isUndefined(options.minLedgerVersion)
|
||||
&& !_.isUndefined(options.maxLedgerVersion)) {
|
||||
if (Number(options.minLedgerVersion) > Number(options.maxLedgerVersion)) {
|
||||
throw error('minLedgerVersion must not be greater than maxLedgerVersion');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateOptions(schema, options) {
|
||||
schemaValidate(schema, options);
|
||||
validateLedgerRange(options);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
address: _.partial(schemaValidate, 'address'),
|
||||
addressAndSecret: validateAddressAndSecret,
|
||||
secret: validateSecret,
|
||||
currency: _.partial(schemaValidate, 'currency'),
|
||||
identifier: _.partial(schemaValidate, 'hash256'),
|
||||
sequence: _.partial(schemaValidate, 'sequence'),
|
||||
order: _.partial(schemaValidate, 'order'),
|
||||
orderbook: _.partial(schemaValidate, 'orderbook'),
|
||||
payment: _.partial(schemaValidate, 'payment'),
|
||||
pathfind: _.partial(schemaValidate, 'pathfind'),
|
||||
settings: _.partial(schemaValidate, 'settings'),
|
||||
trustline: _.partial(schemaValidate, 'trustline'),
|
||||
txJSON: _.partial(schemaValidate, 'tx'),
|
||||
blob: _.partial(schemaValidate, 'blob'),
|
||||
getTransactionsOptions: _.partial(validateOptions, 'transactions-options'),
|
||||
getSettingsOptions: _.partial(validateOptions, 'settings-options'),
|
||||
getAccountInfoOptions: _.partial(validateOptions, 'settings-options'),
|
||||
getTrustlinesOptions: _.partial(validateOptions, 'trustlines-options'),
|
||||
getBalancesOptions: _.partial(validateOptions, 'trustlines-options'),
|
||||
getOrdersOptions: _.partial(validateOptions, 'orders-options'),
|
||||
getOrderbookOptions: _.partial(validateOptions, 'orders-options'),
|
||||
getTransactionOptions: _.partial(validateOptions, 'transaction-options'),
|
||||
options: _.partial(validateOptions, 'options'),
|
||||
instructions: _.partial(schemaValidate, 'instructions')
|
||||
};
|
||||
75
src/api/index.js
Normal file
75
src/api/index.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
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 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 prepareSettings = require('./transaction/settings');
|
||||
const sign = require('./transaction/sign');
|
||||
const submit = require('./transaction/submit');
|
||||
const errors = require('./common').errors;
|
||||
const convertExceptions = require('./common').convertExceptions;
|
||||
const generateWallet = convertExceptions(common.core.Wallet.generate);
|
||||
|
||||
function RippleAPI(options: {}) {
|
||||
const _options = _.assign({}, options, {automatic_resubmission: false});
|
||||
this.remote = new common.core.Remote(_options);
|
||||
}
|
||||
|
||||
RippleAPI.prototype = {
|
||||
connect,
|
||||
disconnect,
|
||||
isConnected,
|
||||
getServerInfo,
|
||||
getFee,
|
||||
getLedgerVersion,
|
||||
|
||||
getTransaction,
|
||||
getTransactions,
|
||||
getTrustlines,
|
||||
getBalances,
|
||||
getPaths,
|
||||
getOrders,
|
||||
getOrderbook,
|
||||
getSettings,
|
||||
getAccountInfo,
|
||||
|
||||
preparePayment,
|
||||
prepareTrustline,
|
||||
prepareOrder,
|
||||
prepareOrderCancellation,
|
||||
prepareSettings,
|
||||
sign,
|
||||
submit,
|
||||
|
||||
generateWallet,
|
||||
errors
|
||||
};
|
||||
|
||||
// these are exposed only for use by unit tests; they are not part of the API
|
||||
RippleAPI._PRIVATE = {
|
||||
common: common,
|
||||
ledgerUtils: require('./ledger/utils'),
|
||||
schemaValidator: require('./common/schema-validator')
|
||||
};
|
||||
|
||||
module.exports = RippleAPI;
|
||||
38
src/api/ledger/accountinfo.js
Normal file
38
src/api/ledger/accountinfo.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const removeUndefined = require('./parse/utils').removeUndefined;
|
||||
const validate = utils.common.validate;
|
||||
const composeAsync = utils.common.composeAsync;
|
||||
|
||||
function formatAccountInfo(response) {
|
||||
const data = response.account_data;
|
||||
return removeUndefined({
|
||||
sequence: data.Sequence,
|
||||
xrpBalance: utils.common.dropsToXrp(data.Balance),
|
||||
ownerCount: data.OwnerCount,
|
||||
previousInitiatedTransactionID: data.AccountTxnID,
|
||||
previousAffectingTransactionID: data.PreviousTxnID,
|
||||
previousAffectingTransactionLedgerVersion: data.PreviousTxnLgrSeq
|
||||
});
|
||||
}
|
||||
|
||||
function getAccountInfoAsync(account, options, callback) {
|
||||
validate.address(account);
|
||||
validate.getAccountInfoOptions(options);
|
||||
|
||||
const request = {
|
||||
account: account,
|
||||
ledger: options.ledgerVersion
|
||||
};
|
||||
|
||||
this.remote.requestAccountInfo(request,
|
||||
composeAsync(formatAccountInfo, callback));
|
||||
}
|
||||
|
||||
function getAccountInfo(account: string, options={}) {
|
||||
return utils.promisify(getAccountInfoAsync.bind(this))(account, options);
|
||||
}
|
||||
|
||||
module.exports = getAccountInfo;
|
||||
49
src/api/ledger/balances.js
Normal file
49
src/api/ledger/balances.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const utils = require('./utils');
|
||||
const getTrustlines = require('./trustlines');
|
||||
const validate = utils.common.validate;
|
||||
const composeAsync = utils.common.composeAsync;
|
||||
|
||||
function getTrustlineBalanceAmount(trustline) {
|
||||
return {
|
||||
currency: trustline.specification.currency,
|
||||
counterparty: trustline.specification.counterparty,
|
||||
value: trustline.state.balance
|
||||
};
|
||||
}
|
||||
|
||||
function formatBalances(balances) {
|
||||
const xrpBalance = {
|
||||
currency: 'XRP',
|
||||
value: balances.xrp
|
||||
};
|
||||
return [xrpBalance].concat(
|
||||
balances.trustlines.map(getTrustlineBalanceAmount));
|
||||
}
|
||||
|
||||
function getTrustlinesAsync(account, options, callback) {
|
||||
getTrustlines.bind(this)(account, options)
|
||||
.then(data => callback(null, data))
|
||||
.catch(callback);
|
||||
}
|
||||
|
||||
function getBalancesAsync(account, options, callback) {
|
||||
validate.address(account);
|
||||
validate.getBalancesOptions(options);
|
||||
|
||||
const ledgerVersion = options.ledgerVersion
|
||||
|| this.remote.getLedgerSequence();
|
||||
async.parallel({
|
||||
xrp: _.partial(utils.getXRPBalance, this.remote, account, ledgerVersion),
|
||||
trustlines: _.partial(getTrustlinesAsync.bind(this), account, options)
|
||||
}, composeAsync(formatBalances, callback));
|
||||
}
|
||||
|
||||
function getBalances(account: string, options={}) {
|
||||
return utils.promisify(getBalancesAsync.bind(this))(account, options);
|
||||
}
|
||||
|
||||
module.exports = getBalances;
|
||||
84
src/api/ledger/orderbook.js
Normal file
84
src/api/ledger/orderbook.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const utils = require('./utils');
|
||||
const parseOrderbookOrder = require('./parse/orderbook-order');
|
||||
const validate = utils.common.validate;
|
||||
const composeAsync = utils.common.composeAsync;
|
||||
|
||||
// account is to specify a "perspective", which affects which unfunded offers
|
||||
// are returned
|
||||
function getBookOffers(remote, account, ledgerVersion, limit,
|
||||
takerGets, takerPays, callback) {
|
||||
remote.requestBookOffers(utils.renameCounterpartyToIssuerInOrder({
|
||||
taker_gets: takerGets,
|
||||
taker_pays: takerPays,
|
||||
ledger: ledgerVersion || 'validated',
|
||||
limit: limit,
|
||||
taker: account
|
||||
}), composeAsync(data => data.offers, callback));
|
||||
}
|
||||
|
||||
function isSameIssue(a, b) {
|
||||
return a.currency === b.currency && a.counterparty === b.counterparty;
|
||||
}
|
||||
|
||||
function directionFilter(direction, order) {
|
||||
return order.specification.direction === direction;
|
||||
}
|
||||
|
||||
function flipOrder(order) {
|
||||
const specification = order.specification;
|
||||
const flippedSpecification = {
|
||||
quantity: specification.totalPrice,
|
||||
totalPrice: specification.quantity,
|
||||
direction: specification.direction === 'buy' ? 'sell' : 'buy'
|
||||
};
|
||||
const newSpecification = _.merge({}, specification, flippedSpecification);
|
||||
return _.merge({}, order, {specification: newSpecification});
|
||||
}
|
||||
|
||||
function alignOrder(base, order) {
|
||||
const quantity = order.specification.quantity;
|
||||
return isSameIssue(quantity, base) ? order : flipOrder(order);
|
||||
}
|
||||
|
||||
function formatBidsAndAsks(orderbook, offers) {
|
||||
// the "base" currency is the currency that you are buying or selling
|
||||
// the "counter" is the currency that the "base" is priced in
|
||||
// a "bid"/"ask" is an order to buy/sell the base, respectively
|
||||
// for bids: takerGets = totalPrice = counter, takerPays = quantity = base
|
||||
// for asks: takerGets = quantity = base, takerPays = totalPrice = counter
|
||||
// quality = takerPays / takerGets; price = totalPrice / quantity
|
||||
// for bids: lowest quality => lowest quantity/totalPrice => highest price
|
||||
// for asks: lowest quality => lowest totalPrice/quantity => lowest price
|
||||
// for both bids and asks, lowest quality is closest to mid-market
|
||||
// we sort the orders so that earlier orders are closer to mid-market
|
||||
const orders = _.sortBy(offers, 'quality').map(parseOrderbookOrder);
|
||||
const alignedOrders = orders.map(_.partial(alignOrder, orderbook.base));
|
||||
const bids = alignedOrders.filter(_.partial(directionFilter, 'buy'));
|
||||
const asks = alignedOrders.filter(_.partial(directionFilter, 'sell'));
|
||||
return {bids, asks};
|
||||
}
|
||||
|
||||
function getOrderbookAsync(account, orderbook, options, callback) {
|
||||
validate.address(account);
|
||||
validate.orderbook(orderbook);
|
||||
validate.getOrderbookOptions(options);
|
||||
|
||||
const getter = _.partial(getBookOffers, this.remote, account,
|
||||
options.ledgerVersion, options.limit);
|
||||
const getOffers = _.partial(getter, orderbook.base, orderbook.counter);
|
||||
const getReverseOffers = _.partial(getter, orderbook.counter, orderbook.base);
|
||||
async.parallel([getOffers, getReverseOffers],
|
||||
composeAsync((data) => formatBidsAndAsks(orderbook, _.flatten(data)),
|
||||
callback));
|
||||
}
|
||||
|
||||
function getOrderbook(account: string, orderbook: Object, options={}) {
|
||||
return utils.promisify(getOrderbookAsync.bind(this))(
|
||||
account, orderbook, options);
|
||||
}
|
||||
|
||||
module.exports = getOrderbook;
|
||||
40
src/api/ledger/orders.js
Normal file
40
src/api/ledger/orders.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const composeAsync = utils.common.composeAsync;
|
||||
const parseAccountOrder = require('./parse/account-order');
|
||||
|
||||
function requestAccountOffers(remote, address, ledgerVersion, options,
|
||||
marker, limit, callback) {
|
||||
remote.requestAccountOffers({
|
||||
account: address,
|
||||
marker: marker,
|
||||
limit: utils.clamp(limit, 10, 400),
|
||||
ledger: ledgerVersion
|
||||
},
|
||||
composeAsync((data) => ({
|
||||
marker: data.marker,
|
||||
results: data.offers.map(_.partial(parseAccountOrder, address))
|
||||
}), callback));
|
||||
}
|
||||
|
||||
function getOrdersAsync(account, options, callback) {
|
||||
validate.address(account);
|
||||
validate.getOrdersOptions(options);
|
||||
|
||||
const ledgerVersion = options.ledgerVersion
|
||||
|| this.remote.getLedgerSequence();
|
||||
const getter = _.partial(requestAccountOffers, this.remote, account,
|
||||
ledgerVersion, options);
|
||||
utils.getRecursive(getter, options.limit,
|
||||
composeAsync((orders) => _.sortBy(orders,
|
||||
(order) => order.properties.sequence), callback));
|
||||
}
|
||||
|
||||
function getOrders(account: string, options={}) {
|
||||
return utils.promisify(getOrdersAsync.bind(this))(account, options);
|
||||
}
|
||||
|
||||
module.exports = getOrders;
|
||||
41
src/api/ledger/parse/account-order.js
Normal file
41
src/api/ledger/parse/account-order.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const flags = utils.core.Remote.flags.offer;
|
||||
const parseAmount = require('./amount');
|
||||
const BigNumber = require('bignumber.js');
|
||||
|
||||
// TODO: remove this function once rippled provides quality directly
|
||||
function computeQuality(takerGets, takerPays) {
|
||||
const quotient = new BigNumber(takerPays.value).dividedBy(takerGets.value);
|
||||
return quotient.toDigits(16, BigNumber.ROUND_HALF_UP).toString();
|
||||
}
|
||||
|
||||
// rippled 'account_offers' returns a different format for orders than 'tx'
|
||||
// the flags are also different
|
||||
function parseAccountOrder(address: string, order: Object): Object {
|
||||
const direction = (order.flags & flags.Sell) === 0 ? 'buy' : 'sell';
|
||||
const takerGetsAmount = parseAmount(order.taker_gets);
|
||||
const takerPaysAmount = parseAmount(order.taker_pays);
|
||||
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount;
|
||||
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount;
|
||||
|
||||
// note: immediateOrCancel and fillOrKill orders cannot enter the order book
|
||||
// so we can omit those flags here
|
||||
const specification = utils.removeUndefined({
|
||||
direction: direction,
|
||||
quantity: quantity,
|
||||
totalPrice: totalPrice,
|
||||
passive: ((order.flags & flags.Passive) !== 0) || undefined
|
||||
});
|
||||
|
||||
const properties = {
|
||||
maker: address,
|
||||
sequence: order.seq,
|
||||
makerExchangeRate: computeQuality(takerGetsAmount, takerPaysAmount)
|
||||
};
|
||||
|
||||
return {specification, properties};
|
||||
}
|
||||
|
||||
module.exports = parseAccountOrder;
|
||||
46
src/api/ledger/parse/account-trustline.js
Normal file
46
src/api/ledger/parse/account-trustline.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
|
||||
type Trustline = {
|
||||
account: string, limit: number, currency: string, quality_in: ?number,
|
||||
quality_out: ?number, no_ripple: boolean, freeze: boolean, authorized: boolean,
|
||||
limit_peer: string, no_ripple_peer: boolean, freeze_peer: boolean,
|
||||
peer_authorized: boolean, balance: any
|
||||
}
|
||||
|
||||
type TrustlineSpecification = {}
|
||||
type TrustlineCounterParty = {}
|
||||
type TrustlineState = {balance: number}
|
||||
type AccountTrustline = {
|
||||
specification: TrustlineSpecification, counterparty: TrustlineCounterParty,
|
||||
state: TrustlineState
|
||||
}
|
||||
|
||||
// rippled 'account_lines' returns a different format for
|
||||
// trustlines than 'tx'
|
||||
function parseAccountTrustline(trustline: Trustline): AccountTrustline {
|
||||
const specification = utils.removeUndefined({
|
||||
limit: trustline.limit,
|
||||
currency: trustline.currency,
|
||||
counterparty: trustline.account,
|
||||
qualityIn: trustline.quality_in || undefined,
|
||||
qualityOut: trustline.quality_out || undefined,
|
||||
ripplingDisabled: trustline.no_ripple || undefined,
|
||||
frozen: trustline.freeze || undefined,
|
||||
authorized: trustline.authorized || undefined
|
||||
});
|
||||
// rippled doesn't provide the counterparty's qualities
|
||||
const counterparty = utils.removeUndefined({
|
||||
limit: trustline.limit_peer,
|
||||
ripplingDisabled: trustline.no_ripple_peer || undefined,
|
||||
frozen: trustline.freeze_peer || undefined,
|
||||
authorized: trustline.peer_authorized || undefined
|
||||
});
|
||||
const state = {
|
||||
balance: trustline.balance
|
||||
};
|
||||
return {specification, counterparty, state};
|
||||
}
|
||||
|
||||
module.exports = parseAccountTrustline;
|
||||
24
src/api/ledger/parse/amount.js
Normal file
24
src/api/ledger/parse/amount.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
|
||||
type Amount = string | {currency: string, issuer: string, value: string}
|
||||
type XRPAmount = {currency: string, value: string}
|
||||
type IOUAmount = {currency: string, value: string, counterparty: string}
|
||||
type Output = XRPAmount | IOUAmount
|
||||
|
||||
function parseAmount(amount: Amount): Output {
|
||||
if (typeof amount === 'string') {
|
||||
return {
|
||||
currency: 'XRP',
|
||||
value: utils.dropsToXrp(amount)
|
||||
};
|
||||
}
|
||||
return {
|
||||
currency: amount.currency,
|
||||
value: amount.value,
|
||||
counterparty: amount.issuer
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = parseAmount;
|
||||
12
src/api/ledger/parse/cancellation.js
Normal file
12
src/api/ledger/parse/cancellation.js
Normal file
@@ -0,0 +1,12 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
|
||||
function parseOrderCancellation(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'OfferCancel');
|
||||
return {
|
||||
orderSequence: tx.OfferSequence
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = parseOrderCancellation;
|
||||
28
src/api/ledger/parse/fields.js
Normal file
28
src/api/ledger/parse/fields.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const BigNumber = require('bignumber.js');
|
||||
const AccountFields = require('./utils').constants.AccountFields;
|
||||
|
||||
function parseField(info, value) {
|
||||
if (info.encoding === 'hex' && !info.length) {
|
||||
return new Buffer(value, 'hex').toString('ascii');
|
||||
}
|
||||
if (info.shift) {
|
||||
return (new BigNumber(value)).shift(-info.shift).toNumber();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function parseFields(data: Object): Object {
|
||||
const settings = {};
|
||||
for (const fieldName in AccountFields) {
|
||||
const fieldValue = data[fieldName];
|
||||
if (fieldValue !== undefined) {
|
||||
const info = AccountFields[fieldName];
|
||||
settings[info.name] = parseField(info, fieldValue);
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
module.exports = parseFields;
|
||||
28
src/api/ledger/parse/order.js
Normal file
28
src/api/ledger/parse/order.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
const utils = require('./utils');
|
||||
const parseAmount = require('./amount');
|
||||
const flags = utils.core.Transaction.flags.OfferCreate;
|
||||
|
||||
function parseOrder(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'OfferCreate');
|
||||
|
||||
const direction = (tx.Flags & flags.Sell) === 0 ? 'buy' : 'sell';
|
||||
const takerGetsAmount = parseAmount(tx.TakerGets);
|
||||
const takerPaysAmount = parseAmount(tx.TakerPays);
|
||||
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount;
|
||||
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount;
|
||||
|
||||
return utils.removeUndefined({
|
||||
direction: direction,
|
||||
quantity: quantity,
|
||||
totalPrice: totalPrice,
|
||||
passive: ((tx.Flags & flags.Passive) !== 0) || undefined,
|
||||
immediateOrCancel: ((tx.Flags & flags.ImmediateOrCancel) !== 0)
|
||||
|| undefined,
|
||||
fillOrKill: ((tx.Flags & flags.FillOrKill) !== 0) || undefined
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseOrder;
|
||||
43
src/api/ledger/parse/orderbook-order.js
Normal file
43
src/api/ledger/parse/orderbook-order.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const flags = utils.core.Remote.flags.offer;
|
||||
const parseAmount = require('./amount');
|
||||
|
||||
function parseOrderbookOrder(order: Object): Object {
|
||||
const direction = (order.Flags & flags.Sell) === 0 ? 'buy' : 'sell';
|
||||
const takerGetsAmount = parseAmount(order.TakerGets);
|
||||
const takerPaysAmount = parseAmount(order.TakerPays);
|
||||
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount;
|
||||
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount;
|
||||
|
||||
// note: immediateOrCancel and fillOrKill orders cannot enter the order book
|
||||
// so we can omit those flags here
|
||||
const specification = utils.removeUndefined({
|
||||
direction: direction,
|
||||
quantity: quantity,
|
||||
totalPrice: totalPrice,
|
||||
passive: ((order.Flags & flags.Passive) !== 0) || undefined
|
||||
});
|
||||
|
||||
const properties = {
|
||||
maker: order.Account,
|
||||
sequence: order.Sequence,
|
||||
makerExchangeRate: utils.adjustQualityForXRP(order.quality,
|
||||
takerGetsAmount.currency, takerPaysAmount.currency)
|
||||
};
|
||||
|
||||
const takerGetsFunded = order.taker_gets_funded ?
|
||||
parseAmount(order.taker_gets_funded) : undefined;
|
||||
const takerPaysFunded = order.taker_pays_funded ?
|
||||
parseAmount(order.taker_pays_funded) : undefined;
|
||||
const available = utils.removeUndefined({
|
||||
fundedAmount: takerGetsFunded,
|
||||
priceOfFundedAmount: takerPaysFunded
|
||||
});
|
||||
const state = _.isEmpty(available) ? undefined : available;
|
||||
return utils.removeUndefined({specification, properties, state});
|
||||
}
|
||||
|
||||
module.exports = parseOrderbookOrder;
|
||||
28
src/api/ledger/parse/pathfind.js
Normal file
28
src/api/ledger/parse/pathfind.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const parseAmount = require('./amount');
|
||||
|
||||
function parsePaths(paths) {
|
||||
return paths.map(steps => steps.map(step =>
|
||||
_.omit(step, ['type', 'type_hex'])));
|
||||
}
|
||||
|
||||
function parsePathfind(sourceAddress: string,
|
||||
destinationAmount: Object, pathfindResult: Object): Object {
|
||||
return pathfindResult.alternatives.map(function(alternative) {
|
||||
return {
|
||||
source: {
|
||||
address: sourceAddress,
|
||||
amount: parseAmount(alternative.source_amount)
|
||||
},
|
||||
destination: {
|
||||
address: pathfindResult.destination_account,
|
||||
amount: destinationAmount
|
||||
},
|
||||
paths: JSON.stringify(parsePaths(alternative.paths_computed))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parsePathfind;
|
||||
67
src/api/ledger/parse/payment.js
Normal file
67
src/api/ledger/parse/payment.js
Normal file
@@ -0,0 +1,67 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const utils = require('./utils');
|
||||
const parseAmount = require('./amount');
|
||||
const Transaction = utils.core.Transaction;
|
||||
|
||||
function isPartialPayment(tx) {
|
||||
return (tx.Flags & Transaction.flags.Payment.PartialPayment) !== 0;
|
||||
}
|
||||
|
||||
function isNoDirectRipple(tx) {
|
||||
return (tx.Flags & Transaction.flags.Payment.NoRippleDirect) !== 0;
|
||||
}
|
||||
|
||||
function isQualityLimited(tx) {
|
||||
return (tx.Flags & Transaction.flags.Payment.LimitQuality) !== 0;
|
||||
}
|
||||
|
||||
function parsePaymentMemos(tx) {
|
||||
if (!Array.isArray(tx.Memos) || tx.Memos.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return tx.Memos.map((m) => {
|
||||
return utils.removeUndefined({
|
||||
type: m.Memo.parsed_memo_type,
|
||||
format: m.Memo.parsed_memo_format,
|
||||
data: m.Memo.parsed_memo_data
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function removeGenericCounterparty(amount, address) {
|
||||
return amount.counterparty === address ?
|
||||
_.omit(amount, 'counterparty') : amount;
|
||||
}
|
||||
|
||||
function parsePayment(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'Payment');
|
||||
|
||||
const source = {
|
||||
address: tx.Account,
|
||||
amount: removeGenericCounterparty(
|
||||
parseAmount(tx.SendMax || tx.Amount), tx.Account),
|
||||
tag: tx.SourceTag
|
||||
};
|
||||
|
||||
const destination = {
|
||||
address: tx.Destination,
|
||||
amount: removeGenericCounterparty(parseAmount(tx.Amount), tx.Destination),
|
||||
tag: tx.DestinationTag
|
||||
};
|
||||
|
||||
return utils.removeUndefined({
|
||||
source: utils.removeUndefined(source),
|
||||
destination: utils.removeUndefined(destination),
|
||||
memos: parsePaymentMemos(tx),
|
||||
invoiceID: tx.InvoiceID,
|
||||
paths: tx.Paths ? JSON.stringify(tx.Paths) : undefined,
|
||||
allowPartialPayment: isPartialPayment(tx) || undefined,
|
||||
noDirectRipple: isNoDirectRipple(tx) || undefined,
|
||||
limitQuality: isQualityLimited(tx) || undefined
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parsePayment;
|
||||
61
src/api/ledger/parse/settings.js
Normal file
61
src/api/ledger/parse/settings.js
Normal file
@@ -0,0 +1,61 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const AccountFlags = require('./utils').constants.AccountFlags;
|
||||
const parseFields = require('./fields');
|
||||
|
||||
function getAccountRootModifiedNode(tx: Object) {
|
||||
const modifiedNodes = tx.meta.AffectedNodes.filter(node =>
|
||||
node.ModifiedNode.LedgerEntryType === 'AccountRoot');
|
||||
assert(modifiedNodes.length === 1);
|
||||
return modifiedNodes[0].ModifiedNode;
|
||||
}
|
||||
|
||||
function parseFlags(tx: Object) {
|
||||
const settings = {};
|
||||
if (tx.TransactionType !== 'AccountSet') {
|
||||
return settings;
|
||||
}
|
||||
|
||||
const node = getAccountRootModifiedNode(tx);
|
||||
const oldFlags = _.get(node.PreviousFields, 'Flags');
|
||||
const newFlags = _.get(node.FinalFields, 'Flags');
|
||||
|
||||
if (oldFlags !== undefined && newFlags !== undefined) {
|
||||
const changedFlags = oldFlags ^ newFlags;
|
||||
const setFlags = newFlags & changedFlags;
|
||||
const clearedFlags = oldFlags & changedFlags;
|
||||
_.forEach(AccountFlags, (flagValue, flagName) => {
|
||||
if (setFlags & flagValue) {
|
||||
settings[flagName] = true;
|
||||
} else if (clearedFlags & flagValue) {
|
||||
settings[flagName] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// enableTransactionIDTracking requires a special case because it
|
||||
// does not affect the Flags field; instead it adds/removes a field called
|
||||
// "AccountTxnID" to/from the account root.
|
||||
|
||||
const oldField = _.get(node.PreviousFields, 'AccountTxnID');
|
||||
const newField = _.get(node.FinalFields, 'AccountTxnID');
|
||||
if (newField && !oldField) {
|
||||
settings.enableTransactionIDTracking = true;
|
||||
} else if (oldField && !newField) {
|
||||
settings.enableTransactionIDTracking = false;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
function parseSettings(tx: Object) {
|
||||
const txType = tx.TransactionType;
|
||||
assert(txType === 'AccountSet' || txType === 'SetRegularKey');
|
||||
|
||||
const regularKey = tx.RegularKey ? {regularKey: tx.RegularKey} : {};
|
||||
return _.assign(regularKey, parseFlags(tx), parseFields(tx));
|
||||
}
|
||||
|
||||
module.exports = parseSettings;
|
||||
46
src/api/ledger/parse/transaction.js
Normal file
46
src/api/ledger/parse/transaction.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
const utils = require('./utils');
|
||||
const parsePayment = require('./payment');
|
||||
const parseTrustline = require('./trustline');
|
||||
const parseOrder = require('./order');
|
||||
const parseOrderCancellation = require('./cancellation');
|
||||
const parseSettings = require('./settings');
|
||||
|
||||
function parseTransactionType(type) {
|
||||
const mapping = {
|
||||
Payment: 'payment',
|
||||
TrustSet: 'trustline',
|
||||
OfferCreate: 'order',
|
||||
OfferCancel: 'orderCancellation',
|
||||
AccountSet: 'settings',
|
||||
SetRegularKey: 'settings'
|
||||
};
|
||||
return mapping[type] || null;
|
||||
}
|
||||
|
||||
function parseTransaction(tx: Object): Object {
|
||||
const type = parseTransactionType(tx.TransactionType);
|
||||
const mapping = {
|
||||
'payment': parsePayment,
|
||||
'trustline': parseTrustline,
|
||||
'order': parseOrder,
|
||||
'orderCancellation': parseOrderCancellation,
|
||||
'settings': parseSettings
|
||||
};
|
||||
const parser = mapping[type];
|
||||
assert(parser !== undefined, 'Unrecognized transaction type');
|
||||
const specification = parser(tx);
|
||||
const outcome = utils.parseOutcome(tx);
|
||||
return utils.removeUndefined({
|
||||
type: type,
|
||||
address: tx.Account,
|
||||
sequence: tx.Sequence,
|
||||
id: tx.hash,
|
||||
specification: utils.removeUndefined(specification),
|
||||
outcome: outcome ? utils.removeUndefined(outcome) : undefined
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseTransaction;
|
||||
38
src/api/ledger/parse/trustline.js
Normal file
38
src/api/ledger/parse/trustline.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
const utils = require('./utils');
|
||||
const flags = utils.core.Transaction.flags.TrustSet;
|
||||
const BigNumber = require('bignumber.js');
|
||||
|
||||
function parseFlag(flagsValue, trueValue, falseValue) {
|
||||
if (flagsValue & trueValue) {
|
||||
return true;
|
||||
}
|
||||
if (flagsValue & falseValue) {
|
||||
return false;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseQuality(quality) {
|
||||
return (new BigNumber(quality)).shift(-9).toNumber();
|
||||
}
|
||||
|
||||
function parseTrustline(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'TrustSet');
|
||||
|
||||
return utils.removeUndefined({
|
||||
limit: tx.LimitAmount.value,
|
||||
currency: tx.LimitAmount.currency,
|
||||
counterparty: tx.LimitAmount.issuer,
|
||||
qualityIn: parseQuality(tx.QualityIn),
|
||||
qualityOut: parseQuality(tx.QualityOut),
|
||||
ripplingDisabled: parseFlag(
|
||||
tx.Flags, flags.SetNoRipple, flags.ClearNoRipple),
|
||||
frozen: parseFlag(tx.Flags, flags.SetFreeze, flags.ClearFreeze),
|
||||
authorized: parseFlag(tx.Flags, flags.SetAuth, 0)
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseTrustline;
|
||||
77
src/api/ledger/parse/utils.js
Normal file
77
src/api/ledger/parse/utils.js
Normal file
@@ -0,0 +1,77 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const transactionParser = require('ripple-lib-transactionparser');
|
||||
const toTimestamp = require('../../../core/utils').toTimestamp;
|
||||
const utils = require('../utils');
|
||||
const BigNumber = require('bignumber.js');
|
||||
|
||||
function adjustQualityForXRP(
|
||||
quality: string, takerGetsCurrency: string, takerPaysCurrency: string
|
||||
) {
|
||||
// quality = takerPays.value/takerGets.value
|
||||
// using drops (1e-6 XRP) for XRP values
|
||||
const numeratorShift = (takerPaysCurrency === 'XRP' ? -6 : 0);
|
||||
const denominatorShift = (takerGetsCurrency === 'XRP' ? -6 : 0);
|
||||
const shift = numeratorShift - denominatorShift;
|
||||
return shift === 0 ? quality :
|
||||
(new BigNumber(quality)).shift(shift).toString();
|
||||
}
|
||||
|
||||
function parseTimestamp(tx: {date: string}): string | void {
|
||||
return tx.date ? (new Date(toTimestamp(tx.date))).toISOString() : undefined;
|
||||
}
|
||||
|
||||
function removeUndefined(obj: Object): Object {
|
||||
return _.omit(obj, _.isUndefined);
|
||||
}
|
||||
|
||||
function removeEmptyCounterparty(amount) {
|
||||
if (amount.counterparty === '') {
|
||||
delete amount.counterparty;
|
||||
}
|
||||
}
|
||||
|
||||
function removeEmptyCounterpartyInBalanceChanges(balanceChanges) {
|
||||
_.forEach(balanceChanges, (changes) => {
|
||||
_.forEach(changes, removeEmptyCounterparty);
|
||||
});
|
||||
}
|
||||
|
||||
function removeEmptyCounterpartyInOrderbookChanges(orderbookChanges) {
|
||||
_.forEach(orderbookChanges, (changes) => {
|
||||
_.forEach(changes, (change) => {
|
||||
_.forEach(change, removeEmptyCounterparty);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function parseOutcome(tx: Object): ?Object {
|
||||
if (!tx.validated) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const balanceChanges = transactionParser.parseBalanceChanges(tx.meta);
|
||||
const orderbookChanges = transactionParser.parseOrderbookChanges(tx.meta);
|
||||
removeEmptyCounterpartyInBalanceChanges(balanceChanges);
|
||||
removeEmptyCounterpartyInOrderbookChanges(orderbookChanges);
|
||||
|
||||
return {
|
||||
result: tx.meta.TransactionResult,
|
||||
timestamp: parseTimestamp(tx),
|
||||
fee: utils.common.dropsToXrp(tx.Fee),
|
||||
balanceChanges: balanceChanges,
|
||||
orderbookChanges: orderbookChanges,
|
||||
ledgerVersion: tx.ledger_index,
|
||||
indexInLedger: tx.meta.TransactionIndex
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseOutcome,
|
||||
removeUndefined,
|
||||
adjustQualityForXRP,
|
||||
dropsToXrp: utils.common.dropsToXrp,
|
||||
constants: utils.common.constants,
|
||||
core: utils.common.core
|
||||
};
|
||||
120
src/api/ledger/pathfind.js
Normal file
120
src/api/ledger/pathfind.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const BigNumber = require('bignumber.js');
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const parsePathfind = require('./parse/pathfind');
|
||||
const NotFoundError = utils.common.errors.NotFoundError;
|
||||
const composeAsync = utils.common.composeAsync;
|
||||
|
||||
type PathFindParams = {
|
||||
src_currencies?: Array<string>, src_account: string, dst_amount: string,
|
||||
dst_account?: string
|
||||
}
|
||||
|
||||
function addParams(params: PathFindParams, result: {}) {
|
||||
return _.assign({}, result, {
|
||||
source_account: params.src_account,
|
||||
source_currencies: params.src_currencies,
|
||||
destination_amount: params.dst_amount
|
||||
});
|
||||
}
|
||||
|
||||
type PathFind = {
|
||||
source: {address: string, currencies: Array<string>},
|
||||
destination: {address: string, amount: string}
|
||||
}
|
||||
|
||||
function requestPathFind(remote, pathfind: PathFind, callback) {
|
||||
const params: PathFindParams = {
|
||||
src_account: pathfind.source.address,
|
||||
dst_account: pathfind.destination.address,
|
||||
dst_amount: utils.common.toRippledAmount(pathfind.destination.amount)
|
||||
};
|
||||
if (typeof params.dst_amount === 'object' && !params.dst_amount.issuer) {
|
||||
// Convert blank issuer to sender's address
|
||||
// (Ripple convention for 'any issuer')
|
||||
// https://ripple.com/build/transactions/
|
||||
// #special-issuer-values-for-sendmax-and-amount
|
||||
// https://ripple.com/build/ripple-rest/#counterparties-in-payments
|
||||
params.dst_amount.issuer = params.dst_account;
|
||||
}
|
||||
if (pathfind.source.currencies && pathfind.source.currencies.length > 0) {
|
||||
params.src_currencies = pathfind.source.currencies.map(amount =>
|
||||
_.omit(utils.common.toRippledAmount(amount), 'value'));
|
||||
}
|
||||
|
||||
remote.requestRipplePathFind(params,
|
||||
composeAsync(_.partial(addParams, params), callback));
|
||||
}
|
||||
|
||||
function addDirectXrpPath(paths, xrpBalance) {
|
||||
// Add XRP "path" only if the source acct has enough XRP to make the payment
|
||||
const destinationAmount = paths.destination_amount;
|
||||
if ((new BigNumber(xrpBalance)).greaterThanOrEqualTo(destinationAmount)) {
|
||||
paths.alternatives.unshift({
|
||||
paths_computed: [],
|
||||
source_amount: paths.destination_amount
|
||||
});
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
function isRippledIOUAmount(amount) {
|
||||
// rippled XRP amounts are specified as decimal strings
|
||||
return (typeof amount === 'object') &&
|
||||
amount.currency && (amount.currency !== 'XRP');
|
||||
}
|
||||
|
||||
function conditionallyAddDirectXRPPath(remote, address, paths, callback) {
|
||||
if (isRippledIOUAmount(paths.destination_amount)
|
||||
|| !_.includes(paths.destination_currencies, 'XRP')) {
|
||||
callback(null, paths);
|
||||
} else {
|
||||
utils.getXRPBalance(remote, address, undefined,
|
||||
composeAsync(_.partial(addDirectXrpPath, paths), callback));
|
||||
}
|
||||
}
|
||||
|
||||
function formatResponse(pathfind, paths) {
|
||||
if (paths.alternatives && paths.alternatives.length > 0) {
|
||||
const address = pathfind.source.address;
|
||||
return parsePathfind(address, pathfind.destination.amount, paths);
|
||||
}
|
||||
if (!_.includes(paths.destination_currencies,
|
||||
pathfind.destination.amount.currency)) {
|
||||
throw new NotFoundError('No paths found. ' +
|
||||
'The destination_account does not accept ' +
|
||||
pathfind.destination.amount.currency + ', they only accept: ' +
|
||||
paths.destination_currencies.join(', '));
|
||||
} else if (paths.source_currencies && paths.source_currencies.length > 0) {
|
||||
throw new NotFoundError('No paths found. Please ensure' +
|
||||
' that the source_account has sufficient funds to execute' +
|
||||
' the payment in one of the specified source_currencies. If it does' +
|
||||
' there may be insufficient liquidity in the network to execute' +
|
||||
' this payment right now');
|
||||
} else {
|
||||
throw new NotFoundError('No paths found.' +
|
||||
' Please ensure that the source_account has sufficient funds to' +
|
||||
' execute the payment. If it does there may be insufficient liquidity' +
|
||||
' in the network to execute this payment right now');
|
||||
}
|
||||
}
|
||||
|
||||
function getPathsAsync(pathfind, callback) {
|
||||
validate.pathfind(pathfind);
|
||||
|
||||
const address = pathfind.source.address;
|
||||
async.waterfall([
|
||||
_.partial(requestPathFind, this.remote, pathfind),
|
||||
_.partial(conditionallyAddDirectXRPPath, this.remote, address)
|
||||
], composeAsync(_.partial(formatResponse, pathfind), callback));
|
||||
}
|
||||
|
||||
function getPaths(pathfind: Object) {
|
||||
return utils.promisify(getPathsAsync.bind(this))(pathfind);
|
||||
}
|
||||
|
||||
module.exports = getPaths;
|
||||
44
src/api/ledger/settings.js
Normal file
44
src/api/ledger/settings.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const parseFields = require('./parse/fields');
|
||||
const composeAsync = utils.common.composeAsync;
|
||||
const AccountFlags = utils.common.constants.AccountFlags;
|
||||
|
||||
function parseFlags(value) {
|
||||
const settings = {};
|
||||
for (const flagName in AccountFlags) {
|
||||
if (value & AccountFlags[flagName]) {
|
||||
settings[flagName] = true;
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
function formatSettings(response) {
|
||||
const data = response.account_data;
|
||||
const parsedFlags = parseFlags(data.Flags);
|
||||
const parsedFields = parseFields(data);
|
||||
return _.assign({}, parsedFlags, parsedFields);
|
||||
}
|
||||
|
||||
function getSettingsAsync(account, options, callback) {
|
||||
validate.address(account);
|
||||
validate.getSettingsOptions(options);
|
||||
|
||||
const request = {
|
||||
account: account,
|
||||
ledger: options.ledgerVersion
|
||||
};
|
||||
|
||||
this.remote.requestAccountInfo(request,
|
||||
composeAsync(formatSettings, callback));
|
||||
}
|
||||
|
||||
function getSettings(account: string, options={}) {
|
||||
return utils.promisify(getSettingsAsync.bind(this))(account, options);
|
||||
}
|
||||
|
||||
module.exports = getSettings;
|
||||
78
src/api/ledger/transaction.js
Normal file
78
src/api/ledger/transaction.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const utils = require('./utils');
|
||||
const parseTransaction = require('./parse/transaction');
|
||||
const validate = utils.common.validate;
|
||||
const errors = utils.common.errors;
|
||||
const RippleError = require('../../core/rippleerror').RippleError;
|
||||
|
||||
function attachTransactionDate(remote, tx, callback) {
|
||||
if (tx.date) {
|
||||
callback(null, tx);
|
||||
return;
|
||||
}
|
||||
if (!tx.ledger_index) {
|
||||
callback(new errors.NotFoundError('ledger_index not found in tx'));
|
||||
return;
|
||||
}
|
||||
|
||||
remote.requestLedger(tx.ledger_index, (error, data) => {
|
||||
if (error) {
|
||||
callback(new errors.NotFoundError('Transaction ledger not found'));
|
||||
} else if (typeof data.ledger.close_time === 'number') {
|
||||
callback(null, _.assign({date: data.ledger.close_time}, tx));
|
||||
} else {
|
||||
callback(new errors.ApiError('Ledger missing close_time'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isTransactionInRange(tx, options) {
|
||||
return (!options.minLedgerVersion
|
||||
|| tx.ledger_index >= options.minLedgerVersion)
|
||||
&& (!options.maxLedgerVersion
|
||||
|| tx.ledger_index <= options.maxLedgerVersion);
|
||||
}
|
||||
|
||||
function getTransactionAsync(identifier, options, callback) {
|
||||
validate.identifier(identifier);
|
||||
validate.getTransactionOptions(options);
|
||||
|
||||
const remote = this.remote;
|
||||
const maxLedgerVersion = Math.min(options.maxLedgerVersion,
|
||||
remote.getLedgerSequence());
|
||||
|
||||
function callbackWrapper(error_, tx) {
|
||||
let error = error_;
|
||||
if (error instanceof RippleError && error.remote &&
|
||||
error.remote.error === 'txnNotFound') {
|
||||
error = new errors.NotFoundError('Transaction not found');
|
||||
}
|
||||
|
||||
if (error instanceof errors.NotFoundError
|
||||
&& !utils.hasCompleteLedgerRange(remote,
|
||||
options.minLedgerVersion, maxLedgerVersion)) {
|
||||
callback(new errors.MissingLedgerHistoryError('Transaction not found,'
|
||||
+ ' but the server\'s ledger history is incomplete'));
|
||||
} else if (!error && !isTransactionInRange(tx, options)) {
|
||||
callback(new errors.NotFoundError('Transaction not found'));
|
||||
} else if (error) {
|
||||
callback(error);
|
||||
} else {
|
||||
callback(error, parseTransaction(tx));
|
||||
}
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
_.partial(remote.requestTx.bind(remote), {hash: identifier, binary: false}),
|
||||
_.partial(attachTransactionDate, remote)
|
||||
], callbackWrapper);
|
||||
}
|
||||
|
||||
function getTransaction(identifier: string, options={}) {
|
||||
return utils.promisify(getTransactionAsync.bind(this))(identifier, options);
|
||||
}
|
||||
|
||||
module.exports = getTransaction;
|
||||
124
src/api/ledger/transactions.js
Normal file
124
src/api/ledger/transactions.js
Normal file
@@ -0,0 +1,124 @@
|
||||
/* @flow */
|
||||
/* eslint-disable max-params */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const parseTransaction = require('./parse/transaction');
|
||||
const getTransaction = require('./transaction');
|
||||
const validate = utils.common.validate;
|
||||
const composeAsync = utils.common.composeAsync;
|
||||
|
||||
function parseAccountTxTransaction(tx) {
|
||||
// rippled uses a different response format for 'account_tx' than 'tx'
|
||||
tx.tx.meta = tx.meta;
|
||||
tx.tx.validated = tx.validated;
|
||||
return parseTransaction(tx.tx);
|
||||
}
|
||||
|
||||
function transactionFilter(address, filters, tx) {
|
||||
if (filters.excludeFailures && tx.outcome.result !== 'tesSUCCESS') {
|
||||
return false;
|
||||
}
|
||||
if (filters.types && !_.includes(filters.types, tx.type)) {
|
||||
return false;
|
||||
}
|
||||
if (filters.initiated === true && tx.address !== address) {
|
||||
return false;
|
||||
}
|
||||
if (filters.initiated === false && tx.address === address) {
|
||||
return false;
|
||||
}
|
||||
if (filters.counterparty && tx.address !== filters.counterparty
|
||||
&& tx.specification.destination.address !== filters.counterparty) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function orderFilter(options, tx) {
|
||||
return !options.startTx || (options.earliestFirst ?
|
||||
utils.compareTransactions(tx, options.startTx) > 0 :
|
||||
utils.compareTransactions(tx, options.startTx) < 0);
|
||||
}
|
||||
|
||||
function getAccountTx(remote, address, options, marker, limit, callback) {
|
||||
const params = {
|
||||
account: address,
|
||||
ledger_index_min: options.minLedgerVersion || -1,
|
||||
ledger_index_max: options.maxLedgerVersion || -1,
|
||||
forward: options.earliestFirst,
|
||||
binary: options.binary,
|
||||
limit: utils.clamp(limit, 10, 400),
|
||||
marker: marker
|
||||
};
|
||||
|
||||
remote.requestAccountTx(params, (error, data) => {
|
||||
return error ? callback(error) : callback(null, {
|
||||
marker: data.marker,
|
||||
results: data.transactions
|
||||
.filter((tx) => tx.validated)
|
||||
.map(parseAccountTxTransaction)
|
||||
.filter(_.partial(transactionFilter, address, options))
|
||||
.filter(_.partial(orderFilter, options))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkForLedgerGaps(remote, options, transactions) {
|
||||
let {minLedgerVersion, maxLedgerVersion} = options;
|
||||
|
||||
// if we reached the limit on number of transactions, then we can shrink
|
||||
// the required ledger range to only guarantee that there are no gaps in
|
||||
// the range of ledgers spanned by those transactions
|
||||
if (options.limit && transactions.length === options.limit) {
|
||||
if (options.earliestFirst) {
|
||||
maxLedgerVersion = _.last(transactions).outcome.ledgerVersion;
|
||||
} else {
|
||||
minLedgerVersion = _.last(transactions).outcome.ledgerVersion;
|
||||
}
|
||||
}
|
||||
|
||||
if (!utils.hasCompleteLedgerRange(remote, minLedgerVersion,
|
||||
maxLedgerVersion)) {
|
||||
throw new utils.common.errors.MissingLedgerHistoryError();
|
||||
}
|
||||
}
|
||||
|
||||
function formatResponse(remote, options, transactions) {
|
||||
const compare = options.earliestFirst ? utils.compareTransactions :
|
||||
_.rearg(utils.compareTransactions, 1, 0);
|
||||
const sortedTransactions = transactions.sort(compare);
|
||||
checkForLedgerGaps(remote, options, sortedTransactions);
|
||||
return sortedTransactions;
|
||||
}
|
||||
|
||||
function getTransactionsInternal(remote, address, options, callback) {
|
||||
const getter = _.partial(getAccountTx, remote, address, options);
|
||||
const format = _.partial(formatResponse, remote, options);
|
||||
utils.getRecursive(getter, options.limit, composeAsync(format, callback));
|
||||
}
|
||||
|
||||
function getTransactionsAsync(account, options, callback) {
|
||||
validate.address(account);
|
||||
validate.getTransactionsOptions(options);
|
||||
|
||||
const defaults = {maxLedgerVersion: this.remote.getLedgerSequence()};
|
||||
if (options.start) {
|
||||
getTransaction.bind(this)(options.start).then(tx => {
|
||||
const ledgerVersion = tx.outcome.ledgerVersion;
|
||||
const bound = options.earliestFirst ?
|
||||
{minLedgerVersion: ledgerVersion} : {maxLedgerVersion: ledgerVersion};
|
||||
const newOptions = _.assign(defaults, options, {startTx: tx}, bound);
|
||||
getTransactionsInternal(this.remote, account, newOptions, callback);
|
||||
}).catch(callback);
|
||||
} else {
|
||||
const newOptions = _.assign(defaults, options);
|
||||
getTransactionsInternal(this.remote, account, newOptions, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function getTransactions(account: string, options={}) {
|
||||
return utils.promisify(getTransactionsAsync.bind(this))(account, options);
|
||||
}
|
||||
|
||||
module.exports = getTransactions;
|
||||
49
src/api/ledger/trustlines.js
Normal file
49
src/api/ledger/trustlines.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const parseAccountTrustline = require('./parse/account-trustline');
|
||||
|
||||
function currencyFilter(currency, trustline) {
|
||||
return currency === null || trustline.specification.currency === currency;
|
||||
}
|
||||
|
||||
function getAccountLines(remote, address, ledgerVersion, options, marker, limit,
|
||||
callback) {
|
||||
const requestOptions = {
|
||||
account: address,
|
||||
ledger: ledgerVersion,
|
||||
marker: marker,
|
||||
limit: utils.clamp(limit, 10, 400),
|
||||
peer: options.counterparty
|
||||
};
|
||||
|
||||
remote.requestAccountLines(requestOptions, (error, data) => {
|
||||
return error ? callback(error) :
|
||||
callback(null, {
|
||||
marker: data.marker,
|
||||
results: data.lines.map(parseAccountTrustline)
|
||||
.filter(_.partial(currencyFilter, options.currency || null))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getTrustlinesAsync(account: string, options: {currency: string,
|
||||
counterparty: string, limit: number, ledgerVersion: number},
|
||||
callback: () => void): void {
|
||||
validate.address(account);
|
||||
validate.getTrustlinesOptions(options);
|
||||
|
||||
const ledgerVersion = options.ledgerVersion
|
||||
|| this.remote.getLedgerSequence();
|
||||
const getter = _.partial(getAccountLines, this.remote, account,
|
||||
ledgerVersion, options);
|
||||
utils.getRecursive(getter, options.limit, callback);
|
||||
}
|
||||
|
||||
function getTrustlines(account: string, options={}) {
|
||||
return utils.promisify(getTrustlinesAsync.bind(this))(account, options);
|
||||
}
|
||||
|
||||
module.exports = getTrustlines;
|
||||
114
src/api/ledger/utils.js
Normal file
114
src/api/ledger/utils.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const common = require('../common');
|
||||
const dropsToXrp = common.dropsToXrp;
|
||||
const composeAsync = common.composeAsync;
|
||||
|
||||
type Callback = (err: any, data: any) => void
|
||||
|
||||
function clamp(value: number, min: number, max: number): number {
|
||||
assert(min <= max, 'Illegal clamp bounds');
|
||||
return Math.min(Math.max(value, min), max);
|
||||
}
|
||||
|
||||
function getXRPBalance(remote: any, address: string, ledgerVersion?: number,
|
||||
callback: Callback): void {
|
||||
remote.requestAccountInfo({account: address, ledger: ledgerVersion},
|
||||
composeAsync((data) => dropsToXrp(data.account_data.Balance), callback));
|
||||
}
|
||||
|
||||
type Getter = (marker: ?string, limit: number, callback: Callback) => void
|
||||
|
||||
// If the marker is omitted from a response, you have reached the end
|
||||
// getter(marker, limit, callback), callback(error, {marker, results})
|
||||
function getRecursiveRecur(getter: Getter, marker?: string, limit: number,
|
||||
callback: Callback): void {
|
||||
getter(marker, limit, (error, data) => {
|
||||
if (error) {
|
||||
return callback(error);
|
||||
}
|
||||
const remaining = limit - data.results.length;
|
||||
if (remaining > 0 && data.marker !== undefined) {
|
||||
getRecursiveRecur(getter, data.marker, remaining, (_error, results) => {
|
||||
return _error ? callback(_error) :
|
||||
callback(null, data.results.concat(results));
|
||||
});
|
||||
} else {
|
||||
return callback(null, data.results.slice(0, limit));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getRecursive(getter: Getter, limit?: number, callback: Callback) {
|
||||
getRecursiveRecur(getter, undefined, limit || Infinity, callback);
|
||||
}
|
||||
|
||||
type Amount = {counterparty?: string, issuer?: string, value: string}
|
||||
|
||||
function renameCounterpartyToIssuer(amount?: Amount): ?{issuer?: string} {
|
||||
if (amount === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const issuer = amount.counterparty === undefined ?
|
||||
amount.issuer : amount.counterparty;
|
||||
const withIssuer = _.assign({}, amount, {issuer: issuer});
|
||||
return _.omit(withIssuer, 'counterparty');
|
||||
}
|
||||
|
||||
type Order = {taker_gets: Amount, taker_pays: Amount}
|
||||
|
||||
function renameCounterpartyToIssuerInOrder(order: Order) {
|
||||
const taker_gets = renameCounterpartyToIssuer(order.taker_gets);
|
||||
const taker_pays = renameCounterpartyToIssuer(order.taker_pays);
|
||||
const changes = {taker_gets: taker_gets, taker_pays: taker_pays};
|
||||
return _.assign({}, order, _.omit(changes, _.isUndefined));
|
||||
}
|
||||
|
||||
function signum(num) {
|
||||
return (num === 0) ? 0 : (num > 0 ? 1 : -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order two rippled transactions based on their ledger_index.
|
||||
* If two transactions took place in the same ledger, sort
|
||||
* them based on TransactionIndex
|
||||
* See: https://ripple.com/build/transactions/
|
||||
*
|
||||
* @param {Object} first
|
||||
* @param {Object} second
|
||||
* @returns {Number} [-1, 0, 1]
|
||||
*/
|
||||
|
||||
type Outcome = {outcome: {ledgerVersion: string, indexInLedger: string}};
|
||||
|
||||
function compareTransactions(first: Outcome, second: Outcome): number {
|
||||
if (first.outcome.ledgerVersion === second.outcome.ledgerVersion) {
|
||||
return signum(Number(first.outcome.indexInLedger) -
|
||||
Number(second.outcome.indexInLedger));
|
||||
}
|
||||
return Number(first.outcome.ledgerVersion) <
|
||||
Number(second.outcome.ledgerVersion) ? -1 : 1;
|
||||
}
|
||||
|
||||
function hasCompleteLedgerRange(remote: any, minLedgerVersion: number,
|
||||
maxLedgerVersion: number): boolean {
|
||||
const firstLedgerVersion = 32570; // earlier versions have been lost
|
||||
return remote.getServer().hasLedgerRange(
|
||||
minLedgerVersion || firstLedgerVersion,
|
||||
maxLedgerVersion || remote.getLedgerSequence());
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getXRPBalance,
|
||||
compareTransactions,
|
||||
renameCounterpartyToIssuer,
|
||||
renameCounterpartyToIssuerInOrder,
|
||||
getRecursive,
|
||||
hasCompleteLedgerRange,
|
||||
promisify: common.promisify,
|
||||
clamp: clamp,
|
||||
common: common
|
||||
};
|
||||
|
||||
63
src/api/server/server.js
Normal file
63
src/api/server/server.js
Normal file
@@ -0,0 +1,63 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const common = require('../common');
|
||||
|
||||
// If a ledger is not received in this time, consider the connection offline
|
||||
const CONNECTION_TIMEOUT = 1000 * 30;
|
||||
|
||||
function isUpToDate(remote): boolean {
|
||||
const server = remote.getServer();
|
||||
return Boolean(server) && (remote._stand_alone
|
||||
|| (Date.now() - server._lastLedgerClose) <= CONNECTION_TIMEOUT);
|
||||
}
|
||||
|
||||
function isConnected(): boolean {
|
||||
return Boolean(this.remote._ledger_current_index) && isUpToDate(this.remote);
|
||||
}
|
||||
|
||||
function getServerInfoAsync(callback: (err: any, data: any) => void): void {
|
||||
this.remote.requestServerInfo((error, response) => {
|
||||
if (error) {
|
||||
const message = _.get(error, ['remote', 'error_message'], error.message);
|
||||
callback(new common.errors.RippledNetworkError(message));
|
||||
} else {
|
||||
callback(null, common.convertKeysFromSnakeCaseToCamelCase(response.info));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getFee(): number {
|
||||
return common.dropsToXrp(this.remote.createTransaction()._computeFee());
|
||||
}
|
||||
|
||||
function getLedgerVersion(): number {
|
||||
return this.remote.getLedgerSequence();
|
||||
}
|
||||
|
||||
function connect() {
|
||||
return common.promisify(callback => {
|
||||
this.remote.connect(() => callback(null));
|
||||
})();
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
return common.promisify(callback => {
|
||||
this.remote.disconnect(() => callback(null));
|
||||
})();
|
||||
}
|
||||
|
||||
function getServerInfo() {
|
||||
return common.promisify(getServerInfoAsync.bind(this))();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
connect,
|
||||
disconnect,
|
||||
isConnected,
|
||||
getServerInfo,
|
||||
getFee,
|
||||
getLedgerVersion
|
||||
};
|
||||
43
src/api/transaction/order.js
Normal file
43
src/api/transaction/order.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const Transaction = utils.common.core.Transaction;
|
||||
|
||||
const OfferCreateFlags = {
|
||||
passive: {set: 'Passive'},
|
||||
immediateOrCancel: {set: 'ImmediateOrCancel'},
|
||||
fillOrKill: {set: 'FillOrKill'}
|
||||
};
|
||||
|
||||
function createOrderTransaction(account, order) {
|
||||
validate.address(account);
|
||||
validate.order(order);
|
||||
|
||||
const transaction = new Transaction();
|
||||
const takerPays = utils.common.toRippledAmount(order.direction === 'buy' ?
|
||||
order.quantity : order.totalPrice);
|
||||
const takerGets = utils.common.toRippledAmount(order.direction === 'buy' ?
|
||||
order.totalPrice : order.quantity);
|
||||
|
||||
transaction.offerCreate(account, takerPays, takerGets);
|
||||
|
||||
utils.setTransactionBitFlags(transaction, order, OfferCreateFlags);
|
||||
if (order.direction === 'sell') {
|
||||
transaction.setFlags('Sell');
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareOrderAsync(account, order, instructions, callback) {
|
||||
const transaction = createOrderTransaction(account, order);
|
||||
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
function prepareOrder(account: string, order: Object, instructions={}) {
|
||||
return utils.promisify(prepareOrderAsync.bind(this))(
|
||||
account, order, instructions);
|
||||
}
|
||||
|
||||
module.exports = prepareOrder;
|
||||
28
src/api/transaction/ordercancellation.js
Normal file
28
src/api/transaction/ordercancellation.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const Transaction = utils.common.core.Transaction;
|
||||
|
||||
function createOrderCancellationTransaction(account, sequence) {
|
||||
validate.address(account);
|
||||
validate.sequence(sequence);
|
||||
|
||||
const transaction = new Transaction();
|
||||
transaction.offerCancel(account, sequence);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareOrderCancellationAsync(account, sequence, instructions,
|
||||
callback) {
|
||||
const transaction = createOrderCancellationTransaction(account, sequence);
|
||||
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
function prepareOrderCancellation(account: string, sequence: number,
|
||||
instructions={}) {
|
||||
return utils.promisify(prepareOrderCancellationAsync.bind(this))(
|
||||
account, sequence, instructions);
|
||||
}
|
||||
|
||||
module.exports = prepareOrderCancellation;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user