mirror of https://github.com/embarklabs/embark.git
re-add embarkjs generation (#1858)
* fix embarkjs generation fix ens setProvider fix embarkjs objects fix generated embarkjs provider generate contracts fix embarkjs-ens * address some of the issues in the code review * address some of the issues in the code review * address some of the issues in the code review * address some of the issues in the code review
This commit is contained in:
parent
b260e81055
commit
718d19f7d3
|
@ -2,9 +2,11 @@
|
|||
// import {SimpleStorage} from '../../embarkArtifacts/contracts';
|
||||
import $ from 'jquery';
|
||||
import SimpleStorage from '../../embarkArtifacts/contracts/SimpleStorage.js';
|
||||
import web3 from '../../embarkArtifacts/contracts/web3_init';
|
||||
window.web3 = web3;
|
||||
// import web3 from '../../embarkArtifacts/contracts/web3_init';
|
||||
// window.web3 = web3;
|
||||
window.SimpleStorage = SimpleStorage;
|
||||
import EmbarkJS from '../../embarkArtifacts/embarkjs.js';
|
||||
window.EmbarkJS = EmbarkJS;
|
||||
|
||||
$("#blockchain button.set").click(function() {
|
||||
var value = parseInt($("#blockchain input.text").val(), 10);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { __ } from 'embark-i18n';
|
||||
import * as fs from "./fs";
|
||||
import VM from "./vm";
|
||||
|
||||
|
@ -60,6 +61,8 @@ class CodeRunner {
|
|||
|
||||
this.vm.doEval(code, tolerateError, (err, result) => {
|
||||
if (err) {
|
||||
this.logger.error(__("Error running code: %s", code));
|
||||
this.logger.error(err.toString());
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ class ContractDeployer {
|
|||
});
|
||||
},
|
||||
(params, next) => {
|
||||
|
||||
if (!params.shouldDeploy) {
|
||||
return this.plugins.emitAndRunActionsForEvent('deployment:contract:undeployed', {contract}, (err, _params) => {
|
||||
next(err, null);
|
||||
|
@ -38,13 +37,12 @@ class ContractDeployer {
|
|||
}
|
||||
|
||||
// TODO: implement `blockchainType` a la `this.deployer[contract.blockchainType].apply(this.deployer, [contract, next])`
|
||||
this.deployer["ethereum"].apply(this.deployer, [contract, next]);
|
||||
},
|
||||
(receipt, next) => {
|
||||
if (!receipt) return next();
|
||||
this.plugins.emitAndRunActionsForEvent('deployment:contract:deployed', {contract, receipt}, (err, _params) => {
|
||||
next(err);
|
||||
});
|
||||
this.deployer["ethereum"].apply(this.deployer, [contract, (err, receipt) => {
|
||||
if (!receipt) return next(err);
|
||||
this.plugins.emitAndRunActionsForEvent('deployment:contract:deployed', { contract, receipt }, (err, _params) => {
|
||||
next(err);
|
||||
});
|
||||
}]);
|
||||
}
|
||||
], (err) => {
|
||||
if (err) {
|
||||
|
|
|
@ -118,12 +118,9 @@ class ENS {
|
|||
this.enabled = true;
|
||||
this.doSetENSProvider = this.config.namesystemConfig.provider === 'ens';
|
||||
|
||||
this.registerEmbarkJSNaming();
|
||||
this.registerEvents();
|
||||
this.registerConsoleCommands();
|
||||
this.events.request2("runcode:whitelist", 'eth-ens-namehash');
|
||||
this.events.request2("runcode:whitelist", 'embarkjs');
|
||||
this.events.request2("runcode:whitelist", 'embarkjs-ens');
|
||||
this.initated = true;
|
||||
cb();
|
||||
}
|
||||
|
@ -202,8 +199,7 @@ class ENS {
|
|||
setProviderAndRegisterDomains(cb = (() => {})) {
|
||||
this.getEnsConfig(async (config) => {
|
||||
if (this.doSetENSProvider) {
|
||||
this.addENSArtifact(config);
|
||||
this.connectEmbarkJSProvider(config);
|
||||
this.setupEmbarkJS(config);
|
||||
}
|
||||
|
||||
const web3 = await this.web3;
|
||||
|
@ -219,6 +215,12 @@ class ENS {
|
|||
});
|
||||
}
|
||||
|
||||
async setupEmbarkJS(config) {
|
||||
this.events.request("embarkjs:plugin:register", 'names', 'ens', 'embarkjs-ens');
|
||||
await this.events.request2("embarkjs:console:register", 'names', 'ens', 'embarkjs-ens');
|
||||
this.events.request("embarkjs:console:setProvider", 'names', 'ens', config);
|
||||
}
|
||||
|
||||
associateStorageToEns(options, cb) {
|
||||
const self = this;
|
||||
// Code inspired by https://github.com/monkybrain/ipfs-to-ens
|
||||
|
@ -417,47 +419,6 @@ class ENS {
|
|||
);
|
||||
}
|
||||
|
||||
addENSArtifact(config, cb = () => {}) {
|
||||
const code = `
|
||||
var EmbarkJS;
|
||||
if (typeof EmbarkJS === 'undefined') {
|
||||
EmbarkJS = require('embarkjs');
|
||||
}
|
||||
const __embarkENS = require('embarkjs-ens');
|
||||
EmbarkJS.Names.registerProvider('ens', __embarkENS.default || __embarkENS);
|
||||
EmbarkJS.Names.setProvider('ens', ${JSON.stringify(config)});
|
||||
`;
|
||||
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.config.embarkConfig.generationDir, 'ens'],
|
||||
file: 'init.js',
|
||||
format: 'js',
|
||||
content: code
|
||||
}, cb);
|
||||
|
||||
}
|
||||
|
||||
async registerEmbarkJSNaming() {
|
||||
const checkEmbarkJS = `return (typeof EmbarkJS === 'undefined');`;
|
||||
const EmbarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS);
|
||||
|
||||
if (EmbarkJSNotDefined) {
|
||||
await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs'));
|
||||
}
|
||||
|
||||
const registerProviderCode = `
|
||||
const __embarkENS = require('embarkjs-ens');
|
||||
EmbarkJS.Names.registerProvider('ens', __embarkENS.default || __embarkENS);
|
||||
`;
|
||||
|
||||
await this.events.request2('runcode:eval', registerProviderCode);
|
||||
}
|
||||
|
||||
async connectEmbarkJSProvider(config) {
|
||||
let providerCode = `\nEmbarkJS.Names.setProvider('ens', ${JSON.stringify(config)});`;
|
||||
await this.events.request2('runcode:eval', providerCode);
|
||||
}
|
||||
|
||||
async configureContractsAndRegister(_options, cb) {
|
||||
const NO_REGISTRATION = 'NO_REGISTRATION';
|
||||
const self = this;
|
||||
|
|
|
@ -39,13 +39,8 @@ class IPFS {
|
|||
return;
|
||||
}
|
||||
|
||||
this.events.request("runcode:whitelist", 'ipfs-api', () => {});
|
||||
this.events.request("runcode:whitelist", 'embarkjs', () => {});
|
||||
this.events.request("runcode:whitelist", 'embarkjs-ipfs', () => {});
|
||||
this.events.on("storage:started", this.registerIpfsObject.bind(this));
|
||||
this.events.on("storage:started", this.connectEmbarkJSProvider.bind(this));
|
||||
|
||||
this.embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSIpfsArtifact.bind(this));
|
||||
this.setupIpfsApi();
|
||||
this.setupEmbarkJS();
|
||||
|
||||
this.events.request("storage:node:register", "ipfs", (readyCb) => {
|
||||
this.events.request('processes:register', 'storage', {
|
||||
|
@ -72,8 +67,35 @@ class IPFS {
|
|||
|
||||
upload_ipfs.deploy(readyCb);
|
||||
});
|
||||
}
|
||||
|
||||
this.registerEmbarkJSStorage();
|
||||
async setupIpfsApi() {
|
||||
this.events.request("runcode:whitelist", 'ipfs-api', () => {});
|
||||
this.events.on("storage:started", this.registerIpfsObject.bind(this));
|
||||
this.registerIpfsObject();
|
||||
this.registerIpfsHelp();
|
||||
}
|
||||
|
||||
async registerIpfsObject() {
|
||||
const {host, port} = this.config;
|
||||
let ipfs = IpfsApi(host, port);
|
||||
await this.events.request2("runcode:register", "ipfs", ipfs);
|
||||
}
|
||||
|
||||
async registerIpfsHelp() {
|
||||
await this.events.request2('console:register:helpCmd', {
|
||||
cmdName: "ipfs",
|
||||
cmdHelp: __("instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)")
|
||||
});
|
||||
}
|
||||
|
||||
async setupEmbarkJS() {
|
||||
this.events.request("embarkjs:plugin:register", 'storage', 'ipfs', 'embarkjs-ipfs');
|
||||
await this.events.request2("embarkjs:console:register", 'storage', 'ipfs', 'embarkjs-ipfs');
|
||||
this.events.on("storage:started", () => {
|
||||
let config = this.embark.config.storageConfig.dappConnection || [];
|
||||
this.events.request("embarkjs:console:setProvider", 'storage', 'ipfs', config);
|
||||
});
|
||||
}
|
||||
|
||||
get config() {
|
||||
|
@ -115,61 +137,6 @@ class IPFS {
|
|||
return this._enabled;
|
||||
}
|
||||
|
||||
async addEmbarkJSIpfsArtifact(params, cb) {
|
||||
const code = `
|
||||
var EmbarkJS;
|
||||
if (typeof EmbarkJS === 'undefined') {
|
||||
EmbarkJS = require('embarkjs');
|
||||
}
|
||||
const __embarkIPFS = require('embarkjs-ipfs');
|
||||
EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS.default || __embarkIPFS);
|
||||
EmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3});
|
||||
`;
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir, 'storage'],
|
||||
file: 'init.js',
|
||||
format: 'js',
|
||||
content: code
|
||||
}, cb);
|
||||
}
|
||||
|
||||
async registerIpfsObject() {
|
||||
const {host, port} = this.config;
|
||||
let ipfs = IpfsApi(host, port);
|
||||
await this.events.request2("runcode:register", "ipfs", ipfs);
|
||||
this.registerIpfsHelp();
|
||||
}
|
||||
|
||||
async registerIpfsHelp() {
|
||||
await this.events.request2('console:register:helpCmd', {
|
||||
cmdName: "ipfs",
|
||||
cmdHelp: __("instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)")
|
||||
});
|
||||
}
|
||||
|
||||
async registerEmbarkJSStorage() {
|
||||
let checkEmbarkJS = `
|
||||
return (typeof EmbarkJS === 'undefined');
|
||||
`;
|
||||
let EmbarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS);
|
||||
|
||||
if (EmbarkJSNotDefined) {
|
||||
await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs'));
|
||||
}
|
||||
|
||||
const registerProviderCode = `
|
||||
const __embarkIPFS = require('embarkjs-ipfs');
|
||||
EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS.default || __embarkIPFS);
|
||||
`;
|
||||
|
||||
await this.events.request2('runcode:eval', registerProviderCode);
|
||||
}
|
||||
|
||||
async connectEmbarkJSProvider() {
|
||||
let providerCode = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3});`;
|
||||
await this.events.request2('runcode:eval', providerCode);
|
||||
}
|
||||
|
||||
registerServiceCheck() {
|
||||
this.events.on('check:backOnline:IPFS', () => {
|
||||
this.logger.info(__('IPFS node detected') + '...');
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import {__} from 'embark-i18n';
|
||||
import {canonicalHost, defaultHost} from 'embark-utils';
|
||||
|
||||
export default class Namesystem {
|
||||
constructor(embark, _options) {
|
||||
this.embark = embark;
|
||||
this.events = this.embark.events;
|
||||
this.embarkConfig = embark.config.embarkConfig;
|
||||
this.namesystemConfig = this.embark.config.namesystemConfig;
|
||||
|
||||
this.namesystemNodes = {};
|
||||
this.events.setCommandHandler("namesystem:node:register", (clientName, startCb) => {
|
||||
|
@ -22,5 +25,15 @@ export default class Namesystem {
|
|||
}
|
||||
]);
|
||||
});
|
||||
embark.registerActionForEvent("pipeline:generateAll:before", this.addArtifactFile.bind(this));
|
||||
}
|
||||
|
||||
addArtifactFile(_params, cb) {
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir, 'config'],
|
||||
file: 'namesystem.json',
|
||||
format: 'json',
|
||||
content: this.namesystemConfig
|
||||
}, cb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {__} from 'embark-i18n';
|
||||
import {buildUrlFromConfig} from 'embark-utils';
|
||||
const UploadSwarm = require('./upload.js');
|
||||
const SwarmAPI = require('swarm-api');
|
||||
const StorageProcessesLauncher = require('./storageProcessesLauncher');
|
||||
const constants = require('embark-core/constants');
|
||||
require('colors');
|
||||
import {buildUrlFromConfig} from 'embark-utils';
|
||||
|
||||
class Swarm {
|
||||
|
||||
|
@ -50,17 +50,12 @@ class Swarm {
|
|||
});
|
||||
});
|
||||
|
||||
this.events.request("runcode:whitelist", 'swarm-api', () => {});
|
||||
this.events.request("runcode:whitelist", 'embarkjs', () => {});
|
||||
this.events.request("runcode:whitelist", 'embarkjs-swarm', () => {});
|
||||
this.events.on("storage:started", this.registerSwarmObject.bind(this));
|
||||
this.events.on("storage:started", this.connectEmbarkJSProvider.bind(this));
|
||||
|
||||
this.embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSSwarmArtifact.bind(this));
|
||||
|
||||
this.providerUrl = buildUrlFromConfig(this.config);
|
||||
this.swarm = new SwarmAPI({gateway: this.providerUrl});
|
||||
|
||||
this.setupSwarmAPI();
|
||||
this.setupEmbarkJS();
|
||||
|
||||
this.events.request("storage:node:register", "swarm", (readyCb) => {
|
||||
this.events.request("processes:register", "storage", {
|
||||
launchFn: (cb) => {
|
||||
|
@ -96,8 +91,27 @@ class Swarm {
|
|||
|
||||
upload_swarm.deploy(readyCb);
|
||||
});
|
||||
}
|
||||
|
||||
this.registerEmbarkJSStorage();
|
||||
setupSwarmAPI() {
|
||||
this.events.request("runcode:whitelist", 'swarm-api', () => {});
|
||||
this.events.on("storage:started", async () => {
|
||||
await this.events.request2("runcode:register", "swarm", this.swarm);
|
||||
await this.events.request2('console:register:helpCmd', {
|
||||
cmdName: "swarm",
|
||||
cmdHelp: __("instantiated swarm-api object configured to the current environment (available if swarm is enabled)")
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async setupEmbarkJS() {
|
||||
this.events.request("embarkjs:plugin:register", 'storage', 'swarm', 'embarkjs-swarm');
|
||||
await this.events.request2("embarkjs:console:register", 'storage', 'swarm', 'embarkjs-swarm');
|
||||
|
||||
this.events.on("storage:started", () => {
|
||||
let config = this.embark.config.storageConfig.dappConnection || [];
|
||||
this.events.request("embarkjs:console:setProvider", 'storage', 'swarm', config);
|
||||
});
|
||||
}
|
||||
|
||||
get config() {
|
||||
|
@ -138,60 +152,6 @@ class Swarm {
|
|||
return this._enabled;
|
||||
}
|
||||
|
||||
async addEmbarkJSSwarmArtifact(params, cb) {
|
||||
const code = `
|
||||
var EmbarkJS;
|
||||
if (typeof EmbarkJS === 'undefined') {
|
||||
EmbarkJS = require('embarkjs');
|
||||
}
|
||||
const __embarkSwarm = require('embarkjs-swarm');
|
||||
EmbarkJS.Storage.registerProvider('swarm', __embarkSwarm.default || __embarkSwarm);
|
||||
EmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3});
|
||||
`;
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir, 'storage'],
|
||||
file: 'init.js',
|
||||
format: 'js',
|
||||
content: code
|
||||
}, cb);
|
||||
}
|
||||
|
||||
async registerSwarmObject() {
|
||||
await this.events.request2("runcode:register", "swarm", this.swarm);
|
||||
this.registerSwarmHelp();
|
||||
}
|
||||
|
||||
async registerSwarmHelp() {
|
||||
await this.events.request2('console:register:helpCmd', {
|
||||
cmdName: "swarm",
|
||||
cmdHelp: __("instantiated swarm-api object configured to the current environment (available if swarm is enabled)")
|
||||
});
|
||||
}
|
||||
|
||||
async registerEmbarkJSStorage() {
|
||||
let checkEmbarkJS = `
|
||||
return (typeof EmbarkJS === 'undefined');
|
||||
`;
|
||||
let embarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS);
|
||||
|
||||
if (embarkJSNotDefined) {
|
||||
await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs'));
|
||||
}
|
||||
|
||||
const registerProviderCode = `
|
||||
const __embarkSwarm = require('embarkjs-swarm');
|
||||
EmbarkJS.Storage.registerProvider('swarm', __embarkSwarm.default || __embarkSwarm);
|
||||
`;
|
||||
|
||||
await this.events.request2('runcode:eval', registerProviderCode);
|
||||
}
|
||||
|
||||
async connectEmbarkJSProvider() {
|
||||
// TODO: should initialize its own object web3 instead of relying on a global one
|
||||
let providerCode = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3});`;
|
||||
await this.events.request2('runcode:eval', providerCode);
|
||||
}
|
||||
|
||||
registerServiceCheck() {
|
||||
this.events.on('check:backOnline:Swarm', () => {
|
||||
this.logger.info(__('Swarm node detected...'));
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
import EmbarkJS from '../embarkjs':
|
||||
|
||||
const <%- className %>Config = <%- JSON.stringify(contract) %>;
|
||||
const <%- className %> = new EmbarkJS.Blockchain.Contract(<%- className %>Config);
|
||||
|
||||
export default <%- className %>;
|
|
@ -1,5 +1,3 @@
|
|||
/* global __dirname module process require */
|
||||
|
||||
const {__} = require('embark-i18n');
|
||||
const Web3 = require('web3');
|
||||
const async = require('async');
|
||||
|
@ -17,30 +15,43 @@ class EmbarkWeb3 {
|
|||
this.embark = embark;
|
||||
this.logger = embark.logger;
|
||||
this.events = embark.events;
|
||||
this.fs = embark.fs;
|
||||
this.config = embark.config;
|
||||
|
||||
this.events.request("runcode:whitelist", 'web3', () => { });
|
||||
this.setupWeb3Api();
|
||||
this.setupEmbarkJS();
|
||||
|
||||
this.events.on("blockchain:started", this.registerWeb3Object.bind(this));
|
||||
embark.registerActionForEvent("pipeline:generateAll:before", this.addWeb3Artifact.bind(this));
|
||||
embark.registerActionForEvent("deployment:contract:deployed", this.registerInVm.bind(this));
|
||||
embark.registerActionForEvent("deployment:contract:undeployed", this.registerInVm.bind(this));
|
||||
embark.registerActionForEvent("deployment:contract:deployed", this.registerArtifact.bind(this));
|
||||
embark.registerActionForEvent("deployment:contract:undeployed", this.registerArtifact.bind(this));
|
||||
}
|
||||
|
||||
this.registerWeb3Help();
|
||||
async setupEmbarkJS() {
|
||||
this.events.request("embarkjs:plugin:register", 'blockchain', 'web3', 'embarkjs-web3');
|
||||
await this.events.request2("embarkjs:console:register", 'blockchain', 'web3', 'embarkjs-web3');
|
||||
this.events.on("blockchain:started", async () => {
|
||||
await this.registerWeb3Object()
|
||||
this.events.request("embarkjs:console:setProvider", 'blockchain', 'web3', '{web3}');
|
||||
});
|
||||
}
|
||||
|
||||
async setupWeb3Api() {
|
||||
this.events.request("runcode:whitelist", 'web3', () => { });
|
||||
this.events.on("blockchain:started", this.registerWeb3Object.bind(this));
|
||||
}
|
||||
|
||||
async registerWeb3Object() {
|
||||
const checkWeb3 = `return (typeof web3 === 'undefined');`;
|
||||
const web3NotDefined = await this.events.request2('runcode:eval', checkWeb3);
|
||||
|
||||
if (!web3NotDefined) return;
|
||||
|
||||
const provider = await this.events.request2("blockchain:client:provider", "ethereum");
|
||||
const web3 = new Web3(provider);
|
||||
await this.events.request2("runcode:register", 'web3', web3);
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
await this.events.request2('runcode:eval', `web3.eth.defaultAccount = '${accounts[0]}'`);
|
||||
}
|
||||
|
||||
async registerWeb3Help() {
|
||||
await this.events.request2('console:register:helpCmd', {
|
||||
cmdName: "web3",
|
||||
cmdHelp: __("instantiated web3.js object configured to the current environment")
|
||||
|
@ -48,60 +59,11 @@ class EmbarkWeb3 {
|
|||
}
|
||||
|
||||
async registerInVm(params, cb) {
|
||||
let contract = params.contract;
|
||||
let abi = JSON.stringify(contract.abiDefinition);
|
||||
let gasLimit = 6000000;
|
||||
const provider = await this.events.request2("blockchain:client:provider", "ethereum");
|
||||
let contractCode = Templates.vanilla_contract({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit, provider: provider });
|
||||
|
||||
try {
|
||||
await this.events.request2('runcode:eval', contractCode);
|
||||
let result = await this.events.request2('runcode:eval', contract.className);
|
||||
result.currentProvider = provider;
|
||||
await this.events.request2("runcode:register", contract.className, result);
|
||||
cb();
|
||||
} catch (err) {
|
||||
cb(err);
|
||||
}
|
||||
}
|
||||
|
||||
addWeb3Artifact(_params, cb) {
|
||||
async.map(this.config.contractsConfig.dappConnection, (conn, mapCb) => {
|
||||
if (conn === '$EMBARK') {
|
||||
// Connect to Embark's endpoint (proxy)
|
||||
return this.events.request("proxy:endpoint:get", mapCb);
|
||||
}
|
||||
mapCb(null, conn);
|
||||
}, (err, results) => {
|
||||
if (err) {
|
||||
this.logger.error(__('Error getting dapp connection'));
|
||||
return cb(err);
|
||||
}
|
||||
let web3Code = Templates.web3_init({connectionList: results});
|
||||
|
||||
// TODO: generate a .node file
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir, 'contracts'],
|
||||
file: 'web3_init.js',
|
||||
format: 'js',
|
||||
content: web3Code
|
||||
}, cb);
|
||||
});
|
||||
this.events.request("embarkjs:contract:runInVm", params.contract, cb);
|
||||
}
|
||||
|
||||
registerArtifact(params, cb) {
|
||||
let contract = params.contract;
|
||||
let abi = JSON.stringify(contract.abiDefinition);
|
||||
let gasLimit = 6000000;
|
||||
|
||||
let contractCode = Templates.contract_artifact({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit });
|
||||
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir, 'contracts'],
|
||||
file: contract.className + '.js',
|
||||
format: 'js',
|
||||
content: contractCode
|
||||
}, cb);
|
||||
this.events.request("embarkjs:contract:generate", params.contract, cb);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import {buildUrlFromConfig, canonicalHost, defaultHost} from 'embark-utils';
|
||||
const {parallel} = require('async');
|
||||
const {fromEvent} = require('rxjs');
|
||||
const {map, takeUntil} = require('rxjs/operators');
|
||||
const Web3 = require('web3');
|
||||
|
||||
import whisper from 'embarkjs-whisper';
|
||||
|
||||
|
@ -9,15 +11,25 @@ const listenTo = whisper.real_listenTo;
|
|||
|
||||
class API {
|
||||
|
||||
constructor(embark, web3) {
|
||||
constructor(embark) {
|
||||
this.embark = embark;
|
||||
this.logger = embark.logger;
|
||||
this.web3 = web3;
|
||||
this.registerAPICalls();
|
||||
this.communicationConfig = embark.config.communicationConfig;
|
||||
|
||||
embark.events.on("blockchain:started", this.registerAPICalls.bind(this));
|
||||
}
|
||||
|
||||
registerAPICalls() {
|
||||
async registerAPICalls() {
|
||||
const self = this;
|
||||
|
||||
const connection = this.communicationConfig.connection || {};
|
||||
const config = {
|
||||
host: canonicalHost(connection.host || defaultHost),
|
||||
port: connection.port || '8546',
|
||||
type: connection.type || 'ws'
|
||||
};
|
||||
this.web3 = new Web3(buildUrlFromConfig(config));
|
||||
|
||||
if (self.apiCallsRegistered) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { __ } from 'embark-i18n';
|
||||
import {dappPath, canonicalHost, defaultHost} from 'embark-utils';
|
||||
let Web3 = require('web3');
|
||||
const constants = require('embark-core/constants');
|
||||
const API = require('./api.js');
|
||||
|
||||
|
@ -11,28 +10,22 @@ class Whisper {
|
|||
this.fs = embark.fs;
|
||||
this.communicationConfig = embark.config.communicationConfig;
|
||||
this.embarkConfig = embark.config.embarkConfig;
|
||||
this.web3 = new Web3();
|
||||
this.embark = embark;
|
||||
this.web3Ready = false;
|
||||
this.webSocketsChannels = {};
|
||||
this.modulesPath = dappPath(embark.config.embarkConfig.generationDir, constants.dappArtifacts.symlinkDir);
|
||||
|
||||
this.api = new API(embark, this.web3);
|
||||
this.api = new API(embark);
|
||||
this.api.registerAPICalls();
|
||||
|
||||
this.events.request("runcode:whitelist", 'embarkjs', () => { });
|
||||
this.events.request("runcode:whitelist", 'embarkjs-whisper', () => { });
|
||||
this.events.request("embarkjs:plugin:register", 'messages', 'whisper', 'embarkjs-whisper');
|
||||
this.events.request("embarkjs:console:register", 'messages', 'whisper', 'embarkjs-whisper');
|
||||
|
||||
// TODO: should launch its own whisper node
|
||||
// this.events.on("communication:started", this.connectEmbarkJSProvider.bind(this));
|
||||
this.events.on("blockchain:started", this.connectEmbarkJSProvider.bind(this));
|
||||
|
||||
embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSWhisperArtifact.bind(this));
|
||||
|
||||
this.events.request("communication:node:register", "whisper", (readyCb) => {
|
||||
// TODO: should launch its own whisper node
|
||||
console.dir("--- whisper readyCb");
|
||||
console.dir('--- registering whisper node');
|
||||
// this.events.request('processes:register', 'communication', {
|
||||
// launchFn: (cb) => {
|
||||
// this.startProcess(cb);
|
||||
|
@ -44,51 +37,6 @@ class Whisper {
|
|||
// });
|
||||
// this.registerServiceCheck()
|
||||
});
|
||||
|
||||
this.registerEmbarkJSCommunication();
|
||||
}
|
||||
|
||||
async addEmbarkJSWhisperArtifact(params, cb) {
|
||||
let connection = this.communicationConfig.connection || {};
|
||||
const config = {
|
||||
server: canonicalHost(connection.host || defaultHost),
|
||||
port: connection.port || '8546',
|
||||
type: connection.type || 'ws'
|
||||
};
|
||||
|
||||
const code = `
|
||||
var EmbarkJS;
|
||||
if (typeof EmbarkJS === 'undefined') {
|
||||
EmbarkJS = require('embarkjs');
|
||||
}
|
||||
const __embarkWhisper = require('embarkjs-whisper');
|
||||
EmbarkJS.Messages.registerProvider('whisper', __embarkWhisper.default || __embarkWhisper);
|
||||
EmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)});
|
||||
`;
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir, 'storage'],
|
||||
file: 'init.js',
|
||||
format: 'js',
|
||||
content: code
|
||||
}, cb);
|
||||
}
|
||||
|
||||
async registerEmbarkJSCommunication() {
|
||||
let checkEmbarkJS = `
|
||||
return (typeof EmbarkJS === 'undefined');
|
||||
`;
|
||||
let EmbarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS);
|
||||
|
||||
if (EmbarkJSNotDefined) {
|
||||
await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs'));
|
||||
}
|
||||
|
||||
const registerProviderCode = `
|
||||
const __embarkWhisper = require('embarkjs-whisper');
|
||||
EmbarkJS.Messages.registerProvider('whisper', __embarkWhisper.default || __embarkWhisper);
|
||||
`;
|
||||
|
||||
await this.events.request2('runcode:eval', registerProviderCode);
|
||||
}
|
||||
|
||||
async connectEmbarkJSProvider() {
|
||||
|
@ -98,11 +46,8 @@ class Whisper {
|
|||
port: connection.port || '8546',
|
||||
type: connection.type || 'ws'
|
||||
};
|
||||
const code = `
|
||||
EmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)});
|
||||
`;
|
||||
|
||||
await this.events.request2('runcode:eval', code);
|
||||
this.events.request("embarkjs:console:setProvider", 'messages', 'whisper', config);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -162,6 +162,7 @@ class EmbarkController {
|
|||
engine.registerModuleGroup("stackComponents");
|
||||
|
||||
// TODO: replace with individual plugins
|
||||
engine.registerModuleGroup("namesystem");
|
||||
engine.registerModuleGroup("blockchain");
|
||||
engine.registerModuleGroup("compiler");
|
||||
engine.registerModuleGroup("contracts");
|
||||
|
@ -171,7 +172,6 @@ class EmbarkController {
|
|||
engine.registerModuleGroup("storage");
|
||||
engine.registerModuleGroup("communication");
|
||||
engine.registerModuleGroup("cockpit");
|
||||
engine.registerModuleGroup("namesystem");
|
||||
engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins});
|
||||
|
||||
const plugin = engine.plugins.createPlugin('cmdcontrollerplugin', {});
|
||||
|
|
|
@ -168,6 +168,7 @@ class Engine {
|
|||
this.registerModule('communication');
|
||||
this.registerModulePackage('embark-namesystem');
|
||||
this.registerModulePackage('embark-process-logs-api-manager');
|
||||
this.registerModule('embark-embarkjs', {plugins: this.plugins});
|
||||
}
|
||||
|
||||
blockchainComponents() {
|
||||
|
|
|
@ -12,6 +12,7 @@ function warnIfLegacy(eventName) {
|
|||
}
|
||||
|
||||
function getOrigin() {
|
||||
if (!(process && process.env && process.env.DEBUGEVENTS)) return "";
|
||||
let origin = ((new Error().stack).split("at ")[3]).trim();
|
||||
origin = origin.split("(")[0].trim();
|
||||
return origin;
|
||||
|
@ -118,6 +119,14 @@ EmbarkEmitter.prototype.request2 = function() {
|
|||
this._emit('request:' + requestName, ...other_args);
|
||||
});
|
||||
|
||||
let ogStack = (new Error().stack);
|
||||
|
||||
promise.catch((e) => {
|
||||
console.dir(ogStack);
|
||||
log("\n======== Exception ========", requestName, "\n " + ogStack + "\n==============");
|
||||
return e;
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ class Blockchain {
|
|||
return cb(err);
|
||||
}
|
||||
let config = {
|
||||
provider: contractsConfig.library || 'web3',
|
||||
dappConnection: results,
|
||||
dappAutoEnable: contractsConfig.dappAutoEnable,
|
||||
warnIfMetamask: this.blockchainConfig.isDev,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { __ } from 'embark-i18n';
|
||||
import {canonicalHost, defaultHost} from 'embark-utils';
|
||||
|
||||
class Communication {
|
||||
constructor(embark, _options){
|
||||
|
@ -29,15 +30,14 @@ class Communication {
|
|||
}
|
||||
|
||||
addArtifactFile(_params, cb) {
|
||||
let config = {
|
||||
// TODO: for consistency we should change this to be dappConnection or connection
|
||||
connection: this.communicationConfig.connection
|
||||
};
|
||||
const connection = this.communicationConfig.connection;
|
||||
this.communicationConfig.connection.server = canonicalHost(connection.host || defaultHost);
|
||||
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir, 'config'],
|
||||
file: 'communication.json',
|
||||
format: 'json',
|
||||
content: config
|
||||
content: this.communicationConfig
|
||||
}, cb);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import EmbarkJS from 'embarkjs';
|
||||
|
||||
<% for (let pluginName in (plugins['messages'] || [])) { %>
|
||||
const __embark<%- pluginName %> = require('<%- plugins['messages'][pluginName] %>');
|
||||
EmbarkJS.Messages.registerProvider('<%- pluginName %>', __embark<%- pluginName %>.default || __embark<%- pluginName %>);
|
||||
<% }; %>
|
||||
|
||||
<% for (let pluginName in (plugins['storage'] || [])) { %>
|
||||
const __embark<%- pluginName %> = require('<%- plugins['storage'][pluginName] %>');
|
||||
EmbarkJS.Storage.registerProvider('<%- pluginName %>', __embark<%- pluginName %>.default || __embark<%- pluginName %>);
|
||||
<% }; %>
|
||||
|
||||
<% for (let pluginName in (plugins['blockchain'] || [])) { %>
|
||||
const __embark<%- pluginName %> = require('<%- plugins['blockchain'][pluginName] %>');
|
||||
EmbarkJS.Blockchain.registerProvider('<%- pluginName %>', __embark<%- pluginName %>.default || __embark<%- pluginName %>);
|
||||
<% }; %>
|
||||
|
||||
<% for (let pluginName in (plugins['names'] || [])) { %>
|
||||
const __embark<%- pluginName %> = require('<%- plugins['names'][pluginName] %>');
|
||||
EmbarkJS.Names.registerProvider('<%- pluginName %>', __embark<%- pluginName %>.default || __embark<%- pluginName %>);
|
||||
<% }; %>
|
||||
|
||||
<% if (plugins['messages'] && Object.values(plugins['messages']).length > 0) { %>
|
||||
const communicationConfig = require('./config/communication.json');
|
||||
EmbarkJS.Messages.setProvider(communicationConfig.provider, communicationConfig.connection);
|
||||
<% }; %>
|
||||
|
||||
<% if (plugins['storage'] && Object.values(plugins['storage']).length > 0) { %>
|
||||
const storageConfig = require('./config/storage.json');
|
||||
EmbarkJS.Storage.setProviders(storageConfig.dappConnection);
|
||||
<% }; %>
|
||||
|
||||
<% if (plugins['blockchain'] && Object.values(plugins['blockchain']).length > 0) { %>
|
||||
const blockchainConfig = require('./config/blockchain.json');
|
||||
EmbarkJS.Blockchain.setProvider(blockchainConfig.provider, {});
|
||||
EmbarkJS.Blockchain.connect(blockchainConfig, (err) => {if (err) { console.error(err); } });
|
||||
<% }; %>
|
||||
|
||||
<% if (plugins['names'] && Object.values(plugins['names']).length > 0) { %>
|
||||
const namesConfig = require('./config/namesystem.json');
|
||||
EmbarkJS.Names.setProvider(namesConfig.provider, namesConfig);
|
||||
<% }; %>
|
||||
|
||||
export default EmbarkJS;
|
|
@ -0,0 +1,2 @@
|
|||
<%- className %>Config = <%- JSON.stringify(contract) %>;
|
||||
<%- className %> = new EmbarkJS.Blockchain.Contract(<%- className %>Config);
|
|
@ -0,0 +1,6 @@
|
|||
import EmbarkJS from '../embarkjs';
|
||||
|
||||
const <%- className %>Config = <%- JSON.stringify(contract) %>;
|
||||
const <%- className %> = new EmbarkJS.Blockchain.Contract(<%- className %>Config);
|
||||
|
||||
export default <%- className %>;
|
|
@ -0,0 +1,130 @@
|
|||
import {__} from 'embark-i18n';
|
||||
|
||||
require('ejs');
|
||||
const Templates = {
|
||||
embarkjs_artifact: require('./embarkjs-artifact.js.ejs'),
|
||||
embarkjs_contract_artifact: require('./embarkjs-contract-artifact.js.ejs'),
|
||||
embarkjs_console_contract: require('./embarkjs-console-contract.js.ejs')
|
||||
};
|
||||
|
||||
class EmbarkJS {
|
||||
|
||||
constructor(embark, _options) {
|
||||
this.embark = embark;
|
||||
this.embarkConfig = embark.config.embarkConfig;
|
||||
this.events = embark.events;
|
||||
this.logger = embark.logger;
|
||||
|
||||
this.events.request("runcode:whitelist", 'embarkjs', () => {
|
||||
this.registerEmbarkJS();
|
||||
});
|
||||
|
||||
this.embarkJSPlugins = {};
|
||||
this.events.setCommandHandler("embarkjs:plugin:register", (stackName, pluginName, packageName) => {
|
||||
this.embarkJSPlugins[stackName] = this.embarkJSPlugins[stackName] || {};
|
||||
this.embarkJSPlugins[stackName][pluginName] = packageName;
|
||||
});
|
||||
|
||||
this.events.setCommandHandler("embarkjs:console:register", (stackName, pluginName, packageName, cb) => {
|
||||
this.events.request("runcode:whitelist", packageName, () => { });
|
||||
this.registerEmbarkJSPlugin(stackName, pluginName, packageName, cb || (() => {}));
|
||||
});
|
||||
|
||||
this.events.setCommandHandler("embarkjs:console:setProvider", this.setProvider.bind(this));
|
||||
this.events.setCommandHandler("embarkjs:contract:generate", this.addContractArtifact.bind(this));
|
||||
this.events.setCommandHandler("embarkjs:contract:runInVm", this.runInVm.bind(this));
|
||||
|
||||
embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSArtifact.bind(this));
|
||||
}
|
||||
|
||||
async registerEmbarkJS() {
|
||||
const checkEmbarkJS = `return (typeof EmbarkJS === 'undefined');`;
|
||||
const embarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS);
|
||||
|
||||
if (!embarkJSNotDefined) return;
|
||||
await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs'));
|
||||
}
|
||||
|
||||
async registerEmbarkJSPlugin(stackName, pluginName, packageName, cb) {
|
||||
await this.registerEmbarkJS();
|
||||
|
||||
let moduleName = stackName;
|
||||
if (moduleName === 'messages') moduleName = 'Messages';
|
||||
if (moduleName === 'storage') moduleName = 'Storage';
|
||||
if (moduleName === 'blockchain') moduleName = 'Blockchain';
|
||||
if (moduleName === 'names') moduleName = 'Names';
|
||||
|
||||
const registerProviderCode = `
|
||||
const __embark_${stackName}_${pluginName} = require('${packageName}');
|
||||
EmbarkJS.${moduleName}.registerProvider('${pluginName}', __embark_${stackName}_${pluginName}.default || __embark_${stackName}_${pluginName});
|
||||
`;
|
||||
|
||||
await this.events.request2('runcode:eval', registerProviderCode);
|
||||
cb();
|
||||
}
|
||||
|
||||
addEmbarkJSArtifact(_params, cb) {
|
||||
let embarkjsCode = Templates.embarkjs_artifact({ plugins: this.embarkJSPlugins });
|
||||
|
||||
// TODO: generate a .node file
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir],
|
||||
file: 'embarkjs.js',
|
||||
format: 'js',
|
||||
content: embarkjsCode
|
||||
}, cb);
|
||||
}
|
||||
|
||||
async setProvider(stackName, pluginName, config) {
|
||||
let moduleName = stackName;
|
||||
if (moduleName === 'messages') moduleName = 'Messages';
|
||||
if (moduleName === 'storage') moduleName = 'Storage';
|
||||
if (moduleName === 'blockchain') moduleName = 'Blockchain';
|
||||
if (moduleName === 'names') moduleName = 'Names';
|
||||
|
||||
let code = "";
|
||||
if (stackName === 'storage') {
|
||||
code = `EmbarkJS.${moduleName}.setProviders(${JSON.stringify(config)});`;
|
||||
} else if (stackName === 'blockchain') {
|
||||
code = `EmbarkJS.${moduleName}.setProvider('${pluginName}', ${config});`;
|
||||
} else {
|
||||
code = `EmbarkJS.${moduleName}.setProvider('${pluginName}', ${JSON.stringify(config)});`;
|
||||
}
|
||||
await this.events.request2('runcode:eval', code);
|
||||
}
|
||||
|
||||
async addContractArtifact(contract, cb) {
|
||||
const abi = JSON.stringify(contract.abiDefinition);
|
||||
const gasLimit = 6000000;
|
||||
|
||||
const contractCode = Templates.embarkjs_contract_artifact({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit });
|
||||
|
||||
this.events.request("pipeline:register", {
|
||||
path: [this.embarkConfig.generationDir, 'contracts'],
|
||||
file: contract.className + '.js',
|
||||
format: 'js',
|
||||
content: contractCode
|
||||
}, cb);
|
||||
}
|
||||
|
||||
async runInVm(contract, cb) {
|
||||
const abi = contract.abiDefinition;
|
||||
const gasLimit = 6000000;
|
||||
const provider = await this.events.request2("blockchain:client:provider", "ethereum");
|
||||
const contractCode = Templates.embarkjs_console_contract({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit, provider: provider });
|
||||
|
||||
try {
|
||||
await this.registerEmbarkJS();
|
||||
await this.events.request2('runcode:eval', contractCode);
|
||||
const result = await this.events.request2('runcode:eval', contract.className);
|
||||
result.currentProvider = provider;
|
||||
await this.events.request2("runcode:register", contract.className, result);
|
||||
cb();
|
||||
} catch (err) {
|
||||
cb(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = EmbarkJS;
|
|
@ -1,5 +1,6 @@
|
|||
/* global global require */
|
||||
const EmbarkJS = global.EmbarkJS || require('embarkjs');
|
||||
let EmbarkJS = global.EmbarkJS || require('embarkjs');
|
||||
EmbarkJS = EmbarkJS.default || EmbarkJS;
|
||||
const ENSFunctions = require('./ENSFunctions').default;
|
||||
const Web3 = require('web3');
|
||||
const namehash = require('eth-ens-namehash');
|
||||
|
@ -159,6 +160,7 @@ __embarkENS.setProvider = function(config) {
|
|||
self.registration = config.registration;
|
||||
self.env = config.env;
|
||||
self.ready = false;
|
||||
|
||||
// FIXME EmbarkJS.onReady doesn't work. Possibility of a race condition
|
||||
EmbarkJS.Blockchain.blockchainConnector.getNetworkId()
|
||||
.then((id) => {
|
||||
|
|
|
@ -51,7 +51,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime-corejs2": "7.3.1",
|
||||
"swarm-api": "0.1.2"
|
||||
"swarm-api": "0.1.2",
|
||||
"web3": "1.0.0-beta.37"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.2.3",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
let __embarkSwarm = {_swarmConnection: undefined};
|
||||
const __embarkSwarm = {_swarmConnection: undefined};
|
||||
let SwarmAPI = require('swarm-api');
|
||||
const Web3 = require('web3');
|
||||
if (SwarmAPI.default) {
|
||||
SwarmAPI = SwarmAPI.default;
|
||||
}
|
||||
|
@ -13,15 +14,15 @@ __embarkSwarm.setProvider = function (options) {
|
|||
this._connectError = new Error(`Cannot connect to Swarm node on ${this._connectUrl}`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if(!options.web3) {
|
||||
reject(__("A web3 object must be passed in to __embarkSwarm.setProvider"));
|
||||
let web3;
|
||||
if (!options.web3) {
|
||||
web3 = new Web3(this._connectUrl);
|
||||
}
|
||||
const {web3, useOnlyGivenProvider} = options;
|
||||
try {
|
||||
if (!web3.bzz.currentProvider && !useOnlyGivenProvider) {
|
||||
if (!web3.bzz.currentProvider) {
|
||||
this._swarmConnection = new SwarmAPI({gateway: this._connectUrl});
|
||||
}
|
||||
else if (useOnlyGivenProvider && web3.bzz.givenProvider !== null) {
|
||||
else {
|
||||
this._swarmConnection = new SwarmAPI({gateway: web3.bzz.givenProvider});
|
||||
}
|
||||
resolve(this);
|
||||
|
|
|
@ -221,8 +221,8 @@ let Contract = function(options) {
|
|||
var self = this;
|
||||
var ContractClass;
|
||||
|
||||
this.abi = options.abi;
|
||||
this.address = options.address;
|
||||
this.abi = options.abi || options.abiDefinition;
|
||||
this.address = options.address || options.deployedAddress;
|
||||
this.gas = options.gas;
|
||||
this.code = '0x' + options.code;
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ Storage.setProviders = function (dappConnOptions, addlOpts) {
|
|||
detectSeries(dappConnOptions, (dappConn, callback) => {
|
||||
let options = dappConn;
|
||||
if (dappConn === '$BZZ') options = {"useOnlyGivenProvider": true};
|
||||
options = {...options, ...addlOpts};
|
||||
options = {...options, ...addlOpts, ...dappConn};
|
||||
try {
|
||||
self.setProvider(dappConn === '$BZZ' ? dappConn : dappConn.provider, options).then(() => {
|
||||
self.isAvailable().then((isAvailable) => {
|
||||
|
|
Loading…
Reference in New Issue