Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DH 5: feat: add init() to reduce downstream boilerplate #72

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
docs
node_modules
package.json
package-lock.json
5 changes: 5 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tabWidth": 2,
"singleQuote": true,
"printWidth": 120
}
61 changes: 31 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,30 @@ npm install @dashevo/dashd-rpc

### RpcClient

Config parameters :
Config parameters :

- protocol : (string - optional) - (default: 'https') - Set the protocol to be used. Either `http` or `https`.
- user : (string - optional) - (default: 'user') - Set the user credential.
- pass : (string - optional) - (default: 'pass') - Set the password credential.
- host : (string - optional) - (default: '127.0.0.1') - The host you want to connect with.
- port : (integer - optional) - (default: 9998) - Set the port on which perform the RPC command.
- protocol : (string - optional) - (default: 'https') - Set the protocol to be used. Either `http` or `https`.
- user : (string - optional) - (default: 'user') - Set the user credential.
- pass : (string - optional) - (default: 'pass') - Set the password credential.
- host : (string - optional) - (default: '127.0.0.1') - The host you want to connect with.
- port : (integer - optional) - (default: 9998) - Set the port on which perform the RPC command.

Promise vs callback based

- `require('@dashevo/dashd-rpc/promise')` to have promises returned
- `require('@dashevo/dashd-rpc')` to have callback functions returned
- `require('@dashevo/dashd-rpc/promise')` to have promises returned
- `require('@dashevo/dashd-rpc')` to have callback functions returned

### Examples

Config:

```javascript
var config = {
protocol: 'http',
user: 'dash',
pass: 'local321',
host: '127.0.0.1',
port: 19998
protocol: 'http',
user: 'dash',
pass: 'local321',
host: '127.0.0.1',
port: 19998,
};
```

Expand All @@ -50,24 +50,25 @@ Promise based:
var RpcClient = require('@dashevo/dashd-rpc/promise');
var rpc = new RpcClient(config);

rpc.getRawMemPool()
.then(ret => {
return Promise.all(ret.result.map(r => rpc.getRawTransaction(r)))
})
.then(rawTxs => {
rawTxs.forEach(rawTx => {
console.log(`RawTX: ${rawTx.result}`);
})
})
.catch(err => {
console.log(err)
})
rpc
.getRawMemPool()
.then((ret) => {
return Promise.all(ret.result.map((r) => rpc.getRawTransaction(r)));
})
.then((rawTxs) => {
rawTxs.forEach((rawTx) => {
console.log(`RawTX: ${rawTx.result}`);
});
})
.catch((err) => {
console.log(err);
});
```

Callback based (legacy):

```javascript
var run = function() {
var run = function () {
var bitcore = require('@dashevo/dashcore-lib');
var RpcClient = require('@dashevo/dashd-rpc');
var rpc = new RpcClient(config);
Expand All @@ -89,7 +90,7 @@ var run = function() {
});
}

rpc.batch(batchCall, function(err, rawtxs) {
rpc.batch(batchCall, function (err, rawtxs) {
if (err) {
console.error(err);
return setTimeout(showNewTransactions, 10000);
Expand Down Expand Up @@ -119,8 +120,8 @@ const RpcClient = require('@dashevo/dashd-rpc');
var client = new RPCclient({
protocol:'http',
user: 'dash',
pass: 'local321',
host: '127.0.0.1',
pass: 'local321',
host: '127.0.0.1',
port: 19998,
timeout: 1000
});
Expand Down
115 changes: 98 additions & 17 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ function RpcClient(opts) {
this.protocol = opts.protocol === 'http' ? http : https;
this.batchedCalls = null;
this.disableAgent = opts.disableAgent || false;
this.onconnected = opts.onconnected;
const queueSize = opts.queue || 16;

const isRejectUnauthorized = typeof opts.rejectUnauthorized !== 'undefined';
Expand All @@ -32,18 +33,28 @@ function RpcClient(opts) {

const cl = console.log.bind(console);

const noop = function () {
};
const noop = function () {};

RpcClient.E_IN_WARMUP = -28;

RpcClient.loggers = {
none: {
info: noop, warn: noop, err: noop, debug: noop,
info: noop,
warn: noop,
err: noop,
debug: noop,
},
normal: {
info: cl, warn: cl, err: cl, debug: noop,
info: cl,
warn: cl,
err: cl,
debug: noop,
},
debug: {
info: cl, warn: cl, err: cl, debug: cl,
info: cl,
warn: cl,
err: cl,
debug: cl,
},
};

Expand Down Expand Up @@ -81,7 +92,7 @@ function innerRpc(request, callback) {

if (self.timeout) {
options.timeout = self.timeout;
};
}

if (self.httpOptions) {
for (const k in self.httpOptions) {
Expand Down Expand Up @@ -162,6 +173,66 @@ function innerRpc(request, callback) {
req.end();
}

RpcClient.prototype.init = async function (opts) {
let rpc = this;
rpc._connected = false;

let retry = opts?.retry || 5000;

let height = 0;
for (;;) {
height = await RpcClient._getHeight(rpc);
if (height) {
break;
}
await sleep(retry);
}

return height;
};

RpcClient._getHeight = async function (rpc) {
let warn = null;
let tip = await rpc
.getChainTips()
//.getBestBlockHash()
.then(function (result) {
// { id, error, result }
if (result.error) {
// impossible, but we'll check anyway
throw new Error(result.error);
}

if (!result.result?.[0].height) {
// also impossible, and we still check anyway
throw new Error('Sanity Fail: missing tip');
}

return result.result[0].height;
})
.catch(function (e) {
if (e.code === RpcClient.E_IN_WARMUP) {
warn = e;
return 0;
}

throw e;
});

if (!rpc._connected) {
rpc._connected = true;
let onconnected = rpc.onconnected || RpcClient._onconnected;
void onconnected.call(rpc, warn);
}

return tip;
};

RpcClient._onconnected = function () {
let rpc = this;
console.info(`[dashd-rpc] client connected to ${rpc.host}:${rpc.port}`);
};

RpcClient.prototype.batch = function (batchCallback, resultCallback) {
this.batchedCalls = [];
batchCallback();
Expand All @@ -171,7 +242,7 @@ RpcClient.prototype.batch = function (batchCallback, resultCallback) {

RpcClient.prototype.setTimeout = function (timeout) {
this.timeout = timeout;
}
};

// For definitions of RPC calls, see various files in: https://github.com/dashpay/dash/tree/master/src
RpcClient.callspec = {
Expand Down Expand Up @@ -235,7 +306,7 @@ RpcClient.callspec = {
getPoolInfo: '',
getRawMemPool: 'bool',
getRawChangeAddress: '',
getRawTransaction: 'str int',
getRawTransaction: 'str bool',
getReceivedByAccount: 'str int',
getReceivedByAddress: 'str int',
getSpentInfo: 'obj',
Expand Down Expand Up @@ -349,12 +420,16 @@ function generateRPCMethods(constructor, apiCalls, rpc) {
id: getRandomId(),
});
} else {
rpc.call(this, {
path,
method: methodName,
params: slice(slicedArguments, 0, slicedArguments.length - 1),
id: getRandomId(),
}, arguments[arguments.length - 1]);
rpc.call(
this,
{
path,
method: methodName,
params: slice(slicedArguments, 0, slicedArguments.length - 1),
id: getRandomId(),
},
arguments[arguments.length - 1]
);
}
};
}
Expand All @@ -368,16 +443,16 @@ function generateRPCMethods(constructor, apiCalls, rpc) {
},
int_str(arg) {
if (typeof arg === 'number') {
return parseFloat(arg)
return parseFloat(arg);
}

return arg.toString()
return arg.toString();
},
float(arg) {
return parseFloat(arg);
},
bool(arg) {
return (arg === true || arg == '1' || arg == 'true' || arg.toString().toLowerCase() == 'true');
return String(arg).toLowerCase() === 'true' || arg > 0;
},
obj(arg) {
if (typeof arg === 'string') {
Expand Down Expand Up @@ -408,6 +483,12 @@ function getRandomId() {
return parseInt(Math.random() * 100000);
}

function sleep(ms) {
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
}

generateRPCMethods(RpcClient, RpcClient.callspec, rpc);

module.exports = RpcClient;
Loading
Loading