Comparing version 0.1.7 to 0.1.8
13
index.js
@@ -36,6 +36,14 @@ const url = require('url') | ||
constructor (auth, inputApiUrl = defaultApiUrl) { | ||
if (auth === undefined || auth.apiKey === undefined) { | ||
if (auth === undefined) { | ||
throw new TypeError('Please provide auth options.') | ||
} | ||
if (auth.apiKey === undefined) { | ||
throw new TypeError('Please provide an apiKey auth option.') | ||
} | ||
if (auth.userEmail === undefined) { | ||
throw new TypeError('Please provide an userEmail auth option.') | ||
} | ||
const apiUrl = url.parse(inputApiUrl) | ||
@@ -46,2 +54,3 @@ if (apiUrl.hostname === null) { | ||
this.userEmail = auth.userEmail | ||
this.apiKey = auth.apiKey | ||
@@ -59,3 +68,3 @@ this.apiUrl = apiUrl | ||
.then(uuid => { | ||
return poller.do(uuid, this.apiKey, this.apiUrl) | ||
return poller.do(uuid, this.apiKey, this.apiUrl, undefined, options.timeout) | ||
}).then(issues => { | ||
@@ -62,0 +71,0 @@ resolve(issues) |
@@ -1,3 +0,18 @@ | ||
exports.do = (uuid, apiKey, apiUrl, pollStep = 1000) => { | ||
return new Promise((resolve, reject) => { | ||
exports.do = (uuid, apiKey, apiUrl, pollStep = 1000, timeout = 10000) => { | ||
let pollIntervalID = null | ||
let timeoutID = null | ||
const clearActions = () => { | ||
clearTimeout(timeoutID) | ||
clearInterval(pollIntervalID) | ||
} | ||
const timeoutPromise = new Promise((resolve, reject) => { | ||
timeoutID = setTimeout(() => { | ||
clearActions() | ||
reject(new Error(`Timed out in ${timeout} ms.`)) | ||
}, timeout) | ||
}) | ||
const pollPromise = new Promise((resolve, reject) => { | ||
const lib = apiUrl.protocol === 'http:' ? require('http') : require('https') | ||
@@ -18,7 +33,7 @@ const getOptions = { | ||
if (res.statusCode === 401) { | ||
clearInterval(intervalID) | ||
clearActions() | ||
reject(new Error(`Unauthorized analysis request, API key: ${this.apiKey}`)) | ||
} | ||
if (res.statusCode === 500) { | ||
clearInterval(intervalID) | ||
clearActions() | ||
reject(new Error('received error 500 from API server')) | ||
@@ -34,7 +49,7 @@ } | ||
} catch (err) { | ||
clearInterval(intervalID) | ||
clearActions() | ||
reject(err) | ||
} | ||
if (res.statusCode === 200) { | ||
clearInterval(intervalID) | ||
clearActions() | ||
resolve(data) | ||
@@ -46,4 +61,9 @@ } | ||
} | ||
const intervalID = setInterval(getFunc, pollStep) | ||
pollIntervalID = setInterval(getFunc, pollStep) | ||
}) | ||
return Promise.race([ | ||
timeoutPromise, | ||
pollPromise | ||
]) | ||
} |
{ | ||
"name": "armlet", | ||
"version": "0.1.7", | ||
"version": "0.1.8", | ||
"description": "A Mythril Platform API client.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -1,4 +0,4 @@ | ||
[![CircleCI](https://circleci.com/gh/fgimenez/armlet.svg?style=svg&circle-token=3794de647a820eabf62e091c80d761a722b17b0c)](https://circleci.com/gh/fgimenez/armlet) | ||
[![CircleCI](https://circleci.com/gh/ConsenSys/armlet.svg?style=svg)](https://circleci.com/gh/ConsenSys/armlet) | ||
# Armlet, a Mythril API client | ||
# Armlet, a Mythril Platform API client | ||
@@ -14,12 +14,22 @@ Armlet is a Node.js client for the Mythril Platform API. | ||
Here is a small example of how you might use this client. For | ||
demonstration purposes, we'll set an Mythril Platform API key and | ||
EMAIL as environment variables: | ||
```console | ||
$ export MYTHRIL_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
$ export EMAIL=me@example.com | ||
``` | ||
Then get the Mythril Platform analysis results with the promise returned by | ||
the exposed function: | ||
```javascript | ||
const { Client } = require('armlet') | ||
const armlet = require('armlet') | ||
const client = new armlet.Client( | ||
{ | ||
apiKey: process.env.MYTHRIL_API_KEY, | ||
userEmail: process.env.EMAIL // adjust this | ||
}) | ||
... | ||
const client = new Client({apiKey: myApiKey}) | ||
client.analyze(myBytecode) | ||
client.analyze({bytecode: '0xf6'}) | ||
.then(issues => { | ||
@@ -31,2 +41,17 @@ console.log(issues) | ||
``` | ||
You can also specify the timeout in milliseconds to wait for the analysis to be | ||
done (the default is 10 seconds). For instance, to wait up to 5 seconds: | ||
```javascript | ||
client.analyze({bytecode: <contract_bytecode>, timeout: 5000}) | ||
.then(issues => { | ||
console.log(issues) | ||
}).catch(err => { | ||
console.log(err) | ||
}) | ||
``` | ||
See the example directory for some simple but runnable examples of how | ||
to use the client. | ||
For more info join the Mythril community at [Discord](https://discord.gg/kktn8Wt). |
@@ -15,2 +15,3 @@ const analyze = require('../index') | ||
const apiKey = 'my-apikey' | ||
const userEmail = 'my-userEmail' | ||
@@ -62,11 +63,15 @@ describe('#armlet', () => { | ||
it('require an apiKey auth option', () => { | ||
(() => new Client()).should.throw(TypeError) | ||
(() => new Client({userEmail: userEmail})).should.throw(TypeError) | ||
}) | ||
it('require an userEmail auth option', () => { | ||
(() => new Client({apiKey: apiKey})).should.throw(TypeError) | ||
}) | ||
it('require a valid apiUrl if given', () => { | ||
(() => new Client({apiKey: apiKey}, 'not-a-valid-url')).should.throw(TypeError) | ||
(() => new Client({userEmail: userEmail, apiKey: apiKey}, 'not-a-valid-url')).should.throw(TypeError) | ||
}) | ||
it('initialize apiUrl to a default value if not given', () => { | ||
const instance = new Client({apiKey: apiKey}) | ||
const instance = new Client({userEmail: userEmail, apiKey: apiKey}) | ||
@@ -79,3 +84,3 @@ instance.apiUrl.should.be.deep.equal(analyze.defaultApiUrl) | ||
beforeEach(() => { | ||
this.instance = new Client({apiKey: apiKey}) | ||
this.instance = new Client({userEmail: userEmail, apiKey: apiKey}) | ||
}) | ||
@@ -157,3 +162,3 @@ | ||
beforeEach(() => { | ||
this.instance = new Client({apiKey: apiKey}, apiUrl) | ||
this.instance = new Client({userEmail: userEmail, apiKey: apiKey}, apiUrl) | ||
}) | ||
@@ -207,2 +212,19 @@ | ||
}) | ||
it('should pass timeout option to poller', async () => { | ||
const timeout = 10 | ||
sinon.stub(requester, 'do') | ||
.withArgs(bytecode, apiKey, parsedApiUrl) | ||
.returns(new Promise(resolve => { | ||
resolve(uuid) | ||
})) | ||
sinon.stub(poller, 'do') | ||
.withArgs(uuid, apiKey, parsedApiUrl, undefined, timeout) | ||
.returns(new Promise(resolve => { | ||
resolve(issues) | ||
})) | ||
await this.instance.analyze({bytecode: bytecode, timeout: timeout}).should.eventually.equal(issues) | ||
}) | ||
}) | ||
@@ -209,0 +231,0 @@ }) |
@@ -16,2 +16,3 @@ const nock = require('nock') | ||
const basePath = `/v1/analyses/${uuid}/issues` | ||
const pollStep = 10 | ||
const expectedIssues = [ | ||
@@ -51,3 +52,3 @@ { | ||
await poller.do(uuid, validApiKey, defaultApiUrl, 10).should.eventually.deep.equal(emptyResult) | ||
await poller.do(uuid, validApiKey, defaultApiUrl, pollStep).should.eventually.deep.equal(emptyResult) | ||
}) | ||
@@ -76,3 +77,3 @@ | ||
await poller.do(uuid, validApiKey, defaultApiUrl, 10).should.eventually.deep.equal(expectedIssues) | ||
await poller.do(uuid, validApiKey, defaultApiUrl, pollStep).should.eventually.deep.equal(expectedIssues) | ||
}) | ||
@@ -101,3 +102,3 @@ | ||
await poller.do(uuid, validApiKey, httpApiUrl, 10).should.eventually.deep.equal(expectedIssues) | ||
await poller.do(uuid, validApiKey, httpApiUrl, pollStep).should.eventually.deep.equal(expectedIssues) | ||
}) | ||
@@ -114,3 +115,3 @@ | ||
await poller.do(uuid, validApiKey, defaultApiUrl, 10).should.be.rejectedWith(Error) | ||
await poller.do(uuid, validApiKey, defaultApiUrl, pollStep).should.be.rejectedWith(Error) | ||
}) | ||
@@ -129,3 +130,3 @@ | ||
await poller.do(uuid, inValidApiKey, defaultApiUrl, 10).should.be.rejectedWith(Error) | ||
await poller.do(uuid, inValidApiKey, defaultApiUrl, pollStep).should.be.rejectedWith(Error) | ||
}) | ||
@@ -154,5 +155,20 @@ | ||
await poller.do(uuid, validApiKey, defaultApiUrl, 10).should.be.rejectedWith(SyntaxError) | ||
await poller.do(uuid, validApiKey, defaultApiUrl, pollStep).should.be.rejectedWith(SyntaxError) | ||
}) | ||
it('should reject after a timeout', async () => { | ||
const timeout = 15 | ||
nock(defaultApiUrl.href, { | ||
reqheaders: { | ||
authorization: `Bearer ${validApiKey}` | ||
} | ||
}) | ||
.get(basePath) | ||
.delay(timeout + pollStep) | ||
.reply(200, expectedIssues) | ||
await poller.do(uuid, validApiKey, defaultApiUrl, pollStep, timeout).should.be.rejectedWith(Error, `Timed out in ${timeout} ms.`) | ||
}) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28064
14
664
56