Compare commits

...

63 Commits

Author SHA1 Message Date
Geert Weening
13f89e2fcc [TASK] bump version to 0.9.0-rc5 2014-10-21 15:05:02 -07:00
Geert Weening
69a0a473a6 [DOC] update release notes 2014-10-21 15:04:52 -07:00
Geert Weening
4ab82d7e01 Merge pull request #188 from geertweening/fix/amount_precision
[FIX] amount precision bugs
2014-10-21 15:01:50 -07:00
Geert Weening
4be209e286 [FIX] amount precision bugs
- leading 0's for fraction part disappearing
- first decimal lower than 5 wouldn't result in dropping the decimal
2014-10-21 13:22:42 -07:00
Geert Weening
8b10325895 [TASK] bump version to 0.9.0-rc4 2014-10-16 14:11:36 -07:00
Geert Weening
70bf600247 [DOC] update release notes 2014-10-16 14:11:14 -07:00
Geert Weening
d42e06d48b [FIX] fraction_part is a string 2014-10-16 14:05:26 -07:00
wltsmrz
9c080b6790 Merge pull request #187 from ripple/amount_precision
[FIX] Amount.to_human() precision slicing instead of rounding
2014-10-16 14:00:29 -07:00
Geert Weening
033257b03b [FIX] Amount.to_human() precision slicing instead of rounding 2014-10-16 13:54:42 -07:00
Geert Weening
39d8bcdfc2 [TASK] bump version to 0.9.0-rc3 2014-10-15 11:32:16 -07:00
Geert Weening
2ddcb4e2b7 [DOC] update release notes 2014-10-15 11:31:52 -07:00
Geert Weening
d972718a53 Merge pull request #185 from shekenahglory/fix/serialize
[FIX] binformat: added missing TransactionResult options
2014-10-14 11:37:35 -07:00
Matthew Fettig
6abed8dd53 [FIX] binformat: added missing TransactionResult options 2014-10-14 11:32:33 -07:00
Geert Weening
e74e697b45 [TASK] bump version to 0.9.0-rc2 2014-10-09 14:46:12 -07:00
Geert Weening
26c59e8565 [DOC] update release notes 2014-10-09 14:45:44 -07:00
Geert Weening
a5e83c4f23 [FIX] run test by _mocha to capture coverage 2014-10-09 14:35:14 -07:00
wltsmrz
900c4bbd2e Merge pull request #184 from geertweening/show_interest_flag
[FEATURE] add flag to show or hide interest in to_human/to_json
2014-10-09 14:31:43 -07:00
Geert Weening
947ec3edc2 [FEATURE] add flag to show or hide interest in to_human/to_json
The show_interest flag will default to true for interest bearing currencies and false for currencies without interest
2014-10-09 14:31:02 -07:00
Geert Weening
957f10d9f1 [TASK] bump version to 0.9.0-rc1 2014-10-09 09:40:31 -07:00
Geert Weening
89aa54dff8 [DOC] update release notes 2014-10-09 09:39:15 -07:00
Geert Weening
bb76530e4b Merge pull request #179 from geertweening/develop
[FEATURE] make maxLoops in seed.get_key() optional
2014-10-09 09:32:17 -07:00
wltsmrz
011e2cc1e3 Merge pull request #182 from shekenahglory/fix/attestation
[FIX] vault client: URI decode attestation token
2014-10-08 18:41:38 -07:00
Matthew Fettig
4c594f8964 [FIX] vault client: URI decode attestation token 2014-10-08 18:17:30 -07:00
Geert Weening
1fcfcf2392 [TASK] bump version to 0.8.3-rc1 2014-10-06 18:23:59 -07:00
Geert Weening
6311abff81 [DOC] update release notes 2014-10-06 18:23:05 -07:00
Geert Weening
ed2da57475 Merge pull request #181 from shekenahglory/feature/identity
Feature/identity
2014-10-06 18:15:38 -07:00
Matthew Fettig
778ccd4805 [TASK] vault client: tests for attestation routes and full summary 2014-10-06 18:03:52 -07:00
Matthew Fettig
327c35252f [FEATURE] vault client: update attestation and attestation summary 2014-10-03 17:17:09 -07:00
Matthew Fettig
5e7af2fba4 [TASK] switch to new attestation endpoint 2014-10-03 17:17:09 -07:00
Matthew Fettig
dce15bc579 [TASK] vault client: add parameters to attest 2014-10-03 17:17:08 -07:00
Matthew Fettig
d5e32db954 [CHORE] vault client: add type to attest parameters 2014-10-03 17:17:08 -07:00
Matthew Fettig
bdfa83592b [FEATURE] identity functions 2014-10-03 17:17:08 -07:00
Geert Weening
23e473b688 [FEATURE] make maxLoops in seed.get_key optional
default to 1 or the index of the requested account +1
2014-10-02 17:26:01 -07:00
wltsmrz
0dfd3a0ae0 Merge pull request #178 from ripplerm/develop
configurable maxAttempts
2014-10-01 02:07:04 -07:00
ripplerm
d107092540 configurable maxAttempts 2014-10-01 14:43:44 +08:00
wltsmrz
c2f379d3b3 Merge pull request #176 from shekenahglory/develop
[FIX] change handling of requestLedger options
2014-09-28 00:34:30 -07:00
Matthew Fettig
57b70300f5 [FIX] change handling of requestLedger options
ledger_index and ledger_hash were being set to true
instead of the specified value, and according to API
docs 'closed','validated', and 'current' can be
supplied to the ledger_index field to get the most
recent of the specified type
2014-09-26 21:41:22 -07:00
Geert Weening
eeba86f9c5 [TASK] bump version to 0.8.2 2014-09-25 10:05:57 -07:00
Geert Weening
e0d68e60ec Merge pull request #172 from booxood/modify-docs-guides-md
Update docs/GUIDES.md
2014-09-24 23:44:08 -07:00
Liucw
254248486b Update docs/GUIDES.md 2014-09-25 14:34:29 +08:00
Geert Weening
1b57cc6d35 [TASK] bump verison to 0.8.2-rc2 2014-09-22 23:59:12 -07:00
Geert Weening
77234f256d [DOC] update release notes 2014-09-22 23:58:49 -07:00
Geert Weening
795d31d2db Merge branch 'release' into develop 2014-09-22 23:50:45 -07:00
wltsmrz
f3f10fd9bd Fix requestLedger arguments 2014-09-18 02:03:29 -07:00
wltsmrz
7100b4be8d Emit server with subscription events 2014-09-18 01:41:23 -07:00
wltsmrz
b1a7200d1b Deprecate account_tx map/reduce/filter 2014-09-18 01:28:43 -07:00
Geert Weening
5d8bb541c6 [TASK] bump version to 0.8.2-rc1 2014-09-17 15:02:44 -07:00
Geert Weening
b51c59b23a [TASK] update release notes 2014-09-17 15:02:21 -07:00
wltsmrz
2cd434e861 Fix orderbook reset on reconnect 2014-09-17 13:42:24 -07:00
wltsmrz
1599eb9629 Add potential missing error handlers 2014-09-17 13:40:49 -07:00
wltsmrz
8ef7481858 Allow mixed letters and numbers in currencies 2014-09-17 13:39:49 -07:00
Geert Weening
344d478b3f [TASK] bump version to 0.8.1 2014-09-15 16:52:23 -07:00
Geert Weening
39b7e27aa6 [TASK] bump version to 0.8.1-rc3 2014-09-12 14:26:25 -07:00
Geert Weening
b1876b4f77 [DOC] update release notes 2014-09-12 14:26:02 -07:00
wltsmrz
db3b41d1ba Merge pull request #167 from ximinez/ripd-549
[BUG] Fix Amount.to_human_full()
2014-09-12 12:16:03 -07:00
Edward Hennis
02b5d14d0f [BUG] Fix Amount.to_human_full()
* Amount.is_native is a function, but was referenced as a bool.
* Duplicate to_text_full tests to test to_human_full.
2014-09-12 10:52:46 -04:00
wltsmrz
0120044c96 Fix undefined fee states when connecting to a rippled that is syncing 2014-09-11 23:44:21 -07:00
wltsmrz
ad6304e857 Merge pull request #166 from geertweening/develop
[DOC] update README install instructions
2014-09-10 18:54:45 -07:00
Geert Weening
7cba84b8cf [DOC] update README install instructions 2014-09-10 18:51:59 -07:00
Geert Weening
5a9a4be163 [TASK] bump version to 0.8.1-rc2 2014-09-10 17:54:11 -07:00
Geert Weening
4d1a31d3c9 Revert "[FOLD] Add postinstall step to build the sjcl.js"
This reverts commit 42c853dbf4.
2014-09-10 17:53:29 -07:00
Geert Weening
6e3ceec4e5 [TASK] update publish scripts 2014-09-10 17:33:52 -07:00
Geert Weening
bc7d3c0af8 [TASK] add release candidate publish script 2014-09-10 17:32:03 -07:00
23 changed files with 1240 additions and 283 deletions

View File

@@ -1,3 +1,34 @@
##0.9.0
+ Add routes to the vault client for KYC attestations ([ed2da574](https://github.com/ripple/ripple-lib/commit/ed2da57475acf5e9d2cf3373858f4274832bd83f))
+ Currency: add `show_interest` flag to show or hide interest in `Currency.to_human()` and `Currency.to_json()` [Example use in tests](https://github.com/ripple/ripple-lib/blob/947ec3edc2e7c8f1ef097e496bf552c74366e749/test/currency-test.js#L123)
+ Configurable maxAttempts for transaction submission ([d107092](https://github.com/ripple/ripple-lib/commit/d10709254061e9e4416d2cb78b5cac1ec0d7ffa5))
+ Binformat: added missing TransactionResult options ([6abed8d](https://github.com/ripple/ripple-lib/commit/6abed8dd5311765b2eb70505dadbdf5121439ca8))
+ Fix: Amount.to_human() precision bugs ([4be209e](https://github.com/ripple/ripple-lib/commit/4be209e286b5b209bec7bcd1212098985e15ff2f))
+ Fix: change handling of requestLedger options ([57b7030](https://github.com/ripple/ripple-lib/commit/57b70300f5f0c7534ede118ddbb5d8762668a4f8))
+ **Breaking change:** make maxLoops in seed.get_key optional. [Example use in tests](https://github.com/ripple/ripple-lib/blob/23e473b6886c457781949c825b3ff48b3984e51f/test/seed-test.js) ([23e473b](https://github.com/ripple/ripple-lib/commit/23e473b6886c457781949c825b3ff48b3984e51f))
##0.8.2
+ Currency: Allow mixed letters and numbers in currencies
+ Deprecate account_tx map/reduce/filter
+ Fix: correct requestLedger arguments
+ Fix: missing subscription on error events for some server methods
+ Fix: orderbook reset on reconnect
+ Fix: ripple-lib crashing. Add potential missing error handlers
##0.8.1
+ Wallet: Add Wallet class that generates wallets
@@ -6,6 +37,11 @@
+ Fix several stability issues, see merged PR's for details
+ Fix bug in Amount.to_human_full()
+ Fix undefined fee states when connecting to a rippled that is syncing
##0.8.0
+ Orderbook: Added tracking of offer funds for determining when offers are not funded

View File

@@ -38,7 +38,16 @@ JavaScript client for [rippled](https://github.com/ripple/rippled)
$ npm install ripple-lib
```
**Building ripple-lib for browser use**
**Via bower (for browser use)**
```
$ bower install ripple
```
See the [bower-ripple repo](https://github.com/ripple/bower-ripple) for additional bower instructions
**Building ripple-lib from github**
```
$ git clone https://github.com/ripple/ripple-lib
@@ -46,7 +55,7 @@ JavaScript client for [rippled](https://github.com/ripple/rippled)
$ npm run build
```
Then use the minified `build/ripple-*-min.js` in your webpage
Then use the minified `build/ripple-*-min.js`
##Quickstart

View File

@@ -111,14 +111,14 @@ See the [wiki](https://ripple.com/wiki/JSON_Messages#subscribe) for details on s
//handle ledger
});
remote.on('transaction', function onTransacstion(transaction) {
request.on('transaction', function onTransacstion(transaction) {
//handle transaction
});
remote.request(function(err) {
request.request(function(err) {
if (err) {
} else {
}
} else {
}
});
});
```
@@ -186,14 +186,7 @@ var Amount = require('ripple-lib').Amount;
var MY_ADDRESS = 'rrrMyAddress';
var MY_SECRET = 'secret';
var BUY_AMOUNT = Amount.from_human('100XRP');
var SELL_AMOUNT = Amount.from_human('1USD');
// EXPIRATION must be a Date object, leave undefined to submit offer that won't expire
var now = new Date();
var tomorrow = new Date(now.getTime() + (24 * 60 * 60 * 1000));
var EXPIRATION = tomorrow;
var GATEWAY = 'rrrGateWay';
var remote = new Remote({ /* Remote options */ });
@@ -201,10 +194,9 @@ remote.connect(function() {
remote.setSecret(MY_ADDRESS, MY_SECRET);
var transaction = remote.createTransaction('OfferCreate', {
account: MY_ADDRESS,
buy: BUY_AMOUNT,
sell: SELL_AMOUNT,
expiration: EXPIRATION
account: MY_ADDRESS,
taker_pays: '1',
taker_gets: '1/USD/' + GATEWAY
});
transaction.submit(function(err, res) {

View File

@@ -1,6 +1,6 @@
{
"name": "ripple-lib",
"version": "0.8.1-rc1",
"version": "0.9.0-rc5",
"description": "Ripple JavaScript client library",
"files": [
"src/js/*",
@@ -38,10 +38,9 @@
"yargs": "~1.3.1"
},
"scripts": {
"postinstall": "node_modules/.bin/gulp concat-sjcl",
"build": "node_modules/.bin/gulp",
"pretest": "node_modules/.bin/gulp concat-sjcl",
"test": "./node_modules/.bin/istanbul test -x build/sjcl.js -x src/js/jsbn/* ./node_modules/mocha/bin/mocha -- --reporter spec test/*-test.js",
"test": "./node_modules/.bin/istanbul test -x build/sjcl.js -x src/js/jsbn/* ./node_modules/mocha/bin/_mocha -- --reporter spec test/*-test.js",
"coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls"
},
"repository": {

View File

@@ -1,3 +1,5 @@
echo "PUBLISH"
function exit_on_error {
res=$?
[[ ${res:-99} -eq 0 ]] || exit $res
@@ -5,6 +7,7 @@ function exit_on_error {
rm -rf build
npm install
gulp
npm test
exit_on_error

43
scripts/publish_rc Normal file
View File

@@ -0,0 +1,43 @@
echo "PUBLISH RELEASE CANDIDATE"
function exit_on_error {
res=$?
[[ ${res:-99} -eq 0 ]] || exit $res
}
rm -rf build
npm install
gulp
npm test
exit_on_error
echo ""
echo "publish rc to npm"
npm publish --tag beta
exit_on_error
rm -rf dist
echo ""
echo "publish to bower"
git clone git@github.com:ripple/bower-ripple.git dist
gulp bower
exit_on_error
cd dist
version=$(cat bower.json | grep -Eo '([0-9]\.?)+(-rc[0-9])?')
echo "version: $version"
git add ripple.js ripple-debug.js ripple-min.js bower.json
exit_on_error
git commit -m "[TASK] add v$version"
exit_on_error
git tag "v$version"
exit_on_error
git push origin master
git push --tags origin master
cd ..

View File

@@ -1109,12 +1109,25 @@ Amount.prototype.to_human = function(opts) {
fraction_part = fraction_part.replace(/0*$/, '');
if (fraction_part.length || !opts.skip_empty_fraction) {
// Enforce the maximum number of decimal digits (precision)
if (typeof opts.precision === 'number') {
if (opts.precision === 0 && fraction_part.charCodeAt(0) >= 53) {
int_part = (Number(int_part) + 1).toString();
if (opts.precision <= 0) {
// increment the int_part if the first decimal is 5 or higher
if (fraction_part.charCodeAt(0) >= 53) {
int_part = (Number(int_part) + 1).toString();
}
fraction_part = '';
} else {
fraction_part = Math.round(fraction_part / Math.pow(10, fraction_part.length - opts.precision)).toString();
// because the division above will cut off the leading 0's we have to add them back again
// XXX look for a more elegant alternative
while (fraction_part.length < opts.precision) {
fraction_part = '0' + fraction_part;
}
}
fraction_part = fraction_part.slice(0, opts.precision);
}
// Limit the number of significant digits (max_sig_digits)
@@ -1179,7 +1192,7 @@ Amount.prototype.to_human_full = function(opts) {
var a = this.to_human(opts);
var c = this._currency.to_human();
var i = this._issuer.to_json(opts);
var o = this.is_native ? (o = a + '/' + c) : (o = a + '/' + c + '/' + i);
var o = this.is_native() ? (o = a + '/' + c) : (o = a + '/' + c + '/' + i);
return o;
};

View File

@@ -382,23 +382,32 @@ exports.metadata = [
];
exports.ter = {
tesSUCCESS: 0,
tecCLAIM: 100,
tecPATH_PARTIAL: 101,
tecUNFUNDED_ADD: 102,
tecUNFUNDED_OFFER: 103,
tecUNFUNDED_PAYMENT: 104,
tecFAILED_PROCESSING: 105,
tecDIR_FULL: 121,
tecINSUF_RESERVE_LINE: 122,
tecINSUF_RESERVE_OFFER: 123,
tecNO_DST: 124,
tecNO_DST_INSUF_XRP: 125,
tecNO_LINE_INSUF_RESERVE: 126,
tecNO_LINE_REDUNDANT: 127,
tecPATH_DRY: 128,
tecUNFUNDED: 129,
tecMASTER_DISABLED: 130,
tecNO_REGULAR_KEY: 131,
tecOWNERS: 132
tesSUCCESS : 0,
tecCLAIM : 100,
tecPATH_PARTIAL : 101,
tecUNFUNDED_ADD : 102,
tecUNFUNDED_OFFER : 103,
tecUNFUNDED_PAYMENT : 104,
tecFAILED_PROCESSING : 105,
tecDIR_FULL : 121,
tecINSUF_RESERVE_LINE : 122,
tecINSUF_RESERVE_OFFER : 123,
tecNO_DST : 124,
tecNO_DST_INSUF_XRP : 125,
tecNO_LINE_INSUF_RESERVE : 126,
tecNO_LINE_REDUNDANT : 127,
tecPATH_DRY : 128,
tecUNFUNDED : 129, // Deprecated, old ambiguous unfunded.
tecMASTER_DISABLED : 130,
tecNO_REGULAR_KEY : 131,
tecOWNERS : 132,
tecNO_ISSUER : 133,
tecNO_AUTH : 134,
tecNO_LINE : 135,
tecINSUFF_FEE : 136,
tecFROZEN : 137,
tecNO_TARGET : 138,
tecNO_PERMISSION : 139,
tecNO_ENTRY : 140,
tecINSUFFICIENT_RESERVE : 141
};

View File

@@ -119,7 +119,9 @@ BlobObj.prototype.init = function(fn) {
self.revision = resp.body.revision;
self.encrypted_secret = resp.body.encrypted_secret;
self.identity_id = resp.body.identity_id;
self.missing_fields = resp.body.missing_fields;
//self.attestations = resp.body.attestation_summary;
if (!self.decrypt(resp.body.blob)) {
return fn(new Error('Error while decrypting blob'));
@@ -561,7 +563,6 @@ BlobObj.prototype.get2FA = function (fn) {
* @params {boolean} options.enabled
* @params {string} options.phone
* @params {string} options.country_code
* @params {string} options.via //sms, etc
*/
BlobObj.prototype.set2FA = function(options, fn) {
@@ -572,8 +573,7 @@ BlobObj.prototype.set2FA = function(options, fn) {
data : {
enabled : options.enabled,
phone : options.phone,
country_code : options.country_code,
via : options.via
country_code : options.country_code
}
};
@@ -1115,48 +1115,6 @@ BlobClient.recoverBlob = function (opts, fn) {
};
};
/**
* updateProfile
* update information stored outside the blob - HMAC signed
* @param {object}
* @param {string} opts.url
* @param {string} opts.username
* @param {string} opts.auth_secret
* @param {srring} opts.blob_id
* @param {object} opts.profile
* @param {string} opts.profile.phone - optional
* @param {string} opts.profile.country - optional
* @param {string} opts.profile.region - optional
* @param {string} opts.profile.city - optional
*/
BlobClient.updateProfile = function (opts, fn) {
var config = {
method: 'POST',
url: opts.url + '/v1/user/' + opts.username + '/profile',
dataType: 'json',
data: opts.profile
};
var signedRequest = new SignedRequest(config);
var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);
request.post(signed.url)
.send(signed.data)
.end(function(err, resp) {
if (err) {
log.error('updateProfile:', err);
fn(new Error('Failed to update profile - XHR error'));
} else if (resp.body && resp.body.result === 'success') {
fn(null, resp.body);
} else if (resp.body) {
log.error('updateProfile:', resp.body);
} else {
fn(new Error('Failed to update profile'));
}
});
};
/**
* updateKeys
@@ -1320,6 +1278,7 @@ BlobClient.create = function(options, fn) {
if (err) {
fn(err);
} else if (resp.body && resp.body.result === 'success') {
blob.identity_id = resp.body.identity_id;
fn(null, blob, resp.body);
} else if (resp.body && resp.body.result === 'error') {
fn(new Error(resp.body.message));
@@ -1363,4 +1322,263 @@ BlobClient.deleteBlob = function(options, fn) {
});
};
/*** identity related functions ***/
/**
* updateProfile
* update information stored outside the blob - HMAC signed
* @param {object}
* @param {string} opts.url
* @param {string} opts.auth_secret
* @param {srring} opts.blob_id
* @param {object} opts.profile
* @param {array} opts.profile.attributes (optional, array of attribute objects)
* @param {array} opts.profile.addresses (optional, array of address objects)
*
* @param {string} attribute.id ... id of existing attribute
* @param {string} attribute.name ... attribute name i.e. ripple_address
* @param {string} attribute.type ... optional, sub-type of attribute
* @param {string} attribute.value ... value of attribute
* @param {string} attribute.domain ... corresponding domain
* @param {string} attribute.status ... “current”, “removed”, etc.
* @param {string} attribute.visibitlity ... “public”, ”private”
*/
BlobClient.updateProfile = function (opts, fn) {
var config = {
method: 'POST',
url: opts.url + '/v1/profile/',
dataType: 'json',
data: opts.profile
};
var signedRequest = new SignedRequest(config);
var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);
request.post(signed.url)
.send(signed.data)
.end(function(err, resp) {
if (err) {
log.error('updateProfile:', err);
fn(new Error('Failed to update profile - XHR error'));
} else if (resp.body && resp.body.result === 'success') {
fn(null, resp.body);
} else if (resp.body) {
log.error('updateProfile:', resp.body);
fn(new Error('Failed to update profile'));
} else {
fn(new Error('Failed to update profile'));
}
});
};
/**
* getProfile
* @param {Object} opts
* @param {string} opts.url
* @param {string} opts.auth_secret
* @param {srring} opts.blob_id
*/
BlobClient.getProfile = function (opts, fn) {
var config = {
method: 'GET',
url: opts.url + '/v1/profile/'
};
var signedRequest = new SignedRequest(config);
var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);
request.get(signed.url)
.send(signed.data)
.end(function(err, resp) {
if (err) {
log.error('getProfile:', err);
fn(new Error('Failed to get profile - XHR error'));
} else if (resp.body && resp.body.result === 'success') {
fn(null, resp.body);
} else if (resp.body) {
log.error('getProfile:', resp.body);
fn(new Error('Failed to get profile'));
} else {
fn(new Error('Failed to get profile'));
}
});
};
/**
* getAttestation
* @param {Object} opts
* @param {string} opts.url
* @param {string} opts.auth_secret
* @param {string} opts.blob_id
* @param {string} opts.type (email,phone,basic_identity)
* @param {object} opts.phone (required for type 'phone')
* @param {string} opts.email (required for type 'email')
*/
BlobClient.getAttestation = function (opts, fn) {
var params = { };
if (opts.phone) params.phone = opts.phone;
if (opts.email) params.email = opts.email;
var config = {
method: 'POST',
url: opts.url + '/v1/attestation/' + opts.type,
dataType: 'json',
data: params
};
var signedRequest = new SignedRequest(config);
var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);
request.post(signed.url)
.send(signed.data)
.end(function(err, resp) {
if (err) {
log.error('attest:', err);
fn(new Error('attestation error - XHR error'));
} else if (resp.body && resp.body.result === 'success') {
if (resp.body.attestation) {
resp.body.decoded = BlobClient.parseAttestation(resp.body.attestation);
}
fn(null, resp.body);
} else if (resp.body) {
log.error('attestation:', resp.body);
fn(new Error('attestation error: ' + resp.body.message || ""));
} else {
fn(new Error('attestation error'));
}
});
};
/**
* getAttestationSummary
* @param {Object} opts
* @param {string} opts.url
* @param {string} opts.auth_secret
* @param {string} opts.blob_id
*/
BlobClient.getAttestationSummary = function (opts, fn) {
var config = {
method: 'GET',
url: opts.url + '/v1/attestation/summary',
dataType: 'json'
};
if (opts.full) config.url += '?full=true';
var signedRequest = new SignedRequest(config);
var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);
request.get(signed.url)
.send(signed.data)
.end(function(err, resp) {
if (err) {
log.error('attest:', err);
fn(new Error('attestation error - XHR error'));
} else if (resp.body && resp.body.result === 'success') {
if (resp.body.attestation) {
resp.body.decoded = BlobClient.parseAttestation(resp.body.attestation);
}
fn(null, resp.body);
} else if (resp.body) {
log.error('attestation:', resp.body);
fn(new Error('attestation error: ' + resp.body.message || ""));
} else {
fn(new Error('attestation error'));
}
});
};
/**
* updateAttestation
* @param {Object} opts
* @param {string} opts.url
* @param {string} opts.auth_secret
* @param {string} opts.blob_id
* @param {string} opts.type (email,phone,profile,identity)
* @param {object} opts.phone (required for type 'phone')
* @param {object} opts.profile (required for type 'profile')
* @param {string} opts.email (required for type 'email')
* @param {string} opts.answers (required for type 'identity')
* @param {string} opts.token (required for completing email or phone attestations)
*/
BlobClient.updateAttestation = function (opts, fn) {
var params = { };
if (opts.phone) params.phone = opts.phone;
if (opts.profile) params.profile = opts.profile;
if (opts.email) params.email = opts.email;
if (opts.token) params.token = opts.token;
if (opts.answers) params.answers = opts.answers;
var config = {
method: 'POST',
url: opts.url + '/v1/attestation/' + opts.type + '/update',
dataType: 'json',
data: params
};
var signedRequest = new SignedRequest(config);
var signed = signedRequest.signHmac(opts.auth_secret, opts.blob_id);
request.post(signed.url)
.send(signed.data)
.end(function(err, resp) {
if (err) {
log.error('attest:', err);
fn(new Error('attestation error - XHR error'));
} else if (resp.body && resp.body.result === 'success') {
if (resp.body.attestation) {
resp.body.decoded = BlobClient.parseAttestation(resp.body.attestation);
}
fn(null, resp.body);
} else if (resp.body) {
log.error('attestation:', resp.body);
fn(new Error('attestation error: ' + resp.body.message || ""));
} else {
fn(new Error('attestation error'));
}
});
};
/**
* parseAttestation
* @param {Object} attestation
*/
BlobClient.parseAttestation = function (attestation) {
var segments = decodeURIComponent(attestation).split('.');
var decoded;
// base64 decode and parse JSON
try {
decoded = {
header : JSON.parse(crypt.decodeBase64(segments[0])),
payload : JSON.parse(crypt.decodeBase64(segments[1])),
signature : segments[2]
};
} catch (e) {
console.log("invalid attestation:", e);
}
return decoded;
};
exports.BlobClient = BlobClient;

View File

@@ -322,4 +322,12 @@ Crypt.base64UrlToBase64 = function(encodedData) {
return encodedData;
};
/**
* base64 to UTF8
*/
Crypt.decodeBase64 = function (data) {
return sjcl.codec.utf8String.fromBits(sjcl.codec.base64.toBits(data));
}
exports.Crypt = Crypt;

View File

@@ -50,7 +50,7 @@ Currency.HEX_CURRENCY_BAD = '0000000000000000000000005852500000000000';
* \s*$ // end with any amount of whitespace
*
*/
Currency.prototype.human_RE = /^\s*([a-zA-Z]{3}|[0-9]{3})(\s*-\s*[- \w]+)?(\s*\(-?\d+\.?\d*%pa\))?\s*$/;
Currency.prototype.human_RE = /^\s*([a-zA-Z0-9]{3})(\s*-\s*[- \w]+)?(\s*\(-?\d+\.?\d*%pa\))?\s*$/;
Currency.from_json = function(j, shouldInterpretXrpAsIou) {
if (j instanceof this) {
@@ -316,17 +316,17 @@ Currency.prototype.to_json = function(opts) {
var opts = opts || {};
var currency;
var fullName = opts && opts.full_name ? " - " + opts.full_name : "";
var fullName = opts && opts.full_name ? ' - ' + opts.full_name : '';
opts.show_interest = opts.show_interest !== void(0) ? opts.show_interest : this.has_interest();
// Any currency with standard properties and a valid code can be abbreviated
// in the JSON wire format as the three character code.
if (!opts.force_hex && /^[A-Z0-9]{3}$/.test(this._iso_code) && !this.has_interest()) {
if (!opts.force_hex && /^[A-Z0-9]{3}$/.test(this._iso_code)) {
currency = this._iso_code + fullName;
if (opts.show_interest) {
var decimals = !isNaN(opts.decimals) ? opts.decimals : void(0);
var interestPercentage = this.has_interest() ? this.get_interest_percentage_at(this._interest_start + 3600 * 24 * 365, decimals) : 0;
currency += ' (' + interestPercentage + '%pa)';
}
// If there is interest, append the annual interest to the full currency name
} else if (!opts.force_hex && this.has_interest()) {
var decimals = opts ? opts.decimals : undefined;
currency = this._iso_code + fullName + " (" + this.get_interest_percentage_at(this._interest_start + 3600 * 24 * 365, decimals) + "%pa)";
} else {
// Fallback to returning the raw currency hex

View File

@@ -78,19 +78,20 @@ function OrderBook(remote, getsC, getsI, paysC, paysI, key) {
});
this.on('unsubscribe', function() {
self._ownerFunds = { };
self.resetCache();
self._remote.removeListener('transaction', updateFundedAmounts);
self._remote.removeListener('transaction', updateTransferRate);
});
this._remote.on('prepare_subscribe', function() {
this._remote.once('prepare_subscribe', function() {
self.subscribe();
});
this._remote.on('disconnect', function() {
self._ownerFunds = { };
self._offerCounts = { };
self._synchronized = false;
self.resetCache();
self._remote.once('prepare_subscribe', function() {
self.subscribe();
});
});
function updateFundedAmounts(message) {
@@ -195,6 +196,16 @@ OrderBook.prototype.unsubscribe = function() {
this.emit('unsubscribe');
};
/**
* Reset cached owner funds, offer counts
*/
OrderBook.prototype.resetCache = function() {
this._ownerFunds = { };
this._offerCounts = { };
this._synchronized = false;
};
/**
* Check that the funds for offer owner have been cached
*
@@ -695,6 +706,9 @@ OrderBook.prototype.requestOffers = function(callback) {
log.info('requested offers', self._key, 'offers: ' + res.offers.length);
}
// Reset offers
self._offers = [ ];
for (var i=0, l=res.offers.length; i<l; i++) {
var offer = res.offers[i];
var fundedAmount;

View File

@@ -94,6 +94,8 @@ function Remote(opts, trace) {
this.fee_cushion = (typeof opts.fee_cushion === 'number') ? opts.fee_cushion : 1.2;
this.max_fee = (typeof opts.max_fee === 'number') ? opts.max_fee : Infinity;
this.max_attempts = (typeof opts.max_attempts === 'number') ? opts.max_attempts : 10;
this._ledger_current_index = void(0);
this._ledger_hash = void(0);
this._ledger_time = void(0);
@@ -615,16 +617,16 @@ Remote.prototype._handleMessage = function(message, server) {
switch (message.type) {
case 'ledgerClosed':
this._handleLedgerClosed(message);
this._handleLedgerClosed(message, server);
break;
case 'serverStatus':
this._handleServerStatus(message);
this._handleServerStatus(message, server);
break;
case 'transaction':
this._handleTransaction(message);
this._handleTransaction(message, server);
break;
case 'path_find':
this._handlePathFind(message);
this._handlePathFind(message, server);
break;
default:
if (this.trace) {
@@ -640,7 +642,7 @@ Remote.prototype._handleMessage = function(message, server) {
* @param {Object} message
*/
Remote.prototype._handleLedgerClosed = function(message) {
Remote.prototype._handleLedgerClosed = function(message, server) {
var self = this;
// XXX If not trusted, need to verify we consider ledger closed.
@@ -659,11 +661,11 @@ Remote.prototype._handleLedgerClosed = function(message) {
this._ledger_current_index = message.ledger_index + 1;
if (this.isConnected()) {
this.emit('ledger_closed', message);
this.emit('ledger_closed', message, server);
} else {
this.once('connect', function() {
// Delay until server is 'online'
self.emit('ledger_closed', message);
self.emit('ledger_closed', message, server);
});
}
}
@@ -675,8 +677,8 @@ Remote.prototype._handleLedgerClosed = function(message) {
* @param {Object} message
*/
Remote.prototype._handleServerStatus = function(message) {
this.emit('server_status', message);
Remote.prototype._handleServerStatus = function(message, server) {
this.emit('server_status', message, server);
};
/**
@@ -685,7 +687,7 @@ Remote.prototype._handleServerStatus = function(message) {
* @param {Object} message
*/
Remote.prototype._handleTransaction = function(message) {
Remote.prototype._handleTransaction = function(message, server) {
var self = this;
// XXX If not trusted, need proof.
@@ -732,8 +734,8 @@ Remote.prototype._handleTransaction = function(message) {
});
}
this.emit('transaction', message);
this.emit('transaction_all', message);
this.emit('transaction', message, server);
this.emit('transaction_all', message, server);
};
/**
@@ -742,7 +744,7 @@ Remote.prototype._handleTransaction = function(message) {
* @param {Object} message
*/
Remote.prototype._handlePathFind = function(message) {
Remote.prototype._handlePathFind = function(message, server) {
var self = this;
// Pass the event to the currently open PathFind object
@@ -750,7 +752,7 @@ Remote.prototype._handlePathFind = function(message) {
this._cur_path_find.notify_update(message);
}
this.emit('path_find_all', message);
this.emit('path_find_all', message, server);
};
/**
@@ -929,20 +931,19 @@ Remote.prototype.requestServerInfo = function(callback) {
* @return {Request} request
*/
Remote.prototype.requestLedger = function(ledger, options, callback) {
Remote.prototype.requestLedger = function(options, callback) {
// XXX This is a bad command. Some variants don't scale.
// XXX Require the server to be trusted.
//utils.assert(this.trusted);
var request = new Request(this, 'ledger');
if (ledger) {
// DEPRECATED: use .ledger_hash() or .ledger_index()
//console.log('request_ledger: ledger parameter is deprecated');
request.message.ledger = ledger;
}
switch (typeof options) {
case 'undefined': break;
case 'function':
callback = options;
break;
case 'object':
Object.keys(options).forEach(function(o) {
switch (o) {
@@ -952,21 +953,23 @@ Remote.prototype.requestLedger = function(ledger, options, callback) {
case 'accounts':
request.message[o] = true;
break;
case 'ledger_index':
case 'ledger_hash':
request.message[o] = options[o];
break;
case 'closed' :
case 'current' :
case 'validated' :
request.message.ledger_index = o;
break;
}
}, options);
break;
case 'function':
callback = options;
options = void(0);
break;
default:
//DEPRECATED
if (this.trace) {
log.info('request_ledger: full parameter is deprecated');
}
request.message.full = true;
request.ledgerSelect(options);
break;
}
@@ -1337,6 +1340,10 @@ Remote.prototype.requestAccountTx = function(options, callback) {
options.ledger_index_max = options.max_ledger;
}
if (options.binary && options.parseBinary === void(0)) {
options.parseBinary = true;
}
Object.keys(options).forEach(function(o) {
switch (o) {
case 'account':
@@ -1356,101 +1363,32 @@ Remote.prototype.requestAccountTx = function(options, callback) {
}
}, options);
function propertiesFilter(obj, transaction) {
var properties = Object.keys(obj);
return function(transaction) {
var result = properties.every(function(property) {
return transaction.tx[property] === obj[property];
});
return result;
};
};
function parseBinaryTransaction(transaction) {
var tx = { validated: transaction.validated };
tx.meta = new SerializedObject(transaction.meta).to_json();
tx.tx = new SerializedObject(transaction.tx_blob).to_json();
tx.tx.ledger_index = transaction.ledger_index;
tx.tx.hash = Transaction.from_json(tx.tx).hash();
return tx;
};
function accountTxFilter(fn) {
if (typeof fn !== 'function') {
throw new Error('Missing filter function');
request.once('success', function(res) {
if (options.parseBinary) {
res.transactions = res.transactions.map(Remote.parseBinaryTransaction);
}
request.emit('transactions', res);
});
var self = this;
function filterHandler() {
var listeners = self.listeners('success');
self.removeAllListeners('success');
self.once('success', function(res) {
if (options.parseBinary) {
res.transactions = res.transactions.map(parseBinaryTransaction);
}
if (fn !== Boolean) {
res.transactions = res.transactions.filter(fn);
}
if (typeof options.map === 'function') {
res.transactions = res.transactions.map(options.map);
}
if (typeof options.reduce === 'function') {
res.transactions = res.transactions.reduce(options.reduce);
}
if (typeof options.pluck === 'string') {
res = res[options.pluck];
}
listeners.forEach(function(listener) {
listener.call(self, res);
});
});
};
this.once('request', filterHandler);
return this;
};
request.filter = accountTxFilter;
if (typeof options.parseBinary !== 'boolean') {
options.parseBinary = true;
}
if (options.binary || (options.map || options.reduce)) {
options.filter = options.filter || Boolean;
}
if (options.filter) {
switch (options.filter) {
case 'inbound':
request.filter(propertiesFilter({ Destination: options.account }));
break;
case 'outbound':
request.filter(propertiesFilter({ Account: options.account }));
break;
default:
if (typeof options.filter === 'object') {
options.filter = propertiesFilter(options.filter);
}
request.filter(options.filter);
}
}
request.callback(callback);
request.callback(callback, 'transactions');
return request;
};
/**
* @param {Object} transaction
* @return {Transaction}
*/
Remote.parseBinaryTransaction = function(transaction) {
var tx = { validated: transaction.validated };
tx.meta = new SerializedObject(transaction.meta).to_json();
tx.tx = new SerializedObject(transaction.tx_blob).to_json();
tx.tx.ledger_index = transaction.ledger_index;
tx.tx.hash = Transaction.from_json(tx.tx).hash();
return tx;
};
/**
* Request the overall transaction history.
*
@@ -1589,10 +1527,14 @@ Remote.prototype.requestSubmit = function(callback) {
* @api private
*/
Remote.prototype._serverPrepareSubscribe = function(callback) {
Remote.prototype._serverPrepareSubscribe = function(server, callback) {
var self = this;
var feeds = [ 'ledger', 'server' ];
if (typeof server === 'function') {
callback = server;
}
if (this._transaction_subs) {
feeds.push('transactions');
}
@@ -1613,11 +1555,17 @@ Remote.prototype._serverPrepareSubscribe = function(callback) {
self.emit('random', utils.hexToArray(message.random));
}
self._handleLedgerClosed(message);
self._handleLedgerClosed(message, server);
self.emit('subscribed');
};
request.on('error', function(err) {
if (self.trace) {
log.info('Initial server subscribe failed', err);
}
});
request.once('success', serverSubscribed);
self.emit('prepare_subscribe', request);
@@ -2261,7 +2209,7 @@ Remote.prototype.createTransaction = function(type, options) {
*/
Remote.prototype.feeTx = function(units) {
var server = this._getServer();
var server = this.getServer();
if (!server) {
throw new Error('No connected servers');
@@ -2280,7 +2228,7 @@ Remote.prototype.feeTx = function(units) {
*/
Remote.prototype.feeTxUnit = function() {
var server = this._getServer();
var server = this.getServer();
if (!server) {
throw new Error('No connected servers');
@@ -2299,7 +2247,7 @@ Remote.prototype.feeTxUnit = function() {
*/
Remote.prototype.reserve = function(owner_count) {
var server = this._getServer();
var server = this.getServer();
if (!server) {
throw new Error('No connected servers');

View File

@@ -93,9 +93,14 @@ function SHA256_RIPEMD160(bits) {
*
* {Uint160} (from_json able), specifies the address matching the KeyPair
* that is desired.
*
* @param maxLoops (optional)
* {Number} specifies the amount of attempts taken to generate
* a matching KeyPair
*/
Seed.prototype.get_key = function (account) {
Seed.prototype.get_key = function (account, maxLoops) {
var account_number = 0, address;
var max_loops = maxLoops || 1;
if (!this.is_valid()) {
throw new Error('Cannot generate keys from invalid seed!');
@@ -103,6 +108,7 @@ Seed.prototype.get_key = function (account) {
if (account) {
if (typeof account === 'number') {
account_number = account;
max_loops = account_number+1;
} else {
address = UInt160.from_json(account);
}
@@ -121,9 +127,9 @@ Seed.prototype.get_key = function (account) {
var sec;
var key_pair;
var max_loops = 1000; // TODO
do {
i = 0;
do {
@@ -135,15 +141,15 @@ Seed.prototype.get_key = function (account) {
sec = sec.add(private_gen).mod(curve.r);
key_pair = KeyPair.from_bn_secret(sec);
if (--max_loops <= 0) {
if (max_loops-- <= 0) {
// We are almost certainly looking for an account that would take same
// value of $too_long {forever, ...}
throw new Error('Too many loops looking for KeyPair yielding '+
address.to_json() +' from ' + this.to_json());
};
} while (address && !key_pair.get_address().equals(address));
}
return key_pair;
} while (address && !key_pair.get_address().equals(address));
return key_pair;
};
exports.Seed = Seed;

View File

@@ -134,7 +134,9 @@ function Server(remote, opts) {
}
});
self._request(self._remote.requestServerInfo());
var serverInfoRequest = self._remote.requestServerInfo();
serverInfoRequest.on('error', function() { });
self._request(serverInfoRequest);
});
};
@@ -184,7 +186,7 @@ Server.websocketConstructor = function() {
Server.prototype._setState = function(state) {
if (state !== this._state) {
if (this._remote.trace) {
log.info(this.getHostID(), 'set_state:', state);
log.info(this.getServerID(), 'set_state:', state);
}
this._state = state;
@@ -228,7 +230,7 @@ Server.prototype._checkActivity = function() {
if (delta > (1000 * 25)) {
if (this._remote.trace) {
log.info(this.getHostID(), 'reconnect: activity delta:', delta);
log.info(this.getServerID(), 'reconnect: activity delta:', delta);
}
this.reconnect();
}
@@ -274,7 +276,7 @@ Server.prototype._updateScore = function(type, data) {
if (this._score > 1e3) {
if (this._remote.trace) {
log.info(this.getHostID(), 'reconnect: score:', this._score);
log.info(this.getServerID(), 'reconnect: score:', this._score);
}
this.reconnect();
}
@@ -407,7 +409,7 @@ Server.prototype.connect = function() {
if (ws === self._ws) {
self.emit('socket_open');
// Subscribe to events
self._request(self._remote._serverPrepareSubscribe());
self._request(self._remote._serverPrepareSubscribe(self));
}
};
@@ -622,6 +624,7 @@ Server.prototype._handlePathFind = function(message) {
* Handle subscription response messages. Subscription response
* messages indicate that a connection to the server is ready
*
* @param {Object} message
* @api private
*/
@@ -632,18 +635,19 @@ Server.prototype._handleResponseSubscribe = function(message) {
// servers with incomplete history
return this.reconnect();
}
if (Server.isLoadStatus(message)) {
this._load_base = message.load_base || 256;
this._load_factor = message.load_factor || 256;
this._fee_ref = message.fee_ref;
this._fee_base = message.fee_base;
this._reserve_base = message.reserve_base;
this._reserve_inc = message.reserve_inc;
}
if (message.pubkey_node) {
// pubkey_node is used to identify the server
this._pubkey_node = message.pubkey_node;
}
if (~(Server.onlineStates.indexOf(message.server_status))) {
if (Server.isLoadStatus(message)) {
this._load_base = message.load_base || 256;
this._load_factor = message.load_factor || 256;
this._fee_ref = message.fee_ref || 10;
this._fee_base = message.fee_base || 10;
this._reserve_base = message.reserve_base;
this._reserve_inc = message.reserve_inc;
}
if (~Server.onlineStates.indexOf(message.server_status)) {
this._setState('online');
}
};

View File

@@ -20,6 +20,7 @@ function TransactionManager(account) {
this._remote = account._remote;
this._nextSequence = void(0);
this._maxFee = this._remote.max_fee;
this._maxAttempts = this._remote.max_attempts;
this._submissionTimeout = this._remote._submission_timeout;
this._pending = new PendingQueue();
@@ -344,7 +345,7 @@ TransactionManager.prototype._request = function(tx) {
var self = this;
var remote = this._remote;
if (tx.attempts > 10) {
if (tx.attempts > this._maxAttempts) {
return tx.emit('error', new RippleError('tejAttemptsExceeded'));
}

View File

@@ -575,8 +575,6 @@ VaultClient.prototype.generateDeviceID = function () {
VaultClient.prototype.resendEmail = blobClient.resendEmail;
VaultClient.prototype.updateProfile = blobClient.updateProfile;
VaultClient.prototype.recoverBlob = blobClient.recoverBlob;
VaultClient.prototype.deleteBlob = blobClient.deleteBlob;
@@ -585,5 +583,11 @@ VaultClient.prototype.requestToken = blobClient.requestToken;
VaultClient.prototype.verifyToken = blobClient.verifyToken;
VaultClient.prototype.getAttestation = blobClient.getAttestation;
VaultClient.prototype.updateAttestation = blobClient.updateAttestation;
VaultClient.prototype.getAttestationSummary = blobClient.getAttestationSummary;
//export by name
exports.VaultClient = VaultClient;

View File

@@ -16,83 +16,220 @@ describe('Amount', function() {
assert(Amount.from_json('1').is_positive());
});
});
describe('Positives', function() {
it('Number 1', function() {
assert(Amount.from_json('1').is_positive());
});
});
// also tested extensively in other cases
describe('to_human', function() {
it('12345.6789 XAU', function() {
assert.strictEqual(Amount.from_human("12345.6789 XAU").to_human(), '12,345.6789');
});
it('12345.678901234 XAU', function() {
assert.strictEqual(Amount.from_human("12345.678901234 XAU").to_human(), '12,345.678901234');
});
it('to human, precision -1, should be ignored, precision needs to be >= 0', function() {
assert.strictEqual(Amount.from_human("12345.678901234 XAU").to_human({precision:-1}), '12,346');
});
it('to human, precision 0', function() {
assert.strictEqual(Amount.from_human("12345.678901234 XAU").to_human({precision:0}), '12,346');
});
it('to human, precision 1', function() {
assert.strictEqual(Amount.from_human("12345.678901234 XAU").to_human({precision:1}), '12,345.7');
});
it('to human, precision 2', function() {
assert.strictEqual(Amount.from_human("12345.678901234 XAU").to_human({precision:2}), '12,345.68');
});
it('to human, precision 3', function() {
assert.strictEqual(Amount.from_human("12345.678901234 XAU").to_human({precision:3}), '12,345.679');
});
it('to human, precision 4', function() {
assert.strictEqual(Amount.from_human("12345.678901234 XAU").to_human({precision:4}), '12,345.6789');
});
it('to human, precision 5', function() {
assert.strictEqual(Amount.from_human("12345.678901234 XAU").to_human({precision:5}), '12,345.67890');
});
it('to human, precision -1, should be ignored, precision needs to be >= 0', function() {
assert.strictEqual(Amount.from_human("0.00012345 XAU").to_human({precision:-1}), '0');
});
it('to human, precision 0', function() {
assert.strictEqual(Amount.from_human("0.00012345 XAU").to_human({precision:0}), '0');
});
it('to human, precision 1', function() {
assert.strictEqual(Amount.from_human("0.00012345 XAU").to_human({precision:1}), '0.0');
});
it('to human, precision 2', function() {
assert.strictEqual(Amount.from_human("0.00012345 XAU").to_human({precision:2}), '0.00');
});
it('to human, precision 5', function() {
assert.strictEqual(Amount.from_human("0.00012345 XAU").to_human({precision:5}), '0.00012');
});
it('to human, precision 6', function() {
assert.strictEqual(Amount.from_human("0.00012345 XAU").to_human({precision:6}), '0.000123');
});
it('to human, precision 16', function() {
assert.strictEqual(Amount.from_human("0.00012345 XAU").to_human({precision:16}), '0.0001234500000000');
});
it('to human, precision 0, first decimal 4', function() {
assert.strictEqual(Amount.from_human("0.4 XAU").to_human({precision:0}), '0');
});
it('to human, precision 0, first decimal 5', function() {
assert.strictEqual(Amount.from_human("0.5 XAU").to_human({precision:0}), '1');
});
it('to human, precision 0, first decimal 8', function() {
assert.strictEqual(Amount.from_human("0.8 XAU").to_human({precision:0}), '1');
});
});
describe('from_human', function() {
it('1 XRP', function() {
assert.strictEqual(Amount.from_human("1 XRP").to_text_full(), '1/XRP');
});
it('1 XRP human', function() {
assert.strictEqual(Amount.from_human("1 XRP").to_human_full(), '1/XRP');
});
it('0.1 XRP', function() {
assert.strictEqual(Amount.from_human("0.1 XRP").to_text_full(), '0.1/XRP');
});
it('0.1 XRP human', function() {
assert.strictEqual(Amount.from_human("0.1 XRP").to_human_full(), '0.1/XRP');
});
it('0.1 USD', function() {
assert.strictEqual(Amount.from_human("0.1 USD").to_text_full(), '0.1/USD/NaN');
});
it('0.1 USD human', function() {
assert.strictEqual(Amount.from_human("0.1 USD").to_human_full(), '0.1/USD/NaN');
});
it('10000 USD', function() {
assert.strictEqual(Amount.from_human("10000 USD").to_text_full(), '10000/USD/NaN');
});
it('10000 USD human', function() {
assert.strictEqual(Amount.from_human("10000 USD").to_human_full(), '10,000/USD/NaN');
});
it('USD 10000', function() {
assert.strictEqual(Amount.from_human("USD 10000").to_text_full(), '10000/USD/NaN');
});
it('USD 10000 human', function() {
assert.strictEqual(Amount.from_human("USD 10000").to_human_full(), '10,000/USD/NaN');
});
it('12345.6789 XAU', function() {
assert.strictEqual(Amount.from_human("12345.6789 XAU").to_text_full(), '12345.6789/XAU/NaN');
});
it('12345.6789 XAU human', function() {
assert.strictEqual(Amount.from_human("12345.6789 XAU").to_human_full(), '12,345.6789/XAU/NaN');
});
it('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000', function() {
assert.strictEqual(Amount.from_human("12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000").to_text_full(), '12345.6789/XAU (-0.5%pa)/NaN');
});
it('12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000 human', function() {
assert.strictEqual(Amount.from_human("12345.6789 015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human_full(), '12,345.6789/XAU (-0.5%pa)/NaN');
});
it('12345.6789 0000000000000000000000005553440000000000', function() {
assert.strictEqual(Amount.from_human("12345.6789 0000000000000000000000005553440000000000").to_text_full(), '12345.6789/USD/NaN');
});
it('12345.6789 0000000000000000000000005553440000000000 human', function() {
assert.strictEqual(Amount.from_human("12345.6789 0000000000000000000000005553440000000000").to_human_full(), '12,345.6789/USD/NaN');
});
it('10 0000000000000000000000005553440000000000', function() {
assert.strictEqual(Amount.from_human("10 0000000000000000000000005553440000000000").to_text_full(), '10/USD/NaN');
});
it('10 0000000000000000000000005553440000000000 human', function() {
assert.strictEqual(Amount.from_human("10 0000000000000000000000005553440000000000").to_human_full(), '10/USD/NaN');
});
it('100 0000000000000000000000005553440000000000', function() {
assert.strictEqual(Amount.from_human("100 0000000000000000000000005553440000000000").to_text_full(), '100/USD/NaN');
});
it('100 0000000000000000000000005553440000000000 human', function() {
assert.strictEqual(Amount.from_human("100 0000000000000000000000005553440000000000").to_human_full(), '100/USD/NaN');
});
it('1000 0000000000000000000000005553440000000000', function() {
assert.strictEqual(Amount.from_human("1000 0000000000000000000000005553440000000000").to_text_full(), '1000/USD/NaN');
});
it('1000 0000000000000000000000005553440000000000 human', function() {
assert.strictEqual(Amount.from_human("1000 0000000000000000000000005553440000000000").to_human_full(), '1,000/USD/NaN');
});
it('-100 0000000000000000000000005553440000000000', function() {
assert.strictEqual(Amount.from_human("-100 0000000000000000000000005553440000000000").to_text_full(), '-100/USD/NaN');
});
it('-100 0000000000000000000000005553440000000000 human', function() {
assert.strictEqual(Amount.from_human("-100 0000000000000000000000005553440000000000").to_human_full(), '-100/USD/NaN');
});
it('-1000 0000000000000000000000005553440000000000', function() {
assert.strictEqual(Amount.from_human("-1000 0000000000000000000000005553440000000000").to_text_full(), '-1000/USD/NaN');
});
it('-1000 0000000000000000000000005553440000000000 human', function() {
assert.strictEqual(Amount.from_human("-1000 0000000000000000000000005553440000000000").to_human_full(), '-1,000/USD/NaN');
});
it('-1000.001 0000000000000000000000005553440000000000', function() {
assert.strictEqual(Amount.from_human("-1000.001 0000000000000000000000005553440000000000").to_text_full(), '-1000.001/USD/NaN');
});
it('-1000.001 0000000000000000000000005553440000000000 human', function() {
assert.strictEqual(Amount.from_human("-1000.001 0000000000000000000000005553440000000000").to_human_full(), '-1,000.001/USD/NaN');
});
it('XAU 12345.6789', function() {
assert.strictEqual(Amount.from_human("XAU 12345.6789").to_text_full(), '12345.6789/XAU/NaN');
});
it('XAU 12345.6789 human', function() {
assert.strictEqual(Amount.from_human("XAU 12345.6789").to_human_full(), '12,345.6789/XAU/NaN');
});
it('101 12345.6789', function() {
assert.strictEqual(Amount.from_human("101 12345.6789").to_text_full(), '12345.6789/101/NaN');
});
it('101 12345.6789 human', function() {
assert.strictEqual(Amount.from_human("101 12345.6789").to_human_full(), '12,345.6789/101/NaN');
});
it('12345.6789 101', function() {
assert.strictEqual(Amount.from_human("12345.6789 101").to_text_full(), '12345.6789/101/NaN');
});
it('12345.6789 101 human', function() {
assert.strictEqual(Amount.from_human("12345.6789 101").to_human_full(), '12,345.6789/101/NaN');
});
});
describe('from_json', function() {
it('1 XRP', function() {
assert.strictEqual(Amount.from_json("1/XRP").to_text_full(), "1/XRP/NaN");
});
it('1 XRP human', function() {
assert.strictEqual(Amount.from_json("1/XRP").to_human_full(), "1/XRP/NaN");
});
});
describe('from_number', function() {
it('Number 1', function() {
assert.strictEqual(Amount.from_number(1).to_text_full(), '1/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Number 1 human', function() {
assert.strictEqual(Amount.from_number(1).to_human_full(), '1/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Number 2', function() {
assert.strictEqual(Amount.from_number(2).to_text_full(), '2/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Number 2 human', function() {
assert.strictEqual(Amount.from_number(2).to_human_full(), '2/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply 2 "1" with 3 "1", by product_human', function () {
assert.strictEqual(Amount.from_number(2).product_human(Amount.from_number(3)).to_text_full(), '6/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply 2 "1" with 3 "1", by product_human human', function () {
assert.strictEqual(Amount.from_number(2).product_human(Amount.from_number(3)).to_human_full(), '6/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply 3 USD with 3 "1"', function () {
assert.strictEqual(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_number(3)).to_text_full(), '9/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply 3 USD with 3 "1" human', function () {
assert.strictEqual(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_number(3)).to_human_full(), '9/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply -1 "1" with 3 USD', function () {
assert.strictEqual(Amount.from_number(-1).multiply(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_text_full(), '-3/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply -1 "1" with 3 USD human', function () {
assert.strictEqual(Amount.from_number(-1).multiply(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full(), '-3/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply -1 "1" with 3 USD, by product_human', function () {
assert.strictEqual(Amount.from_number(-1).product_human(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_text_full(), '-3/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
it('Multiply -1 "1" with 3 USD, by product_human human', function () {
assert.strictEqual(Amount.from_number(-1).product_human(Amount.from_json('3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full(), '-3/1/rrrrrrrrrrrrrrrrrrrrBZbvji');
});
});
describe('text_full_rewrite', function() {
it('Number 1', function() {
@@ -162,12 +299,21 @@ describe('Amount', function() {
it('parse dem', function() {
assert.strictEqual(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_text_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('parse dem human', function() {
assert.strictEqual(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('parse dem', function() {
assert.strictEqual(Amount.from_json('10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_text_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('parse dem human', function() {
assert.strictEqual(Amount.from_json('10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Parse 800/USD/mtgox', function () {
assert.strictEqual('800/USD/'+config.accounts['mtgox'].account, Amount.from_json('800/USD/mtgox').to_text_full());
});
it('Parse 800/USD/mtgox human', function () {
assert.strictEqual('800/USD/'+config.accounts['mtgox'].account, Amount.from_json('800/USD/mtgox').to_human_full());
});
it('Parse native 0', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').to_text_full());
});
@@ -211,7 +357,52 @@ describe('Amount', function() {
assert.strictEqual('0/111/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/111/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_text_full());
});
it('Parse 0.0/12D/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', function () {
assert.strictEqual('0/XRP/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/12D/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_text_full());
assert.strictEqual('0/12D/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/12D/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_text_full());
});
it('Parse native 0 human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').to_human_full());
});
it('Parse native 0.0 human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0.0').to_human_full());
});
it('Parse native -0 human', function () {
assert.strictEqual('0/XRP', Amount.from_json('-0').to_human_full());
});
it('Parse native -0.0 human', function () {
assert.strictEqual('0/XRP', Amount.from_json('-0.0').to_human_full());
});
it('Parse native 1000 human', function () {
assert.strictEqual('0.001/XRP', Amount.from_json('1000').to_human_full());
});
it('Parse native 12.3 human', function () {
assert.strictEqual('12.3/XRP', Amount.from_json('12.3').to_human_full());
});
it('Parse native -12.3 human', function () {
assert.strictEqual('-12.3/XRP', Amount.from_json('-12.3').to_human_full());
});
it('Parse 123./USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh human', function () {
assert.strictEqual('123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('123./USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full());
});
it('Parse 12300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh human', function () {
assert.strictEqual('12,300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('12300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full());
});
it('Parse 12.3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh human', function () {
assert.strictEqual('12.3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('12.3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full());
});
it('Parse 1.2300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh human', function () {
assert.strictEqual('1.23/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('1.2300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full());
});
it('Parse -0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh human', function () {
assert.strictEqual('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full());
});
it('Parse -0.0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh human', function () {
assert.strictEqual('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-0.0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full());
});
it('Parse 0.0/111/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh human', function () {
assert.strictEqual('0/111/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/111/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full());
});
it('Parse 0.0/12D/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh human', function () {
assert.strictEqual('0/12D/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/12D/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').to_human_full());
});
});
describe('Amount to_json', function() {
@@ -370,6 +561,144 @@ describe('Amount', function() {
it('Divide EUR by XRP, neg, <1', function () {
assert.strictEqual('-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('2000')).to_text_full());
});
it('Negate native 123 human', function () {
assert.strictEqual('-0.000123/XRP', Amount.from_json('123').negate().to_human_full());
});
it('Negate native -123 human', function () {
assert.strictEqual('0.000123/XRP', Amount.from_json('-123').negate().to_human_full());
});
it('Negate non-native 123 human', function () {
assert.strictEqual('-123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').negate().to_human_full());
});
it('Negate non-native -123 human', function () {
assert.strictEqual('123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').negate().to_human_full());
});
it('Clone non-native -123 human', function () {
assert.strictEqual('-123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').clone().to_human_full());
});
it('Add XRP to XRP human', function () {
assert.strictEqual('0.0002/XRP', Amount.from_json('150').add(Amount.from_json('50')).to_human_full());
});
it('Add USD to USD human', function () {
assert.strictEqual('200.52/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('150.02/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').add(Amount.from_json('50.5/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Add 0 USD to 1 USD human', function() {
assert.strictEqual('1' , Amount.from_json('1/USD').add('0/USD').to_human());
});
it('Subtract USD from USD human', function() {
assert.strictEqual('99.52/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('150.02/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').subtract(Amount.from_json('50.5/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply 0 XRP with 0 XRP human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').multiply(Amount.from_json('0')).to_human_full());
});
it('Multiply 0 USD with 0 XRP human', function () {
assert.strictEqual('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('0')).to_human_full());
});
it('Multiply 0 XRP with 0 USD human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').multiply(Amount.from_json('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply 1 XRP with 0 XRP human', function () {
assert.strictEqual('0/XRP', Amount.from_json('1').multiply(Amount.from_json('0')).to_human_full());
});
it('Multiply 1 USD with 0 XRP human', function () {
assert.strictEqual('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('0')).to_human_full());
});
it('Multiply 1 XRP with 0 USD human', function () {
assert.strictEqual('0/XRP', Amount.from_json('1').multiply(Amount.from_json('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply 0 XRP with 1 XRP human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').multiply(Amount.from_json('1')).to_human_full());
});
it('Multiply 0 USD with 1 XRP human', function () {
assert.strictEqual('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('1')).to_human_full());
});
it('Multiply 0 XRP with 1 USD human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').multiply(Amount.from_json('1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD human', function () {
assert.equal('0.002/XRP', Amount.from_json('200').multiply(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD human', function () {
assert.strictEqual('0.2/XRP', Amount.from_json('20000').multiply(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD human', function () {
assert.strictEqual('20/XRP', Amount.from_json('2000000').multiply(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD, neg human', function () {
assert.strictEqual('-0.002/XRP', Amount.from_json('200').multiply(Amount.from_json('-10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD, neg, frac human', function () {
assert.strictEqual('-0.222/XRP', Amount.from_json('-6000').multiply(Amount.from_json('37/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply USD with USD human', function () {
assert.strictEqual('20,000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply USD with USD human', function () {
assert.strictEqual('200,000,000,000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('2000000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('100000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply EUR with USD, result < 1 human', function () {
assert.strictEqual('100,000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply EUR with USD, neg human', function () {
assert.strictEqual('-48,000,000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-24000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply EUR with USD, neg, <1 human', function () {
assert.strictEqual('-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0.1/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('-1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply EUR with XRP, factor < 1 human', function () {
assert.strictEqual('100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('2000')).to_human_full());
});
it('Multiply EUR with XRP, neg human', function () {
assert.strictEqual('-500/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('5')).to_human_full());
});
it('Multiply EUR with XRP, neg, <1 human', function () {
assert.strictEqual('-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').multiply(Amount.from_json('2000')).to_human_full());
});
it('Multiply XRP with XRP human', function () {
assert.strictEqual('0.0001/XRP', Amount.from_json('10').multiply(Amount.from_json('10')).to_human_full());
});
it('Divide XRP by USD human', function () {
assert.strictEqual('0.00002/XRP', Amount.from_json('200').divide(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide XRP by USD human', function () {
assert.strictEqual('0.002/XRP', Amount.from_json('20000').divide(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide XRP by USD human', function () {
assert.strictEqual('0.2/XRP', Amount.from_json('2000000').divide(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide XRP by USD, neg human', function () {
assert.strictEqual('-0.00002/XRP', Amount.from_json('200').divide(Amount.from_json('-10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide XRP by USD, neg, frac human', function () {
assert.strictEqual('-0.000162/XRP', Amount.from_json('-6000').divide(Amount.from_json('37/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide USD by USD human', function () {
assert.strictEqual('200/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide USD by USD, fractional human', function () {
assert.strictEqual('57,142.85714285714/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('2000000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('35/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide USD by USD human', function () {
assert.strictEqual('20/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('2000000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('100000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide EUR by USD, factor < 1 human', function () {
assert.strictEqual('0.1/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide EUR by USD, neg human', function () {
assert.strictEqual('-12/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-24000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide EUR by USD, neg, <1 human', function () {
assert.strictEqual('-0.1/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('-1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Divide EUR by XRP, result < 1 human', function () {
assert.strictEqual('0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('2000')).to_human_full());
});
it('Divide EUR by XRP, neg human', function () {
assert.strictEqual('-20/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('5')).to_human_full());
});
it('Divide EUR by XRP, neg, <1 human', function () {
assert.strictEqual('-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').divide(Amount.from_json('2000')).to_human_full());
});
it('Divide by zero should throw', function() {
assert.throws(function() {
Amount.from_json(1).divide(Amount.from_json(0));
@@ -607,12 +936,87 @@ describe('Amount', function() {
it('Multiply USD with XAU (dem)', function () {
assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_text_full(), '19900.00316303882/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply 0 XRP with 0 XRP human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').product_human(Amount.from_json('0')).to_human_full());
});
it('Multiply 0 USD with 0 XRP human', function () {
assert.strictEqual('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('0')).to_human_full());
});
it('Multiply 0 XRP with 0 USD human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').product_human(Amount.from_json('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply 1 XRP with 0 XRP human', function () {
assert.strictEqual('0/XRP', Amount.from_json('1').product_human(Amount.from_json('0')).to_human_full());
});
it('Multiply 1 USD with 0 XRP human', function () {
assert.strictEqual('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('0')).to_human_full());
});
it('Multiply 1 XRP with 0 USD human', function () {
assert.strictEqual('0/XRP', Amount.from_json('1').product_human(Amount.from_json('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply 0 XRP with 1 XRP human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').product_human(Amount.from_json('1')).to_human_full());
});
it('Multiply 0 USD with 1 XRP human', function () {
assert.strictEqual('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('1')).to_human_full());
});
it('Multiply 0 XRP with 1 USD human', function () {
assert.strictEqual('0/XRP', Amount.from_json('0').product_human(Amount.from_json('1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD human', function () {
assert.equal('0.002/XRP', Amount.from_json('200').product_human(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD human', function () {
assert.strictEqual('0.2/XRP', Amount.from_json('20000').product_human(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD human', function () {
assert.strictEqual('20/XRP', Amount.from_json('2000000').product_human(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD, neg human', function () {
assert.strictEqual('-0.002/XRP', Amount.from_json('200').product_human(Amount.from_json('-10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply XRP with USD, neg, frac human', function () {
assert.strictEqual('-0.222/XRP', Amount.from_json('-6000').product_human(Amount.from_json('37/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply USD with USD human', function () {
assert.strictEqual('20,000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply USD with USD human', function () {
assert.strictEqual('200,000,000,000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('2000000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('100000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply EUR with USD, result < 1 human', function () {
assert.strictEqual('100,000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Amount.from_json('100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full());
});
it('Multiply EUR with USD, neg human', function () {
assert.strictEqual(Amount.from_json('-24000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full(), '-48,000,000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply EUR with USD, neg, <1 human', function () {
assert.strictEqual(Amount.from_json('0.1/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('-1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh')).to_human_full(), '-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply EUR with XRP, factor < 1 human', function () {
assert.strictEqual(Amount.from_json('0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('2000')).to_human_full(), '0.0001/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply EUR with XRP, neg human', function () {
assert.strictEqual(Amount.from_json('-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('5')).to_human_full(), '-0.0005/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply EUR with XRP, neg, <1 human', function () {
assert.strictEqual(Amount.from_json('-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('2000')).to_human_full(), '-0.0001/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Multiply XRP with XRP human', function () {
assert.strictEqual(Amount.from_json('10000000').product_human(Amount.from_json('10')).to_human_full(), '0.0001/XRP');
});
it('Multiply USD with XAU (dem) human', function () {
assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').product_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_human_full(), '19,900.00316303882/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
});
describe('ratio_human', function() {
it('Divide USD by XAU (dem)', function () {
assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').ratio_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_text_full(), '201.0049931765529/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Divide USD by XAU (dem) human', function () {
assert.strictEqual(Amount.from_json('2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').ratio_human(Amount.from_json('10/015841551A748AD2C1F76FF6ECB0CCCD00000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'), {reference_date: 443845330 + 31535000}).to_human_full(), '201.0049931765529/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
});
describe('_invert', function() {
@@ -625,6 +1029,15 @@ describe('Amount', function() {
it('Invert 0.02', function () {
assert.strictEqual(Amount.from_json('0.02/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').invert().to_text_full(), '50/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Invert 1 human', function () {
assert.strictEqual(Amount.from_json('1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').invert().to_human_full(), '1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Invert 20 human', function () {
assert.strictEqual(Amount.from_json('20/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').invert().to_human_full(), '0.05/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it('Invert 0.02 human', function () {
assert.strictEqual(Amount.from_json('0.02/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh').invert().to_human_full(), '50/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
});
describe('from_quality', function() {
@@ -658,6 +1071,36 @@ describe('Amount', function() {
it('USD/XAU(dem) inverse', function () {
assert.strictEqual(Amount.from_quality('CDFD3AFB2F8C5DBEF75B081F7C957FF5509563266F28F36C5704A0FB0BAD8800', '015841551A748AD2C1F76FF6ECB0CCCD00000000', 'rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN', {inverse: true, base_currency: 'USD', reference_date: 443845330 + 31535000}).to_text_full(), '0.007675186123263489/XAU (-0.5%pa)/rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN');
});
it('BTC/XRP human', function () {
assert.strictEqual(Amount.from_quality('7B73A610A009249B0CC0D4311E8BA7927B5A34D86634581C5F0FF9FF678E1000', 'XRP', NaN, {base_currency: 'BTC'}).to_human_full(), '44,970/XRP');
});
it('BTC/XRP inverse human', function () {
assert.strictEqual(Amount.from_quality('37AAC93D336021AE94310D0430FFA090F7137C97D473488C4A0918D0DEF8624E', 'XRP', NaN, {inverse: true, base_currency: 'BTC'}).to_human_full(), '39,053.954453/XRP');
});
it('XRP/USD human', function () {
assert.strictEqual(Amount.from_quality('DFA3B6DDAB58C7E8E5D944E736DA4B7046C30E4F460FD9DE4D05DCAA8FE12000', 'USD', 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', {base_currency: 'XRP'}).to_human_full(), '0.0165/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B');
});
it('XRP/USD inverse human', function () {
assert.strictEqual(Amount.from_quality('4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5C22A840E27DCA9B', 'USD', 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', {inverse: true, base_currency: 'XRP'}).to_human_full(), '0.010251/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B');
});
it('BTC/USD human', function () {
assert.strictEqual(Amount.from_quality('6EAB7C172DEFA430DBFAD120FDC373B5F5AF8B191649EC9858038D7EA4C68000', 'USD', 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', {base_currency: 'BTC'}).to_human_full(), '1,000/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B');
});
it('BTC/USD inverse human', function () {
assert.strictEqual(Amount.from_quality('20294C923E80A51B487EB9547B3835FD483748B170D2D0A455071AFD498D0000', 'USD', 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', {inverse: true, base_currency: 'BTC'}).to_human_full(), '0.5/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B');
});
it('XAU(dem)/XRP human', function () {
assert.strictEqual(Amount.from_quality('587322CCBDE0ABD01704769A73A077C32FB39057D813D4165F1FF973CAF997EF', 'XRP', NaN, {base_currency: '015841551A748AD2C1F76FF6ECB0CCCD00000000', reference_date: 443845330 + 31535000}).to_human_full(), '90,452.246928/XRP');
});
it('XAU(dem)/XRP inverse human', function () {
assert.strictEqual(Amount.from_quality('F72C7A9EAE4A45ED1FB547AD037D07B9B965C6E662BEBAFA4A03F2A976804235', 'XRP', NaN, {inverse: true, base_currency: '015841551A748AD2C1F76FF6ECB0CCCD00000000', reference_date: 443845330 + 31535000}).to_human_full(), '90,442.196677/XRP');
});
it('USD/XAU(dem) human', function () {
assert.strictEqual(Amount.from_quality('4743E58E44974B325D42FD2BB683A6E36950F350EE46DD3A521B644B99782F5F', '015841551A748AD2C1F76FF6ECB0CCCD00000000', 'rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN', {base_currency: 'USD', reference_date: 443845330 + 31535000}).to_human_full(), '0.007710100231303007/XAU (-0.5%pa)/rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN');
});
it('USD/XAU(dem) inverse human', function () {
assert.strictEqual(Amount.from_quality('CDFD3AFB2F8C5DBEF75B081F7C957FF5509563266F28F36C5704A0FB0BAD8800', '015841551A748AD2C1F76FF6ECB0CCCD00000000', 'rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN', {inverse: true, base_currency: 'USD', reference_date: 443845330 + 31535000}).to_human_full(), '0.007675186123263489/XAU (-0.5%pa)/rUyPiNcSFFj6uMR2gEaD8jUerQ59G1qvwN');
});
});
describe('apply interest', function() {
@@ -679,5 +1122,23 @@ describe('Amount', function() {
demAmount.set_issuer("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
assert.strictEqual(demAmount.to_text_full(), '10.75853086191915/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it ('from_json apply interest 10 XAU human', function() {
var demAmount = Amount.from_json('10/0158415500000000C1F76FF6ECB0BAC600000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
assert.strictEqual(demAmount.to_human_full(), '10/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
demAmount = demAmount.applyInterest(459990264);
assert.strictEqual(demAmount.to_human_full(), '9.294949401870435/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it ('from_json apply interest XAU human', function() {
var demAmount = Amount.from_json('1235.5/0158415500000000C1F76FF6ECB0BAC600000000/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
assert.strictEqual(demAmount.to_human_full(), '1,235.5/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
demAmount = demAmount.applyInterest(459990264);
assert.strictEqual(demAmount.to_human_full(), '1,148.390998601092/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
it ('from_human with reference date human', function() {
var demAmount = Amount.from_human('10 0158415500000000C1F76FF6ECB0BAC600000000', {reference_date:459990264});
demAmount.set_issuer("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
assert.strictEqual(demAmount.to_human_full(), '10.75853086191915/XAU (-0.5%pa)/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh');
});
});
});

View File

@@ -40,8 +40,8 @@ describe('Currency', function() {
});
it('from_json("1D2").to_human()', function() {
var r = currency.from_json("1D2");
assert(!r.is_valid());
assert.strictEqual('XRP', r.to_json());
assert(r.is_valid());
assert.strictEqual('1D2', r.to_json());
});
it('from_json("XAU").to_json() hex', function() {
var r = currency.from_json("XAU");
@@ -82,6 +82,9 @@ describe('Currency', function() {
var cur = currency.from_human('EUR (0.5361%pa)');
assert.strictEqual(cur.to_json(), 'EUR (0.54%pa)');
assert.strictEqual(cur.to_json({decimals:4, full_name:'Euro'}), 'EUR - Euro (0.5361%pa)');
assert.strictEqual(cur.to_json({decimals:void(0), full_name:'Euro'}), 'EUR - Euro (0.54%pa)');
assert.strictEqual(cur.to_json({decimals:undefined, full_name:'Euro'}), 'EUR - Euro (0.54%pa)');
assert.strictEqual(cur.to_json({decimals:'henk', full_name:'Euro'}), 'EUR - Euro (0.54%pa)');
assert.strictEqual(cur.get_interest_percentage_at(undefined, 4), 0.5361);
});
it('From human "TYX - 30-Year Treasuries (1.5%pa)"', function() {
@@ -111,8 +114,28 @@ describe('Currency', function() {
assert.strictEqual('XRP', currency.from_json(NaN).to_human());
});
it('"015841551A748AD2C1F76FF6ECB0CCCD00000000") == "015841551A748AD2C1F76FF6ECB0CCCD00000000"', function() {
assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human(),
'XAU (-0.5%pa)');
assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human(), 'XAU (-0.5%pa)');
});
it('"015841551A748AD2C1F76FF6ECB0CCCD00000000") == "015841551A748AD2C1F76FF6ECB0CCCD00000000"', function() {
assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({full_name:'Gold'}), 'XAU - Gold (-0.5%pa)');
});
it('to_human interest XAU with full name, do not show interest', function() {
assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({full_name:'Gold', show_interest:false}), 'XAU - Gold');
});
it('to_human interest XAU with full name, show interest', function() {
assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({full_name:'Gold', show_interest:true}), 'XAU - Gold (-0.5%pa)');
});
it('to_human interest XAU, do show interest', function() {
assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({show_interest:true}), 'XAU (-0.5%pa)');
});
it('to_human interest XAU, do not show interest', function() {
assert.strictEqual(currency.from_json("015841551A748AD2C1F76FF6ECB0CCCD00000000").to_human({show_interest:false}), 'XAU');
});
it('to_human with full_name "USD - US Dollar show interest"', function() {
assert.strictEqual(currency.from_json('USD').to_human({full_name:'US Dollar', show_interest:true}), 'USD - US Dollar (0%pa)');
});
it('to_human with full_name "USD - US Dollar do not show interest"', function() {
assert.strictEqual(currency.from_json('USD').to_human({full_name:'US Dollar', show_interest:false}), 'USD - US Dollar');
});
it('to_human with full_name "USD - US Dollar"', function() {
assert.strictEqual('USD - US Dollar', currency.from_json('USD').to_human({full_name:'US Dollar'}));
@@ -128,6 +151,7 @@ describe('Currency', function() {
var cur = currency.from_json("TIM");
assert.strictEqual(cur.to_human({full_name: null}), "TIM");
});
});
describe('from_hex', function() {

View File

@@ -1546,7 +1546,7 @@ describe('OrderBook', function() {
]
book.once('model', function(model) {
book.on('model', function(model) {
assert.deepEqual(model, expected);
assert.strictEqual(book._synchronized, true);
done();

View File

@@ -5,7 +5,6 @@ var config = require('./testutils').get_config();
describe('Seed', function() {
it('can generate many addresses', function () {
var seed = Seed.from_json("masterpassphrase");
var test_data = [
// Format:
@@ -28,10 +27,10 @@ describe('Seed', function() {
function assert_helper(seed_json, address_or_nth, expected) {
var seed = Seed.from_json(seed_json);
var keypair = seed.get_key(address_or_nth);
assert.strictEqual(keypair.to_hex_pub(),
expected);
var keypair = seed.get_key(address_or_nth, 500);
assert.strictEqual(keypair.to_hex_pub(), expected);
}
for (var nth = 0; nth < test_data.length; nth++) {
var seed_json = test_data[nth][0];
var address = test_data[nth][1];
@@ -47,7 +46,30 @@ describe('Seed', function() {
// This isn't too bad as it only needs to generate one keypair `seq`
assert_helper(seed_json, nth_for_seed, expected);
};
});
it('should return the key_pair for a valid account and secret pair', function() {
var address = 'r3GgMwvgvP8h4yVWvjH1dPZNvC37TjzBBE';
var seed = Seed.from_json('shsWGZcmZz6YsWWmcnpfr6fLTdtFV');
var keyPair = seed.get_key(address);
assert.strictEqual(keyPair.get_address().to_json(), address);
assert.strictEqual(keyPair.to_hex_pub(), '02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8');
});
it('should not find a KeyPair for a secret that does not belong to the given account', function() {
var address = 'r3GgMwvgvP8h4yVWvjH1dPZNvC37TjzBBE';
var secret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb';
var seed = Seed.from_json('snoPBrXtMeMyMHUVTgbuqAfg1SUTb');
try {
seed.get_key(address);
assert(false, 'should throw an error');
} catch(e) {
assert.strictEqual(e.message, 'Too many loops looking for KeyPair yielding '+address+' from '+secret);
}
});
});
// vim:sw=2:sts=2:ts=8:et

View File

@@ -530,6 +530,51 @@ describe('Server', function() {
server.connect();
});
it('Connect - syncing state', function(done) {
// Test that fee and load defaults are not overwritten by
// undefined properties on server subscribe response
var wss = new ws.Server({ port: 5748 });
wss.once('connection', function(ws) {
ws.once('message', function(message) {
var m = JSON.parse(message);
assert.deepEqual(m, {
command: 'subscribe',
id: 0,
streams: [ 'ledger', 'server' ]
});
ws.send(JSON.stringify({
id: 0,
status: 'success',
type: 'response',
result: {
load_base: 256,
load_factor: 256,
server_status: 'syncing'
}
}));
wss.close();
});
});
var server = new Server(new Remote(), 'ws://localhost:5748');
server.once('connect', function() {
assert(server.isConnected());
assert.strictEqual(server._load_base, 256);
assert.strictEqual(server._load_factor, 256);
assert.strictEqual(server._fee_base, 10);
assert.strictEqual(server._fee_ref, 10);
done();
});
server.connect();
});
it('Reconnect', function(done) {
var server = new Server(new Remote(), 'ws://localhost:5748');
server._connected = true;

View File

@@ -20,6 +20,7 @@ var exampleData = {
email_token : '77825040-9096-4695-9cbc-76720f6a8649',
activateLink : 'https://staging.ripple.com/client/#/register/activate/',
device_id : "ac1b6f6dbca98190eb9687ba06f0e066",
identity_id : "17fddb71-a5c2-44ce-8b50-4b381339d4f2",
blob: {
url: 'https://id.staging.ripple.com',
id: 'ef203d3e76552c0592384f909e6f61f1d1f02f61f07643ce015d8b0c9710dd2f',
@@ -103,12 +104,29 @@ var recoverRes = {
result: 'success'
}
}
var getProfileRes = {
"result":"success",
"addresses":[],
"attributes":[{
"attribute_id":"4034e477-ffc9-48c4-bcbc-058293f081d8",
"identity_id":"17fddb71-a5c2-44ce-8b50-4b381339d4f2",
"name":"email",
"type":"default",
"domain":null,
"value":"example@example.com",
"visibility":"public",
"updated":null
}
]
};
var blob = new Blob();
blob.url = exampleData.blob.url;
blob.id = exampleData.blob.id;
blob.device_id = exampleData.device_id;
blob.key = exampleData.blob.key;
blob.identity_id = exampleData.blob.identity_id;
blob.data = exampleData.blob.data;
blob.revision = exampleData.blob.data.revision;
@@ -133,14 +151,12 @@ var mockDelete;
if (!online) {
mockRippleTxt = nock('https://ripple.com')
.persist()
.get('/ripple.txt')
.reply(200, rippleTxtRes, {
'Content-Type': 'text/plain'
});
mockRippleTxt2 = nock('https://' + exampleData.domain)
.persist()
.get('/ripple.txt')
.reply(200, rippleTxtRes, {
'Content-Type': 'text/plain'
@@ -153,21 +169,21 @@ if (!online) {
'Content-Type': 'text/plain'
});
mockRegister = nock('https://id.staging.ripple.com').persist();
mockRegister = nock('https://id.staging.ripple.com');
mockRegister.filteringPath(/(v1\/user\?signature(.+))/g, 'register/')
.post('/register/')
.reply(200, { result: 'error', message: 'User already exists' }, {
'Content-Type': 'application/json'
});
mockDelete = nock('https://id.staging.ripple.com').persist();
mockDelete = nock('https://id.staging.ripple.com');
mockDelete.filteringPath(/(v1\/user\/(.+))/g, 'delete/')
.delete('/delete/')
.reply(200, { result: 'success' }, {
'Content-Type': 'application/json'
});
mockBlob = nock('https://id.staging.ripple.com').persist();
mockBlob = nock('https://id.staging.ripple.com');
mockBlob.get('/v1/authinfo?domain=' + exampleData.domain + '&username=' + exampleData.username.toLowerCase())
.reply(200, JSON.stringify(authInfoRes.body), {
'Content-Type': 'application/json'
@@ -185,47 +201,40 @@ if (!online) {
'Content-Type': 'application/json'
});
mockRename = nock('https://id.staging.ripple.com/v1/user/').persist();
mockRename = nock('https://id.staging.ripple.com/v1/user/');
mockRename.filteringPath(/((.+)\/rename(.+))/g, 'rename/')
.post('rename/')
.reply(200, {result:'success',message:'rename'}, {
'Content-Type': 'application/json'
});
mockUpdate = nock('https://id.staging.ripple.com/v1/user/').persist();
mockUpdate.filteringPath(/((.+)\/update(.+))/g, 'update/')
mockUpdate = nock('https://id.staging.ripple.com/v1/user/');
mockUpdate.filteringPath(/((.+)\/updatekeys(.+))/g, 'update/')
.post('update/')
.reply(200, {result:'success',message:'updateKeys'}, {
'Content-Type': 'application/json'
});
mockRecover = nock('https://id.staging.ripple.com/').persist();
mockRecover = nock('https://id.staging.ripple.com/')
mockRecover.filteringPath(/((.+)user\/recov\/(.+))/g, 'recov/')
.get('recov/')
.reply(200, recoverRes.body, {
'Content-Type': 'application/json'
});
mockVerify = nock('https://id.staging.ripple.com/v1/user/').persist();
mockVerify = nock('https://id.staging.ripple.com/v1/user/');
mockVerify.filteringPath(/((.+)\/verify(.+))/g, 'verify/')
.get('verify/')
.reply(200, {result:'error', message:'invalid token'}, {
'Content-Type': 'application/json'
});
mockEmail = nock('https://id.staging.ripple.com/v1/user').persist();
mockEmail = nock('https://id.staging.ripple.com/v1/user');
mockEmail.filteringPath(/((.+)\/email(.+))/g, 'email/')
.post('email/')
.reply(200, {result:'success'}, {
'Content-Type': 'application/json'
});
mockProfile = nock('https://id.staging.ripple.com/v1/user').persist();
mockProfile.filteringPath(/((.+)\/profile(.+))/g, 'profile/')
.post('profile/')
.reply(200, {result:'success'}, {
'Content-Type': 'application/json'
});
}
describe('Ripple Txt', function () {
@@ -419,6 +428,7 @@ describe('VaultClient', function () {
});
});
/*
describe('#updateProfile', function () {
it('should update profile parameters associated with a blob', function (done) {
this.timeout(10000);
@@ -442,7 +452,7 @@ describe('VaultClient', function () {
});
});
});
*/
});
@@ -693,7 +703,95 @@ describe('Blob', function () {
});
});
});
describe('identityVault', function() {
it('#identity - Get Attestation', function (done) {
var options = {
url : blob.url,
auth_secret : blob.data.auth_secret,
blob_id : blob.id,
};
options.type = 'identity';
nock('https://id.staging.ripple.com')
.filteringPath(/(v1\/attestation\/identity(.+))/g, '')
.post('/')
.reply(200, {
result: 'success',
status: 'verified',
attestation: 'eyJ6IjoieiJ9.eyJ6IjoieiJ9.sig',
blinded:'eyJ6IjoieiJ9.eyJ6IjoieiJ9.sig'
}, {'Content-Type': 'application/json'});
client.getAttestation(options, function(err, resp) {
assert.ifError(err);
assert.strictEqual(resp.result, 'success');
assert.strictEqual(typeof resp.attestation, 'string');
assert.strictEqual(typeof resp.blinded, 'string');
assert.deepEqual(resp.decoded, {"header":{"z":"z"},"payload":{"z":"z"},"signature":"sig"})
done();
});
});
it('#identity - Update Attestation', function (done) {
var options = {
url : blob.url,
auth_secret : blob.data.auth_secret,
blob_id : blob.id,
};
options.type = 'identity';
nock('https://id.staging.ripple.com')
.filteringPath(/(v1\/attestation\/identity\/update(.+))/g, '')
.post('/')
.reply(200, {
result: 'success',
status: 'verified',
attestation: 'eyJ6IjoieiJ9.eyJ6IjoieiJ9.sig',
blinded:'eyJ6IjoieiJ9.eyJ6IjoieiJ9.sig'
}, {'Content-Type': 'application/json'});
client.updateAttestation(options, function(err, resp) {
assert.ifError(err);
assert.strictEqual(resp.result, 'success');
assert.strictEqual(typeof resp.attestation, 'string');
assert.strictEqual(typeof resp.blinded, 'string');
assert.deepEqual(resp.decoded, {"header":{"z":"z"},"payload":{"z":"z"},"signature":"sig"})
done();
});
});
it('#identity - Get Attestation Summary', function (done) {
var options = {
url : blob.url,
auth_secret : blob.data.auth_secret,
blob_id : blob.id,
};
nock('https://id.staging.ripple.com')
.filteringPath(/(v1\/attestation\/summary(.+))/g, '')
.get('/')
.reply(200, {
result: 'success',
attestation: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjY2ZGI3MzgxIn0%3D.eyJwcm9maWxlX3ZlcmlmaWVkIjpmYWxzZSwiaWRlbnRpdHlfdmVyaWZpZWQiOmZhbHNlLCJpc3MiOiJodHRwczovL2lkLnJpcHBsZS5jb20iLCJzdWIiOiIwNDMzNTA0ZS0yYTRmLTQ1NjktODQwMi1lYWI2YTU0YTgzYjUiLCJleHAiOjE0MTI4MTc2NjksImlhdCI6MTQxMjgxNTgwOX0%3D.Jt14Y2TsM7fKqGWn0j16cPldlYqRr7%2F2dptBsdZuZhRGRTREO4TSpZZhBaU95WL3M9eXIfaoSs8f2pTOa%2BBGAYHZSZK4%2FLqeWdDH8zz8Bx9YFqGije1KmHQR%2FeoWSp1GTEfcq5Oho4nSHozHhGNN8IrDkl8woMvWb%2FE1938Y5Zl2vyv7wjlNUF4ND33XWzJkvQjzIK15uYfaB%2FUIsNW32udfHAdkigesdMDNm%2BRGBqHMDZeAMdVxzrDzE3m8oWKDMJXbcaLmk75COfJrLWYiZCHd7VcReyPEZegwEucetZJ9uDnoBcvw0%2B6hIRmjTN6Gy1eeBoJaiDYsWuOwInbIlw%3D%3D',
}, {'Content-Type': 'application/json'});
client.getAttestationSummary(options, function(err, resp) {
assert.ifError(err);
assert.strictEqual(resp.result, 'success');
assert.strictEqual(typeof resp.attestation, 'string');
assert.strictEqual(typeof resp.decoded.header, 'object');
assert.strictEqual(typeof resp.decoded.payload, 'object');
assert.strictEqual(typeof resp.decoded.signature, 'string');
done();
});
});
});
//only do these offline
if (!online) {