From a53416da4994dab2080af4a4cdd3a6a6cc58b47f Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Wed, 24 Oct 2018 19:01:21 +0200 Subject: [PATCH 1/6] Updating to web3.js 1.0.0, adds initial batch implementation --- angular.json | 8 +- package.json | 6 +- patch.js | 13 ++ .../address-input.component.spec.ts | 9 +- .../channel-table.component.spec.ts | 54 +++-- .../payment-history.component.ts | 9 +- .../token-network-selector.component.spec.ts | 8 +- .../token-network-selector.component.ts | 3 +- src/app/services/raiden.config.ts | 36 ++-- src/app/services/raiden.service.spec.ts | 138 +------------ src/app/services/raiden.service.ts | 186 +++++------------- .../token-info-retriever.service.spec.ts | 57 ++++++ .../services/token-info-retriever.service.ts | 174 ++++++++++++++++ 13 files changed, 382 insertions(+), 319 deletions(-) create mode 100644 patch.js create mode 100644 src/app/services/token-info-retriever.service.spec.ts create mode 100644 src/app/services/token-info-retriever.service.ts diff --git a/angular.json b/angular.json index a72940ad..2c9fa279 100644 --- a/angular.json +++ b/angular.json @@ -27,9 +27,7 @@ "src/styles.css", "src/webui-app-theme.scss" ], - "scripts": [ - "node_modules/web3/dist/web3.min.js" - ] + "scripts": [ ] }, "configurations": { "production": { @@ -75,9 +73,7 @@ "karmaConfig": "./karma.conf.js", "polyfills": "src/polyfills.ts", "tsConfig": "src/tsconfig.spec.json", - "scripts": [ - "node_modules/web3/dist/web3.min.js" - ], + "scripts": [ ], "styles": [ "src/styles.css" ], diff --git a/package.json b/package.json index 69e0d241..2ed0cd8d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "build:prod": "ng build --prod --aot", "test": "ng test", "lint": "ng lint", - "e2e": "ng e2e" + "e2e": "ng e2e", + "postinstall": "node patch.js" }, "private": true, "dependencies": { @@ -36,7 +37,7 @@ "ngx-clipboard": "11.1.3", "ngx-toastr": "^9.0.2", "rxjs": "^6.2.2", - "web3": "0.20.6", + "web3": "^1.0.0-beta.36", "zone.js": "^0.8.26" }, "devDependencies": { @@ -47,6 +48,7 @@ "@types/jasmine": "~2.8.8", "@types/jasminewd2": "~2.0.3", "@types/node": "10.7.1", + "@types/web3": "^1.0.11", "codelyzer": "^4.4.4", "jasmine-core": "^3.2.1", "jasmine-spec-reporter": "~4.2.1", diff --git a/patch.js b/patch.js new file mode 100644 index 00000000..0ae1e8bb --- /dev/null +++ b/patch.js @@ -0,0 +1,13 @@ +const fs = require('fs'); +const f = 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js'; + +fs.readFile(f, 'utf8', function (err, data) { + if (err) { + return console.log(err); + } + const result = data.replace(/node: false/g, 'node: {crypto: true, stream: true}'); + + fs.writeFile(f, result, 'utf8', function (err) { + if (err) return console.log(err); + }); +}); \ No newline at end of file diff --git a/src/app/components/address-input/address-input.component.spec.ts b/src/app/components/address-input/address-input.component.spec.ts index 1877c7ed..98c74df7 100644 --- a/src/app/components/address-input/address-input.component.spec.ts +++ b/src/app/components/address-input/address-input.component.spec.ts @@ -17,8 +17,6 @@ describe('AddressInputComponent', () => { let fixture: ComponentFixture; const nonEip55Address = '0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359'; - const errorPlaceholder = 'Token network'; - let input: HTMLInputElement; let mockConfig: MockConfig; @@ -26,7 +24,7 @@ describe('AddressInputComponent', () => { const debugElement = fixture.debugElement.query(By.directive(MatError)); const element = debugElement.query(By.css('span')); const span = element.nativeElement as HTMLSpanElement; - return span.innerText; + return span.innerText.trim(); } function mockInput(inputValue: string) { @@ -90,7 +88,7 @@ describe('AddressInputComponent', () => { it('should show error when address is not in checksum format', () => { component.displayIdenticon = true; - mockConfig.web3.checksumAddress = '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359'; + mockConfig.updateChecksumAddress('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359'); fixture.detectChanges(); mockInput(nonEip55Address); @@ -117,7 +115,8 @@ describe('AddressInputComponent', () => { }); it('should show an error if the address is own address', () => { - mockConfig.web3.isChecksum = true; + mockConfig.setIsChecksum(true); + const service = TestBed.get(RaidenService); const address = '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359'; spyOnProperty(service, 'raidenAddress', 'get').and.returnValue(address); diff --git a/src/app/components/channel-table/channel-table.component.spec.ts b/src/app/components/channel-table/channel-table.component.spec.ts index 4834974a..65553fce 100644 --- a/src/app/components/channel-table/channel-table.component.spec.ts +++ b/src/app/components/channel-table/channel-table.component.spec.ts @@ -9,6 +9,8 @@ import { ToastrModule, ToastrService } from 'ngx-toastr'; import { EMPTY } from 'rxjs'; import { of } from 'rxjs/internal/observable/of'; import { delay, startWith } from 'rxjs/operators'; +// @ts-ignore +import * as Web3 from 'web3'; import { CdkDetailRowDirective } from '../../directives/cdk-detail-row.directive'; import { Channel } from '../../models/channel'; import { UserToken } from '../../models/usertoken'; @@ -31,26 +33,42 @@ import { TokenNetworkSelectorComponent } from '../token-network-selector/token-n import { ChannelTableComponent } from './channel-table.component'; import Spy = jasmine.Spy; +class MockWeb3 extends Web3 { + isChecksum = false; + checksumAddress = ''; + + constructor() { + super(); + + const mockWeb3 = this; + this.eth.getBlockNumber = function () { + return Promise.resolve(3694423); + }; + this.utils.checkAddressChecksum = function () { + return mockWeb3.isChecksum; + }; + + this.utils.toChecksumAddress = function () { + return mockWeb3.checksumAddress; + }; + } + +} + export class MockConfig extends RaidenConfig { + public web3: Web3 = new MockWeb3(); + + updateChecksumAddress(address: string): void { + this.mock.checksumAddress = address; + } + + private get mock(): MockWeb3 { + return (this.web3 as MockWeb3); + } - public web3: any = { - isChecksum: false, - checksumAddress: '', - eth: { - latestBlock: 3694423, - contract: () => { - }, - getBlockNumber: () => { - - } - }, - isChecksumAddress(value) { - return this.isChecksum; - }, - toChecksumAddress(value) { - return this.checksumAddress; - } - }; + setIsChecksum(isChecksum: boolean): void { + this.mock.isChecksum = isChecksum; + } } describe('ChannelTableComponent', () => { diff --git a/src/app/components/payment-history/payment-history.component.ts b/src/app/components/payment-history/payment-history.component.ts index 1bf8fa1f..e7ad0ded 100644 --- a/src/app/components/payment-history/payment-history.component.ts +++ b/src/app/components/payment-history/payment-history.component.ts @@ -57,15 +57,16 @@ export class PaymentHistoryComponent implements OnInit, OnDestroy { private indenticonCache: IdenticonCacheService ) { this.partnerInformation$ = this.route.queryParamMap.pipe( - concatMap((params: ParamMap) => { + map((params: ParamMap) => { const tokenAddress = params.get('token_address'); const partnerAddress = params.get('partner_address'); - return this.raidenService.getUserToken(tokenAddress).pipe(map(value => ({ + const token = this.raidenService.getUserToken(tokenAddress); + return { tokenAddress: tokenAddress, partnerAddress: partnerAddress, - token: value - }))); + token: token + }; }), tap(x => this._decimals = x.token.decimals), share() diff --git a/src/app/components/token-network-selector/token-network-selector.component.spec.ts b/src/app/components/token-network-selector/token-network-selector.component.spec.ts index d61cb34e..3df10d05 100644 --- a/src/app/components/token-network-selector/token-network-selector.component.spec.ts +++ b/src/app/components/token-network-selector/token-network-selector.component.spec.ts @@ -60,7 +60,7 @@ describe('TokenNetworkSelectorComponent', () => { const debugElement = fixture.debugElement.query(By.directive(MatError)); const element = debugElement.query(By.css('span')); const span = element.nativeElement as HTMLSpanElement; - return span.innerText; + return span.innerText.trim(); } function mockInput(inputValue: string = '') { @@ -115,7 +115,7 @@ describe('TokenNetworkSelectorComponent', () => { const inputDebugElement = fixture.debugElement.query(By.css('input[type=text]')); input = inputDebugElement.nativeElement as HTMLInputElement; - mockConfig.web3.isChecksum = true; + mockConfig.setIsChecksum(true); }); it('should create', () => { @@ -162,8 +162,8 @@ describe('TokenNetworkSelectorComponent', () => { }); it('should show error when address is not in checksum format', () => { - mockConfig.web3.isChecksum = false; - mockConfig.web3.checksumAddress = '0xeB7f4BBAa1714F3E5a12fF8B681908D7b98BD195'; + mockConfig.setIsChecksum(false); + mockConfig.updateChecksumAddress('0xeB7f4BBAa1714F3E5a12fF8B681908D7b98BD195'); mockInput('0xeb7f4bbaa1714f3e5a12ff8b681908d7b98bd195'); fixture.detectChanges(); expect(errorMessage()).toBe('Address is not in checksum format: 0xeB7f4BBAa1714F3E5a12fF8B681908D7b98BD195'); diff --git a/src/app/components/token-network-selector/token-network-selector.component.ts b/src/app/components/token-network-selector/token-network-selector.component.ts index 09bd0988..5d36fcb8 100644 --- a/src/app/components/token-network-selector/token-network-selector.component.ts +++ b/src/app/components/token-network-selector/token-network-selector.component.ts @@ -90,7 +90,8 @@ export class TokenNetworkSelectorComponent implements OnInit, ControlValueAccess const errors = this.tokenFc.errors; if (!errors) { - this.raidenService.getUserToken(c.value).subscribe(value => this.valueChanged.emit(value)); + const userToken = this.raidenService.getUserToken(c.value); + this.valueChanged.emit(userToken); } return errors; } diff --git a/src/app/services/raiden.config.ts b/src/app/services/raiden.config.ts index a5d16a84..1d06cde4 100644 --- a/src/app/services/raiden.config.ts +++ b/src/app/services/raiden.config.ts @@ -1,10 +1,9 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { EnvironmentType } from './enviroment-type.enum'; - import { SharedService } from './shared.service'; - -declare var Web3; +// @ts-ignore +import * as Web3 from 'web3'; interface RDNConfig { raiden: string; @@ -34,34 +33,35 @@ const default_config: RDNConfig = { export class RaidenConfig { public config: RDNConfig = default_config; public api: string; - public web3: any; + public web3: Web3; constructor( private http: HttpClient, private sharedService: SharedService - ) { } + ) { + } - load(url: string) { - return new Promise((resolve) => { + load(url: string): Promise { + return new Promise((resolve, reject) => { this.http.get(url) .subscribe((config) => { this.config = Object.assign({}, default_config, config); this.api = this.config.raiden; + this.sharedService.httpTimeout = this.config.http_timeout; + this.web3 = new Web3(new Web3.providers.HttpProvider(this.config.web3, 2000)); // make a simple test call to web3 - this.web3.version.getNetwork((err, res) => { - if (err) { - console.error(`Invalid web3 endpoint, switching to fallback ${this.config.web3_fallback}`, err); - this.config.web3 = this.config.web3_fallback; - this.web3 = new Web3(new Web3.providers.HttpProvider(this.config.web3)); - } else { - // on success, reconstruct without timeout, - // because of long (events) running requests - this.web3 = new Web3(new Web3.providers.HttpProvider(this.config.web3)); - } - this.sharedService.httpTimeout = this.config.http_timeout; + + this.web3.eth.net.getId().catch(reason => { + console.error(`Invalid web3 endpoint, switching to fallback ${this.config.web3_fallback}`, reason); + this.config.web3 = this.config.web3_fallback; + this.web3 = new Web3(new Web3.providers.HttpProvider(this.config.web3)); + reject(reason); + }).then(() => { + this.web3 = new Web3(new Web3.providers.HttpProvider(this.config.web3)); resolve(); }); + }); }); } diff --git a/src/app/services/raiden.service.spec.ts b/src/app/services/raiden.service.spec.ts index 3bed49d3..071215dc 100644 --- a/src/app/services/raiden.service.spec.ts +++ b/src/app/services/raiden.service.spec.ts @@ -8,8 +8,10 @@ import { Channel } from '../models/channel'; import { UserToken } from '../models/usertoken'; import { RaidenConfig } from './raiden.config'; -import { CallbackFunc, RaidenService } from './raiden.service'; +import { RaidenService } from './raiden.service'; import { SharedService } from './shared.service'; +import { TokenInfoRetrieverService } from './token-info-retriever.service'; +import Spy = jasmine.Spy; describe('RaidenService', () => { @@ -21,6 +23,8 @@ describe('RaidenService', () => { let service: RaidenService; + let retrieverSpy: Spy; + const channel1: Channel = { state: 'opened', channel_identifier: 1, @@ -57,7 +61,8 @@ describe('RaidenService', () => { useClass: MockConfig }, RaidenService, - SharedService + SharedService, + TokenInfoRetrieverService ] }); @@ -67,6 +72,8 @@ describe('RaidenService', () => { sharedService = TestBed.get(SharedService); service = TestBed.get(RaidenService); + retrieverSpy = spyOn(TestBed.get(TokenInfoRetrieverService), 'createBatch'); + spyOn(sharedService, 'error'); spyOn(service, 'raidenAddress$').and.returnValue(of('0x504300C525CbE91Adb3FE0944Fe1f56f5162C75C')); }); @@ -148,24 +155,7 @@ describe('RaidenService', () => { balance: 20 }; - service.tokenContract = { - at: () => ({ - name: (callback: CallbackFunc) => { - callback(null, token.name); - }, - balanceOf: (address: String, callback: CallbackFunc) => { - callback(null, { - toNumber: () => token.balance - }); - }, - symbol: (callback: CallbackFunc) => { - callback(null, token.symbol); - }, - decimals: (callback: CallbackFunc) => { - callback(null, new BigNumber(token.decimals)); - } - }) - }; + spyOn(service, 'getUserToken').and.returnValue(of(token)); service.getChannels().subscribe((channels: Array) => { channels.forEach(value => { @@ -190,114 +180,6 @@ describe('RaidenService', () => { }); tick(); - - mockHttp.expectOne({ - url: `${endpoint}/address`, - method: 'GET' - }).flush({ - own_address: '0x504300C525CbE91Adb3FE0944Fe1f56f5162C75C' - }, { - status: 200, - statusText: 'All Good' - }); - flush(); - })); - - it('should show an error message for JSON RPC errors while fetching channels', fakeAsync(() => { - - const rpcError = Error('Invalid JSON RPC response'); - - // noinspection JSUnusedLocalSymbols - service.tokenContract = { - at: () => ({ - name: (callback: CallbackFunc) => { - throw rpcError; - }, - balanceOf: (address: String, callback: CallbackFunc) => { - throw rpcError; - }, - symbol: (callback: CallbackFunc) => { - throw rpcError; - } - }) - }; - - service.getChannels().subscribe(() => { - fail('Call should fail with error'); - }, (error) => { - expect(error).toBeTruthy(); - }); - - mockHttp.expectOne({ - url: `${endpoint}/channels`, - method: 'GET' - }).flush([ - channel1, - channel2 - ], { - status: 200, - statusText: 'All good' - }); - - mockHttp.expectOne({ - url: `${endpoint}/address`, - method: 'GET' - }).flush({ - own_address: '0x504300C525CbE91Adb3FE0944Fe1f56f5162C75C' - }, { - status: 200, - statusText: 'All Good' - }); - - expect(sharedService.error).toHaveBeenCalledTimes(1); - - // @ts-ignore - const payload = sharedService.error.calls.first().args[0]; - - expect(payload.title).toBe('Raiden Error', 'It should be a Raiden Error'); - expect(payload.description).toContain('Could not access the JSON-RPC endpoint'); - - flush(); - })); - - - it('should show an error message for JSON RPC errors when fetching a token', fakeAsync(() => { - const rpcError = Error('Invalid JSON RPC response'); - - // noinspection JSUnusedLocalSymbols - service.tokenContract = { - at: () => ({ - name: (callback: CallbackFunc) => { - throw rpcError; - }, - balanceOf: (address: String, callback: CallbackFunc) => { - throw rpcError; - }, - symbol: (callback: CallbackFunc) => { - throw rpcError; - } - }) - }; - - service.getUserToken(tokenAddress, false).subscribe(() => { - fail('There should be an error'); - }, (error) => { - expect(error).toBeTruthy(); - expect(error.message).toContain('Could not access the JSON-RPC endpoint'); - }); - - tick(); - - mockHttp.expectOne({ - url: `${endpoint}/address`, - method: 'GET' - }).flush({ - own_address: '0x504300C525CbE91Adb3FE0944Fe1f56f5162C75C' - }, { - status: 200, - statusText: 'All Good' - }); - flush(); })); }); diff --git a/src/app/services/raiden.service.ts b/src/app/services/raiden.service.ts index e3817aca..d262a030 100644 --- a/src/app/services/raiden.service.ts +++ b/src/app/services/raiden.service.ts @@ -1,20 +1,20 @@ import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http'; import { Injectable, NgZone } from '@angular/core'; -import { bindNodeCallback, combineLatest, from, Observable, of, throwError, zip } from 'rxjs'; -import { catchError, first, flatMap, map, share, shareReplay, switchMap, tap, toArray } from 'rxjs/operators'; +import { from, Observable, of, throwError, zip } from 'rxjs'; +import { fromPromise } from 'rxjs/internal-compatibility'; +import { catchError, first, flatMap, map, shareReplay, switchMap, tap, toArray } from 'rxjs/operators'; +import { Block } from 'web3/eth/types'; import { Channel } from '../models/channel'; import { Connections } from '../models/connection'; import { Event, EventsParam } from '../models/event'; import { PaymentEvent } from '../models/payment-event'; import { SwapToken } from '../models/swaptoken'; - import { UserToken } from '../models/usertoken'; import { amountFromDecimal, amountToDecimal } from '../utils/amount.converter'; import { EnvironmentType } from './enviroment-type.enum'; - import { RaidenConfig } from './raiden.config'; import { SharedService } from './shared.service'; -import { tokenabi } from './tokenabi'; +import { TokenInfoRetrieverService } from './token-info-retriever.service'; export type CallbackFunc = (error: Error, result: any) => void; @@ -23,18 +23,16 @@ export type CallbackFunc = (error: Error, result: any) => void; }) export class RaidenService { - public tokenContract: any; readonly raidenAddress$: Observable; private userTokens: { [id: string]: UserToken | null } = {}; - private defaultDecimals = 18; constructor( private http: HttpClient, private zone: NgZone, private raidenConfig: RaidenConfig, private sharedService: SharedService, + private tokenInfoRetriever: TokenInfoRetrieverService ) { - this.tokenContract = this.raidenConfig.web3.eth.contract(tokenabi); this.raidenAddress$ = this.http.get<{ our_address: string }>(`${this.raidenConfig.api}/address`).pipe( map((data) => this._raidenAddress = data.our_address), catchError((error) => this.handleError(error)), @@ -58,62 +56,65 @@ export class RaidenService { } getBlockNumber(): Observable { - return bindNodeCallback((cb: CallbackFunc) => - this.raidenConfig.web3.eth.getBlockNumber(this.zoneEncap(cb)))(); + return fromPromise(this.raidenConfig.web3.eth.getBlockNumber()); } public checkChecksumAddress(address: string): boolean { - return this.raidenConfig.web3.isChecksumAddress(address); + return this.raidenConfig.web3.utils.checkAddressChecksum(address); } public toChecksumAddress(address: string): string { - return this.raidenConfig.web3.toChecksumAddress(address); + return this.raidenConfig.web3.utils.toChecksumAddress(address); } public getChannels(): Observable> { - return this.http.get>(`${this.raidenConfig.api}/channels`).pipe( + let tokens$: Observable; + if (Object.keys(this.userTokens).length === 0) { + tokens$ = this.getTokens(true); + } else { + tokens$ = of(null); + } + + const fetchChannels = this.http.get>(`${this.raidenConfig.api}/channels`).pipe( flatMap((channels: Array) => from(channels)), - flatMap((channel: Channel) => { - return this.getUserToken(channel.token_address).pipe( - map((token: UserToken | null) => { - channel.userToken = token; - return channel; - }) - ); + map((channel: Channel) => { + channel.userToken = this.getUserToken(channel.token_address); + return channel; }), toArray(), catchError((error) => this.handleError(error)), ); + + return tokens$.pipe(flatMap(() => fetchChannels)); } public getTokens(refresh: boolean = false): Observable> { - const tokens$ = this.http.get>(`${this.raidenConfig.api}/tokens`); + const tokens$: Observable<{ [address: string]: UserToken }> = this.http.get>(`${this.raidenConfig.api}/tokens`) + .pipe(flatMap(tokenAddresses => fromPromise(this.tokenInfoRetriever.createBatch(tokenAddresses, this._raidenAddress)))); const connections$ = refresh ? this.http.get(`${this.raidenConfig.api}/connections`) : of(null); - return combineLatest(tokens$, connections$).pipe( - map(([tokenArray, connections]): Array> => - tokenArray.map((token) => - this.getUserToken(token, refresh).pipe( - map((userToken) => userToken && connections ? - Object.assign( - userToken, - {connected: connections[token]} - ) : userToken - ) - ) - ) - ), - switchMap((obsArray) => obsArray && obsArray.length ? - zip(...obsArray).pipe(first()) : - of([]) - ), - map((tokenArray) => tokenArray.filter((token) => !!token)), - catchError((error) => this.handleError(error)), - ); + return zip(tokens$, connections$).pipe(map(([userTokens, connections]) => { + Object.keys(userTokens).forEach(address => { + const token = userTokens[address]; + if (connections) { + token.connected = connections[address]; + } + + const cachedToken = this.userTokens[address]; + if (cachedToken) { + this.userTokens[address] = Object.assign(cachedToken, token); + } else { + this.userTokens[address] = token; + } + }); + + return Object.values(this.userTokens); + })); } + public getChannel(tokenAddress: string, partnerAddress: string): Observable { return this.http.get( `${this.raidenConfig.api}/channels/${tokenAddress}/${partnerAddress}`, @@ -250,14 +251,13 @@ export class RaidenService { `${this.raidenConfig.api}/tokens/${tokenAddress}`, {}, ).pipe( - switchMap(() => this.getUserToken(tokenAddress).pipe( - map((userToken) => { - if (userToken === null) { - throw new Error(`No contract on address: ${tokenAddress}`); - } - return userToken; - }), - )), + map(() => { + const userToken = this.getUserToken(tokenAddress); + if (userToken === null) { + throw new Error(`No contract on address: ${tokenAddress}`); + } + return userToken; + }), tap((userToken: UserToken) => { this.sharedService.success({ title: 'Token registered', @@ -347,94 +347,14 @@ export class RaidenService { } public blocknumberToDate(block: number): Observable { - return bindNodeCallback((b: number, cb: CallbackFunc) => - this.raidenConfig.web3.eth.getBlock(b, this.zoneEncap(cb)) - )(block).pipe( - map((blk) => new Date(blk.timestamp * 1000)), + return fromPromise(this.raidenConfig.web3.eth.getBlock(block)).pipe( + map((blk: Block) => new Date(blk.timestamp * 1000)), first(), ); } - public getUserToken( - tokenAddress: string, - refresh: boolean = false, - ): Observable { - - const tokenContractInstance = this.tokenContract.at(tokenAddress); - const tokenMap = this.userTokens; - const userToken: UserToken | null | undefined = tokenMap[tokenAddress]; - - const balance$: Observable = this.raidenAddress$.pipe( - flatMap(value => { - return bindNodeCallback((addr: string, cb: CallbackFunc) => - tokenContractInstance.balanceOf(addr, this.zoneEncap(cb)) - )(value).pipe( - map((balance) => balance.toNumber()) - ); - }) - ); - - if (userToken === undefined) { - const decimals$: Observable = bindNodeCallback((cb: CallbackFunc) => - tokenContractInstance.decimals(this.zoneEncap(cb)) - )().pipe( - map(value => value.toNumber()), - catchError(() => of(this.defaultDecimals)) - ); - - const symbol$: Observable = bindNodeCallback((cb: CallbackFunc) => - tokenContractInstance.symbol(this.zoneEncap(cb)) - )().pipe(catchError(() => of(''))); - - const name$: Observable = bindNodeCallback((cb: CallbackFunc) => - tokenContractInstance.name(this.zoneEncap(cb)) - )().pipe(catchError(() => of(''))); - - return zip( - symbol$, - name$, - balance$, - decimals$ - ).pipe( - map(([symbol, name, balance, decimals]): UserToken => { - return ({ - address: tokenAddress, - symbol, - name, - balance, - decimals: decimals - }); - }), - tap((token) => tokenMap[tokenAddress] = token), - share(), - catchError((error) => { - const message = (error as Error).message; - if (message.startsWith('Invalid JSON RPC response')) { - const errorMessage = 'Could not access the JSON-RPC endpoint, ' + - 'Please make sure that CORS for this domain is enabled on your ethereum client.'; - return throwError(Error(errorMessage)); - } - return throwError(error); - }) - ); - - } else if (refresh && userToken !== null) { - return balance$.pipe( - map((balance) => { - if (balance === null) { - return null; - } - userToken.balance = balance; - return userToken; - }), - ); - } else { - return of(userToken); - } - } - - private zoneEncap(cb: CallbackFunc): CallbackFunc { - return (err, res) => this.zone.run(() => cb(err, res)); + public getUserToken(tokenAddress: string): UserToken | null { + return this.userTokens[tokenAddress]; } private handleError(error: Response | Error | any) { diff --git a/src/app/services/token-info-retriever.service.spec.ts b/src/app/services/token-info-retriever.service.spec.ts new file mode 100644 index 00000000..cf1803e2 --- /dev/null +++ b/src/app/services/token-info-retriever.service.spec.ts @@ -0,0 +1,57 @@ +import { HttpClientModule } from '@angular/common/http'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { TestBed, async } from '@angular/core/testing'; +import { MockConfig } from '../components/channel-table/channel-table.component.spec'; +import { RaidenConfig } from './raiden.config'; +import { SharedService } from './shared.service'; + +import { TokenInfoRetrieverService } from './token-info-retriever.service'; +// @ts-ignore +import * as Web3 from 'web3'; + +describe('TokenInfoRetriever', () => { + let service: TokenInfoRetrieverService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + HttpClientModule, + HttpClientTestingModule + ], + providers: [ + TokenInfoRetrieverService, + SharedService, + { + provide: RaidenConfig, + useClass: MockConfig + }, + ] + }); + + const config = TestBed.get(RaidenConfig); + config.web3 = new Web3(); + service = TestBed.get(TokenInfoRetrieverService); + }); + + it('should be truthy', async(() => { + expect(service).toBeTruthy(); + })); + + it('should reject promise if there is a JSON RPC response error', (done) => { + const promise = service.createBatch([ + '0x0f114a1e9db192502e7856309cc899952b3db1ed' + ], '0x82641569b2062B545431cF6D7F0A418582865ba7'); + promise.then(value => { + fail(value); + done(); + }).catch(reason => { + const error = (reason as Error); + expect(error.message).toContain('Invalid JSON RPC response'); + done(); + }); + }); + + it('should ', () => { + + }); +}); diff --git a/src/app/services/token-info-retriever.service.ts b/src/app/services/token-info-retriever.service.ts new file mode 100644 index 00000000..ca2ac008 --- /dev/null +++ b/src/app/services/token-info-retriever.service.ts @@ -0,0 +1,174 @@ +import { Injectable } from '@angular/core'; +import BigNumber from 'bignumber.js'; +import Contract from 'web3/eth/contract'; +import { UserToken } from '../models/usertoken'; +import { RaidenConfig } from './raiden.config'; +import { CallbackFunc } from './raiden.service'; +import { tokenabi } from './tokenabi'; +// @ts-ignore +import * as Web3 from 'web3'; + +function override(object, methodName, callback) { + object[methodName] = callback(object[methodName]); +} + +@Injectable({ + providedIn: 'root' +}) +export class TokenInfoRetrieverService { + private tokenContract: Contract; + private readonly web3: Web3; + + constructor(private raidenConfig: RaidenConfig) { + this.web3 = this.raidenConfig.web3; + this.tokenContract = new this.web3.eth.Contract(tokenabi) as Contract; + } + + createBatch( + tokenAddresses: string[], + raidenAddress: string + ): Promise<{ [address: string]: UserToken }> { + const web3 = this.web3; + + const userTokens: { [address: string]: UserToken } = {}; + + return new Promise<{ [address: string]: UserToken }>((resolve, reject) => { + const timeout = setTimeout(() => reject(new Error(`timeout after 60000 ms`)), 60000); + let done = false; + try { + let unprocessed = 0; + + const pending = function () { + unprocessed += 1; + }; + + const complete = function () { + clearTimeout(timeout); + unprocessed -= 1; + if (done && unprocessed === 0) { + resolve(userTokens); + } + }; + + let batch = new web3.BatchRequest(); + + tokenAddresses.forEach(tokenAddress => { + batch = this.addTokenToBatch(tokenAddress, raidenAddress, userTokens, batch, pending, complete); + // @ts-ignore + if (batch.requests.length >= 800) { + batch.execute(); + batch = new web3.BatchRequest(); + } + }); + + done = true; + + // @ts-ignore + if (batch.requests.length > 0) { + batch.execute(); + } + } catch (e) { + reject(e); + } + }); + + } + + private createToken(address: string): UserToken { + return { + address, + name: '', + symbol: '', + decimals: 18, + balance: 0 + }; + } + + private addTokenToBatch( + tokenAddress: string, + raidenAddress: string, + tokens: { [address: string]: UserToken | null }, + batch, + pending: () => void, + complete: () => void + ) { + this.tokenContract.options.address = tokenAddress; + const contract = this.tokenContract; + + const updateValue = (property: string, defaultValue: any, error: Error, result: any) => { + if (error && error.message && error.message.startsWith('Invalid JSON RPC response')) { + throw error; + } + complete(); + let token = tokens[tokenAddress]; + let value: any; + + if (error) { + console.error(error); + value = defaultValue; + } else { + if (result instanceof BigNumber) { + value = (result as BigNumber).toNumber(); + } else { + value = result; + } + } + + if (!token) { + token = this.createToken(tokenAddress); + } + + token[property] = value; + tokens[tokenAddress] = token; + }; + + const balanceMethod = contract.methods.balanceOf; + if (balanceMethod) { + const callback: CallbackFunc = (error: Error, result: any) => updateValue('balance', 0, error, result); + // @ts-ignore + const request = balanceMethod(raidenAddress).call.request(callback); + batch.add(request); + pending(); + } + + if (!tokens[tokenAddress]) { + + const addRequest = (property, defaultResponse) => { + const callback: CallbackFunc = ((error: Error, result: any) => updateValue(property, defaultResponse, error, result)); + const method = contract.methods[property]; + if (method) { + // @ts-ignore + const request = method().call.request(callback); + this.monkeyPatchRequest(request, defaultResponse); + batch.add(request); + pending(); + } + }; + + + addRequest('decimals', 18); + addRequest('name', ''); + addRequest('symbol', ''); + } + + return batch; + } + + private monkeyPatchRequest(request: any, defaultResponse: any): void { + override(request, 'format', function (original) { + return function (output) { + let result: any; + try { + result = original(output); + } catch (e) { + if (e && e.message && e.message.startsWith('Invalid JSON RPC response')) { + throw e; + } + console.error(e); + result = defaultResponse; + } + return result; + }; + }); + } +} From eae6d0c3b5488a1a4733254fbdb5a1f2769125af Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Mon, 3 Dec 2018 18:34:25 +0100 Subject: [PATCH 2/6] Adds BatchManager --- src/app/services/batch-manager.spec.ts | 319 ++++++++++++++++++ src/app/services/batch-manager.ts | 111 ++++++ src/app/services/raiden.service.ts | 4 +- .../token-info-retriever.service.spec.ts | 31 +- .../services/token-info-retriever.service.ts | 203 ++++------- 5 files changed, 510 insertions(+), 158 deletions(-) create mode 100644 src/app/services/batch-manager.spec.ts create mode 100644 src/app/services/batch-manager.ts diff --git a/src/app/services/batch-manager.spec.ts b/src/app/services/batch-manager.spec.ts new file mode 100644 index 00000000..a67e3c15 --- /dev/null +++ b/src/app/services/batch-manager.spec.ts @@ -0,0 +1,319 @@ +import { BatchManager } from "./batch-manager"; +import { hexToString } from 'web3-utils' +import { formatters } from 'web3-core-helpers' +import Spy = jasmine.Spy; + +interface JsonRPCRequest { + format?: any; + jsonrpc: string; + method: string; + params: any[]; + id: number; +} + +interface JsonRPCResponse { + jsonrpc: string; + id: number; + result?: any; + error?: RPRCResponseError; +} + +interface RPRCResponseError { + code: number; + message: string; +} + +interface Provider { + send( + payload: JsonRPCRequest, + callback: (e: Error, val: JsonRPCResponse) => void + ): any; +} + +export class FakeHttpProvider implements Provider { + private countId = 1; + + private response = []; + private error = []; + + public send(payload: JsonRPCRequest, callback: (e: Error, val: JsonRPCResponse) => void) { + + if (payload.id) { + this.countId = payload.id + } + + if (!(payload instanceof Array) || !(payload instanceof Object)) { + throw Error('payload should be either object or array') + } + + const response = this.getResponseOrError('response', payload); + const error = this.getResponseOrError('error', payload); + + // @ts-ignore + setTimeout(() => callback(error, response), 1) + } + + public getResponseOrError(type: any, payload: any | Array): JsonRPCResponse | JsonRPCResponse[] { + let response: JsonRPCResponse | JsonRPCResponse[]; + + if (type === 'error') { + response = this.error.shift(); + } else { + response = this.response.shift() || this.getResponseStub(); + } + + if (response) { + if (response instanceof Array) { + + let currentResponse: JsonRPCResponse[]; + + if (response.length > payload.length) { + currentResponse = response.slice(0, payload.length); + this.response.push(response.slice(payload.length, response.length)); + } else { + currentResponse = response; + } + + response = currentResponse.map((resp, index) => { + resp.id = payload[index] ? payload[index].id : this.countId++; + return resp; + }); + + } else { + response.id = payload.id; + } + + } + + return response; + } + + public injectBatchResults(results: Array, error: boolean = false) { + this.response.push(results.map(value => { + let response: JsonRPCResponse; + + if (error) { + response = this.getErrorStub(); + response.error = value + } else { + response = this.getResponseStub(); + response.result = value; + } + + return response + })) + } + + public injectResult(result: string) { + const response = this.getResponseStub(); + response.result = result; + this.response.push(response) + } + + public injectInvalidResponse(response: object) { + this.response.push(response); + } + + public injectError(error: any) { + const errorStub = this.getErrorStub(); + errorStub.error = error; + this.error.push(errorStub) + } + + private getResponseStub(): JsonRPCResponse { + let countId = this.countId; + return { + jsonrpc: '2.0', + id: countId, + result: null + } + } + + private getErrorStub(): JsonRPCResponse { + let countId = this.countId; + return { + jsonrpc: '2.0', + id: countId, + error: { + code: 50010, + message: 'Invalid Response?' + } + } + } +} + +function getEthCallStub(): JsonRPCRequest { + return { + jsonrpc: '2.0', + id: 3, + method: 'eth_call', + params: [ + { + data: '0x06fdde03', + to: '0xa72fe7fe1f1323586a80c6b631202bb15b0419ab' + }, + 'latest' + ] + } +} + +function getRPCResult(): string { + return "0x0" +} + +describe('BatchManager', () => { + let batchManager: BatchManager; + let httpProvider: FakeHttpProvider; + let providerSpy: Spy; + + beforeEach(() => { + httpProvider = new FakeHttpProvider(); + // @ts-ignore + batchManager = new BatchManager(httpProvider); + providerSpy = spyOn(httpProvider, 'send'); + providerSpy.and.callThrough(); + }); + + it('should throw an exception if there is at least one error in the batch', async () => { + batchManager.add({request: getEthCallStub()}); + batchManager.add({request: getEthCallStub()}); + httpProvider.injectResult(getRPCResult()); + httpProvider.injectError('err'); + + try { + await batchManager.execute(); + fail('There should be no result') + } catch (e) { + expect(e).toBeTruthy("There should be an error thrown") + } + }); + + + it('should process small batch and have the results', async () => { + httpProvider.injectBatchResults([ + getRPCResult(), + getRPCResult() + ]); + + batchManager.add({request: getEthCallStub()}); + batchManager.add({request: getEthCallStub()}); + + let result = await batchManager.execute(); + + expect(result).toBeTruthy('there should be a result'); + expect(result.length).toBe(2, 'there should be two ') + }); + + it('should only call through the http provider for the batch', async () => { + + const results = []; + + let batchSize = 800; + + for (let i = 0; i < batchSize; i++) { + let ethCallStub = getEthCallStub(); + ethCallStub.id = i + 1; + batchManager.add({request: ethCallStub}); + + results.push(getRPCResult()) + } + + httpProvider.injectBatchResults(results); + + let result = await batchManager.execute(); + + expect(result).toBeTruthy('there should be a result'); + expect(result.length).toBe(batchSize, 'there should be 800 results in the batch'); + expect(httpProvider.send).toHaveBeenCalledTimes(1); + }); + + it('should internally split the batch if more than 800 requests are batched', async () => { + const results = []; + + let batchSize = 1600; + + for (let i = 0; i < batchSize; i++) { + let ethCallStub = getEthCallStub(); + ethCallStub.id = i + 1; + batchManager.add({request: ethCallStub}); + + results.push(getRPCResult()) + } + + httpProvider.injectBatchResults(results); + + let result = await batchManager.execute(); + + expect(result).toBeTruthy('there should be a result'); + expect(result.length).toBe(batchSize, 'there should be 1600 results in response'); + expect(httpProvider.send).toHaveBeenCalledTimes(2); + }); + + + it('should fail on Error', async () => { + let ethCallStub = getEthCallStub(); + batchManager.add({request: ethCallStub}); + httpProvider.injectBatchResults([getRPCResult()], true); + + try { + await batchManager.execute(); + fail('there should be no result') + } catch (e) { + expect(e).toBeTruthy(); + } + }); + + it('should fail on an invalid response', async () => { + let ethCallStub = getEthCallStub(); + batchManager.add({request: ethCallStub}); + httpProvider.injectInvalidResponse({ + jsonrpc: '2.0', + id: 2 + }); + + try { + await batchManager.execute(); + fail('there should be no result') + } catch (e) { + expect(e).toMatch('Invalid JSON RPC response') + } + }); + + it('should ignore failure if there is a default value and the formatter throws', async () => { + let ethCallStub = getEthCallStub(); + ethCallStub.format = function () { + throw Error('format failed') + }; + batchManager.add({ + request: ethCallStub, + defaultValue: '' + }); + + httpProvider.injectBatchResults(['0x4d4b520000000000000000000000000000000000000000000000000000000000']); + + let result = await batchManager.execute(); + + expect(result.length).toBe(1); + expect(result[0]).toBe(''); + }); + + it('should fail if there is no default value and the formatter throws', async () => { + let ethCallStub = getEthCallStub(); + ethCallStub.format = function () { + throw Error('format failed') + }; + batchManager.add({ + request: ethCallStub + }); + + httpProvider.injectBatchResults(['0x4d4b520000000000000000000000000000000000000000000000000000000000']); + + try { + await batchManager.execute(); + fail('there should be no result') + } catch (e) { + expect(e).toBeTruthy(); + expect(e.message).toMatch('format failed'); + } + }); +}); \ No newline at end of file diff --git a/src/app/services/batch-manager.ts b/src/app/services/batch-manager.ts new file mode 100644 index 00000000..3317f377 --- /dev/null +++ b/src/app/services/batch-manager.ts @@ -0,0 +1,111 @@ +import { Manager } from 'web3-core-requestmanager' +import { JsonRPCRequest, Provider } from 'web3/providers'; +import { errors } from 'web3-core-helpers' + +export interface BatchRequest { + readonly request: JsonRPCRequest | any; + readonly defaultValue?: any; +} + +export class BatchManager { + private static BATCH_LIMIT = 800; + + private requests: Array = []; + private requestManager: Manager; + + constructor(provider: Provider) { + this.requestManager = new Manager(provider) + } + + private static defaultOrThrow(defaultValue: any, error: Error): any { + if (defaultValue == undefined) { + throw error + } else { + return defaultValue + } + } + + private static chunkArray(myArray: Array, chunk_size): Array> { + const results = []; + + while (myArray.length) { + results.push(myArray.splice(0, chunk_size)); + } + + return results; + } + + async execute(): Promise> { + const batches = BatchManager.chunkArray(this.requests, BatchManager.BATCH_LIMIT); + const results = []; + + for (let i = 0; i < batches.length; i++) { + const batch = batches[i]; + let rpcRequests = batch.map(value => value.request); + const batchResults = await this.sendBatch(rpcRequests) || []; + + let allResults = batch.map((request, index) => { + return batchResults[index] || {}; + }); + + const processedResults = []; + for (let index = 0; index < allResults.length; index++) { + processedResults[index] = this.processResult(allResults[index], batch[index]) + } + results.push(...processedResults); + } + this.requests = []; + + return results; + } + + public add(request: BatchRequest): number { + return this.requests.push(request); + } + + private processResult(result: any, currentRequest: BatchRequest): Object { + let resultValue: Object; + let defaultValue = currentRequest.defaultValue; + + if (result && result.error) { + throw errors.ErrorResponse(result) + } else if (!this.isValidResponse(result)) { + throw errors.InvalidResponse(result) + } else { + try { // @ts-ignore + let format = currentRequest.request.format; + resultValue = format ? format(result.result) : result.result; + } catch (e) { + resultValue = BatchManager.defaultOrThrow(defaultValue, e); + } + } + + return resultValue; + } + + private sendBatch(rpcRequests: any): Promise> { + return new Promise>((resolve, reject) => { + this.requestManager.sendBatch(rpcRequests, (err: any, results: Array) => { + if (err) { + reject(err) + } else { + resolve(results); + } + + }) + }) + } + + private isValidResponse(response: any) { + + return Array.isArray(response) ? response.every(validateSingleMessage) : validateSingleMessage(response); + + function validateSingleMessage(message) { + return !!message && + !message.error && + message.jsonrpc === '2.0' && + (typeof message.id === 'number' || typeof message.id === 'string') && + message.result !== undefined; // only undefined is not valid json object + } + } +} diff --git a/src/app/services/raiden.service.ts b/src/app/services/raiden.service.ts index d262a030..edd2b62f 100644 --- a/src/app/services/raiden.service.ts +++ b/src/app/services/raiden.service.ts @@ -16,8 +16,6 @@ import { RaidenConfig } from './raiden.config'; import { SharedService } from './shared.service'; import { TokenInfoRetrieverService } from './token-info-retriever.service'; -export type CallbackFunc = (error: Error, result: any) => void; - @Injectable({ providedIn: 'root' }) @@ -90,7 +88,7 @@ export class RaidenService { public getTokens(refresh: boolean = false): Observable> { const tokens$: Observable<{ [address: string]: UserToken }> = this.http.get>(`${this.raidenConfig.api}/tokens`) - .pipe(flatMap(tokenAddresses => fromPromise(this.tokenInfoRetriever.createBatch(tokenAddresses, this._raidenAddress)))); + .pipe(flatMap(tokenAddresses => fromPromise(this.tokenInfoRetriever.createBatch(tokenAddresses, this._raidenAddress, this.userTokens)))); const connections$ = refresh ? this.http.get(`${this.raidenConfig.api}/connections`) : of(null); diff --git a/src/app/services/token-info-retriever.service.spec.ts b/src/app/services/token-info-retriever.service.spec.ts index cf1803e2..872c82e3 100644 --- a/src/app/services/token-info-retriever.service.spec.ts +++ b/src/app/services/token-info-retriever.service.spec.ts @@ -1,6 +1,6 @@ import { HttpClientModule } from '@angular/common/http'; import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { TestBed, async } from '@angular/core/testing'; +import { async, TestBed } from '@angular/core/testing'; import { MockConfig } from '../components/channel-table/channel-table.component.spec'; import { RaidenConfig } from './raiden.config'; import { SharedService } from './shared.service'; @@ -8,6 +8,7 @@ import { SharedService } from './shared.service'; import { TokenInfoRetrieverService } from './token-info-retriever.service'; // @ts-ignore import * as Web3 from 'web3'; +import { UserToken } from "../models/usertoken"; describe('TokenInfoRetriever', () => { let service: TokenInfoRetrieverService; @@ -29,6 +30,7 @@ describe('TokenInfoRetriever', () => { }); const config = TestBed.get(RaidenConfig); + config.web3 = new Web3(); service = TestBed.get(TokenInfoRetrieverService); }); @@ -37,21 +39,16 @@ describe('TokenInfoRetriever', () => { expect(service).toBeTruthy(); })); - it('should reject promise if there is a JSON RPC response error', (done) => { - const promise = service.createBatch([ - '0x0f114a1e9db192502e7856309cc899952b3db1ed' - ], '0x82641569b2062B545431cF6D7F0A418582865ba7'); - promise.then(value => { - fail(value); - done(); - }).catch(reason => { - const error = (reason as Error); - expect(error.message).toContain('Invalid JSON RPC response'); - done(); - }); - }); - - it('should ', () => { - + it('should fail with a JSON RPC response error', async () => { + const userTokens: { [address: string]: UserToken | null } = {}; + + try { + await service.createBatch([ + '0x0f114A1E9Db192502E7856309cc899952b3db1ED' + ], '0x82641569b2062B545431cF6D7F0A418582865ba7', userTokens); + fail('There should be no result') + } catch (e) { + expect(e.message).toContain('Invalid JSON RPC response'); + } }); }); diff --git a/src/app/services/token-info-retriever.service.ts b/src/app/services/token-info-retriever.service.ts index ca2ac008..b58406fc 100644 --- a/src/app/services/token-info-retriever.service.ts +++ b/src/app/services/token-info-retriever.service.ts @@ -1,174 +1,101 @@ import { Injectable } from '@angular/core'; -import BigNumber from 'bignumber.js'; import Contract from 'web3/eth/contract'; import { UserToken } from '../models/usertoken'; import { RaidenConfig } from './raiden.config'; -import { CallbackFunc } from './raiden.service'; import { tokenabi } from './tokenabi'; // @ts-ignore import * as Web3 from 'web3'; - -function override(object, methodName, callback) { - object[methodName] = callback(object[methodName]); -} +import { BatchManager } from "./batch-manager"; @Injectable({ providedIn: 'root' }) export class TokenInfoRetrieverService { - private tokenContract: Contract; private readonly web3: Web3; + private readonly tokenContract: Contract; + private readonly batchManager: BatchManager; constructor(private raidenConfig: RaidenConfig) { this.web3 = this.raidenConfig.web3; this.tokenContract = new this.web3.eth.Contract(tokenabi) as Contract; + this.batchManager = new BatchManager(this.web3.currentProvider) } - createBatch( + async createBatch( tokenAddresses: string[], - raidenAddress: string - ): Promise<{ [address: string]: UserToken }> { - const web3 = this.web3; - - const userTokens: { [address: string]: UserToken } = {}; - - return new Promise<{ [address: string]: UserToken }>((resolve, reject) => { - const timeout = setTimeout(() => reject(new Error(`timeout after 60000 ms`)), 60000); - let done = false; - try { - let unprocessed = 0; - - const pending = function () { - unprocessed += 1; - }; - - const complete = function () { - clearTimeout(timeout); - unprocessed -= 1; - if (done && unprocessed === 0) { - resolve(userTokens); - } - }; - - let batch = new web3.BatchRequest(); - - tokenAddresses.forEach(tokenAddress => { - batch = this.addTokenToBatch(tokenAddress, raidenAddress, userTokens, batch, pending, complete); - // @ts-ignore - if (batch.requests.length >= 800) { - batch.execute(); - batch = new web3.BatchRequest(); - } - }); - - done = true; - - // @ts-ignore - if (batch.requests.length > 0) { - batch.execute(); - } - } catch (e) { - reject(e); - } - }); + raidenAddress: string, + userTokens: { [address: string]: UserToken | null }): Promise<{ [address: string]: UserToken }> { + let batchManager = this.batchManager; - } + const map: { [index: number]: { method: string; address: string } } = {}; - private createToken(address: string): UserToken { - return { - address, - name: '', - symbol: '', - decimals: 18, - balance: 0 - }; - } + function add(methods, nameProperty: string, tokenAddress: string, defaultValue: any = undefined) { + let index = batchManager.add({ + request: methods[nameProperty]().call.request(), + defaultValue: defaultValue, + }); - private addTokenToBatch( - tokenAddress: string, - raidenAddress: string, - tokens: { [address: string]: UserToken | null }, - batch, - pending: () => void, - complete: () => void - ) { - this.tokenContract.options.address = tokenAddress; - const contract = this.tokenContract; - - const updateValue = (property: string, defaultValue: any, error: Error, result: any) => { - if (error && error.message && error.message.startsWith('Invalid JSON RPC response')) { - throw error; - } - complete(); - let token = tokens[tokenAddress]; - let value: any; - - if (error) { - console.error(error); - value = defaultValue; - } else { - if (result instanceof BigNumber) { - value = (result as BigNumber).toNumber(); - } else { - value = result; - } + map[index - 1] = { + method: nameProperty, + address: tokenAddress + }; + } + + tokenAddresses.forEach(tokenAddress => { + let contract = this.tokenContract; + contract.options.address = tokenAddress; + + let methods = contract.methods; + + if (!userTokens[tokenAddress]) { + add(methods, 'name', tokenAddress, ''); + add(methods, 'symbol', tokenAddress, ''); + add(methods, 'decimals', tokenAddress, 18); } - if (!token) { - token = this.createToken(tokenAddress); + // @ts-ignore + let request = methods.balanceOf(raidenAddress).call.request(); + + const balanceIndex = this.batchManager.add({ + request: request + }); + + map[balanceIndex - 1] = { + method: 'balanceOf', + address: tokenAddress } + }); - token[property] = value; - tokens[tokenAddress] = token; - }; - const balanceMethod = contract.methods.balanceOf; - if (balanceMethod) { - const callback: CallbackFunc = (error: Error, result: any) => updateValue('balance', 0, error, result); - // @ts-ignore - const request = balanceMethod(raidenAddress).call.request(callback); - batch.add(request); - pending(); - } + let results = await this.batchManager.execute(); - if (!tokens[tokenAddress]) { - - const addRequest = (property, defaultResponse) => { - const callback: CallbackFunc = ((error: Error, result: any) => updateValue(property, defaultResponse, error, result)); - const method = contract.methods[property]; - if (method) { - // @ts-ignore - const request = method().call.request(callback); - this.monkeyPatchRequest(request, defaultResponse); - batch.add(request); - pending(); - } - }; + results.forEach((value, index) => { + let element = map[index]; + if (!element) { + console.log(index); + throw Error(`could not find element for index ${index}`) + } - addRequest('decimals', 18); - addRequest('name', ''); - addRequest('symbol', ''); - } + let token: UserToken = userTokens[element.address]; + if (!token) { + token = TokenInfoRetrieverService.createToken(element.address); + } - return batch; + token[element.method] = value; + userTokens[element.address] = token; + }); + + return userTokens; } - private monkeyPatchRequest(request: any, defaultResponse: any): void { - override(request, 'format', function (original) { - return function (output) { - let result: any; - try { - result = original(output); - } catch (e) { - if (e && e.message && e.message.startsWith('Invalid JSON RPC response')) { - throw e; - } - console.error(e); - result = defaultResponse; - } - return result; - }; - }); + private static createToken(address: string): UserToken { + return { + address, + name: '', + symbol: '', + decimals: 18, + balance: 0 + }; } } From 04b1ba7e17d264847261060b929c50a9444d7a0a Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Tue, 4 Dec 2018 12:28:26 +0100 Subject: [PATCH 3/6] Fixes some tests setup that would cause flaky tests. --- .../channel-events.component.spec.ts | 17 ++++++++++++----- .../event-list/event-list.component.spec.ts | 2 +- .../token-network-selector.component.spec.ts | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/app/components/channel-events/channel-events.component.spec.ts b/src/app/components/channel-events/channel-events.component.spec.ts index 5965f1eb..c5fa386b 100644 --- a/src/app/components/channel-events/channel-events.component.spec.ts +++ b/src/app/components/channel-events/channel-events.component.spec.ts @@ -2,7 +2,6 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ActivatedRoute } from '@angular/router'; -import { RouterTestingModule } from '@angular/router/testing'; import { of } from 'rxjs'; import { CdkDetailRowDirective } from '../../directives/cdk-detail-row.directive'; import { MaterialComponentsModule } from '../../modules/material-components/material-components.module'; @@ -38,10 +37,18 @@ describe('ChannelEventsComponent', () => { { provide: ActivatedRoute, useValue: { - paramMap: of({channel_identifier: 123}), + paramMap: of({ + channel_identifier: 123, + get: () => { + return 123; + } + }), queryParamMap: of({ token_address: '0x', - partner_address: '0x' + partner_address: '0x', + get: () => { + return '0x'; + } }) } }, @@ -62,7 +69,7 @@ describe('ChannelEventsComponent', () => { fixture.detectChanges(); }); - it('should create', () => { + it('should create', async (() => { expect(component).toBeTruthy(); - }); + })); }); diff --git a/src/app/components/event-list/event-list.component.spec.ts b/src/app/components/event-list/event-list.component.spec.ts index 8a7d1ec6..97a08bbc 100644 --- a/src/app/components/event-list/event-list.component.spec.ts +++ b/src/app/components/event-list/event-list.component.spec.ts @@ -1,4 +1,3 @@ -import { NoopAnimationDriver } from '@angular/animations/browser/src/render/animation_driver'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -46,6 +45,7 @@ describe('EventListComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(EventListComponent); component = fixture.componentInstance; + component.eventsParam = {activity: true}; fixture.detectChanges(); }); diff --git a/src/app/components/token-network-selector/token-network-selector.component.spec.ts b/src/app/components/token-network-selector/token-network-selector.component.spec.ts index 3df10d05..84bdf71b 100644 --- a/src/app/components/token-network-selector/token-network-selector.component.spec.ts +++ b/src/app/components/token-network-selector/token-network-selector.component.spec.ts @@ -106,7 +106,7 @@ describe('TokenNetworkSelectorComponent', () => { raidenSpy = spyOn(raidenService, 'getTokens'); raidenSpy.and.returnValue(of(tokens)); mockConfig = TestBed.get(RaidenConfig); - spyOn(raidenService, 'getUserToken').and.returnValue(of(connectedToken)); + spyOn(raidenService, 'getUserToken').and.returnValue(connectedToken); fixture = TestBed.createComponent(TokenNetworkSelectorComponent); component = fixture.componentInstance; From 7a88792399fd2140b9307dbeaf9bf8a9050b983e Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Tue, 4 Dec 2018 17:01:25 +0100 Subject: [PATCH 4/6] Adds tests for TokenInfoRetriever, fixes lint issues --- .../channel-table.component.spec.ts | 10 +- src/app/services/batch-manager.spec.ts | 85 +++++++------ src/app/services/batch-manager.ts | 34 +++--- src/app/services/raiden.config.ts | 13 ++ src/app/services/raiden.service.spec.ts | 4 +- src/app/services/raiden.service.ts | 10 +- .../token-info-retriever.service.spec.ts | 112 ++++++++++++++++-- .../services/token-info-retriever.service.ts | 49 ++++---- 8 files changed, 219 insertions(+), 98 deletions(-) diff --git a/src/app/components/channel-table/channel-table.component.spec.ts b/src/app/components/channel-table/channel-table.component.spec.ts index 65553fce..c87bf9fa 100644 --- a/src/app/components/channel-table/channel-table.component.spec.ts +++ b/src/app/components/channel-table/channel-table.component.spec.ts @@ -31,6 +31,7 @@ import { TokenInputComponent } from '../token-input/token-input.component'; import { TokenNetworkSelectorComponent } from '../token-network-selector/token-network-selector.component'; import { ChannelTableComponent } from './channel-table.component'; +import { BatchManager } from '../../services/batch-manager'; import Spy = jasmine.Spy; class MockWeb3 extends Web3 { @@ -57,15 +58,20 @@ class MockWeb3 extends Web3 { export class MockConfig extends RaidenConfig { public web3: Web3 = new MockWeb3(); + private testBatchManager: BatchManager = new BatchManager(this.web3.currentProvider); - updateChecksumAddress(address: string): void { - this.mock.checksumAddress = address; + get batchManager(): BatchManager { + return this.testBatchManager; } private get mock(): MockWeb3 { return (this.web3 as MockWeb3); } + updateChecksumAddress(address: string): void { + this.mock.checksumAddress = address; + } + setIsChecksum(isChecksum: boolean): void { this.mock.isChecksum = isChecksum; } diff --git a/src/app/services/batch-manager.spec.ts b/src/app/services/batch-manager.spec.ts index a67e3c15..af4e61ef 100644 --- a/src/app/services/batch-manager.spec.ts +++ b/src/app/services/batch-manager.spec.ts @@ -1,6 +1,6 @@ -import { BatchManager } from "./batch-manager"; -import { hexToString } from 'web3-utils' -import { formatters } from 'web3-core-helpers' +import { BatchManager } from './batch-manager'; +import { hexToString } from 'web3-utils'; +import { formatters } from 'web3-core-helpers'; import Spy = jasmine.Spy; interface JsonRPCRequest { @@ -36,21 +36,20 @@ export class FakeHttpProvider implements Provider { private response = []; private error = []; - public send(payload: JsonRPCRequest, callback: (e: Error, val: JsonRPCResponse) => void) { - + public send(payload: JsonRPCRequest, callback: (e: Error, val: JsonRPCResponse) => void): any { if (payload.id) { - this.countId = payload.id + this.countId = payload.id; } if (!(payload instanceof Array) || !(payload instanceof Object)) { - throw Error('payload should be either object or array') + throw Error('payload should be either object or array'); } const response = this.getResponseOrError('response', payload); const error = this.getResponseOrError('error', payload); // @ts-ignore - setTimeout(() => callback(error, response), 1) + setTimeout(() => callback(error, response), 1); } public getResponseOrError(type: any, payload: any | Array): JsonRPCResponse | JsonRPCResponse[] { @@ -94,20 +93,20 @@ export class FakeHttpProvider implements Provider { if (error) { response = this.getErrorStub(); - response.error = value + response.error = value; } else { response = this.getResponseStub(); response.result = value; } - return response - })) + return response; + })); } public injectResult(result: string) { const response = this.getResponseStub(); response.result = result; - this.response.push(response) + this.response.push(response); } public injectInvalidResponse(response: object) { @@ -117,20 +116,20 @@ export class FakeHttpProvider implements Provider { public injectError(error: any) { const errorStub = this.getErrorStub(); errorStub.error = error; - this.error.push(errorStub) + this.error.push(errorStub); } private getResponseStub(): JsonRPCResponse { - let countId = this.countId; + const countId = this.countId; return { jsonrpc: '2.0', id: countId, result: null - } + }; } private getErrorStub(): JsonRPCResponse { - let countId = this.countId; + const countId = this.countId; return { jsonrpc: '2.0', id: countId, @@ -138,7 +137,7 @@ export class FakeHttpProvider implements Provider { code: 50010, message: 'Invalid Response?' } - } + }; } } @@ -154,11 +153,11 @@ function getEthCallStub(): JsonRPCRequest { }, 'latest' ] - } + }; } function getRPCResult(): string { - return "0x0" + return '0x0'; } describe('BatchManager', () => { @@ -182,9 +181,9 @@ describe('BatchManager', () => { try { await batchManager.execute(); - fail('There should be no result') + fail('There should be no result'); } catch (e) { - expect(e).toBeTruthy("There should be an error thrown") + expect(e).toBeTruthy('There should be an error thrown'); } }); @@ -198,29 +197,29 @@ describe('BatchManager', () => { batchManager.add({request: getEthCallStub()}); batchManager.add({request: getEthCallStub()}); - let result = await batchManager.execute(); + const result = await batchManager.execute(); expect(result).toBeTruthy('there should be a result'); - expect(result.length).toBe(2, 'there should be two ') + expect(result.length).toBe(2, 'there should be two '); }); it('should only call through the http provider for the batch', async () => { const results = []; - let batchSize = 800; + const batchSize = 800; for (let i = 0; i < batchSize; i++) { - let ethCallStub = getEthCallStub(); + const ethCallStub = getEthCallStub(); ethCallStub.id = i + 1; batchManager.add({request: ethCallStub}); - results.push(getRPCResult()) + results.push(getRPCResult()); } httpProvider.injectBatchResults(results); - let result = await batchManager.execute(); + const result = await batchManager.execute(); expect(result).toBeTruthy('there should be a result'); expect(result.length).toBe(batchSize, 'there should be 800 results in the batch'); @@ -230,19 +229,19 @@ describe('BatchManager', () => { it('should internally split the batch if more than 800 requests are batched', async () => { const results = []; - let batchSize = 1600; + const batchSize = 1600; for (let i = 0; i < batchSize; i++) { - let ethCallStub = getEthCallStub(); + const ethCallStub = getEthCallStub(); ethCallStub.id = i + 1; batchManager.add({request: ethCallStub}); - results.push(getRPCResult()) + results.push(getRPCResult()); } httpProvider.injectBatchResults(results); - let result = await batchManager.execute(); + const result = await batchManager.execute(); expect(result).toBeTruthy('there should be a result'); expect(result.length).toBe(batchSize, 'there should be 1600 results in response'); @@ -251,20 +250,20 @@ describe('BatchManager', () => { it('should fail on Error', async () => { - let ethCallStub = getEthCallStub(); + const ethCallStub = getEthCallStub(); batchManager.add({request: ethCallStub}); httpProvider.injectBatchResults([getRPCResult()], true); try { await batchManager.execute(); - fail('there should be no result') + fail('there should be no result'); } catch (e) { expect(e).toBeTruthy(); } }); it('should fail on an invalid response', async () => { - let ethCallStub = getEthCallStub(); + const ethCallStub = getEthCallStub(); batchManager.add({request: ethCallStub}); httpProvider.injectInvalidResponse({ jsonrpc: '2.0', @@ -273,16 +272,16 @@ describe('BatchManager', () => { try { await batchManager.execute(); - fail('there should be no result') + fail('there should be no result'); } catch (e) { - expect(e).toMatch('Invalid JSON RPC response') + expect(e).toMatch('Invalid JSON RPC response'); } }); it('should ignore failure if there is a default value and the formatter throws', async () => { - let ethCallStub = getEthCallStub(); + const ethCallStub = getEthCallStub(); ethCallStub.format = function () { - throw Error('format failed') + throw Error('format failed'); }; batchManager.add({ request: ethCallStub, @@ -291,16 +290,16 @@ describe('BatchManager', () => { httpProvider.injectBatchResults(['0x4d4b520000000000000000000000000000000000000000000000000000000000']); - let result = await batchManager.execute(); + const result = await batchManager.execute(); expect(result.length).toBe(1); expect(result[0]).toBe(''); }); it('should fail if there is no default value and the formatter throws', async () => { - let ethCallStub = getEthCallStub(); + const ethCallStub = getEthCallStub(); ethCallStub.format = function () { - throw Error('format failed') + throw Error('format failed'); }; batchManager.add({ request: ethCallStub @@ -310,10 +309,10 @@ describe('BatchManager', () => { try { await batchManager.execute(); - fail('there should be no result') + fail('there should be no result'); } catch (e) { expect(e).toBeTruthy(); expect(e.message).toMatch('format failed'); } }); -}); \ No newline at end of file +}); diff --git a/src/app/services/batch-manager.ts b/src/app/services/batch-manager.ts index 3317f377..483f2cb6 100644 --- a/src/app/services/batch-manager.ts +++ b/src/app/services/batch-manager.ts @@ -1,6 +1,6 @@ -import { Manager } from 'web3-core-requestmanager' +import { Manager } from 'web3-core-requestmanager'; import { JsonRPCRequest, Provider } from 'web3/providers'; -import { errors } from 'web3-core-helpers' +import { errors } from 'web3-core-helpers'; export interface BatchRequest { readonly request: JsonRPCRequest | any; @@ -14,14 +14,14 @@ export class BatchManager { private requestManager: Manager; constructor(provider: Provider) { - this.requestManager = new Manager(provider) + this.requestManager = new Manager(provider); } private static defaultOrThrow(defaultValue: any, error: Error): any { - if (defaultValue == undefined) { - throw error + if (defaultValue === undefined) { + throw error; } else { - return defaultValue + return defaultValue; } } @@ -35,22 +35,22 @@ export class BatchManager { return results; } - async execute(): Promise> { + public async execute(): Promise> { const batches = BatchManager.chunkArray(this.requests, BatchManager.BATCH_LIMIT); const results = []; for (let i = 0; i < batches.length; i++) { const batch = batches[i]; - let rpcRequests = batch.map(value => value.request); + const rpcRequests = batch.map(value => value.request); const batchResults = await this.sendBatch(rpcRequests) || []; - let allResults = batch.map((request, index) => { + const allResults = batch.map((request, index) => { return batchResults[index] || {}; }); const processedResults = []; for (let index = 0; index < allResults.length; index++) { - processedResults[index] = this.processResult(allResults[index], batch[index]) + processedResults[index] = this.processResult(allResults[index], batch[index]); } results.push(...processedResults); } @@ -65,15 +65,15 @@ export class BatchManager { private processResult(result: any, currentRequest: BatchRequest): Object { let resultValue: Object; - let defaultValue = currentRequest.defaultValue; + const defaultValue = currentRequest.defaultValue; if (result && result.error) { - throw errors.ErrorResponse(result) + throw errors.ErrorResponse(result); } else if (!this.isValidResponse(result)) { - throw errors.InvalidResponse(result) + throw errors.InvalidResponse(result); } else { try { // @ts-ignore - let format = currentRequest.request.format; + const format = currentRequest.request.format; resultValue = format ? format(result.result) : result.result; } catch (e) { resultValue = BatchManager.defaultOrThrow(defaultValue, e); @@ -87,13 +87,13 @@ export class BatchManager { return new Promise>((resolve, reject) => { this.requestManager.sendBatch(rpcRequests, (err: any, results: Array) => { if (err) { - reject(err) + reject(err); } else { resolve(results); } - }) - }) + }); + }); } private isValidResponse(response: any) { diff --git a/src/app/services/raiden.config.ts b/src/app/services/raiden.config.ts index 1d06cde4..d1a96c99 100644 --- a/src/app/services/raiden.config.ts +++ b/src/app/services/raiden.config.ts @@ -4,6 +4,7 @@ import { EnvironmentType } from './enviroment-type.enum'; import { SharedService } from './shared.service'; // @ts-ignore import * as Web3 from 'web3'; +import { BatchManager } from './batch-manager'; interface RDNConfig { raiden: string; @@ -41,6 +42,12 @@ export class RaidenConfig { ) { } + private _batchManager: BatchManager; + + public get batchManager(): BatchManager { + return this._batchManager; + } + load(url: string): Promise { return new Promise((resolve, reject) => { this.http.get(url) @@ -56,13 +63,19 @@ export class RaidenConfig { console.error(`Invalid web3 endpoint, switching to fallback ${this.config.web3_fallback}`, reason); this.config.web3 = this.config.web3_fallback; this.web3 = new Web3(new Web3.providers.HttpProvider(this.config.web3)); + this.createBatchManager(); reject(reason); }).then(() => { this.web3 = new Web3(new Web3.providers.HttpProvider(this.config.web3)); + this.createBatchManager(); resolve(); }); }); }); } + + private createBatchManager() { + this._batchManager = new BatchManager(this.web3.currentProvider); + } } diff --git a/src/app/services/raiden.service.spec.ts b/src/app/services/raiden.service.spec.ts index 071215dc..c49f0674 100644 --- a/src/app/services/raiden.service.spec.ts +++ b/src/app/services/raiden.service.spec.ts @@ -1,7 +1,6 @@ import { HttpClientModule } from '@angular/common/http'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { fakeAsync, flush, inject, TestBed, tick } from '@angular/core/testing'; -import { BigNumber } from 'bignumber.js'; import { of } from 'rxjs'; import { MockConfig } from '../components/channel-table/channel-table.component.spec'; import { Channel } from '../models/channel'; @@ -155,7 +154,8 @@ describe('RaidenService', () => { balance: 20 }; - spyOn(service, 'getUserToken').and.returnValue(of(token)); + spyOn(service, 'getUserToken').and.returnValue(token); + spyOn(service, 'getTokens').and.returnValue(of([token])); service.getChannels().subscribe((channels: Array) => { channels.forEach(value => { diff --git a/src/app/services/raiden.service.ts b/src/app/services/raiden.service.ts index edd2b62f..377dede2 100644 --- a/src/app/services/raiden.service.ts +++ b/src/app/services/raiden.service.ts @@ -87,8 +87,14 @@ export class RaidenService { } public getTokens(refresh: boolean = false): Observable> { - const tokens$: Observable<{ [address: string]: UserToken }> = this.http.get>(`${this.raidenConfig.api}/tokens`) - .pipe(flatMap(tokenAddresses => fromPromise(this.tokenInfoRetriever.createBatch(tokenAddresses, this._raidenAddress, this.userTokens)))); + const tokensUrl = `${this.raidenConfig.api}/tokens`; + const tokens$: Observable<{ [address: string]: UserToken }> = this.http.get>(tokensUrl).pipe( + flatMap(tokenAddresses => fromPromise(this.tokenInfoRetriever.createBatch( + tokenAddresses, + this._raidenAddress, + this.userTokens + ))) + ); const connections$ = refresh ? this.http.get(`${this.raidenConfig.api}/connections`) : of(null); diff --git a/src/app/services/token-info-retriever.service.spec.ts b/src/app/services/token-info-retriever.service.spec.ts index 872c82e3..c05ccf29 100644 --- a/src/app/services/token-info-retriever.service.spec.ts +++ b/src/app/services/token-info-retriever.service.spec.ts @@ -6,12 +6,14 @@ import { RaidenConfig } from './raiden.config'; import { SharedService } from './shared.service'; import { TokenInfoRetrieverService } from './token-info-retriever.service'; -// @ts-ignore -import * as Web3 from 'web3'; -import { UserToken } from "../models/usertoken"; +import { BatchManager, BatchRequest } from './batch-manager'; +import { UserToken } from '../models/usertoken'; +import Spy = jasmine.Spy; describe('TokenInfoRetriever', () => { let service: TokenInfoRetrieverService; + let batchManager: BatchManager; + let addSpy: Spy; beforeEach(() => { TestBed.configureTestingModule({ @@ -25,13 +27,41 @@ describe('TokenInfoRetriever', () => { { provide: RaidenConfig, useClass: MockConfig - }, + } ] }); const config = TestBed.get(RaidenConfig); - config.web3 = new Web3(); + function createMethod(name: string) { + return function method() { + return { + call: { + request: () => { + return name; + } + } + }; + }; + } + + config.web3.eth.Contract = () => { + return { + options: {}, + methods: { + 'name': createMethod('name'), + 'decimals': createMethod('decimals'), + 'symbol': createMethod('symbol'), + 'balanceOf': createMethod('balanceOf') + } + }; + }; + + let count = 1; + + + batchManager = config.batchManager; + addSpy = spyOn(batchManager, 'add').and.callFake(() => count++); service = TestBed.get(TokenInfoRetrieverService); }); @@ -39,16 +69,84 @@ describe('TokenInfoRetriever', () => { expect(service).toBeTruthy(); })); - it('should fail with a JSON RPC response error', async () => { + it('should propagate an error when the batch manager promise fails', async () => { + + spyOn(batchManager, 'execute').and.returnValue(new Promise((resolve, reject) => { + reject(new Error('Invalid JSON RPC response')); + })); + const userTokens: { [address: string]: UserToken | null } = {}; try { await service.createBatch([ '0x0f114A1E9Db192502E7856309cc899952b3db1ED' ], '0x82641569b2062B545431cF6D7F0A418582865ba7', userTokens); - fail('There should be no result') + fail('There should be no result'); } catch (e) { expect(e.message).toContain('Invalid JSON RPC response'); } }); + + it('should have add 4 requests the first time', async () => { + spyOn(batchManager, 'execute').and.returnValue(new Promise((resolve) => { + resolve(['TEST', 'TST', 18, 50]); + })); + + const userTokens: { [address: string]: UserToken | null } = {}; + const tokens = await service.createBatch([ + '0x0f114A1E9Db192502E7856309cc899952b3db1ED' + ], '0x82641569b2062B545431cF6D7F0A418582865ba7', userTokens); + + expect(addSpy).toHaveBeenCalledTimes(4); + expect(tokens['0x0f114A1E9Db192502E7856309cc899952b3db1ED']).toBeTruthy(); + + const calls = addSpy.calls; + + expect((calls.argsFor(0)[0] as BatchRequest).request).toBe('name'); + expect((calls.argsFor(1)[0] as BatchRequest).request).toBe('symbol'); + expect((calls.argsFor(2)[0] as BatchRequest).request).toBe('decimals'); + expect((calls.argsFor(3)[0] as BatchRequest).request).toBe('balanceOf'); + + const userToken = tokens['0x0f114A1E9Db192502E7856309cc899952b3db1ED']; + + expect(userToken.name).toBe('TEST'); + expect(userToken.symbol).toBe('TST'); + expect(userToken.address).toBe('0x0f114A1E9Db192502E7856309cc899952b3db1ED'); + expect(userToken.decimals).toBe(18); + expect(userToken.balance).toBe(50); + }); + + it('should have only on request if token is already cached', async () => { + spyOn(batchManager, 'execute').and.returnValue(new Promise((resolve) => { + resolve([150]); + })); + + const userTokens: { [address: string]: UserToken | null } = { + '0x0f114A1E9Db192502E7856309cc899952b3db1ED': { + name: 'TEST', + symbol: 'TST', + decimals: 18, + address: '0x0f114A1E9Db192502E7856309cc899952b3db1ED', + balance: 10 + } + }; + const tokens = await service.createBatch([ + '0x0f114A1E9Db192502E7856309cc899952b3db1ED' + ], '0x82641569b2062B545431cF6D7F0A418582865ba7', userTokens); + + expect(addSpy).toHaveBeenCalledTimes(1); + expect(tokens['0x0f114A1E9Db192502E7856309cc899952b3db1ED']).toBeTruthy(); + + const calls = addSpy.calls; + + expect((calls.argsFor(0)[0] as BatchRequest).request).toBe('balanceOf'); + + const userToken = tokens['0x0f114A1E9Db192502E7856309cc899952b3db1ED']; + + expect(userToken.name).toBe('TEST'); + expect(userToken.symbol).toBe('TST'); + expect(userToken.address).toBe('0x0f114A1E9Db192502E7856309cc899952b3db1ED'); + expect(userToken.decimals).toBe(18); + expect(userToken.balance).toBe(150); + }); }); diff --git a/src/app/services/token-info-retriever.service.ts b/src/app/services/token-info-retriever.service.ts index b58406fc..a87a4eeb 100644 --- a/src/app/services/token-info-retriever.service.ts +++ b/src/app/services/token-info-retriever.service.ts @@ -5,12 +5,13 @@ import { RaidenConfig } from './raiden.config'; import { tokenabi } from './tokenabi'; // @ts-ignore import * as Web3 from 'web3'; -import { BatchManager } from "./batch-manager"; +import { BatchManager } from './batch-manager'; @Injectable({ providedIn: 'root' }) export class TokenInfoRetrieverService { + private readonly web3: Web3; private readonly tokenContract: Contract; private readonly batchManager: BatchManager; @@ -18,19 +19,29 @@ export class TokenInfoRetrieverService { constructor(private raidenConfig: RaidenConfig) { this.web3 = this.raidenConfig.web3; this.tokenContract = new this.web3.eth.Contract(tokenabi) as Contract; - this.batchManager = new BatchManager(this.web3.currentProvider) + this.batchManager = this.raidenConfig.batchManager; + } + + private static createToken(address: string): UserToken { + return { + address, + name: '', + symbol: '', + decimals: 18, + balance: 0 + }; } async createBatch( tokenAddresses: string[], raidenAddress: string, userTokens: { [address: string]: UserToken | null }): Promise<{ [address: string]: UserToken }> { - let batchManager = this.batchManager; + const batchManager = this.batchManager; const map: { [index: number]: { method: string; address: string } } = {}; - function add(methods, nameProperty: string, tokenAddress: string, defaultValue: any = undefined) { - let index = batchManager.add({ + function add(methods, nameProperty: string, tokenAddress: string, defaultValue?: any) { + const index = batchManager.add({ request: methods[nameProperty]().call.request(), defaultValue: defaultValue, }); @@ -42,10 +53,10 @@ export class TokenInfoRetrieverService { } tokenAddresses.forEach(tokenAddress => { - let contract = this.tokenContract; + const contract = this.tokenContract; contract.options.address = tokenAddress; - let methods = contract.methods; + const methods = contract.methods; if (!userTokens[tokenAddress]) { add(methods, 'name', tokenAddress, ''); @@ -54,7 +65,7 @@ export class TokenInfoRetrieverService { } // @ts-ignore - let request = methods.balanceOf(raidenAddress).call.request(); + const request = methods.balanceOf(raidenAddress).call.request(); const balanceIndex = this.batchManager.add({ request: request @@ -63,18 +74,16 @@ export class TokenInfoRetrieverService { map[balanceIndex - 1] = { method: 'balanceOf', address: tokenAddress - } + }; }); - - let results = await this.batchManager.execute(); + const results = await this.batchManager.execute(); results.forEach((value, index) => { - let element = map[index]; + const element = map[index]; if (!element) { - console.log(index); - throw Error(`could not find element for index ${index}`) + throw Error(`could not find element for index ${index}`); } let token: UserToken = userTokens[element.address]; @@ -82,20 +91,10 @@ export class TokenInfoRetrieverService { token = TokenInfoRetrieverService.createToken(element.address); } - token[element.method] = value; + token[element.method !== 'balanceOf' ? element.method : 'balance'] = value; userTokens[element.address] = token; }); return userTokens; } - - private static createToken(address: string): UserToken { - return { - address, - name: '', - symbol: '', - decimals: 18, - balance: 0 - }; - } } From 3768c6505eed2c88f6cea84161fa0d259dce2a8b Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Tue, 11 Dec 2018 16:39:27 +0100 Subject: [PATCH 5/6] Update package-lock.json --- package-lock.json | 1565 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 1297 insertions(+), 268 deletions(-) diff --git a/package-lock.json b/package-lock.json index 001db57e..ec69ff7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "raidenwebui", - "version": "0.5.0", + "version": "0.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -862,6 +862,15 @@ } } }, + "@types/bn.js": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.3.tgz", + "integrity": "sha512-auZ3vEo3UW8tZc9NhF0MTnutKlf+YhsfC3+dwskFcil/EoqqZF60pGuJ2v2Ae1OJTUp3DJnjOJMqrpkmKB904w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/jasmine": { "version": "2.8.12", "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.12.tgz", @@ -880,8 +889,7 @@ "@types/node": { "version": "10.7.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.7.1.tgz", - "integrity": "sha512-EGoI4ylB/lPOaqXqtzAyL8HcgOuCtH2hkEaLmkueOYufsTFWBn4VCvlCDC2HW8Q+9iF+QVC3sxjDKQYjHQeZ9w==", - "dev": true + "integrity": "sha512-EGoI4ylB/lPOaqXqtzAyL8HcgOuCtH2hkEaLmkueOYufsTFWBn4VCvlCDC2HW8Q+9iF+QVC3sxjDKQYjHQeZ9w==" }, "@types/q": { "version": "0.0.32", @@ -895,6 +903,22 @@ "integrity": "sha512-rI0LGoMiZGUM+tjDakQpwZOvcmQoubiJ7hxqrYU12VRxBuGGvOThxrBOU/QmJKlKg1WG6FMzuvcEyLffvVSsmw==", "dev": true }, + "@types/underscore": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.8.9.tgz", + "integrity": "sha512-vfzZGgZKRFy7KEWcBGfIFk+h6B+thDCLfkD1exMBMRlUsx2icA+J6y4kAbZs/TjSTeY1duw89QUU133TSzr60Q==", + "dev": true + }, + "@types/web3": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@types/web3/-/web3-1.0.14.tgz", + "integrity": "sha512-N841xEBVwg0QNin3Zu+Yf7eEKKeJ0MROMc+FvfgtX8r/fwynFhSZVj3VONVcr9QP/Wffq+aggj+4lgrvG3lnFQ==", + "dev": true, + "requires": { + "@types/bn.js": "*", + "@types/underscore": "*" + } + }, "@webassemblyjs/ast": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.4.3.tgz", @@ -1148,7 +1172,6 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, "requires": { "mime-types": "~2.1.18", "negotiator": "0.6.1" @@ -1175,6 +1198,11 @@ "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", "dev": true }, + "aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" + }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -1246,6 +1274,11 @@ "color-convert": "^1.9.0" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", @@ -1377,7 +1410,6 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, "requires": { "safer-buffer": "~2.1.0" } @@ -1386,7 +1418,6 @@ "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", @@ -1422,8 +1453,7 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "assign-symbols": { "version": "1.0.0", @@ -1453,14 +1483,12 @@ "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "atob": { "version": "2.1.2", @@ -1485,14 +1513,12 @@ "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "babel-code-frame": { "version": "6.26.0", @@ -1690,8 +1716,7 @@ "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, "base64id": { "version": "1.0.0", @@ -1709,7 +1734,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, "requires": { "tweetnacl": "^0.14.3" } @@ -1740,6 +1764,15 @@ "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", "dev": true }, + "bl": { + "version": "1.2.2", + "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", @@ -1750,8 +1783,6 @@ "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "optional": true, "requires": { "inherits": "~2.0.0" } @@ -1776,20 +1807,17 @@ "bluebird": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", - "dev": true + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "body-parser": { "version": "1.18.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, "requires": { "bytes": "3.0.0", "content-type": "~1.0.4", @@ -1864,14 +1892,12 @@ "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, "browserify-aes": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, "requires": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -1885,7 +1911,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, "requires": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", @@ -1896,7 +1921,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, "requires": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", @@ -1908,17 +1932,23 @@ "version": "4.0.1", "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, "requires": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" } }, + "browserify-sha3": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.1.tgz", + "integrity": "sha1-P/NKMAbvFcD7NWflQbkaI0ASPRE=", + "requires": { + "js-sha3": "^0.3.1" + } + }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, "requires": { "bn.js": "^4.1.1", "browserify-rsa": "^4.0.0", @@ -1972,7 +2002,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, "requires": { "buffer-alloc-unsafe": "^1.1.0", "buffer-fill": "^1.0.0" @@ -1981,14 +2010,17 @@ "buffer-alloc-unsafe": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, "buffer-from": { "version": "1.1.1", @@ -2002,11 +2034,15 @@ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", "dev": true }, + "buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, "builtin-modules": { "version": "1.1.1", @@ -2029,8 +2065,7 @@ "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cacache": { "version": "10.0.4", @@ -2113,8 +2148,7 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chalk": { "version": "2.4.1", @@ -2164,7 +2198,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -2330,7 +2363,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -2338,8 +2370,7 @@ "commander": { "version": "2.17.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" }, "commondir": { "version": "1.0.1", @@ -2477,14 +2508,12 @@ "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "convert-source-map": { "version": "1.6.0", @@ -2498,14 +2527,17 @@ "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" }, "copy-concurrently": { "version": "1.0.5", @@ -2551,8 +2583,16 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } }, "cosmiconfig": { "version": "4.0.0", @@ -2582,7 +2622,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, "requires": { "bn.js": "^4.1.0", "elliptic": "^6.0.0" @@ -2592,7 +2631,6 @@ "version": "1.2.0", "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, "requires": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -2605,7 +2643,6 @@ "version": "1.1.7", "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, "requires": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -2630,7 +2667,6 @@ "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, "requires": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", @@ -2645,11 +2681,6 @@ "randomfill": "^1.0.3" } }, - "crypto-js": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" - }, "css-parse": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", @@ -2732,7 +2763,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -2753,7 +2783,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -2767,8 +2796,108 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } }, "deep-equal": { "version": "1.0.1", @@ -2899,8 +3028,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", @@ -2911,14 +3039,12 @@ "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, "requires": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" @@ -2927,8 +3053,7 @@ "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "detect-indent": { "version": "4.0.0", @@ -2961,7 +3086,6 @@ "version": "5.0.3", "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, "requires": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", @@ -3042,6 +3166,11 @@ } } }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -3073,6 +3202,11 @@ "domelementtype": "1" } }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, "duplexify": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", @@ -3089,7 +3223,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -3098,8 +3231,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "ejs": { "version": "2.6.1", @@ -3117,7 +3249,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -3137,14 +3268,12 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -3300,8 +3429,7 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "1.0.5", @@ -3390,8 +3518,37 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", + "requires": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + }, + "dependencies": { + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + } + } + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "keccakjs": "^0.2.1", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" + } }, "ethereum-blockies-base64": { "version": "1.0.2", @@ -3401,6 +3558,76 @@ "pnglib": "0.0.1" } }, + "ethers": { + "version": "4.0.0-beta.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.1.tgz", + "integrity": "sha512-SoYhktEbLxf+fiux5SfCEwdzWENMvgIbMZD90I62s4GZD9nEjgEWy8ZboI3hck193Vs0bDoTohDISx84f2H2tw==", + "requires": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + }, + "setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + }, + "uuid": { + "version": "2.0.1", + "resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + } + } + }, + "ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", + "requires": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, "eventemitter3": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", @@ -3426,7 +3653,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, "requires": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -3608,7 +3834,6 @@ "version": "4.16.4", "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", - "dev": true, "requires": { "accepts": "~1.3.5", "array-flatten": "1.1.1", @@ -3645,16 +3870,14 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" } } }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -3745,8 +3968,7 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "2.0.1", @@ -3779,6 +4001,14 @@ "websocket-driver": ">=0.5.1" } }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, "file-loader": { "version": "1.1.11", "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", @@ -3789,6 +4019,11 @@ "schema-utils": "^0.4.5" } }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -3832,7 +4067,6 @@ "version": "1.1.1", "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -3893,6 +4127,14 @@ } } }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3911,14 +4153,12 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -3928,8 +4168,7 @@ "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" }, "fragment-cache": { "version": "0.2.1", @@ -3943,8 +4182,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "from2": { "version": "2.3.0", @@ -3965,6 +4203,31 @@ "null-check": "^1.0.0" } }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0" + } + }, + "fs-promise": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-2.0.3.tgz", + "integrity": "sha1-9k5PhUvPaJqovdy6JokW2z20aFQ=", + "requires": { + "any-promise": "^1.3.0", + "fs-extra": "^2.0.0", + "mz": "^2.6.0", + "thenify-all": "^1.6.0" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -4515,7 +4778,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -4570,8 +4832,7 @@ "get-stream": { "version": "3.0.0", "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "get-value": { "version": "2.0.6", @@ -4583,7 +4844,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -4658,6 +4918,22 @@ } } }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "^2.19.0", + "process": "~0.5.1" + }, + "dependencies": { + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + } + } + }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", @@ -4690,11 +4966,36 @@ "minimatch": "~3.0.2" } }, + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + } + }, "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, "handle-thing": { "version": "1.2.5", @@ -4734,14 +5035,12 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, "requires": { "ajv": "^6.5.5", "har-schema": "^2.0.0" @@ -4794,12 +5093,25 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -4842,7 +5154,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -4852,7 +5163,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "dev": true, "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -4868,7 +5178,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, "requires": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -5000,7 +5309,6 @@ "version": "1.6.3", "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, "requires": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -5008,6 +5316,11 @@ "statuses": ">= 1.4.0 < 2" } }, + "http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" + }, "http-parser-js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", @@ -5041,7 +5354,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -5085,16 +5397,29 @@ "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, + "idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "requires": { + "punycode": "2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" + } + } + }, "ieee754": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", - "dev": true + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" }, "iferr": { "version": "0.1.5", @@ -5293,8 +5618,7 @@ "ipaddr.js": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", - "dev": true + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" }, "is-accessor-descriptor": { "version": "0.1.6", @@ -5349,8 +5673,7 @@ "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, "is-data-descriptor": { "version": "0.1.4", @@ -5448,6 +5771,11 @@ "number-is-nan": "^1.0.0" } }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, "is-glob": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", @@ -5457,6 +5785,16 @@ "is-extglob": "^2.1.1" } }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -5477,6 +5815,11 @@ } } }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -5501,6 +5844,11 @@ "path-is-inside": "^1.0.1" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -5531,11 +5879,15 @@ "has": "^1.0.1" } }, - "is-stream": { + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { "version": "1.0.2", @@ -5549,8 +5901,7 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", @@ -5573,8 +5924,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isbinaryfile": { "version": "3.0.3", @@ -5600,8 +5950,7 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul": { "version": "0.4.5", @@ -5854,6 +6203,15 @@ "handlebars": "^4.0.11" } }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, "jasmine": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.3.0.tgz", @@ -5899,6 +6257,11 @@ "dev": true, "optional": true }, + "js-sha3": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.3.1.tgz", + "integrity": "sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM=" + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -5926,8 +6289,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsesc": { "version": "1.3.0", @@ -5944,8 +6306,7 @@ "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.4.1", @@ -5955,8 +6316,7 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json3": { "version": "3.3.2", @@ -5970,11 +6330,18 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "jsonfile": { + "version": "2.4.0", + "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -6134,6 +6501,15 @@ "source-map-support": "^0.5.5" } }, + "keccakjs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", + "integrity": "sha1-HWM6+QfvMFu/ny+mFtVsRFYd+k0=", + "requires": { + "browserify-sha3": "^0.0.1", + "sha3": "^1.1.0" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -6381,6 +6757,11 @@ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", "dev": true }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, "lru-cache": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.4.tgz", @@ -6395,7 +6776,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, "requires": { "pify": "^3.0.0" } @@ -6451,7 +6831,6 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -6461,8 +6840,7 @@ "media-typer": { "version": "0.3.0", "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { "version": "4.0.0", @@ -6516,14 +6894,12 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { "version": "3.1.10", @@ -6550,7 +6926,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, "requires": { "bn.js": "^4.0.0", "brorand": "^1.0.1" @@ -6565,14 +6940,12 @@ "mime-db": { "version": "1.37.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", - "dev": true + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" }, "mime-types": { "version": "2.1.21", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", - "dev": true, "requires": { "mime-db": "~1.37.0" } @@ -6583,6 +6956,19 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "^0.1.0" + } + }, "mini-css-extract-plugin": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.5.tgz", @@ -6610,14 +6996,12 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { "version": "3.0.4", @@ -6630,8 +7014,7 @@ "minimist": { "version": "0.0.8", "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mississippi": { "version": "2.0.0", @@ -6694,11 +7077,28 @@ "version": "0.5.1", "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } }, + "mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", + "requires": { + "mkdirp": "*" + } + }, + "mock-fs": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.7.0.tgz", + "integrity": "sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA==" + }, + "mout": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", + "integrity": "sha1-ujYR318OWx/7/QEWa48C0fX6K5k=" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -6716,8 +7116,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multicast-dns": { "version": "6.2.3", @@ -6735,12 +7134,25 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nan": { "version": "2.11.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", - "dev": true, - "optional": true + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==" + }, + "nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" }, "nanomatch": { "version": "1.2.13", @@ -6764,8 +7176,7 @@ "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, "neo-async": { "version": "2.6.0", @@ -7062,17 +7473,31 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", + "requires": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-component": { "version": "0.0.3", @@ -7166,6 +7591,14 @@ "isobject": "^3.0.1" } }, + "oboe": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.3.tgz", + "integrity": "sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8=", + "requires": { + "http-https": "^1.0.0" + } + }, "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -7176,7 +7609,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, "requires": { "ee-first": "1.1.1" } @@ -7283,6 +7715,11 @@ "os-tmpdir": "^1.0.0" } }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -7292,8 +7729,7 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-is-promise": { "version": "1.1.0", @@ -7325,6 +7761,14 @@ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", "dev": true }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", @@ -7361,7 +7805,6 @@ "version": "5.1.1", "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true, "requires": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", @@ -7399,6 +7842,15 @@ } } }, + "parse-headers": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", + "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", + "requires": { + "for-each": "^0.3.2", + "trim": "0.0.1" + } + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -7435,8 +7887,7 @@ "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, "pascalcase": { "version": "0.1.1", @@ -7488,8 +7939,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { "version": "3.0.0", @@ -7504,7 +7954,6 @@ "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true, "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -7513,29 +7962,30 @@ "sha.js": "^2.4.8" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "^2.0.0" } @@ -7649,6 +8099,11 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -7674,8 +8129,7 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "promise": { "version": "7.3.1", @@ -7840,7 +8294,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", - "dev": true, "requires": { "forwarded": "~0.1.2", "ipaddr.js": "1.8.0" @@ -7861,14 +8314,12 @@ "psl": { "version": "1.1.29", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", - "dev": true + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" }, "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, "requires": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", @@ -7919,8 +8370,17 @@ "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "5.1.1", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } }, "querystring": { "version": "0.2.0", @@ -7963,7 +8423,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -7972,23 +8431,25 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, "requires": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" } }, + "randomhex": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", + "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=" + }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, "requires": { "bytes": "3.0.0", "http-errors": "1.6.3", @@ -8084,7 +8545,6 @@ "version": "2.3.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -8238,7 +8698,6 @@ "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -8335,7 +8794,6 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "requires": { "glob": "^7.0.5" } @@ -8344,7 +8802,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -8382,8 +8839,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex": { "version": "1.1.0", @@ -8397,8 +8853,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sass-graph": { "version": "2.2.4", @@ -8451,6 +8906,36 @@ "ajv-keywords": "^3.1.0" } }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "requires": { + "nan": "^2.0.8" + } + }, + "scrypt-js": { + "version": "2.0.3", + "resolved": "http://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" + }, + "scrypt.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", + "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", + "requires": { + "scrypt": "^6.0.2", + "scryptsy": "^1.2.1" + } + }, + "scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "requires": { + "pbkdf2": "^3.0.3" + } + }, "scss-tokenizer": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", @@ -8474,6 +8959,24 @@ } } }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "requires": { + "commander": "~2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + } + } + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -8540,7 +9043,6 @@ "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, "requires": { "debug": "2.6.9", "depd": "~1.1.2", @@ -8560,8 +9062,7 @@ "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" } } }, @@ -8590,7 +9091,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -8598,6 +9098,18 @@ "send": "0.16.2" } }, + "servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "requires": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -8630,25 +9142,37 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "sha.js": { "version": "2.4.11", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, + "sha3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", + "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", + "requires": { + "nan": "2.10.0" + }, + "dependencies": { + "nan": { + "version": "2.10.0", + "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + } + } + }, "shallow-clone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", @@ -8689,6 +9213,21 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -9100,7 +9639,6 @@ "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", - "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -9155,8 +9693,7 @@ "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" }, "stdout-stream": { "version": "1.4.1", @@ -9236,6 +9773,11 @@ } } }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -9251,7 +9793,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -9274,12 +9815,28 @@ "is-utf8": "^0.2.0" } }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", @@ -9359,6 +9916,37 @@ "has-flag": "^3.0.0" } }, + "swarm-js": { + "version": "0.1.37", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.37.tgz", + "integrity": "sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ==", + "requires": { + "bluebird": "^3.5.0", + "buffer": "^5.0.5", + "decompress": "^4.0.0", + "eth-lib": "^0.1.26", + "fs-extra": "^2.1.2", + "fs-promise": "^2.0.0", + "got": "^7.1.0", + "mime-types": "^2.1.16", + "mkdirp-promise": "^5.0.1", + "mock-fs": "^4.1.0", + "setimmediate": "^1.0.5", + "tar.gz": "^1.0.5", + "xhr-request-promise": "^0.1.2" + }, + "dependencies": { + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + } + } + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -9375,19 +9963,65 @@ "version": "2.2.1", "resolved": "http://registry.npmjs.org/tar/-/tar-2.2.1.tgz", "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "optional": true, "requires": { "block-stream": "*", "fstream": "^1.0.2", "inherits": "2" } }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "tar.gz": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tar.gz/-/tar.gz-1.0.7.tgz", + "integrity": "sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg==", + "requires": { + "bluebird": "^2.9.34", + "commander": "^2.8.1", + "fstream": "^1.0.8", + "mout": "^0.11.0", + "tar": "^2.1.1" + }, + "dependencies": { + "bluebird": { + "version": "2.11.0", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + } + } + }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "through": { "version": "2.3.8", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.5", @@ -9405,6 +10039,11 @@ "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", "dev": true }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, "timers-browserify": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", @@ -9435,6 +10074,11 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -9493,7 +10137,6 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" @@ -9502,8 +10145,7 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" } } }, @@ -9513,6 +10155,11 @@ "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", "dev": true }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -9642,7 +10289,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -9650,8 +10296,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "type-check": { "version": "0.3.2", @@ -9666,7 +10311,6 @@ "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "~2.1.18" @@ -9678,6 +10322,14 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, "typescript": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", @@ -9745,8 +10397,38 @@ "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "unbzip2-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz", + "integrity": "sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==", + "requires": { + "buffer": "^3.0.1", + "through": "^2.3.6" + }, + "dependencies": { + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" + }, + "buffer": { + "version": "3.6.0", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "requires": { + "base64-js": "0.0.8", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + } + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" }, "union-value": { "version": "1.0.0", @@ -9804,8 +10486,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "unset-value": { "version": "1.0.0", @@ -9931,6 +10612,24 @@ "requires-port": "^1.0.0" } }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "^1.0.1" + } + }, + "url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -9956,9 +10655,9 @@ } }, "utf8": { - "version": "2.1.2", - "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", - "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" + "version": "2.1.1", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" }, "util": { "version": "0.10.4", @@ -9972,8 +10671,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "util.promisify": { "version": "1.0.0", @@ -9994,14 +10692,12 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "validate-npm-package-license": { "version": "3.0.4", @@ -10025,14 +10721,12 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -10075,20 +10769,297 @@ } }, "web3": { - "version": "0.20.6", - "resolved": "http://registry.npmjs.org/web3/-/web3-0.20.6.tgz", - "integrity": "sha1-PpcwauAk+yThCj11yIQwJWIhUSA=", + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.0.0-beta.37.tgz", + "integrity": "sha512-8XLgUspdzicC/xHG82TLrcF/Fxzj2XYNJ1KTYnepOI77bj5rvpsxxwHYBWQ6/JOjk0HkZqoBfnXWgcIHCDhZhQ==", + "requires": { + "web3-bzz": "1.0.0-beta.37", + "web3-core": "1.0.0-beta.37", + "web3-eth": "1.0.0-beta.37", + "web3-eth-personal": "1.0.0-beta.37", + "web3-net": "1.0.0-beta.37", + "web3-shh": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-bzz": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.0.0-beta.37.tgz", + "integrity": "sha512-E+dho49Nsm/QpQvYWOF35YDsQrMvLB19AApENxhlQsu6HpWQt534DQul0t3Y/aAh8rlKD6Kanxt8LhHDG3vejQ==", + "requires": { + "got": "7.1.0", + "swarm-js": "0.1.37", + "underscore": "1.8.3" + } + }, + "web3-core": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.0.0-beta.37.tgz", + "integrity": "sha512-cIwEqCj7OJyefQNauI0HOgW4sSaOQ98V99H2/HEIlnCZylsDzfw7gtQUdwnRFiIyIxjbWy3iWsjwDPoXNPZBYg==", + "requires": { + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-core-requestmanager": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-core-helpers": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.37.tgz", + "integrity": "sha512-efaLOzN28RMnbugnyelgLwPWWaSwElQzcAJ/x3PZu+uPloM/lE5x0YuBKvIh7/PoSMlHqtRWj1B8CpuQOUQ5Ew==", + "requires": { + "underscore": "1.8.3", + "web3-eth-iban": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-core-method": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.0.0-beta.37.tgz", + "integrity": "sha512-pKWFUeqnVmzx3VrZg+CseSdrl/Yrk2ioid/HzolNXZE6zdoITZL0uRjnsbqXGEzgRRd1Oe/pFndpTlRsnxXloA==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-promievent": "1.0.0-beta.37", + "web3-core-subscriptions": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-core-promievent": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.37.tgz", + "integrity": "sha512-GTF2r1lP8nJBeA5Gxq5yZpJy9l8Fb9CXGZPfF8jHvaRdQHtm2Z+NDhqYmF833lcdkokRSyfPcXlz1mlWeClFpg==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "1.1.1" + }, + "dependencies": { + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + } + } + }, + "web3-core-requestmanager": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.37.tgz", + "integrity": "sha512-66VUqye5BGp1Zz1r8psCxdNH+GtTjaFwroum2Osx+wbC5oRjAiXkkadiitf6wRb+edodjEMPn49u7B6WGNuewQ==", + "requires": { + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37", + "web3-providers-http": "1.0.0-beta.37", + "web3-providers-ipc": "1.0.0-beta.37", + "web3-providers-ws": "1.0.0-beta.37" + } + }, + "web3-core-subscriptions": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.37.tgz", + "integrity": "sha512-FdXl8so9kwkRRWziuCSpFsAuAdg9KvpXa1fQlT16uoGcYYfxwFO/nkwyBGQzkZt7emShI2IRugcazyPCZDwkOA==", + "requires": { + "eventemitter3": "1.1.1", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37" + }, + "dependencies": { + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + } + } + }, + "web3-eth": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.0.0-beta.37.tgz", + "integrity": "sha512-Eb3aGtkz3G9q+Z9DKgSQNbn/u8RtcZQQ0R4sW9hy5KK47GoT6vab5c6DiD3QWzI0BzitHzR5Ji+3VHf/hPUGgw==", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-core-subscriptions": "1.0.0-beta.37", + "web3-eth-abi": "1.0.0-beta.37", + "web3-eth-accounts": "1.0.0-beta.37", + "web3-eth-contract": "1.0.0-beta.37", + "web3-eth-ens": "1.0.0-beta.37", + "web3-eth-iban": "1.0.0-beta.37", + "web3-eth-personal": "1.0.0-beta.37", + "web3-net": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-eth-abi": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.37.tgz", + "integrity": "sha512-g9DKZGM2OqwKp/tX3W/yihcj7mQCtJ6CXyZXEIZfuDyRBED/iSEIFfieDOd+yo16sokLMig6FG7ADhhu+19hdA==", + "requires": { + "ethers": "4.0.0-beta.1", + "underscore": "1.8.3", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-eth-accounts": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.37.tgz", + "integrity": "sha512-uvbHL62/zwo4GDmwKdqH9c/EgYd8QVnAfpVw8D3epSISpgbONNY7Hr4MRMSd/CqAP12l2Ls9JVQGLhhC83bW6g==", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "scrypt.js": "0.2.0", + "underscore": "1.8.3", + "uuid": "2.0.1", + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + }, + "dependencies": { + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "uuid": { + "version": "2.0.1", + "resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + } + } + }, + "web3-eth-contract": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.37.tgz", + "integrity": "sha512-h1B3A8Z/C7BlnTCHkrWbXZQTViDxfR12lKMeTkT8Sqj5phFmxrBlPE4ORy4lf1Dk5b23mZYE0r/IRACx4ThCrQ==", + "requires": { + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-core-promievent": "1.0.0-beta.37", + "web3-core-subscriptions": "1.0.0-beta.37", + "web3-eth-abi": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-eth-ens": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.37.tgz", + "integrity": "sha512-dR3UkrVzdRrJhfP57xBPx0CMiVnCcYFvh+u2XMkGydrhHgupSUkjqGr89xry/j1T0BkuN9mikpbyhdCVMXqMbg==", + "requires": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.8.3", + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-promievent": "1.0.0-beta.37", + "web3-eth-abi": "1.0.0-beta.37", + "web3-eth-contract": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-eth-iban": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.37.tgz", + "integrity": "sha512-WQRniGJFxH/XCbd7miO6+jnUG+6bvuzfeufPIiOtCbeIC1ypp1kSqER8YVBDrTyinU1xnf1U5v0KBZ2yiWBJxQ==", + "requires": { + "bn.js": "4.11.6", + "web3-utils": "1.0.0-beta.37" + }, + "dependencies": { + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + } + } + }, + "web3-eth-personal": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.37.tgz", + "integrity": "sha512-B4dZpGbD+nGnn48i6nJBqrQ+HB7oDmd+Q3wGRKOsHSK5HRWO/KwYeA7wgwamMAElkut50lIsT9EJl4Apfk3G5Q==", + "requires": { + "web3-core": "1.0.0-beta.37", + "web3-core-helpers": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-net": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-net": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.0.0-beta.37.tgz", + "integrity": "sha512-xG/uBtMdDa1UMXw9KjDUgf3fXA/fDEJUYUS0TDn+U9PMgngA+UVECHNNvQTrVVDxEky38V3sahwIDiopNsQdsw==", + "requires": { + "web3-core": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-utils": "1.0.0-beta.37" + } + }, + "web3-providers-http": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.0.0-beta.37.tgz", + "integrity": "sha512-FM/1YDB1jtZuTo78habFj7S9tNHoqt0UipdyoQV29b8LkGKZV9Vs3is8L24hzuj1j/tbwkcAH+ewIseHwu0DTg==", + "requires": { + "web3-core-helpers": "1.0.0-beta.37", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.37.tgz", + "integrity": "sha512-NdRPRxYMIU0C3u18NI8u4bwbhI9pCg5nRgDGYcmSAx5uOBxiYcQy+hb0WkJRRhBoyIXJmy+s26FoH8904+UnPg==", + "requires": { + "oboe": "2.1.3", + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37" + } + }, + "web3-providers-ws": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.37.tgz", + "integrity": "sha512-8p6ZLv+1JYa5Vs8oBn33Nn3VGFBbF+wVfO+b78RJS1Qf1uIOzjFVDk3XwYDD7rlz9G5BKpxhaQw+6EGQ7L02aw==", "requires": { - "bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", - "crypto-js": "^3.1.4", - "utf8": "^2.1.1", - "xhr2": "*", - "xmlhttprequest": "*" + "underscore": "1.8.3", + "web3-core-helpers": "1.0.0-beta.37", + "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + } + }, + "web3-shh": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.0.0-beta.37.tgz", + "integrity": "sha512-h5STG/xqZNQWtCLYOu7NiMqwqPea8SfkKQUPUFxXKIPVCFVKpHuQEwW1qcPQRJMLhlQIv17xuoUe1A+RzDNbrw==", + "requires": { + "web3-core": "1.0.0-beta.37", + "web3-core-method": "1.0.0-beta.37", + "web3-core-subscriptions": "1.0.0-beta.37", + "web3-net": "1.0.0-beta.37" + } + }, + "web3-utils": { + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.37.tgz", + "integrity": "sha512-kA1fyhO8nKgU21wi30oJQ/ssvu+9srMdjOTKbHYbQe4ATPcr5YNwwrxG3Bcpbu1bEwRUVKHCkqi+wTvcAWBdlQ==", + "requires": { + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randomhex": "0.1.5", + "underscore": "1.8.3", + "utf8": "2.1.1" }, "dependencies": { - "bignumber.js": { - "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", - "from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git" + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" } } }, @@ -10450,6 +11421,16 @@ "webpack-sources": "^1.3.0" } }, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible", + "requires": { + "debug": "^2.2.0", + "nan": "^2.3.3", + "typedarray-to-buffer": "^3.1.2", + "yaeti": "^0.0.6" + } + }, "websocket-driver": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", @@ -10531,17 +11512,52 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, "requires": { "async-limiter": "~1.0.0", "safe-buffer": "~5.1.0", "ultron": "~1.1.0" } }, - "xhr2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", - "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" + "xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "requires": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "requires": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "xhr-request-promise": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz", + "integrity": "sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0=", + "requires": { + "xhr-request": "^1.0.1" + } + }, + "xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", + "requires": { + "cookiejar": "^2.1.1" + } }, "xml2js": { "version": "0.4.19", @@ -10587,8 +11603,7 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "xxhashjs": { "version": "0.2.2", @@ -10605,6 +11620,11 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, + "yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", @@ -10668,6 +11688,15 @@ } } }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", From a935cdb05306ef5aeeaa67457d012c769a6a91b2 Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Fri, 14 Dec 2018 14:33:23 +0100 Subject: [PATCH 6/6] Add comment for the patch --- patch.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/patch.js b/patch.js index 0ae1e8bb..64d99c84 100644 --- a/patch.js +++ b/patch.js @@ -1,3 +1,7 @@ +// TODO: This is a workaround for the following issue: +// https://github.com/angular/angular-cli/issues/1548 +// It should be removed as soon as the error should be fixed. + const fs = require('fs'); const f = 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js';