diff --git a/package.json b/package.json index 47bfa35..fb06a38 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "build-dashboard": "cd src/frontend/dashboard; npm run build; cp -r dist/dashboard/* ../../../static", "build-widget": "rollup -c src/frontend/widget/rollup.config.js; mkdir -p plugins/PluginManager; cp FrontendPlugin.js plugins/PluginManager", "clean": "rm -rf lib static plugins data conf dist widget .rpt2_cache *.js *.ts src/frontend/dashboard/dist", - "update-frontblock": "rm -rf node_modules/frontblock*; npm install" + "update-frontblock": "rm -rf node_modules/frontblock*; npm install", + "webpack": "webpack --entry ./lib/FrontblockLib.js --output ./FrontblockLib.min.js" }, "repository": { "type": "git", diff --git a/src/frontend/dashboard/angular.json b/src/frontend/dashboard/angular.json index 6d6286e..7e5f0e9 100644 --- a/src/frontend/dashboard/angular.json +++ b/src/frontend/dashboard/angular.json @@ -35,7 +35,7 @@ "scripts": [ "node_modules/systemjs/dist/system.js", "node_modules/@webcomponents/custom-elements/custom-elements.min.js", - "node_modules/@clr/icons/clr-icons.min.js" + "node_modules/@clr/icons/clr-icons.min.js" ] }, "configurations": { diff --git a/src/frontend/dashboard/package-lock.json b/src/frontend/dashboard/package-lock.json index a71f301..5c4df88 100644 --- a/src/frontend/dashboard/package-lock.json +++ b/src/frontend/dashboard/package-lock.json @@ -2588,6 +2588,17 @@ "bsert": "~0.0.10" } }, + "btc-hdkey": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/btc-hdkey/-/btc-hdkey-0.0.17.tgz", + "integrity": "sha512-1hzd8DeK/cjrBY6nJ+LenBTGL5rQ+dFBaDEoDSmQ/7zvV3EoV9rsa/aYLLke0Q5XPfbxC1lV/Ro5KpNULA7EYQ==", + "requires": { + "bip39": "^3.0.2", + "bitcoinjs-lib": "^5.1.3", + "bsert": "0.0.10", + "hdkey": "^1.1.1" + } + }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -2973,6 +2984,11 @@ } } }, + "coinselect": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/coinselect/-/coinselect-3.1.11.tgz", + "integrity": "sha1-4fBjvRpYgvZzXuBRm52LWsSpMJk=" + }, "coinstring": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/coinstring/-/coinstring-2.3.0.tgz", diff --git a/src/frontend/dashboard/package.json b/src/frontend/dashboard/package.json index d89051f..6a197f8 100644 --- a/src/frontend/dashboard/package.json +++ b/src/frontend/dashboard/package.json @@ -24,12 +24,16 @@ "@clr/icons": "^2.1.1", "@clr/ui": "^2.1.1", "@webcomponents/custom-elements": "^1.0.0", + "btc-hdkey": "0.0.17", + "coinselect": "^3.1.11", "frontblock": "latest", "frontblock-generic": "^0.22.0", "key-file-storage": "^2.2.4", + "node-fetch": "^2.6.0", "rxjs": "~6.5.2", "systemjs": "^0.21.3", "tslib": "^1.9.0", + "uuid": "^3.3.2", "zone.js": "~0.10.1" }, "devDependencies": { diff --git a/src/frontend/dashboard/src/app/ApiClient/apiclient-consumptions.component.ts b/src/frontend/dashboard/src/app/ApiClient/apiclient-consumptions.component.ts index 480536f..2c524a1 100644 --- a/src/frontend/dashboard/src/app/ApiClient/apiclient-consumptions.component.ts +++ b/src/frontend/dashboard/src/app/ApiClient/apiclient-consumptions.component.ts @@ -1,40 +1,16 @@ import { Component, OnInit, isDevMode } from '@angular/core'; -import { SubscriptionResponse, parseResponse, SuccessResponse } from 'frontblock-generic/Types.js'; +import { SubscriptionResponse, parseResponse, SuccessResponse, Coin } from 'frontblock-generic/Types.js'; +import { default as uuid } from 'uuid/v4' -const fb = !isDevMode() ? window["fb"] : { - ApiClient: { - setConfig: async () => { - await new Promise((resolve, reject) => { - setTimeout(() => { - resolve('Promise A win!'); - }, 500) - }) - }, - getConsumptions: async () => { - return await new Promise((resolve, reject) => { - setTimeout(() => { - resolve([new SubscriptionResponse("654", "321"), new SubscriptionResponse("456", "123")]); - }, 500) - }) - }, - getSubscriptions: async () => { - return await new Promise((resolve, reject) => { - setTimeout(() => { - resolve([new SubscriptionResponse("321"), new SubscriptionResponse("123")]); - }, 500) - }) - }, - unsubscribe: (uid) => new SuccessResponse(), - quit: (uid) => new SuccessResponse() - } -} +declare const fb + @Component({ - selector: 'consumptions', - template: ` + selector: 'consumers', + template: `
-
+
- Consumptions + Consumers
@@ -47,16 +23,18 @@ const fb = !isDevMode() ? window["fb"] : {
-
-
+
+
UUID + Subscription UUID Expiry Creation - + {{line.uid}} - {{line.expiry}} + {{line.message}} + {{line.expiry | date}} {{line.created | date}} @@ -64,7 +42,11 @@ const fb = !isDevMode() ? window["fb"] : { - {{entries.length}} entries + + Users per page + {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} + of {{pagination.totalItems}} users +
@@ -76,9 +58,9 @@ const fb = !isDevMode() ? window["fb"] : { ` }) export class ApiclientConsumptionComponent implements OnInit { - loading:boolean = false - actionName:string = "load" - entries:SubscriptionResponse[] = [] + loading: boolean = false + actionName: string = "load" + entries: SubscriptionResponse[] = [] alerts: { severity: "danger" | "warning" | "success" message: string @@ -88,24 +70,24 @@ export class ApiclientConsumptionComponent implements OnInit { ngOnInit() { } - async load(){ + async load() { this.loading = true this.entries = await fb.ApiClient.getConsumptions() - if(this.entries.length === 0){ - this.alerts.push({ severity: "warning", message: "0 results were returned"}) + if (this.entries.length === 0) { + this.alerts.push({ severity: "warning", message: "0 results were returned" }) } this.loading = false this.actionName = "refresh" } - async quit(uid:string){ + async quit(uid: string) { const r = await fb.ApiClient.quit(uid) - const res = parseResponse(r) - if(res instanceof SuccessResponse){ - this.alerts.push({ severity: "success", message: "Quit consuming "+uid}) + const res = parseResponse(r) + if (res instanceof SuccessResponse) { + this.alerts.push({ severity: "success", message: "Quit consuming " + uid }) this.load() - }else{ - this.alerts.push({ severity: "danger", message: "Error "+res.message}) + } else { + this.alerts.push({ severity: "danger", message: "Error " + res.message }) } } } diff --git a/src/frontend/dashboard/src/app/ApiClient/apiclient-dev.component.ts b/src/frontend/dashboard/src/app/ApiClient/apiclient-dev.component.ts deleted file mode 100644 index 96675ef..0000000 --- a/src/frontend/dashboard/src/app/ApiClient/apiclient-dev.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { SidebarEntry } from 'frontblock-generic/Plugin'; -import { environment } from "../../environments/environment" - -@Component({ - selector: 'apiclient', //!!!! - template: ` -
-
- -
-
- -
-
-
-
- -
-
- ` -}) -export class ApiclientDevComponent implements OnInit { - - constructor() { } - - ngOnInit() { } - -} - -export const sidebarEntry:SidebarEntry = { - icon: "wrench", - route: "dev/apiclient", - text: "DEV ApiClient", -} diff --git a/src/frontend/dashboard/src/app/ApiClient/apiclient-settings-form.component.ts b/src/frontend/dashboard/src/app/ApiClient/apiclient-settings-form.component.ts index 5f0ba9a..60fbf08 100644 --- a/src/frontend/dashboard/src/app/ApiClient/apiclient-settings-form.component.ts +++ b/src/frontend/dashboard/src/app/ApiClient/apiclient-settings-form.component.ts @@ -2,17 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { FrontblockApiConf } from 'frontblock'; import { isDevMode } from '@angular/core'; -const fb = !isDevMode ? window["fb"] : { - ApiClient: { - setConfig: async () => { - await new Promise((resolve, reject) => { - setTimeout(() => { - resolve('Promise A win!'); - }, 500) - }) - } - } -} +declare const fb @Component({ selector: 'settings', diff --git a/src/frontend/dashboard/src/app/ApiClient/apiclient-subscriptions.component.ts b/src/frontend/dashboard/src/app/ApiClient/apiclient-subscriptions.component.ts index 3508009..13552f9 100644 --- a/src/frontend/dashboard/src/app/ApiClient/apiclient-subscriptions.component.ts +++ b/src/frontend/dashboard/src/app/ApiClient/apiclient-subscriptions.component.ts @@ -1,33 +1,7 @@ import { Component, OnInit, isDevMode } from '@angular/core'; -import { SubscriptionResponse, SuccessResponse, parseResponse } from 'frontblock-generic/Types.js'; - -const fb = !isDevMode() ? window["fb"] : { - ApiClient: { - setConfig: async () => { - await new Promise((resolve, reject) => { - setTimeout(() => { - resolve('Promise A win!'); - }, 500) - }) - }, - getConsumptions: async () => { - return await new Promise((resolve, reject) => { - setTimeout(() => { - resolve([new SubscriptionResponse("654", "321"), new SubscriptionResponse("456", "123")]); - }, 500) - }) - }, - getSubscriptions: async () => { - return await new Promise((resolve, reject) => { - setTimeout(() => { - resolve([new SubscriptionResponse("321"), new SubscriptionResponse("123")]); - }, 500) - }) - }, - unsubscribe: (uid) => new SuccessResponse(), - quit: (uid) => new SuccessResponse() - } -} +import { SubscriptionResponse, SuccessResponse, parseResponse, Coin } from 'frontblock-generic/Types.js'; +import { default as uuid } from 'uuid/v4' +declare const fb @Component({ selector: 'subscriptions', @@ -52,20 +26,34 @@ const fb = !isDevMode() ? window["fb"] : {
UUID + - + {{line.uid}} - {{line.expiry}} - {{line.created | date}} + - {{entries.length}} entries + + Users per page + {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} + of {{pagination.totalItems}} users +
@@ -81,7 +69,7 @@ const fb = !isDevMode() ? window["fb"] : { export class ApiclientSubscriptionComponent implements OnInit { loading: boolean = false actionName: string = "load" - entries: SubscriptionResponse[] = [] + entries: (SubscriptionResponse )[] = [] alerts: { severity: "danger" | "warning" | "success" message: string diff --git a/src/frontend/dashboard/src/app/ApiClient/module.ts b/src/frontend/dashboard/src/app/ApiClient/module.ts index 2ba8bf2..dee338c 100644 --- a/src/frontend/dashboard/src/app/ApiClient/module.ts +++ b/src/frontend/dashboard/src/app/ApiClient/module.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; -import { ApiclientDevComponent as ApiclientComponent } from './apiclient-dev.component'; import { ApiclientFormComponent } from './apiclient-settings-form.component'; import { ApiclientConsumptionComponent } from './apiclient-consumptions.component'; import { ApiclientSubscriptionComponent } from './apiclient-subscriptions.component'; @@ -21,12 +20,11 @@ import { FormsModule } from '@angular/forms'; RouterModule.forChild([ {path: "settings", component: ApiclientFormComponent}, {path: "subscriptions", component: ApiclientSubscriptionComponent}, - {path: "consumptions", component: ApiclientConsumptionComponent}, + {path: "consumers", component: ApiclientConsumptionComponent}, ]), ], exports: [RouterModule], declarations: [ - ApiclientComponent, ApiclientFormComponent, ApiclientConsumptionComponent, ApiclientSubscriptionComponent @@ -42,8 +40,8 @@ export class PluginModule implements FrontendPlugin{ route: "settings", text: "Settings" },{ - route: "consumptions", - text: "Consumptions" + route: "consumers", + text: "Consumers" },{ route: "subscriptions", text: "Subscriptions" diff --git a/src/frontend/dashboard/src/app/PluginManager/plugins.component.ts b/src/frontend/dashboard/src/app/PluginManager/plugins.component.ts index 0bb93ad..85b5822 100644 --- a/src/frontend/dashboard/src/app/PluginManager/plugins.component.ts +++ b/src/frontend/dashboard/src/app/PluginManager/plugins.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, isDevMode } from '@angular/core'; declare const fb @Component({ selector: 'plugins', //!!!! @@ -15,35 +15,64 @@ declare const fb
-
-
-
- Plugins -
-
-
- - - {{entry.name}} - - - - - - + + + + - - - -
-
-
+ +
-
` }) export class PluginsComponent implements OnInit { @@ -56,14 +85,20 @@ export class PluginsComponent implements OnInit { name: "test II: Return of test", available: "0.0.1", installed: "0.0.1", - status: "Available" + status: "Stopped" }, { name: "test 3", available: "0.0.2", - installed: "0.0.1", + installed: "", + status: "Available" + }, { + name: "test IV: minor bump", + available: "0.9.27", + installed: "0.0.11", status: "Stopped" },] + reloading = false updatepending = false updateCandidate = "" @@ -78,7 +113,9 @@ export class PluginsComponent implements OnInit { } delete(name) { - this.plugins.find((el) => el.name === name).status = "Available" + let plugin = this.plugins.find((el) => el.name === name) + plugin.status = "Available" + plugin.installed = "" } showConfirmation(name) { @@ -98,6 +135,21 @@ export class PluginsComponent implements OnInit { this.updatepending = !this.updatepending } + async reload(){ + this.reloading = true + if(isDevMode()){ + await new Promise((resolve, reject) => { + setTimeout(resolve, 1000) + }) + this.plugins = this.plugins.map(plugin => { + const parts = plugin.available.split('.') + plugin.available = parts[0]+"."+parts[1]+"."+(parseInt(parts[2])+1) + return plugin + }) + this.reloading = false + } + } + ngOnInit() { } } diff --git a/src/frontend/dashboard/src/app/Wallet/btc/address-viewer.component.ts b/src/frontend/dashboard/src/app/Wallet/btc/address-viewer.component.ts new file mode 100644 index 0000000..de724f0 --- /dev/null +++ b/src/frontend/dashboard/src/app/Wallet/btc/address-viewer.component.ts @@ -0,0 +1,115 @@ + + +import { Component, OnInit, isDevMode } from '@angular/core'; +import { PluginsComponent } from './btc.component'; +declare const fb +@Component({ + selector: 'address-viewer', //!!!! + template: ` +
+
+ Addresses +
+ + + + {{line.message}} + + + + + + Address + Balance + Pending + Estimate total + + + {{line.address}} + {{line.confirmed.balance}} + {{line.unconfirmed.balance}} + {{line.total.balance}} + +
+
+ +
+ +
+
Public key
+ {{parent.keys[line.address].publicExtendedKey}} +
Private key
+ {{parent.keys[line.address].privateExtendedKey}} +
+
+
+
+ + + + per page + {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} + of {{pagination.totalItems}} + + +
+ + + Address + Balance + Pending + Estimate total + + + {{line.address}} + {{line.confirmed.balance}} + {{line.unconfirmed.balance}} + {{line.total.balance}} + +
+
+ +
+ +
+
Public key
+ {{parent.keys[line.address].publicExtendedKey}} +
Private key
+ {{parent.keys[line.address].privateExtendedKey}} +
+
+
+
+ + + + per page + {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} + of {{pagination.totalItems}} + + +
+
+ ` +}) +export class AddressViewerComponent implements OnInit { + + regularAddresses = [] + changeAddresses = [] + keys = {} + parent:PluginsComponent + ngOnInit() { } + + setParent(parent:PluginsComponent){ + this.parent = parent + } + + setRegularAddresses(addresses){ + this.regularAddresses = addresses + } + + setChangeAddresses(addresses){ + this.changeAddresses = addresses + } +} + diff --git a/src/frontend/dashboard/src/app/Wallet/btc/btc.component.ts b/src/frontend/dashboard/src/app/Wallet/btc/btc.component.ts new file mode 100644 index 0000000..9be6a21 --- /dev/null +++ b/src/frontend/dashboard/src/app/Wallet/btc/btc.component.ts @@ -0,0 +1,508 @@ +import { Component, OnInit, isDevMode, ViewChild, AfterViewInit } from '@angular/core'; +import { WalletGeneratorComponent } from './wallet-generator.component'; +import { WalletPickerComponent } from './wallet-picker.component'; +import { HDKey } from "btc-hdkey" +import { AddressViewerComponent } from './address-viewer.component'; +const fetch = require("node-fetch") +const coinselect = require('coinselect/accumulative') +import { TransactionBuilder } from 'bitcoinjs-lib' +import { networks } from 'bitcoinjs-lib' +let feeRate = 55 // satoshis per byte + +const hdkey = new HDKey() +declare const fb +@Component({ + selector: 'plugins', //!!!! + template: ` + + + + +
+ + +
+ + +
+ + +
+ +
+ + + +
+ +
+
+
+ Send +
+ +
+ + + +
+ + +
+
+ +
+ + +
+ + + +
+ + +
+
+ {{rootkey.publicExtendedKey}} +
+ + + + {{line.message}} + + + + +
+

Balance: {{balance.confirmed}}

+

+ Unconfirmed: {{balance.unconfirmed}}
+ Estimated total: {{balance.total}} +

+
+
+ + +
+ + +
+ + +
+ +
+
+ + + + + + + ` +}) +export class PluginsComponent implements AfterViewInit { + + wallets:{ + [someLabel in string]:{ + key:string + name:string + } + } = {} + txToSend:any + rootkey = { + publicExtendedKey: "", + privateExtendedKey: "" + } + keys = {} + regaddresses = [] + changeaddresses = [] + balance = { + confirmed: 0, + total: 0, + unconfirmed: 0 + } + mode : { + net:network + } = { + net: "testnet" + } + sendto:string + amount:number + + constructor(){ + window["btc"] = () => this + } + @ViewChild(AddressViewerComponent, {static: false}) + AddressViewerComponent:AddressViewerComponent + + @ViewChild(WalletGeneratorComponent, {static: false}) + WalletGeneratorComponent:WalletGeneratorComponent + + @ViewChild(WalletPickerComponent, {static: false}) + WalletPickerComponent:WalletPickerComponent + + ngAfterViewInit(): void { + this.WalletGeneratorComponent.setParent(this) + this.WalletPickerComponent.setParent(this) + this.AddressViewerComponent.setParent(this) + + //tprv8cXm1S7PGS2fHuLjZajuDZZsvxerzv4zZJJAhkLAWZzwz5rE7efHm31xsqpzfoGMHBNC8bkRcsjiMdmkSuNn5C1qNqk7rrk1pCuhk4HfVak + //tpubD9Do9r9dQoiLBNNXTEQVcyDzVzAoAFFu8btwzGNTvqoLpa6zk3UswXdq3zeArrakUu8huCtG1L5pTqNYNftanuutf57fn1C74rBzFybH1xe + this.loadKey("tprv8cXm1S7PGS2fHuLjZajuDZZsvxerzv4zZJJAhkLAWZzwz5rE7efHm31xsqpzfoGMHBNC8bkRcsjiMdmkSuNn5C1qNqk7rrk1pCuhk4HfVak") + } + + addWallet(wallet){ + /* store somewhere */ + + this.wallets[wallet.name] = wallet + this.WalletPickerComponent.setWallets(this.wallets) + + } + + showWizard(){ + this.WalletGeneratorComponent.open() + } + + loadKey(key:string){ + this.wallets = {} + this.txToSend = null + this.sendto = "" + this.regaddresses = [] + + const t = hdkey.checkHDKey(key) + if(t){ + this.mode = t + } + + this.rootkey = hdkey.HDKeyFromExtendedKey(key) + this.refresh() + } + + async refresh(){ + this.keys = {} + this.changeaddresses = [] + this.regaddresses = [] + this.AddressViewerComponent.setChangeAddresses([]) + this.AddressViewerComponent.setRegularAddresses([]) + this.balance.total = 0 + this.balance.unconfirmed = 0 + this.balance.confirmed = 0 + + let p1 = this.updateChange() + let p2 = this.update() + + let balances:any[] = await Promise.all([p1,p2]) + balances.forEach(balance => { + this.balance.confirmed += balance.confirmed + this.balance.total += balance.total + this.balance.unconfirmed += balance.unconfirmed + }) + + console.log(this.changeaddresses) + + this.AddressViewerComponent.setChangeAddresses(this.changeaddresses) + this.AddressViewerComponent.setRegularAddresses(this.regaddresses) + } + + + async getInfo(rootAddr: string, n = 10, skip = 0, changeAddresses = false): Promise{ + const t = hdkey.checkHDKey(rootAddr) + if(!t){ + return false + } + let addresses: string[] = [] + for(let i = skip; i < skip+n; i++){ + let addr + if(changeAddresses){ + addr = hdkey.deriveAddress(rootAddr, i, 'm/1/') + }else{ + addr = hdkey.deriveAddress(rootAddr, i) + } + if(!addr){ + return false + } + addresses.push(addr) + } + let lookupstr = addresses.join(',') + try{ + let r = await fetch(api[t.net]+'/address/'+lookupstr, { + 'method':'GET', + 'mode':'cors', + 'data': {limit: 200} + }) + if(r.status !== 200){ + return {success: false} + } + + let json = (await r).json() + return json + }catch(e){ + return {success: false} + } + } + + async getTxs(address: string, type:network){ + let r = await fetch(api[type]+'/address/'+address, { + 'method':'GET', + 'mode':'cors' + }) + if(r.status !== 200){ + return {success: false} + } + + return (await r).json() + } + + async getUnspentTxs(addresses:string[], type:network):Promise{ + let lookupstr = addresses.join(',') + try{ + let r = await fetch(api[type]+'/address/'+lookupstr+'/unspent', { + 'method':'GET', + 'mode':'cors' + }) + if(r.status !== 200){ + return {success: false} + } + + return (await r).json() + }catch(e){ + return {success: false} + } + } + + + getKeyForAddress(keyName){ + return this.keys[keyName] + } + + async update(){ + let n = 1 + let regAddresses + + while(true){ + try{ + regAddresses = await this.getInfo(this.rootkey.publicExtendedKey, 115*n, 115*(n-1)) + }catch(e){ + break + } + if(regAddresses.success === true){ + if('addresses' in regAddresses){ // multiple + this.regaddresses = [...this.regaddresses, ...regAddresses.addresses] + } + if('address' in regAddresses){ + this.regaddresses.push(regAddresses.address) + } + n++ + }else{ + console.log('No more balance found after attempting ', 115*n, 'addresses') + if(this.rootkey.privateExtendedKey != null){ + for(let i = 0; i < 115*n; i++){ + const keyN = hdkey.deriveKey(this.rootkey.privateExtendedKey, i) + const addrN = hdkey.addressFromHDKey(keyN._publicKey, this.mode.net) + this.keys[addrN] = keyN + } + } + break + } + } + + if(this.regaddresses.length === 0){ + const addr = hdkey.deriveAddress(this.rootkey.publicExtendedKey, 0) + this.regaddresses.push({ + address: addr, + confirmed: {balance: 0}, + unconfirmed: {balance: 0}, + total: {balance: 0}, + }) + return { + total: 0, + unconfirmed: 0, + confirmed: 0 + } + } + const resMap: any = {} + this.regaddresses.forEach(a => { + resMap[a.address] = a + }) + + const confirmed = Object.values(resMap).reduce((accum:any, obj:any) => { + return accum + parseFloat(obj.confirmed.balance) + }, 0) + const unconfirmed = Object.values(resMap).reduce((accum:any, obj:any) => { + return accum + parseFloat(obj.unconfirmed.balance) + }, 0) + + return { + total: confirmed+unconfirmed, + unconfirmed: unconfirmed, + confirmed: confirmed + } + } + + async updateChange(){ + let n = 1 + let res + + while(true){ + try{ + res = await this.getInfo(this.rootkey.publicExtendedKey, 115*n, 115*(n-1), true) + }catch(e){ + break + } + if(res.success === true){ + if('addresses' in res){ // multiple + this.changeaddresses = [...this.changeaddresses, ...res.addresses] + } + if('address' in res){ + this.changeaddresses.push(res.address) + } + n++ + }else{ + console.log('No more balance found after attempting ', 115*n, 'addresses') + if(this.rootkey.privateExtendedKey != null){ + for(let i = 0; i < 115*n; i++){ + const keyN = hdkey.deriveKey(this.rootkey.privateExtendedKey, i, 'm/1/') + const addrN = hdkey.addressFromHDKey(keyN._publicKey, this.mode.net) + this.keys[addrN] = keyN + } + } + break + } + } + + if(this.changeaddresses.length === 0){ + const addr = hdkey.deriveAddress(this.rootkey.publicExtendedKey, 0, 'm/1/') + this.changeaddresses.push({ + address: addr, + confirmed: {balance: 0}, + unconfirmed: {balance: 0}, + total: {balance: 0}, + }) + return { + total: 0, + unconfirmed: 0, + confirmed: 0 + } + } + + const resMap: any = {} + this.changeaddresses.forEach(a => { + resMap[a.address] = a + }) + + const confirmed = Object.values(resMap).reduce((accum:any, obj:any) => { + return accum + parseFloat(obj.confirmed.balance) + }, 0) + const unconfirmed = Object.values(resMap).reduce((accum:any, obj:any) => { + return accum + parseFloat(obj.unconfirmed.balance) + }, 0) + + return { + confirmed: confirmed, + unconfirmed: unconfirmed, + total: unconfirmed + confirmed + } + } + + async createTx(target:string, value:number){ + + console.log(target, value) + + if(target == null || typeof target !== 'string' || target === '' || value == null || value <= 0 ){ + //this.error = 'Bad inputs. Expected bitcoin address and number' + return + } + + if(value > this.balance.confirmed){ + //this.error = 'Insufficient funds' + return + } + + let addresses: string[] = this.regaddresses.map(a => a.address) + addresses = [...addresses, ...this.changeaddresses.map(a => a.address)] + const txs = await this.getUnspentTxs(addresses, this.mode.net) + + if(txs == null || txs.success !== true || txs.unspent.length === 0){ + //this.error = 'No UTXOs found' + return + } + + const utxos = txs.unspent.map(t => { + return { + address: t.addresses[0], + txId: t.txid, + vout: t.n, + value: t.value * 100000000 + } + }) + + let { inputs, outputs, fee } = coinselect(utxos, [{address: target, value: value*100000000}], feeRate) + + // .inputs and .outputs will be undefined if no solution was found + if (!inputs || !outputs){ + //this.error = 'Could not build a valid transaction' + return + } + + const txb = new TransactionBuilder(networks[this.mode.net]) + + + txb.setVersion(1) + inputs.forEach((input) => { + txb.addInput(input.txId, input.vout) + }) + outputs.forEach((output) => { + if (!output.address) { + output.address = hdkey.deriveAddress(this.rootkey.publicExtendedKey, this.changeaddresses.length, 'm/1/') + } + txb.addOutput(output.address, output.value) + }) + inputs.forEach((input, i) => { + txb.sign(i, this.keys[input.address]) + }) + + this.txToSend = txb.build() + + this.sendTx() + } + + async sendTx(){ + if(this.txToSend == null){ + //this.error = 'No transaction to send!' + return + } + + let url + if(this.mode.net === 'mainnet'){ + url = 'https://api.smartbit.com.au/v1/blockchain/pushtx' + }else{ + url = 'https://testnet-api.smartbit.com.au/v1/blockchain/pushtx' + } + let r = await fetch(url, { + 'method':'POST', + 'body': JSON.stringify({'hex': this.txToSend.toHex()}) + }) + this.txToSend = null + if(r.status === 200){ + console.log(r) + this.refresh() + }else{ + //this.error = 'The API '+url+' returned a non-200 error code '+r.status+' '+r.statusText + console.log(r) + } + } +} + + +type network = 'testnet' | 'mainnet' +type keyType = 'public' | 'private' + +type bip32Keypair = { publicExtendedKey: string, privateExtendedKey: string } + +const api = { + testnet: 'https://testnet-api.smartbit.com.au/v1/blockchain', + mainnet: 'https://api.smartbit.com.au/v1/blockchain' +} \ No newline at end of file diff --git a/src/frontend/dashboard/src/app/Wallet/btc/wallet-generator.component.ts b/src/frontend/dashboard/src/app/Wallet/btc/wallet-generator.component.ts new file mode 100644 index 0000000..8efc1fe --- /dev/null +++ b/src/frontend/dashboard/src/app/Wallet/btc/wallet-generator.component.ts @@ -0,0 +1,265 @@ +import { Component, OnInit, isDevMode, ViewChild } from '@angular/core'; +import { ClrWizard } from '@clr/angular'; +import { HDKey } from "btc-hdkey" +import { PluginsComponent } from './btc.component'; + +declare const fb +@Component({ + selector: 'wallet-generator', //!!!! + template: ` + + Bitcoin wallet generator and importer + + Cancel + Back + Next + Finish + + + Menemonic/BIP39 (optional) + + Menemonic/BIP39 + +

+ A menemonic is a collection of words that is supposed to be easier to remember than a complex seed. It may be used to reconstruct the private key. +

+

+ Enter your menemonic below or generate a new one. +

+ +
+ + + + + +
+ + Cancel + {{menemonic.length==0?"Skip":"Next"}} + +
+ + + Seed phrase (optional) + + Seed phrase + +

+ If you entered a menemonic in the previous step, a seed was generated from it. +

+

+ If you would like to use your own seed enter it below. Use something sufficiently hard to guess. +

+ + + + + + + Cancel + Back + {{seed.length==0?"Skip":"Next"}} + +
+ + + Extended Key/BIP32 +

+ Accepts keys in the xpub and xprv (BIP32) format +

+ +
+ + + Confirm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeValue
menemonic{{menemonic}}
seed
xpub
xprv
+ + + + + + Cancel + Finish + +
+
+ + ` +}) +export class WalletGeneratorComponent implements OnInit { + @ViewChild("wizard", {static: false}) wizard: ClrWizard; + key:string = "" + keyInvalid = true + accept = false + seed:string = "" + mdOpen: boolean = false + checkKey: boolean = true + menemonic:string = "" + keypair: any = {} + testnet: boolean = false + profileName + private hdKey = new HDKey() + private parent:PluginsComponent + + ngOnInit() { } + + open(){ + this.key = "" + this.keyInvalid = true + this.seed = "" + this.checkKey = true + this.menemonic = "" + this.keypair = {} + this.testnet = false + this.wizard.reset() + this.mdOpen = true + } + + setParent(parent:PluginsComponent){ + this.parent = parent + } + + async generateMenemonic(){ + this.menemonic = this.hdKey.randomMenemonic() + } + + async seedFromMenemonic(){ + try{ + this.seed = this.hdKey.seedFromMenemonic(this.menemonic) + }catch(e){ + /* invalid menemonic */ + console.log(e) + } + } + + async accountFromSeed(){ + this.keypair = this.hdKey.deriveAccount(this.seed, this.testnet?"testnet":"mainnet", 0) + console.log(this.keypair) + this.key = this.keypair.privateExtendedKey != null?this.keypair.privateExtendedKey:this.keypair.publicExtendedKey + this.keyInvalid = false + } + + async importKey(){ + this.hdKey.HDKeyFromExtendedKey(this.key) + } + + checkBip32(){ + return this.hdKey.checkHDKey(this.keypair.privateExtendedKey != null?this.keypair.privateExtendedKey:this.keypair.publicExtendedKey) + } + + finish(){ + this.parent.addWallet({ + name: this.key.substr(4,15), + key: this.key + }) + } + + public doCustomClick(buttonType: string): void { + if ("menemonic-next" === buttonType) { + if(this.menemonic.length != 0){ + this.seedFromMenemonic() + } + this.wizard.next(); + } + + if ("myfinish" === buttonType) { + this.finish() + this.wizard.close() + } + + if ("seed-next" === buttonType) { + if(this.seed.length != 0){ + this.accountFromSeed() + } + this.wizard.next(); + } + + if ("back" === buttonType) { + this.wizard.previous(); + } + } + + updateSeed(){ + this.menemonic = "" + } + + updateKey(){ + this.keyInvalid = true + this.menemonic = "" + this.seed = "" + let key + try{ + key = this.hdKey.HDKeyFromExtendedKey(this.key) + }catch(e){ + /* invalid key */ + console.log("bad key") + } + if(key){ + this.keypair = key + this.keyInvalid = false + } + } +} \ No newline at end of file diff --git a/src/frontend/dashboard/src/app/Wallet/btc/wallet-picker.component.ts b/src/frontend/dashboard/src/app/Wallet/btc/wallet-picker.component.ts new file mode 100644 index 0000000..a4a1a2d --- /dev/null +++ b/src/frontend/dashboard/src/app/Wallet/btc/wallet-picker.component.ts @@ -0,0 +1,50 @@ + + +import { Component, OnInit, isDevMode } from '@angular/core'; +import { PluginsComponent } from './btc.component'; +declare const fb +@Component({ + selector: 'walletpicker', //!!!! + + template: ` +
+
+ Wallets +
+ + + + {{line.message}} + + + + + + New / Import + + + + + + {{line.name}} + + +
+ ` +}) +export class WalletPickerComponent implements OnInit { + private parent:PluginsComponent + wallets = [] + + setWallets(wallets){ + this.wallets = Object.values(wallets) + } + + setParent(parent:PluginsComponent){ + this.parent = parent + } + + ngOnInit() { } + +} + diff --git a/src/frontend/dashboard/src/app/Wallet/module.ts b/src/frontend/dashboard/src/app/Wallet/module.ts new file mode 100644 index 0000000..6627e5a --- /dev/null +++ b/src/frontend/dashboard/src/app/Wallet/module.ts @@ -0,0 +1,60 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; + +import { PluginsComponent } from './btc/btc.component'; +import { WalletPickerComponent } from './btc/wallet-picker.component'; +import { AddressViewerComponent } from './btc/address-viewer.component'; + +import { FrontendPlugin, SidebarEntries } from 'frontblock-generic/Plugin'; +import { ClarityModule } from '@clr/angular'; +import { FormsModule } from '@angular/forms'; +import { WalletGeneratorComponent } from './btc/wallet-generator.component'; + + +@NgModule({ + imports: [ + FormsModule, + ClarityModule, + + CommonModule, + RouterModule.forChild([ + {path: "btc", component: PluginsComponent}, + ]), + ], + exports: [RouterModule], + declarations: [ + PluginsComponent, + WalletPickerComponent, + AddressViewerComponent, + WalletGeneratorComponent + ] +}) +export class PluginModule implements FrontendPlugin{ + getSidebarEntry(): SidebarEntries { + return { + icon: "wallet", + text: "Wallets", + parentRoute: "wallet", + links: [{ + route: "btc", + text: "BTC Wallet" + },{ + route: "ltc", + text: "LTC Wallet" + },{ + route: "eth", + text: "ETH Wallet" + },{ + route: "xrp", + text: "XRP Wallet" + },{ + route: "xlm", + text: "XLM Wallet" + },{ + route: "settings", + text: "Settings" + }] + } + } +} diff --git a/src/frontend/dashboard/src/app/app.component.scss b/src/frontend/dashboard/src/app/app.component.scss index b3c8c89..b09567c 100644 --- a/src/frontend/dashboard/src/app/app.component.scss +++ b/src/frontend/dashboard/src/app/app.component.scss @@ -1,3 +1,10 @@ .heightmax{ height: 100% +} +.break-word { + word-wrap: break-word; + } +.monospace { + font-family: monospace; + font-size: 90% } \ No newline at end of file diff --git a/src/frontend/dashboard/src/app/app.component.ts b/src/frontend/dashboard/src/app/app.component.ts index 6cebd83..46ed6a4 100644 --- a/src/frontend/dashboard/src/app/app.component.ts +++ b/src/frontend/dashboard/src/app/app.component.ts @@ -1,7 +1,6 @@ -import { Component, ChangeDetectorRef, NgZone, ViewChild, OnInit, AfterContentInit } from '@angular/core'; +import { Component, ChangeDetectorRef, NgZone, ViewChild, OnInit, AfterContentInit, isDevMode } from '@angular/core'; import { SidebarComponent } from './sidebar/sidebar.component'; import { SidebarEntryService } from './sidebar-entry-service.service'; - @Component({ selector: 'app-root', templateUrl: './app.component.html', @@ -15,6 +14,9 @@ export class AppComponent implements AfterContentInit { constructor(private zone:NgZone, private sidebarService: SidebarEntryService){ window["refresh"] = setInterval(() => zone.run(()=>{ /*this triggers an angular reload*/}), 200) + if(isDevMode()){ + require("../assets/FrontblockLib") + } } ngAfterContentInit(){ diff --git a/src/frontend/dashboard/src/app/content-area/main.component.html b/src/frontend/dashboard/src/app/content-area/main.component.html index 717dc5e..3548d48 100644 --- a/src/frontend/dashboard/src/app/content-area/main.component.html +++ b/src/frontend/dashboard/src/app/content-area/main.component.html @@ -1,3 +1,3 @@ -
+
diff --git a/src/frontend/dashboard/src/app/dynamic-loader/dynamic-loader.component.ts b/src/frontend/dashboard/src/app/dynamic-loader/dynamic-loader.component.ts index 9d100e2..c35249b 100644 --- a/src/frontend/dashboard/src/app/dynamic-loader/dynamic-loader.component.ts +++ b/src/frontend/dashboard/src/app/dynamic-loader/dynamic-loader.component.ts @@ -39,12 +39,11 @@ import { AfterViewInit, Component, ViewChild } from '@angular/core'; import { SidebarComponent } from '../sidebar/sidebar.component'; import { Router } from '@angular/router'; import { FrontendPlugin, SidebarEntries, SidebarEntry } from "frontblock-generic/Plugin" -import { SidebarEntryService } from '../sidebar-entry-service.service'; import { environment } from "../../environments/environment" const fb = environment.production ? window["fb"] : { PluginManager: { - getLoadedPluginNames: () => ["ApiClient", "PluginManager"] + getLoadedPluginNames: () => ["ApiClient", "PluginManager", "Wallet"] } } diff --git a/src/frontend/dashboard/src/app/header-bar/header-bar.component.ts b/src/frontend/dashboard/src/app/header-bar/header-bar.component.ts index 6dda03f..f14285f 100644 --- a/src/frontend/dashboard/src/app/header-bar/header-bar.component.ts +++ b/src/frontend/dashboard/src/app/header-bar/header-bar.component.ts @@ -6,7 +6,7 @@ import { Component, OnInit, isDevMode } from '@angular/core'; styleUrls: ['./header-bar.component.scss'] }) export class HeaderBarComponent implements OnInit { - devmode = isDevMode()?"{ DEV }":"" + devmode = isDevMode()?"{ ng-DEV }":"" constructor() { } ngOnInit() { diff --git a/src/frontend/dashboard/src/assets/.gitkeep b/src/frontend/dashboard/src/assets/.gitkeep index e69de29..bf603bd 100644 --- a/src/frontend/dashboard/src/assets/.gitkeep +++ b/src/frontend/dashboard/src/assets/.gitkeep @@ -0,0 +1 @@ +./FrontblockLib.js \ No newline at end of file diff --git a/src/frontend/dashboard/src/assets/FrontblockLib.js b/src/frontend/dashboard/src/assets/FrontblockLib.js new file mode 100644 index 0000000..ed1d145 --- /dev/null +++ b/src/frontend/dashboard/src/assets/FrontblockLib.js @@ -0,0 +1,19 @@ +!function(t){var e={};function n(r){if(e[r])return e[r].exports;var s=e[r]={i:r,l:!1,exports:{}};return t[r].call(s.exports,s,s.exports,n),s.l=!0,s.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var s in t)n.d(r,s,function(e){return t[e]}.bind(null,s));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=6)}([function(t,e,n){"use strict"; +/*! + * assert.js - assertions for javascript + * Copyright (c) 2018, Christopher Jeffrey (MIT License). + * https://github.com/chjj/bsert + */class r extends Error{constructor(t){"string"==typeof t&&(t={message:t}),null!==t&&"object"==typeof t||(t={});let e=null,n="fail",r=Boolean(t.generatedMessage);var s;if(null!=t.message&&(e="string"==typeof(s=t.message)?s:E(s)?d(s):p(s)),"string"==typeof t.operator&&(n=t.operator),null==e){if("fail"===n)e="Assertion failed.";else{e=`${p(t.actual)} ${n} ${p(t.expected)}`}r=!0}super(e);let o=this.constructor;"function"==typeof t.stackStartFunction?o=t.stackStartFunction:"function"==typeof t.stackStartFn&&(o=t.stackStartFn),this.type="AssertionError",this.name="AssertionError [ERR_ASSERTION]",this.code="ERR_ASSERTION",this.generatedMessage=r,this.actual=t.actual,this.expected=t.expected,this.operator=n,Error.captureStackTrace&&Error.captureStackTrace(this,o)}}function s(t,e){if(!t){let n=!1;if(0===arguments.length)e="No value argument passed to `assert()`.",n=!0;else if(null==e)e="Assertion failed.",n=!0;else if(E(e))throw e;throw new r({message:e,actual:t,expected:!0,operator:"==",generatedMessage:n,stackStartFn:s})}}function o(t,e,n){if(!Object.is(t,e)){if(E(n))throw n;throw new r({message:n,actual:t,expected:e,operator:"strictEqual",stackStartFn:o})}}function i(t,e,n){if(Object.is(t,e)){if(E(n))throw n;throw new r({message:n,actual:t,expected:e,operator:"notStrictEqual",stackStartFn:i})}}function a(t,e,n){"string"==typeof e&&(n=e,e=void 0);let s=!1,o=null;l("function"==typeof t,"func","function");try{t()}catch(t){s=!0,o=t}if(s){if(g(o,e,n,a)){let t=!1;throw null==n&&(n="Got unwanted exception.",t=!0),new r({message:n,actual:o,expected:e,operator:"doesNotThrow",generatedMessage:t,stackStartFn:a})}throw o}}async function h(t,e,n){"string"==typeof e&&(n=e,e=void 0);let s=!1,o=null;"function"!=typeof t&&l(O(t),"func","promise");try{O(t)?await t:await t()}catch(t){s=!0,o=t}if(!s){let t=!1;throw null==n&&(n="Missing expected rejection.",t=!0),new r({message:n,actual:void 0,expected:e,operator:"rejects",generatedMessage:t,stackStartFn:h})}if(!g(o,e,n,h))throw o}async function u(t,e,n){"string"==typeof e&&(n=e,e=void 0);let s=!1,o=null;"function"!=typeof t&&l(O(t),"func","promise");try{O(t)?await t:await t()}catch(t){s=!0,o=t}if(s){if(g(o,e,n,u)){let t=!1;throw null==n&&(n="Got unwanted rejection.",t=!0),new r({message:n,actual:void 0,expected:e,operator:"doesNotReject",generatedMessage:t,stackStartFn:u})}throw o}}function c(t,e,n){if(!y(t,e,!1)){if(E(n))throw n;throw new r({message:n,actual:t,expected:e,operator:"deepStrictEqual",stackStartFn:c})}}function f(t,e,n){if(y(t,e,!0)){if(E(n))throw n;throw new r({message:n,actual:t,expected:e,operator:"notDeepStrictEqual",stackStartFn:f})}}function l(t,e,n){if(!t){let t;t=null==e?"Invalid type for parameter.":null==n?`Invalid type for "${e}".`:`"${e}" must be a(n) ${n}.`;const r=new TypeError(t);throw Error.captureStackTrace&&Error.captureStackTrace(r,l),r}}function p(t){switch(typeof t){case"undefined":return"undefined";case"object":return null===t?"null":`[${function(t){const e=function(t){return v(t).slice(8,-1)}(t);if(null==t)return e;if("Object"!==e&&"Error"!==e)return e;let n,r;try{n=t.constructor}catch(t){}if(null==n)return e;try{r=n.name}catch(t){return e}return"string"!=typeof r||0===r.length?e:r}(t)}]`;case"boolean":case"number":return`${t}`;case"string":return t.length>80&&(t=`${t.substring(0,77)}...`),JSON.stringify(t);case"symbol":return d(t);case"function":return`[${function(t){let e;try{e=t.name}catch(t){}return"string"!=typeof e||0===e.length?"Function":`Function: ${e}`}(t)}]`;case"bigint":return`${t}n`;default:return`[${typeof t}]`}}function d(t){try{return String(t)}catch(t){return"Object"}}function g(t,e,n,s){if(null==e)return!0;if(S(e))return e.test(t);if("function"!=typeof e){if(s===a||s===u)throw new TypeError('"expected" must not be an object.');if("object"!=typeof e)throw new TypeError('"expected" must be an object.');let o=!1;if(null==n){n=`Missing expected ${s===h?"rejection":"exception"}.`,o=!0}if(null==t||"object"!=typeof t)throw new r({actual:t,expected:e,message:n,operator:s.name,generatedMessage:o,stackStartFn:s});const i=Object.keys(e);if(E(e)&&i.push("name","message"),0===i.length)throw new TypeError('"expected" may not be an empty object.');for(const a of i){const i=e[a],h=t[a];if(("string"!=typeof h||!S(i)||!i.test(h))&&!(a in t&&y(h,i,!1)))throw new r({actual:t,expected:e,message:n,operator:s.name,generatedMessage:o,stackStartFn:s})}return!0}return void 0!==e.prototype&&t instanceof e||!Error.isPrototypeOf(e)&&!0===e.call({},t)}function y(t,e,n){try{return w(t,e,null)}catch(t){return n}}function w(t,e,n){if(Object.is(t,e))return!0;if(!A(t)||!A(e))return!1;if(v(t)!==v(e))return!1;if(Object.getPrototypeOf(t)!==Object.getPrototypeOf(e))return!1;if(b(t)&&b(e))return t.equals(e);if(t instanceof Date)return Object.is(t.getTime(),e.getTime());if(S(t))return t.source===e.source&&t.global===e.global&&t.multiline===e.multiline&&t.lastIndex===e.lastIndex&&t.ignoreCase===e.ignoreCase;if(E(t)&&t.message!==e.message)return!1;if(function(t){return t instanceof ArrayBuffer}(t)&&(t=new Uint8Array(t),e=new Uint8Array(e)),function(t){return ArrayBuffer.isView(t)}(t)&&!b(t)){if(b(e))return!1;const n=new Uint8Array(t.buffer),r=new Uint8Array(e.buffer);if(n.length!==r.length)return!1;for(let t=0;t>>1?null:s}return e}s.AssertionError=r,s.assert=s,s.strict=s,s.ok=s,s.equal=o,s.notEqual=i,s.strictEqual=o,s.notStrictEqual=i,s.fail=function t(e){let n=!1;if(E(e))throw e;throw null==e&&(e="Assertion failed.",n=!0),new r({message:e,actual:!1,expected:!0,operator:"fail",generatedMessage:n,stackStartFn:t})},s.throws=function t(e,n,s){"string"==typeof n&&(s=n,n=void 0);let o=!1,i=null;l("function"==typeof e,"func","function");try{e()}catch(t){o=!0,i=t}if(!o){let e=!1;throw null==s&&(s="Missing expected exception.",e=!0),new r({message:s,actual:void 0,expected:n,operator:"throws",generatedMessage:e,stackStartFn:t})}if(!g(i,n,s,t))throw i},s.doesNotThrow=a,s.rejects=h,s.doesNotReject=u,s.ifError=function t(e){if(null!=e){let n="ifError got unwanted exception: ";throw"object"==typeof e&&"string"==typeof e.message?0===e.message.length&&e.constructor?n+=e.constructor.name:n+=e.message:n+=p(e),new r({message:n,actual:e,expected:null,operator:"ifError",generatedMessage:!0,stackStartFn:t})}},s.deepEqual=c,s.notDeepEqual=f,s.deepStrictEqual=c,s.notDeepStrictEqual=f,s.bufferEqual=function t(e,n,s,o){if(R(s)||(o=s,s=null),null==s&&(s="hex"),n=_(e,n,s),l(b(e),"actual","buffer"),l(b(n),"expected","buffer"),e!==n&&!e.equals(n)){if(E(o))throw o;throw new r({message:o,actual:e.toString(s),expected:n.toString(s),operator:"bufferEqual",stackStartFn:t})}},s.notBufferEqual=function t(e,n,s,o){if(R(s)||(o=s,s=null),null==s&&(s="hex"),n=_(e,n,s),l(b(e),"actual","buffer"),l(b(n),"expected","buffer"),e===n||e.equals(n)){if(E(o))throw o;throw new r({message:o,actual:e.toString(s),expected:n.toString(s),operator:"notBufferEqual",stackStartFn:t})}},s.enforce=l,s.range=function t(e,n){if(!e){const e=new RangeError(null!=n?`"${n}" is out of range.`:"Parameter is out of range.");throw Error.captureStackTrace&&Error.captureStackTrace(e,t),e}},t.exports=s},function(t,e,n){"use strict";(function(t){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +var r=n(11),s=n(12),o=n(13);function i(){return h.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(t,e){if(i()=i())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i().toString(16)+" bytes");return 0|t}function d(t,e){if(h.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var n=t.length;if(0===n)return 0;for(var r=!1;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return q(t).length;default:if(r)return F(t).length;e=(""+e).toLowerCase(),r=!0}}function g(t,e,n){var r=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return C(this,e,n);case"utf8":case"utf-8":return _(this,e,n);case"ascii":return k(this,e,n);case"latin1":case"binary":return T(this,e,n);case"base64":return R(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return x(this,e,n);default:if(r)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),r=!0}}function y(t,e,n){var r=t[e];t[e]=t[n],t[n]=r}function w(t,e,n,r,s){if(0===t.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=s?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(s)return-1;n=t.length-1}else if(n<0){if(!s)return-1;n=0}if("string"==typeof e&&(e=h.from(e,r)),h.isBuffer(e))return 0===e.length?-1:m(t,e,n,r,s);if("number"==typeof e)return e&=255,h.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?s?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):m(t,[e],n,r,s);throw new TypeError("val must be string, number or Buffer")}function m(t,e,n,r,s){var o,i=1,a=t.length,h=e.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(t.length<2||e.length<2)return-1;i=2,a/=2,h/=2,n/=2}function u(t,e){return 1===i?t[e]:t.readUInt16BE(e*i)}if(s){var c=-1;for(o=n;oa&&(n=a-h),o=n;o>=0;o--){for(var f=!0,l=0;ls&&(r=s):r=s;var o=e.length;if(o%2!=0)throw new TypeError("Invalid hex string");r>o/2&&(r=o/2);for(var i=0;i>8,s=n%256,o.push(s),o.push(r);return o}(e,t.length-n),t,n,r)}function R(t,e,n){return 0===e&&n===t.length?r.fromByteArray(t):r.fromByteArray(t.slice(e,n))}function _(t,e,n){n=Math.min(t.length,n);for(var r=[],s=e;s239?4:u>223?3:u>191?2:1;if(s+f<=n)switch(f){case 1:u<128&&(c=u);break;case 2:128==(192&(o=t[s+1]))&&(h=(31&u)<<6|63&o)>127&&(c=h);break;case 3:o=t[s+1],i=t[s+2],128==(192&o)&&128==(192&i)&&(h=(15&u)<<12|(63&o)<<6|63&i)>2047&&(h<55296||h>57343)&&(c=h);break;case 4:o=t[s+1],i=t[s+2],a=t[s+3],128==(192&o)&&128==(192&i)&&128==(192&a)&&(h=(15&u)<<18|(63&o)<<12|(63&i)<<6|63&a)>65535&&h<1114112&&(c=h)}null===c?(c=65533,f=1):c>65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c),s+=f}return function(t){var e=t.length;if(e<=P)return String.fromCharCode.apply(String,t);var n="",r=0;for(;r0&&(t=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(t+=" ... ")),""},h.prototype.compare=function(t,e,n,r,s){if(!h.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===n&&(n=t?t.length:0),void 0===r&&(r=0),void 0===s&&(s=this.length),e<0||n>t.length||r<0||s>this.length)throw new RangeError("out of range index");if(r>=s&&e>=n)return 0;if(r>=s)return-1;if(e>=n)return 1;if(this===t)return 0;for(var o=(s>>>=0)-(r>>>=0),i=(n>>>=0)-(e>>>=0),a=Math.min(o,i),u=this.slice(r,s),c=t.slice(e,n),f=0;fs)&&(n=s),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var o=!1;;)switch(r){case"hex":return v(this,t,e,n);case"utf8":case"utf-8":return b(this,t,e,n);case"ascii":return E(this,t,e,n);case"latin1":case"binary":return A(this,t,e,n);case"base64":return O(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,t,e,n);default:if(o)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),o=!0}},h.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var P=4096;function k(t,e,n){var r="";n=Math.min(t.length,n);for(var s=e;sr)&&(n=r);for(var s="",o=e;on)throw new RangeError("Trying to access beyond buffer length")}function N(t,e,n,r,s,o){if(!h.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>s||et.length)throw new RangeError("Index out of range")}function I(t,e,n,r){e<0&&(e=65535+e+1);for(var s=0,o=Math.min(t.length-n,2);s>>8*(r?s:1-s)}function B(t,e,n,r){e<0&&(e=4294967295+e+1);for(var s=0,o=Math.min(t.length-n,4);s>>8*(r?s:3-s)&255}function L(t,e,n,r,s,o){if(n+r>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function U(t,e,n,r,o){return o||L(t,0,n,4),s.write(t,e,n,r,23,4),n+4}function M(t,e,n,r,o){return o||L(t,0,n,8),s.write(t,e,n,r,52,8),n+8}h.prototype.slice=function(t,e){var n,r=this.length;if((t=~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),(e=void 0===e?r:~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),e0&&(s*=256);)r+=this[t+--e]*s;return r},h.prototype.readUInt8=function(t,e){return e||j(t,1,this.length),this[t]},h.prototype.readUInt16LE=function(t,e){return e||j(t,2,this.length),this[t]|this[t+1]<<8},h.prototype.readUInt16BE=function(t,e){return e||j(t,2,this.length),this[t]<<8|this[t+1]},h.prototype.readUInt32LE=function(t,e){return e||j(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},h.prototype.readUInt32BE=function(t,e){return e||j(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},h.prototype.readIntLE=function(t,e,n){t|=0,e|=0,n||j(t,e,this.length);for(var r=this[t],s=1,o=0;++o=(s*=128)&&(r-=Math.pow(2,8*e)),r},h.prototype.readIntBE=function(t,e,n){t|=0,e|=0,n||j(t,e,this.length);for(var r=e,s=1,o=this[t+--r];r>0&&(s*=256);)o+=this[t+--r]*s;return o>=(s*=128)&&(o-=Math.pow(2,8*e)),o},h.prototype.readInt8=function(t,e){return e||j(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},h.prototype.readInt16LE=function(t,e){e||j(t,2,this.length);var n=this[t]|this[t+1]<<8;return 32768&n?4294901760|n:n},h.prototype.readInt16BE=function(t,e){e||j(t,2,this.length);var n=this[t+1]|this[t]<<8;return 32768&n?4294901760|n:n},h.prototype.readInt32LE=function(t,e){return e||j(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},h.prototype.readInt32BE=function(t,e){return e||j(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},h.prototype.readFloatLE=function(t,e){return e||j(t,4,this.length),s.read(this,t,!0,23,4)},h.prototype.readFloatBE=function(t,e){return e||j(t,4,this.length),s.read(this,t,!1,23,4)},h.prototype.readDoubleLE=function(t,e){return e||j(t,8,this.length),s.read(this,t,!0,52,8)},h.prototype.readDoubleBE=function(t,e){return e||j(t,8,this.length),s.read(this,t,!1,52,8)},h.prototype.writeUIntLE=function(t,e,n,r){(t=+t,e|=0,n|=0,r)||N(this,t,e,n,Math.pow(2,8*n)-1,0);var s=1,o=0;for(this[e]=255&t;++o=0&&(o*=256);)this[e+s]=t/o&255;return e+n},h.prototype.writeUInt8=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,1,255,0),h.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},h.prototype.writeUInt16LE=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,2,65535,0),h.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):I(this,t,e,!0),e+2},h.prototype.writeUInt16BE=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,2,65535,0),h.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):I(this,t,e,!1),e+2},h.prototype.writeUInt32LE=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,4,4294967295,0),h.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):B(this,t,e,!0),e+4},h.prototype.writeUInt32BE=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,4,4294967295,0),h.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):B(this,t,e,!1),e+4},h.prototype.writeIntLE=function(t,e,n,r){if(t=+t,e|=0,!r){var s=Math.pow(2,8*n-1);N(this,t,e,n,s-1,-s)}var o=0,i=1,a=0;for(this[e]=255&t;++o>0)-a&255;return e+n},h.prototype.writeIntBE=function(t,e,n,r){if(t=+t,e|=0,!r){var s=Math.pow(2,8*n-1);N(this,t,e,n,s-1,-s)}var o=n-1,i=1,a=0;for(this[e+o]=255&t;--o>=0&&(i*=256);)t<0&&0===a&&0!==this[e+o+1]&&(a=1),this[e+o]=(t/i>>0)-a&255;return e+n},h.prototype.writeInt8=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,1,127,-128),h.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},h.prototype.writeInt16LE=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,2,32767,-32768),h.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):I(this,t,e,!0),e+2},h.prototype.writeInt16BE=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,2,32767,-32768),h.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):I(this,t,e,!1),e+2},h.prototype.writeInt32LE=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,4,2147483647,-2147483648),h.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):B(this,t,e,!0),e+4},h.prototype.writeInt32BE=function(t,e,n){return t=+t,e|=0,n||N(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),h.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):B(this,t,e,!1),e+4},h.prototype.writeFloatLE=function(t,e,n){return U(this,t,e,!0,n)},h.prototype.writeFloatBE=function(t,e,n){return U(this,t,e,!1,n)},h.prototype.writeDoubleLE=function(t,e,n){return M(this,t,e,!0,n)},h.prototype.writeDoubleBE=function(t,e,n){return M(this,t,e,!1,n)},h.prototype.copy=function(t,e,n,r){if(n||(n=0),r||0===r||(r=this.length),e>=t.length&&(e=t.length),e||(e=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),t.length-e=0;--s)t[s+e]=this[s+n];else if(o<1e3||!h.TYPED_ARRAY_SUPPORT)for(s=0;s>>=0,n=void 0===n?this.length:n>>>0,t||(t=0),"number"==typeof t)for(o=e;o55295&&n<57344){if(!s){if(n>56319){(e-=3)>-1&&o.push(239,191,189);continue}if(i+1===r){(e-=3)>-1&&o.push(239,191,189);continue}s=n;continue}if(n<56320){(e-=3)>-1&&o.push(239,191,189),s=n;continue}n=65536+(s-55296<<10|n-56320)}else s&&(e-=3)>-1&&o.push(239,191,189);if(s=null,n<128){if((e-=1)<0)break;o.push(n)}else if(n<2048){if((e-=2)<0)break;o.push(n>>6|192,63&n|128)}else if(n<65536){if((e-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function q(t){return r.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(D,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function $(t,e,n,r){for(var s=0;s=e.length||s>=t.length);++s)e[s+n]=t[s];return s}}).call(this,n(2))},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){"use strict";var r,s="object"==typeof Reflect?Reflect:null,o=s&&"function"==typeof s.apply?s.apply:function(t,e,n){return Function.prototype.apply.call(t,e,n)};r=s&&"function"==typeof s.ownKeys?s.ownKeys:Object.getOwnPropertySymbols?function(t){return Object.getOwnPropertyNames(t).concat(Object.getOwnPropertySymbols(t))}:function(t){return Object.getOwnPropertyNames(t)};var i=Number.isNaN||function(t){return t!=t};function a(){a.init.call(this)}t.exports=a,a.EventEmitter=a,a.prototype._events=void 0,a.prototype._eventsCount=0,a.prototype._maxListeners=void 0;var h=10;function u(t){return void 0===t._maxListeners?a.defaultMaxListeners:t._maxListeners}function c(t,e,n,r){var s,o,i,a;if("function"!=typeof n)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof n);if(void 0===(o=t._events)?(o=t._events=Object.create(null),t._eventsCount=0):(void 0!==o.newListener&&(t.emit("newListener",e,n.listener?n.listener:n),o=t._events),i=o[e]),void 0===i)i=o[e]=n,++t._eventsCount;else if("function"==typeof i?i=o[e]=r?[n,i]:[i,n]:r?i.unshift(n):i.push(n),(s=u(t))>0&&i.length>s&&!i.warned){i.warned=!0;var h=new Error("Possible EventEmitter memory leak detected. "+i.length+" "+String(e)+" listeners added. Use emitter.setMaxListeners() to increase limit");h.name="MaxListenersExceededWarning",h.emitter=t,h.type=e,h.count=i.length,a=h,console&&console.warn&&console.warn(a)}return t}function f(t,e,n){var r={fired:!1,wrapFn:void 0,target:t,type:e,listener:n},s=function(){for(var t=[],e=0;e0&&(i=e[0]),i instanceof Error)throw i;var a=new Error("Unhandled error."+(i?" ("+i.message+")":""));throw a.context=i,a}var h=s[t];if(void 0===h)return!1;if("function"==typeof h)o(h,this,e);else{var u=h.length,c=d(h,u);for(n=0;n=0;o--)if(n[o]===e||n[o].listener===e){i=n[o].listener,s=o;break}if(s<0)return this;0===s?n.shift():function(t,e){for(;e+1=0;r--)this.removeListener(t,e[r]);return this},a.prototype.listeners=function(t){return l(this,t,!0)},a.prototype.rawListeners=function(t){return l(this,t,!1)},a.listenerCount=function(t,e){return"function"==typeof t.listenerCount?t.listenerCount(e):p.call(t,e)},a.prototype.listenerCount=p,a.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(t,e,n){"use strict";(function(e){t.exports={Client:e.WebSocket||e.MozWebSocket,EventSource:e.EventSource}}).call(this,n(2))},function(t,e,n){"use strict";(function(e){const r=n(0),s=e.alloc(0),o={OPEN:0,CLOSE:1,PING:2,PONG:3,MESSAGE:4,UPGRADE:5,NOOP:6};class i{constructor(t,n,i){r("number"==typeof t),r(t>>>0===t),r(t<=o.NOOP),r("boolean"==typeof i),i?(null==n&&(n=s),r(e.isBuffer(n))):(null==n&&(n=""),r("string"==typeof n)),this.type=t,this.data=n,this.binary=i}toString(){let t="";return this.binary?(t+="b",t+=this.type.toString(10),t+=this.data.toString("base64")):(t+=this.type.toString(10),t+=this.data),t}static fromString(t){r("string"==typeof t);let n,s=t.charCodeAt(0),i=!1;return 98===s?(r(t.length>1),s=t.charCodeAt(1),n=e.from(t.substring(2),"base64"),i=!0):n=t.substring(1),r((s-=48)>=0&&s<=9),r(s<=o.NOOP),new this(s,n,i)}size(){let t=1;return this.binary?t+=this.data.length:t+=e.byteLength(this.data,"utf8"),t}toRaw(){const t=e.allocUnsafe(this.size());return t[0]=this.type,this.binary?this.data.copy(t,1):this.data.length>0&&t.write(this.data,1,"utf8"),t}static fromRaw(t){r(e.isBuffer(t)),r(t.length>0);const n=t[0];return r(n<=o.NOOP),new this(n,t.slice(1),!0)}}i.types=o,i.table=["open","close","ping","pong","message","upgrade","noop"],t.exports=i}).call(this,n(1).Buffer)},function(module,exports,__webpack_require__){"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const Types_1=__webpack_require__(7);var bsock=__webpack_require__(8);class FrontblockConfigLib{constructor(){this.parseSubResponse=Types_1.parseSubResponse,this.parseResponse=Types_1.parseResponse,this.socket=bsock.connect(2e4,"localhost",!1),this.init()}async init(){const t=await this.info();for(const e of t){let t;switch(e.info.type){case"call":t=this.callGenerator(e.name,e.args);break;case"hook":t=this.hookGenerator(e.name,e.args);break;case"unhook":t=this.unhookGenerator(e.name,e.args)}null==this[e.owner]&&(this[e.owner]={}),this[e.owner][e.name]=t,this[e.owner][e.name].bind(this)}}async info(){return await this.socket.call("info")}callGenerator(fnName,fnArgs){return eval("( () => async ("+fnArgs+') => { return await this.socket.call("'+fnName+'", '+fnArgs+")} )()")}hookGenerator(fnName,fnArgs){return eval("( () => async ("+fnArgs+(0!==fnArgs.length?",":"")+' callback) => {\n const r = await this.socket.call("'+fnName+'", '+fnArgs+")\n const res = await this.parseSubResponse(r);\n if(res.uid != null){\n this.socket.hook(res.uid, callback)\n }\n return res\n } )()")}unhookGenerator(fnName,fnArgs){return eval("( () => async ("+fnArgs+') => {\n const r = await this.socket.call("'+fnName+'", '+fnArgs+")\n const res = await this.parseResponse(r)\n console.log(res)\n if(res.uid != null)\n this.socket.unhook(res.uid)\n return res\n } )()")}}exports.FrontblockConfigLib=FrontblockConfigLib,window.fb=new FrontblockConfigLib,window.setup=async()=>{await Promise.all([fb.PluginManager.installPlugin("ApiClient"),fb.PluginManager.installPlugin("HtmlSupplier"),fb.PluginManager.installPlugin("PaymentManager"),fb.PluginManager.installPlugin("BTCWallet")]),await fb.PluginManager.installPlugin("PluginManager"),location.reload()}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class r{constructor(t){this.message=t}}e.Response=r;class s extends r{constructor(t){super(t),this.result="Success"}}e.SuccessResponse=s;class o extends r{constructor(t="Unknown error"){super(t),this.result="Error"}}e.ErrorResponse=o;class i extends s{constructor(t,e){super(e),this.uid=t}}function a(t){return null==t.result?new o("Faulty response"):"Success"==t.result?null!=t.uid?new i(t.uid,t.message):new s:"Error"==t.result?new o(t.message):new o("Faulty response")}e.SubscriptionResponse=i,e.parseResponse=a,e.parseSubResponse=function(t){let e=a(t);return e instanceof s?null==t.uid?new o("Expected a SubscriptionResponse but got a SuccessResponse"):new i(t.uid,t.message):e}},function(t,e,n){"use strict";const r=n(4),s=n(9),o=n(10);e.WebSocket=r,e.Server=s,e.server=()=>new s,e.createServer=s.createServer.bind(s),e.attach=s.attach.bind(s),e.Socket=o,e.socket=()=>new o,e.connect=o.connect.bind(o)},function(t,e,n){"use strict";const r=n(3);t.exports=class extends r{constructor(t){super(),this.sockets=new Set,this.channels=new Map,this.mounts=[]}attach(){return this}mount(){}async open(){}async close(){}join(){return!0}leave(){return!0}channel(){return null}to(){}all(){}static attach(t,e){return new this(e).attach(t)}static createServer(t){return new this(t)}}},function(t,e,n){"use strict";(function(e){const r=n(0),s=n(3),o=n(4).Client,i=n(14),a=n(5),h=n(15),u=n(23),c=n(24),f=n(25);class l{constructor(t,e,n){this.resolve=t,this.reject=e,this.time=n}}function p(t){return null!==t&&"number"!=typeof t&&"string"!=typeof t?null:t}function d(t){return"string"!=typeof t?"No message.":t}function g(t){return"string"!=typeof t?null:t}function y(t,e,n){if(!t){const t=new TypeError(`'${e}' must be a(n) ${n}.`);throw Error.captureStackTrace&&Error.captureStackTrace(t,y),t}}t.exports=class extends s{constructor(){super(),this.server=null,this.ws=null,this.protocol="",this.url="ws://127.0.0.1:80/socket.io/?transport=websocket",this.ssl=!1,this.host="127.0.0.1",this.port=80,this.inbound=!1,this.handshake=!1,this.opened=!1,this.connected=!1,this.challenge=!1,this.destroyed=!1,this.reconnection=!0,this.time=0,this.sequence=0,this.pingInterval=25e3,this.pingTimeout=6e4,this.lastPing=0,this.parser=new u,this.binary=!1,this.packet=null,this.timer=null,this.jobs=new Map,this.hooks=new Map,this.channels=new Set,this.events=new s,this.buffer=[],this.admin=!1,this.auth=!1}accept(t,e,n,s){r(!this.ws,"Cannot accept twice."),r(t),r(e),r(n),r(n.remoteAddress),r(null!=n.remotePort),r(s);let o="ws",i=n.remoteAddress,a=n.remotePort;return n.encrypted&&(o="wss"),-1!==i.indexOf(":")&&(i=`[${i}]`),a||(a=0),this.server=t,this.binary=-1===e.url.indexOf("b64=1"),this.url=`${o}://${i}:${a}/socket.io/?transport=websocket`,this.ssl="wss"===o,this.host=n.remoteAddress,this.port=n.remotePort,this.inbound=!0,this.ws=s,this.init(),this}connect(t,e,n,s){r(!this.ws,"Cannot connect twice."),"string"==typeof t&&(s=e,[t,e,n]=h.parseURL(t));let i="ws";n&&(i="wss"),e||(e="127.0.0.1"),r("string"==typeof e),r((65535&t)===t,"Must pass a port."),r(!n||"boolean"==typeof n),r(!s||Array.isArray(s));let a=e;-1!==e.indexOf(":")&&"["!==e[0]&&(a=`[${e}]`);const u=`${i}://${a}:${t}/socket.io/?transport=websocket`;return this.binary=!0,this.url=u,this.ssl=n,this.host=e,this.port=t,this.inbound=!1,this.ws=new o(u,s),this.init(),this}init(){this.protocol=this.ws.protocol,this.time=Date.now(),this.observe(),this.parser.on("error",t=>{this.emit("error",t)}),this.parser.on("frame",async t=>{try{await this.handleFrame(t)}catch(t){this.emit("error",t)}}),this.start()}observe(){const t=this.ws;r(t),t.binaryType="arraybuffer",t.onopen=async()=>{await this.onOpen()},t.onmessage=async t=>{await this.onMessage(t)},t.onerror=async t=>{await this.onError(t)},t.onclose=async t=>{await this.onClose(t)}}async onOpen(){this.destroyed||this.inbound&&(r(!this.opened),r(!this.connected),r(!this.handshake),this.opened=!0,this.handshake=!0,await this.emitAsync("open"),this.sendHandshake(),this.connected=!0,await this.emitAsync("connect"),this.sendConnect())}async emitAsync(t,...e){const n=this.listeners(t);for(const t of n)try{await t(...e)}catch(t){this.emit("error",t)}}async onMessage(t){if(this.destroyed)return;let n;try{n=await function(t){return new Promise((n,r)=>{if("string"!=typeof t)if(t&&"object"==typeof t)if(e.isBuffer(t))n(t);else if(t instanceof ArrayBuffer){const r=e.from(t);n(r)}else if(t.buffer instanceof ArrayBuffer){const r=e.from(t.buffer,t.byteOffset,t.byteLength);n(r)}else{if("undefined"!=typeof Blob&&Blob&&t instanceof Blob){const r=new FileReader;return r.onloadend=()=>{const t=e.from(r.result);n(t)},void r.readAsArrayBuffer(t)}r(new Error("Bad data object."))}else r(new Error("Bad data object."));else n(t)})}(t.data)}catch(t){return void this.emit("error",t)}"string"!=typeof n?this.parser.feedBinary(n):this.parser.feedString(n)}async onError(t){this.destroyed||(this.emit("error",new Error(t.message)),this.inbound?this.destroy():this.close())}async onClose(t){if(this.destroyed)return;if(1e3===t.code||1001===t.code)return this.connected||this.emit("error",new Error("Could not connect.")),this.inbound?void this.destroy():void this.close();const e=c[t.code]||"UNKNOWN_CODE",n=t.reason||"Unknown reason",r=new Error(`Websocket Closed: ${n} (code=${e}).`);r.reason=t.reason||"",r.code=t.code||0,this.emit("error",r),this.inbound?this.destroy():this.reconnection?this.close():this.destroy()}close(){if(!this.destroyed){this.time=Date.now(),this.packet=null,this.handshake=!1,this.connected=!1,this.challenge=!1,this.sequence=0,this.lastPing=0;for(const[t,e]of this.jobs)this.jobs.delete(t),e.reject(new Error("Job timed out."));r(this.ws),this.ws.onopen=()=>{},this.ws.onmessage=()=>{},this.ws.onerror=()=>{},this.ws.onclose=()=>{},this.ws.close(),this.emitAsync("disconnect")}}error(t){this.destroyed||this.emit("error",new Error(t))}destroy(){this.destroyed||(this.close(),this.stop(),this.opened=!1,this.destroyed=!0,this.buffer.length=0,this.emitAsync("close"),this.removeAllListeners(),this.on("error",()=>{}))}send(t){this.destroyed||(r(this.ws),t.binary&&this.binary?this.ws.send(t.toRaw()):this.ws.send(t.toString()))}reconnect(){r(!this.inbound),this.close(),this.ws=new o(this.url),this.time=Date.now(),this.observe()}start(){r(this.ws),r(null==this.timer),this.timer=setInterval(()=>this.stall(),5e3)}stop(){null!=this.timer&&(clearInterval(this.timer),this.timer=null)}stall(){const t=Date.now();if(r(this.ws),!this.connected)return t-this.time>1e4?this.inbound||!this.reconnection?(this.error("Timed out waiting for connection."),void this.destroy()):(this.error("Timed out waiting for connection. Reconnecting..."),void this.reconnect()):void 0;for(const[e,n]of this.jobs)t-n.time>6e5&&(this.jobs.delete(e),n.reject(new Error("Job timed out.")));return this.inbound||this.challenge?!this.inbound&&t-this.lastPing>this.pingTimeout?(this.error("Connection is stalling (ping)."),this.inbound?void this.destroy():void this.close()):void 0:(this.challenge=!0,this.lastPing=t,void this.sendPing())}async handleFrame(t){if(!this.destroyed)switch(t.type){case a.types.OPEN:return this.handleOpen(t);case a.types.CLOSE:return this.handleClose(t);case a.types.PING:return this.handlePing(t);case a.types.PONG:return this.handlePong(t);case a.types.MESSAGE:return this.handleMessage(t);case a.types.UPGRADE:return this.handleUpgrade(t);case a.types.NOOP:return this.handleNoop(t);default:throw new Error("Unknown frame.")}}async handleOpen(t){if(this.inbound)throw new Error("Inbound socket sent an open frame.");if(t.binary)throw new Error("Received a binary open frame.");if(this.handshake)throw new Error("Duplicate open frame.");const e=JSON.parse(t.data);y(e&&"object"==typeof e,"open","object");const{pingInterval:n,pingTimeout:r}=e;y(n>>>0===n,"interval","uint32"),y(r>>>0===r,"timeout","uint32"),this.pingInterval=n,this.pingTimeout=r,this.handshake=!0,this.opened||(this.opened=!0,await this.emitAsync("open"))}async handleClose(t){if(this.inbound)throw new Error("Inbound socket sent a close frame.");this.close()}async handlePing(){if(!this.inbound)throw new Error("Outbound socket sent a ping frame.");this.sendPong()}async handlePong(){if(this.inbound)throw new Error("Inbound socket sent a pong frame.");if(!this.challenge)return this.error("Remote node sent bad pong."),void this.destroy();this.challenge=!1}async handleMessage(t){if(this.packet){const e=this.packet;if(!t.binary)throw new Error("Received non-binary frame as attachment.");return e.buffers.push(t.data),e.buffers.length===e.attachments?(this.packet=null,this.handlePacket(e)):void 0}if(t.binary)throw new Error("Received binary frame as a message.");const e=i.fromString(t.data);if(!(e.attachments>0))return this.handlePacket(e);this.packet=e}async handleUpgrade(t){if(!this.inbound)throw new Error("Outbound socket sent an upgrade frame.");throw new Error("Cannot upgrade from websocket.")}async handleNoop(t){}sendFrame(t,e,n){this.send(new a(t,e,n))}sendOpen(t){this.sendFrame(a.types.OPEN,t,!1)}sendClose(t){this.sendFrame(a.types.CLOSE,t,!1)}sendPing(t){this.sendFrame(a.types.PING,t,!1)}sendPong(t){this.sendFrame(a.types.PONG,t,!1)}sendMessage(t){this.sendFrame(a.types.MESSAGE,t,!1)}sendBinary(t){this.sendFrame(a.types.MESSAGE,t,!0)}sendHandshake(){const t=JSON.stringify({sid:"00000000000000000000",upgrades:[],pingInterval:this.pingInterval,pingTimeout:this.pingTimeout});this.sendOpen(t)}async handlePacket(t){if(!this.destroyed)switch(t.type){case i.types.CONNECT:return this.handleConnect();case i.types.DISCONNECT:return this.handleDisconnect();case i.types.EVENT:case i.types.BINARY_EVENT:{const e=t.getData();return y(Array.isArray(e),"args","array"),y(e.length>0,"args","array"),y("string"==typeof e[0],"event","string"),-1!==t.id?this.handleCall(t.id,e):this.handleEvent(e)}case i.types.ACK:case i.types.BINARY_ACK:{y(-1!==t.id,"id","uint32");const e=t.getData();y(null==e||Array.isArray(e),"args","array");let n=null,r=null;return e&&e.length>0&&(n=e[0]),e&&e.length>1&&(r=e[1]),null==r&&(r=null),n?(y("object"==typeof n,"error","object"),this.handleError(t.id,n)):this.handleAck(t.id,r)}case i.types.ERROR:{const e=t.getData();return y(e&&"object"==typeof e,"error","object"),this.handleError(-1,e)}default:throw new Error("Unknown packet.")}}async handleConnect(){if(this.inbound)throw new Error("Inbound socket sent connect packet.");this.connected=!0,await this.emitAsync("connect");for(const t of this.buffer)this.sendPacket(t);this.buffer.length=0}async handleDisconnect(){this.close()}async handleEvent(t){try{const e=t[0];if(f.hasOwnProperty(e))throw new Error(`Cannot emit blacklisted event: ${e}.`);this.events.emit(...t)}catch(t){this.emit("error",t),this.sendError(-1,t)}}async handleCall(t,e){let n;try{const r=e.shift();if(f.hasOwnProperty(r))throw new Error(`Cannot emit blacklisted event: ${r}.`);const s=this.hooks.get(r);if(!s)throw new Error(`Call not found: ${r}.`);n=await s(...e)}catch(e){return this.emit("error",e),void this.sendError(t,e)}null==n&&(n=null),this.sendAck(t,n)}async handleAck(t,e){const n=this.jobs.get(t);if(!n)throw new Error(`Job not found for ${t}.`);this.jobs.delete(t),n.resolve(e)}async handleError(t,e){const n=d(e.message),r=g(e.name),s=g(e.type),o=p(e.code);if(-1===t){const t=new Error(n);return t.name=r,t.type=s,t.code=o,void this.emit("error",t)}const i=this.jobs.get(t);if(!i)throw new Error(`Job not found for ${t}.`);this.jobs.delete(t);const a=new Error(n);a.name=r,a.type=s,a.code=o,i.reject(a)}sendPacket(t){this.sendMessage(t.toString());for(const e of t.buffers)this.sendBinary(e)}sendConnect(){this.sendPacket(new i(i.types.CONNECT))}sendDisconnect(){this.sendPacket(new i(i.types.DISCONNECT))}sendEvent(t){const e=new i;e.type=i.types.EVENT,e.setData(t),this.connected?this.sendPacket(e):this.buffer.push(e)}sendCall(t,e){const n=new i;n.type=i.types.EVENT,n.id=t,n.setData(e),this.connected?this.sendPacket(n):this.buffer.push(n)}sendAck(t,e){const n=new i;n.type=i.types.ACK,n.id=t,n.setData([null,e]),this.sendPacket(n)}sendError(t,e){const n=d(e.message),r=g(e.name),s=g(e.type),o=p(e.code);if(-1===t){const t=new i;return t.type=i.types.ERROR,t.setData({message:n,name:r,type:s,code:o}),void this.sendPacket(t)}const a=new i;a.type=i.types.ACK,a.id=t,a.setData([{message:n,name:r,type:s,code:o}]),this.sendPacket(a)}bind(t,e){y("string"==typeof t,"event","string"),y("function"==typeof e,"handler","function"),r(!f.hasOwnProperty(t),"Blacklisted event."),this.events.on(t,e)}unbind(t,e){y("string"==typeof t,"event","string"),y("function"==typeof e,"handler","function"),r(!f.hasOwnProperty(t),"Blacklisted event."),this.events.removeListener(t,e)}fire(...t){y(t.length>0,"event","string"),y("string"==typeof t[0],"event","string"),this.sendEvent(t)}hook(t,e){y("string"==typeof t,"event","string"),y("function"==typeof e,"handler","function"),r(!this.hooks.has(t),"Hook already bound."),r(!f.hasOwnProperty(t),"Blacklisted event."),this.hooks.set(t,e)}unhook(t){y("string"==typeof t,"event","string"),r(!f.hasOwnProperty(t),"Blacklisted event."),this.hooks.delete(t)}call(...t){y(t.length>0,"event","string"),y("string"==typeof t[0],"event","string");const e=this.sequence;return this.sequence+=1,this.sequence>>>=0,r(!this.jobs.has(e),"ID collision."),this.sendCall(e,t),new Promise((t,n)=>{this.jobs.set(e,new l(t,n,Date.now()))})}channel(t){return this.channels.has(t)}join(t){return!!this.server&&this.server.join(this,t)}leave(t){return!!this.server&&this.server.leave(this,t)}static accept(t,e,n,r){return(new this).accept(t,e,n,r)}static connect(t,e,n,r){return(new this).connect(t,e,n,r)}}}).call(this,n(1).Buffer)},function(t,e,n){"use strict";e.byteLength=function(t){var e=u(t),n=e[0],r=e[1];return 3*(n+r)/4-r},e.toByteArray=function(t){for(var e,n=u(t),r=n[0],i=n[1],a=new o(function(t,e,n){return 3*(e+n)/4-n}(0,r,i)),h=0,c=i>0?r-4:r,f=0;f>16&255,a[h++]=e>>8&255,a[h++]=255&e;2===i&&(e=s[t.charCodeAt(f)]<<2|s[t.charCodeAt(f+1)]>>4,a[h++]=255&e);1===i&&(e=s[t.charCodeAt(f)]<<10|s[t.charCodeAt(f+1)]<<4|s[t.charCodeAt(f+2)]>>2,a[h++]=e>>8&255,a[h++]=255&e);return a},e.fromByteArray=function(t){for(var e,n=t.length,s=n%3,o=[],i=0,a=n-s;ia?a:i+16383));1===s?(e=t[n-1],o.push(r[e>>2]+r[e<<4&63]+"==")):2===s&&(e=(t[n-2]<<8)+t[n-1],o.push(r[e>>10]+r[e>>4&63]+r[e<<2&63]+"="));return o.join("")};for(var r=[],s=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,h=i.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var n=t.indexOf("=");return-1===n&&(n=e),[n,n===e?0:4-n%4]}function c(t,e,n){for(var s,o,i=[],a=e;a>18&63]+r[o>>12&63]+r[o>>6&63]+r[63&o]);return i.join("")}s["-".charCodeAt(0)]=62,s["_".charCodeAt(0)]=63},function(t,e){e.read=function(t,e,n,r,s){var o,i,a=8*s-r-1,h=(1<>1,c=-7,f=n?s-1:0,l=n?-1:1,p=t[e+f];for(f+=l,o=p&(1<<-c)-1,p>>=-c,c+=a;c>0;o=256*o+t[e+f],f+=l,c-=8);for(i=o&(1<<-c)-1,o>>=-c,c+=r;c>0;i=256*i+t[e+f],f+=l,c-=8);if(0===o)o=1-u;else{if(o===h)return i?NaN:1/0*(p?-1:1);i+=Math.pow(2,r),o-=u}return(p?-1:1)*i*Math.pow(2,o-r)},e.write=function(t,e,n,r,s,o){var i,a,h,u=8*o-s-1,c=(1<>1,l=23===s?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:o-1,d=r?1:-1,g=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(a=isNaN(e)?1:0,i=c):(i=Math.floor(Math.log(e)/Math.LN2),e*(h=Math.pow(2,-i))<1&&(i--,h*=2),(e+=i+f>=1?l/h:l*Math.pow(2,1-f))*h>=2&&(i++,h/=2),i+f>=c?(a=0,i=c):i+f>=1?(a=(e*h-1)*Math.pow(2,s),i+=f):(a=e*Math.pow(2,f-1)*Math.pow(2,s),i=0));s>=8;t[n+p]=255&a,p+=d,a/=256,s-=8);for(i=i<0;t[n+p]=255&i,p+=d,i/=256,u-=8);t[n+p-d]|=128*g}},function(t,e){var n={}.toString;t.exports=Array.isArray||function(t){return"[object Array]"==n.call(t)}},function(t,e,n){"use strict";(function(e){const r=n(0),s={CONNECT:0,DISCONNECT:1,EVENT:2,ACK:3,ERROR:4,BINARY_EVENT:5,BINARY_ACK:6};class o{constructor(t){this.type=t||0,this.attachments=0,this.nsp="/",this.id=-1,this.data="",this.buffers=[]}setData(t){r(void 0!==t),r("number"!=typeof t),r("function"!=typeof t);const[n,o]=function(t){const n=[],r=function t(n,r,s,o){if(null===r||"object"!=typeof r)return r;if(e.isBuffer(r)){const t=o.get(r);if(null!=t)return t;const e={_placeholder:!0,num:s.length};return o.set(r,e),s.push(r),e}if(o.has(r))throw new TypeError("Converting circular structure to JSON.");if(Array.isArray(r)){const e=[];o.set(r,null);for(let n=0;n0)switch(this.type){case s.EVENT:this.type=s.BINARY_EVENT;break;case s.ACK:this.type=s.BINARY_ACK}return this}getData(){return 0===this.data.length?null:(t=this.data,e=this.buffers,JSON.parse(t,(t,n)=>(function(t){return null!==t&&"object"==typeof t&&!0===t._placeholder&&t.num>>>0===t.num})(n)&&n.num0);let e=0,n=0,o=0,a="/",h=-1,u="";switch([e,n]=function(t,e){const n=t.charCodeAt(e)-48;return n<0||n>9?-1:[e+1,n]}(t,e),r(-1!==n),r(n<=s.BINARY_ACK),n){case s.BINARY_EVENT:case s.BINARY_ACK:[e,o]=i(t,e),r(-1!==o),r(e9)break;s*=10,s+=o,r((n+=1)<=10)}return r(s<=4294967295),0===n&&(s=-1),[e,s]}o.types=s,t.exports=o}).call(this,n(1).Buffer)},function(t,e,n){"use strict";const r=n(0),s=n(16);e.parseURL=function(t){-1===t.indexOf("://")&&(t=`ws://${t}`);const e=s.parse(t);if("http:"!==e.protocol&&"https:"!==e.protocol&&"ws:"!==e.protocol&&"wss:"!==e.protocol)throw new Error("Invalid protocol for websocket URL.");if(!e.hostname)throw new Error("Malformed URL.");const n=e.hostname;let o=80,i=!1;return"https:"!==e.protocol&&"wss:"!==e.protocol||(o=443,i=!0),e.port&&(o=parseInt(e.port,10),r((65535&o)===o),r(0!==o)),[o,n,i]}},function(t,e,n){"use strict";var r=n(17),s=n(19);function o(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}e.parse=v,e.resolve=function(t,e){return v(t,!1,!0).resolve(e)},e.resolveObject=function(t,e){return t?v(t,!1,!0).resolveObject(e):e},e.format=function(t){s.isString(t)&&(t=v(t));return t instanceof o?t.format():o.prototype.format.call(t)},e.Url=o;var i=/^([a-z0-9.+-]+:)/i,a=/:[0-9]*$/,h=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,u=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),c=["'"].concat(u),f=["%","/","?",";","#"].concat(c),l=["/","?","#"],p=/^[+a-z0-9A-Z_-]{0,63}$/,d=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,g={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},w={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},m=n(20);function v(t,e,n){if(t&&s.isObject(t)&&t instanceof o)return t;var r=new o;return r.parse(t,e,n),r}o.prototype.parse=function(t,e,n){if(!s.isString(t))throw new TypeError("Parameter 'url' must be a string, not "+typeof t);var o=t.indexOf("?"),a=-1!==o&&o127?N+="x":N+=j[I];if(!N.match(p)){var L=C.slice(0,P),U=C.slice(P+1),M=j.match(d);M&&(L.push(M[1]),U.unshift(M[2])),U.length&&(v="/"+U.join(".")+v),this.hostname=L.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),T||(this.hostname=r.toASCII(this.hostname));var D=this.port?":"+this.port:"",Y=this.hostname||"";this.host=Y+D,this.href+=this.host,T&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==v[0]&&(v="/"+v))}if(!g[A])for(P=0,x=c.length;P0)&&n.host.split("@"))&&(n.auth=T.shift(),n.host=n.hostname=T.shift());return n.search=t.search,n.query=t.query,s.isNull(n.pathname)&&s.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.href=n.format(),n}if(!O.length)return n.pathname=null,n.search?n.path="/"+n.search:n.path=null,n.href=n.format(),n;for(var R=O.slice(-1)[0],_=(n.host||t.host||O.length>1)&&("."===R||".."===R)||""===R,P=0,k=O.length;k>=0;k--)"."===(R=O[k])?O.splice(k,1):".."===R?(O.splice(k,1),P++):P&&(O.splice(k,1),P--);if(!E&&!A)for(;P--;P)O.unshift("..");!E||""===O[0]||O[0]&&"/"===O[0].charAt(0)||O.unshift(""),_&&"/"!==O.join("/").substr(-1)&&O.push("");var T,C=""===O[0]||O[0]&&"/"===O[0].charAt(0);S&&(n.hostname=n.host=C?"":O.length?O.shift():"",(T=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@"))&&(n.auth=T.shift(),n.host=n.hostname=T.shift()));return(E=E||n.host&&O.length)&&!C&&O.unshift(""),O.length?n.pathname=O.join("/"):(n.pathname=null,n.path=null),s.isNull(n.pathname)&&s.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.auth=t.auth||n.auth,n.slashes=n.slashes||t.slashes,n.href=n.format(),n},o.prototype.parseHost=function(){var t=this.host,e=a.exec(t);e&&(":"!==(e=e[0])&&(this.port=e.substr(1)),t=t.substr(0,t.length-e.length)),t&&(this.hostname=t)}},function(t,e,n){(function(t,r){var s;/*! https://mths.be/punycode v1.4.1 by @mathias */!function(o){e&&e.nodeType,t&&t.nodeType;var i="object"==typeof r&&r;i.global!==i&&i.window!==i&&i.self;var a,h=2147483647,u=36,c=1,f=26,l=38,p=700,d=72,g=128,y="-",w=/^xn--/,m=/[^\x20-\x7E]/,v=/[\x2E\u3002\uFF0E\uFF61]/g,b={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},E=u-c,A=Math.floor,O=String.fromCharCode;function S(t){throw new RangeError(b[t])}function R(t,e){for(var n=t.length,r=[];n--;)r[n]=e(t[n]);return r}function _(t,e){var n=t.split("@"),r="";return n.length>1&&(r=n[0]+"@",t=n[1]),r+R((t=t.replace(v,".")).split("."),e).join(".")}function P(t){for(var e,n,r=[],s=0,o=t.length;s=55296&&e<=56319&&s65535&&(e+=O((t-=65536)>>>10&1023|55296),t=56320|1023&t),e+=O(t)}).join("")}function T(t,e){return t+22+75*(t<26)-((0!=e)<<5)}function C(t,e,n){var r=0;for(t=n?A(t/p):t>>1,t+=A(t/e);t>E*f>>1;r+=u)t=A(t/E);return A(r+(E+1)*t/(t+l))}function x(t){var e,n,r,s,o,i,a,l,p,w,m,v=[],b=t.length,E=0,O=g,R=d;for((n=t.lastIndexOf(y))<0&&(n=0),r=0;r=128&&S("not-basic"),v.push(t.charCodeAt(r));for(s=n>0?n+1:0;s=b&&S("invalid-input"),((l=(m=t.charCodeAt(s++))-48<10?m-22:m-65<26?m-65:m-97<26?m-97:u)>=u||l>A((h-E)/i))&&S("overflow"),E+=l*i,!(l<(p=a<=R?c:a>=R+f?f:a-R));a+=u)i>A(h/(w=u-p))&&S("overflow"),i*=w;R=C(E-o,e=v.length+1,0==o),A(E/e)>h-O&&S("overflow"),O+=A(E/e),E%=e,v.splice(E++,0,O)}return k(v)}function j(t){var e,n,r,s,o,i,a,l,p,w,m,v,b,E,R,_=[];for(v=(t=P(t)).length,e=g,n=0,o=d,i=0;i=e&&mA((h-n)/(b=r+1))&&S("overflow"),n+=(a-e)*b,e=a,i=0;ih&&S("overflow"),m==e){for(l=n,p=u;!(l<(w=p<=o?c:p>=o+f?f:p-o));p+=u)R=l-w,E=u-w,_.push(O(T(w+R%E,0))),l=A(R/E);_.push(O(T(l,0))),o=C(n,b,r==s),n=0,++r}++n,++e}return _.join("")}a={version:"1.4.1",ucs2:{decode:P,encode:k},decode:x,encode:j,toASCII:function(t){return _(t,function(t){return m.test(t)?"xn--"+j(t):t})},toUnicode:function(t){return _(t,function(t){return w.test(t)?x(t.slice(4).toLowerCase()):t})}},void 0===(s=function(){return a}.call(e,n,e,t))||(t.exports=s)}()}).call(this,n(18)(t),n(2))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){"use strict";t.exports={isString:function(t){return"string"==typeof t},isObject:function(t){return"object"==typeof t&&null!==t},isNull:function(t){return null===t},isNullOrUndefined:function(t){return null==t}}},function(t,e,n){"use strict";e.decode=e.parse=n(21),e.encode=e.stringify=n(22)},function(t,e,n){"use strict";function r(t,e){return Object.prototype.hasOwnProperty.call(t,e)}t.exports=function(t,e,n,o){e=e||"&",n=n||"=";var i={};if("string"!=typeof t||0===t.length)return i;var a=/\+/g;t=t.split(e);var h=1e3;o&&"number"==typeof o.maxKeys&&(h=o.maxKeys);var u=t.length;h>0&&u>h&&(u=h);for(var c=0;c=0?(f=g.substr(0,y),l=g.substr(y+1)):(f=g,l=""),p=decodeURIComponent(f),d=decodeURIComponent(l),r(i,p)?s(i[p])?i[p].push(d):i[p]=[i[p],d]:i[p]=d}return i};var s=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)}},function(t,e,n){"use strict";var r=function(t){switch(typeof t){case"string":return t;case"boolean":return t?"true":"false";case"number":return isFinite(t)?t:"";default:return""}};t.exports=function(t,e,n,a){return e=e||"&",n=n||"=",null===t&&(t=void 0),"object"==typeof t?o(i(t),function(i){var a=encodeURIComponent(r(i))+n;return s(t[i])?o(t[i],function(t){return a+encodeURIComponent(r(t))}).join(e):a+encodeURIComponent(r(t[i]))}).join(e):a?encodeURIComponent(r(a))+n+encodeURIComponent(r(t)):""};var s=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)};function o(t,e){if(t.map)return t.map(e);for(var n=[],r=0;ri)return void this.error("Frame too large.");let n;try{n=o.fromRaw(t)}catch(t){return void this.emit("error",t)}this.emit("frame",n)}feedString(t){if(r("string"==typeof t),e.byteLength(t,"utf8")>i)return void this.error("Frame too large.");let n;try{n=o.fromString(t)}catch(t){return void this.emit("error",t)}this.emit("frame",n)}}}).call(this,n(1).Buffer)},function(t,e,n){"use strict";t.exports={1e3:"NORMAL_CLOSURE",1001:"GOING_AWAY",1002:"PROTOCOL_ERROR",1003:"UNSUPPORTED_DATA",1004:"RESERVED",1005:"NO_STATUS_RECVD",1006:"ABNORMAL_CLOSURE",1007:"INVALID_FRAME_PAYLOAD_DATA",1008:"POLICY_VIOLATION",1009:"MESSAGE_TOO_BIG",1010:"MISSING_EXTENSION",1011:"INTERNAL_ERROR",1012:"SERVICE_RESTART",1013:"TRY_AGAIN_LATER",1014:"BAD_GATEWAY",1015:"TLS_HANDSHAKE"}},function(t,e,n){"use strict";t.exports={connect:!0,connect_error:!0,connect_timeout:!0,connecting:!0,disconnect:!0,error:!0,reconnect:!0,reconnect_attempt:!0,reconnect_failed:!0,reconnect_error:!0,reconnecting:!0,ping:!0,pong:!0}}]); \ No newline at end of file diff --git a/src/frontend/dashboard/src/polyfills.ts b/src/frontend/dashboard/src/polyfills.ts index aa665d6..609f346 100644 --- a/src/frontend/dashboard/src/polyfills.ts +++ b/src/frontend/dashboard/src/polyfills.ts @@ -61,3 +61,7 @@ import 'zone.js/dist/zone'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS */ +// Add global to window, assigning the value of window itself. +(window as any).global = window; +global.Buffer = global.Buffer || require('buffer').Buffer; +global.process = global.process || require('process')