Skip to content

Commit

Permalink
Add support for big numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro Branco committed Feb 10, 2017
1 parent f2eca4c commit 3ee0621
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 4 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ client.getInfo().then(([body, headers]) => console.log(body, headers));
const [body, headers] = await client.getInfo();
```

### Floating point number precision in JavaScript

Due to [Javascript's limited floating point precision](http://floating-point-gui.de/), all big numbers (numbers with more than 15 significant digits) are returned as strings to prevent precision loss.

### Version Checking
By default, all methods are exposed on the client independently of the version it is connecting to. This is the most flexible option as defining methods for unavailable RPC calls does not cause any harm and the library is capable of handling a `Method not found` response error correctly.

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@uphold/request-logger": "^1.2.0",
"bluebird": "^3.4.1",
"debugnyan": "^1.0.0",
"json-bigint": "^0.2.0",
"lodash": "^4.0.0",
"request": "^2.53.0",
"semver": "^5.1.0",
Expand Down
10 changes: 9 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Module dependencies.
*/

import JSONBigInt from 'json-bigint';
import Parser from './parser';
import Promise from 'bluebird';
import Requester from './requester';
Expand All @@ -12,6 +13,12 @@ import methods from './methods';
import requestLogger from './logging/request-logger';
import semver from 'semver';

/**
* JSONBigInt parser.
*/

const { stringify } = JSONBigInt({ storeAsString: true, strict: true }); // eslint-disable-line new-cap

/**
* Source arguments to find out if a callback has been passed.
*/
Expand Down Expand Up @@ -122,7 +129,8 @@ class Client {

return this.request.postAsync({
auth: _.pickBy(this.auth, _.identity),
body,
body: stringify(body),
json: false,
uri: '/'
})
.bind(this)
Expand Down
11 changes: 9 additions & 2 deletions src/logging/request-obfuscator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
* Module dependencies.
*/

import JSONBigInt from 'json-bigint';
import methods from '../methods';
import { defaults, get, has, isArray, isEmpty, isString, map, mapKeys } from 'lodash';

/**
* JSONBigInt parser.
*/

const { parse, stringify } = JSONBigInt({ storeAsString: true, strict: true }); // eslint-disable-line new-cap

/**
* Map all methods to lowercase.
*/
Expand Down Expand Up @@ -83,15 +90,15 @@ function obfuscateRequest(request) {
return;
}

request.body = JSON.parse(request.body);
request.body = parse(request.body);

if (isArray(request.body)) {
request.body = map(request.body, obfuscateRequestBody);
} else {
request.body = obfuscateRequestBody(request.body);
}

request.body = JSON.stringify(request.body);
request.body = stringify(request.body);
}

/**
Expand Down
10 changes: 10 additions & 0 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
* Module dependencies.
*/

import JSONBigInt from 'json-bigint';
import RpcError from './errors/rpc-error';
import _ from 'lodash';

/**
* JSONBigInt parser.
*/

const { parse } = JSONBigInt({ storeAsString: true, strict: true }); // eslint-disable-line new-cap

/**
* Get response result and errors.
*/
Expand Down Expand Up @@ -52,6 +59,9 @@ export default class Parser {
throw new RpcError(response.statusCode);
}

// Parsing the body with custom parser to support BigNumbers.
body = parse(body);

if (!Array.isArray(body)) {
return get(body, { headers: this.headers, response });
}
Expand Down
2 changes: 1 addition & 1 deletion test/index_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ describe('Client', () => {
it('should return the proof-of-work difficulty', async () => {
const difficulty = await new Client(config.bitcoind).getDifficulty();

difficulty.should.be.a.Number();
difficulty.should.be.a.String();
});
});

Expand Down
8 changes: 8 additions & 0 deletions test/logging/request-obfuscator_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ describe('RequestObfuscator', () => {
request.should.eql({ headers: { authorization: 'Basic ******' } });
});

it('should keep a bignumber precision in `request.body`', () => {
const request = { body: '{"id":"1485369469422","method":"foobar","params":[9223372036854775807]}' };

obfuscate(request);

request.should.eql({ body: '{"id":"1485369469422","method":"foobar","params":["9223372036854775807"]}' });
});

it('should obfuscate the private key from `request.body` when `method` is `importprivkey`', () => {
const request = { body: '{"id":"1485369469422","method":"importprivkey","params":["foobar"]}' };

Expand Down

0 comments on commit 3ee0621

Please sign in to comment.