Updates from release v0.1.13
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"ms-vscode.vscode-typescript-tslint-plugin"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Run Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "Build extension with watcher"
|
||||
},
|
||||
{
|
||||
"name": "Launch Extension with Drizzle UI",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "Run extension with Drizzle UI"
|
||||
},
|
||||
{
|
||||
"name": "Extension Tests",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/test/**/*.js"
|
||||
],
|
||||
"env": {
|
||||
"CODE_TEST": "true"
|
||||
},
|
||||
"preLaunchTask": "Build extension with watcher"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debugger Server",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/out/src/debugger.js",
|
||||
"args": [ "--server=4711" ]
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Run Extension and Debugger separately",
|
||||
"configurations": [ "Run Extension", "Debugger Server" ]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"files.exclude": {
|
||||
"out": false // set this to true to hide the "out" folder with the compiled JS files
|
||||
},
|
||||
"search.exclude": {
|
||||
"out": true // set this to false to include "out" folder in search results
|
||||
},
|
||||
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
|
||||
"typescript.tsc.autoDetect": "off",
|
||||
"cSpell.words": [
|
||||
"Azure Blockchain Service",
|
||||
"Blanco",
|
||||
"Bytecode",
|
||||
"Ethereum",
|
||||
"blockchain",
|
||||
"endregion",
|
||||
"infura",
|
||||
"microservices",
|
||||
"openzeppelin",
|
||||
"subfolder"
|
||||
],
|
||||
"javascript.referencesCodeLens.enabled": true,
|
||||
"typescript.implementationsCodeLens.enabled": true,
|
||||
"typescript.referencesCodeLens.enabled": true
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build extension",
|
||||
"type": "npm",
|
||||
"script": "compile",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "Clean tests folder",
|
||||
"type": "npm",
|
||||
"script": "clean",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "Build extension with watcher",
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never"
|
||||
},
|
||||
"group": "build",
|
||||
"dependsOn": [
|
||||
"Clean tests folder"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Install dependencies for Drizzle UI",
|
||||
"type": "npm",
|
||||
"script": "install",
|
||||
"path": "drizzleUI/",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "Build Drizzle UI",
|
||||
"type": "npm",
|
||||
"script": "build:ext:dev",
|
||||
"path": "drizzleUI/",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "Run extension with Drizzle UI",
|
||||
"dependsOn": [
|
||||
"Install dependencies for Drizzle UI",
|
||||
"Build Drizzle UI",
|
||||
"Build extension"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -10,6 +10,7 @@ out/**
|
|||
!out/src/extension.js
|
||||
!out/src/debugger.js
|
||||
!out/src/web3ProviderResolver.js
|
||||
!out/src/checkTruffleConfigTemplate.js
|
||||
src/**
|
||||
test/**
|
||||
.editorconfig
|
||||
|
|
38
CHANGELOG.md
|
@ -2,7 +2,24 @@
|
|||
|
||||
All notable changes to the "azure blockchain" extension will be documented in this file.
|
||||
|
||||
## 0.1.13
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Added progress notifications for long running tasks.
|
||||
- Updated transaction bytecode copy option to support libraries and complex contracts.
|
||||
- Added the ability to upgrade contracts deployed as part of OpenZeppelin.
|
||||
- Added the ability for contract build redirects from configuration to be respected.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Updated requirements for minimum VS Code version to 1.36.1. This was to resolve some issues specific to Mac OS.
|
||||
- Updated notifications for code generation to be accurate for each type (logic app, flow app, function).
|
||||
|
||||
### Internal Improvements
|
||||
|
||||
- Test runner enhancements to fix some test issues (timing)
|
||||
- Updated search tags for SEO
|
||||
|
||||
## 0.1.12
|
||||
|
||||
|
@ -20,7 +37,7 @@ All notable changes to the "azure blockchain" extension will be documented in th
|
|||
- Bumped HD wallet provider to latest Truffle version
|
||||
- Minimized output channel logs
|
||||
- Fixed output channel issue which shows JavaScript object after contract migration
|
||||
- Preview features added for token (TTI compliant) generation were added.
|
||||
- Preview features added for token (TTI compliant) generation were added.
|
||||
|
||||
## 0.1.10
|
||||
|
||||
|
@ -55,14 +72,14 @@ All notable changes to the "azure blockchain" extension will be documented in th
|
|||
|
||||
## 0.1.5
|
||||
|
||||
- Backend test coverage
|
||||
- Cleanup of packaging output, optimization
|
||||
- Truffle installation fails on new installs fix
|
||||
- Improved support for multiple ganache instances
|
||||
- Preflight validation for ABS deployments
|
||||
- Cleanup of code generation output
|
||||
- Ganache commands cleanup
|
||||
- Add command to export private key from mnemonic
|
||||
- Backend test coverage
|
||||
- Cleanup of packaging output, optimization
|
||||
- Truffle installation fails on new installs fix
|
||||
- Improved support for multiple ganache instances
|
||||
- Preflight validation for ABS deployments
|
||||
- Cleanup of code generation output
|
||||
- Ganache commands cleanup
|
||||
- Add command to export private key from mnemonic
|
||||
- Better error handling ABS deployments
|
||||
|
||||
## 0.1.4
|
||||
|
@ -83,7 +100,6 @@ All notable changes to the "azure blockchain" extension will be documented in th
|
|||
|
||||
- Updated menu options
|
||||
|
||||
## 0.1.0
|
||||
## 0.1.0
|
||||
|
||||
- Initial release
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ Azure Blockchain Development Kit simplifies how you create, connect to, build an
|
|||
- Supported Operating Systems
|
||||
- Windows 10
|
||||
- Mac OSX
|
||||
- VS Code 1.32.0 (or greater)
|
||||
- VS Code 1.36.1 (or greater)
|
||||
- Python 2.7.15
|
||||
- Node 10.15.x
|
||||
- Git 2.10.x
|
||||
|
@ -30,9 +30,9 @@ The first thing to do is to create an Azure Blockchain Service in your subscript
|
|||
|
||||
2. Choose your subscription, resource group and region to deploy to.
|
||||
|
||||
4. Enter the name of your [Consortium](https://docs.microsoft.com/azure/blockchain/service/consortium)
|
||||
3. Enter the name of your [Consortium](https://docs.microsoft.com/azure/blockchain/service/consortium)
|
||||
|
||||
5. Wait until your resource has been created in Azure.
|
||||
4. Wait until your resource has been created in Azure.
|
||||
`Note: Deploying the Azure Blockchain Service takes quite some time to complete. Please check the deployment status in the Azure portal.`
|
||||
|
||||
## Create a new Solidity Contract
|
||||
|
@ -55,8 +55,7 @@ For developers who are not familiar with Truffle, or prefer to use the Command P
|
|||
|
||||
Once complete, your project directory should look like this:
|
||||
|
||||
![completed directory](https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/newProjectDir.png)
|
||||
|
||||
[![completed directory](https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/newProjectDirCloseup.png)](https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/newProjectDir.png#lightbox)
|
||||
|
||||
## Build your Solidity Contract
|
||||
|
||||
|
|
|
@ -11,45 +11,47 @@
|
|||
"lint:fix": "npm run lint -- --fix"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.5.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.5.5",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.5.5",
|
||||
"@babel/plugin-syntax-bigint": "^7.4.4",
|
||||
"@babel/plugin-transform-runtime": "^7.5.5",
|
||||
"@babel/preset-env": "^7.5.5",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"babel-eslint": "^10.0.2",
|
||||
"@babel/core": "^7.7.7",
|
||||
"@babel/plugin-proposal-class-properties": "^7.7.4",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.7.7",
|
||||
"@babel/plugin-syntax-bigint": "^7.7.4",
|
||||
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||
"@babel/preset-env": "^7.7.7",
|
||||
"@babel/preset-react": "^7.7.4",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-loader": "^8.0.6",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^3.1.0",
|
||||
"eslint": "^6.1.0",
|
||||
"eslint-config-airbnb": "^17.1.1",
|
||||
"eslint-loader": "^2.2.1",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-jest": "^22.14.0",
|
||||
"cross-env": "^6.0.3",
|
||||
"css-loader": "^3.4.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-airbnb": "^18.0.1",
|
||||
"eslint-loader": "^3.0.3",
|
||||
"eslint-plugin-import": "^2.19.1",
|
||||
"eslint-plugin-jest": "^23.2.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-react": "^7.14.3",
|
||||
"file-loader": "^4.1.0",
|
||||
"eslint-plugin-react": "^7.17.0",
|
||||
"eslint-plugin-react-hooks": "^2.3.0",
|
||||
"file-loader": "^5.0.2",
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"less": "^3.9.0",
|
||||
"less": "^3.10.3",
|
||||
"less-loader": "^5.0.0",
|
||||
"mini-css-extract-plugin": "^0.8.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"style-loader": "^0.23.1",
|
||||
"url-loader": "^2.1.0",
|
||||
"webpack": "^4.38.0",
|
||||
"webpack-cli": "^3.3.6"
|
||||
"string-replace-loader": "^2.2.0",
|
||||
"style-loader": "^1.1.2",
|
||||
"url-loader": "^3.0.0",
|
||||
"webpack": "^4.41.5",
|
||||
"webpack-cli": "^3.3.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@drizzle/react-components": "^1.5.1",
|
||||
"@drizzle/react-plugin": "^1.5.1",
|
||||
"@drizzle/store": "^1.5.1",
|
||||
"@material-ui/core": "^4.2.1",
|
||||
"@material-ui/icons": "^4.2.1",
|
||||
"@truffle/hdwallet-provider": "^1.0.23",
|
||||
"react": "^16.10.2",
|
||||
"react-dom": "^16.10.2"
|
||||
"@material-ui/core": "^4.8.2",
|
||||
"@material-ui/icons": "^4.5.1",
|
||||
"@truffle/hdwallet-provider": "^1.0.28",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import BooleanInput from './BooleanInput';
|
||||
import TextInput from './TextInput';
|
||||
|
||||
const InputComponentMapping = {
|
||||
address: TextInput,
|
||||
string: TextInput,
|
||||
uint: TextInput,
|
||||
bool: BooleanInput,
|
||||
};
|
||||
|
||||
export default InputComponentMapping;
|
|
@ -1,56 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { TextField } from '@material-ui/core';
|
||||
|
||||
class ContractProperty extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
property: {
|
||||
name: '',
|
||||
value: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getPropertyInfo();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.getPropertyInfo();
|
||||
}
|
||||
|
||||
getPropertyInfo = () => {
|
||||
this.props.property.method().call().then(result => {
|
||||
const property = Object.assign({ name: this.props.property.name, value: result });
|
||||
if (property.name !== this.state.property.name
|
||||
|| property.value !== this.state.property.value) {
|
||||
this.setState({ property });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { property } = this.state;
|
||||
|
||||
return <TextField
|
||||
className='metadata text field'
|
||||
disabled
|
||||
fullWidth
|
||||
id='contract-address'
|
||||
label={property.name}
|
||||
value={property.value}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
||||
export default ContractProperty;
|
||||
|
||||
ContractProperty.propTypes = {
|
||||
property: PropTypes.object.isRequired,
|
||||
};
|
|
@ -4,10 +4,36 @@
|
|||
import App from './App';
|
||||
import { contractEventNotifier } from 'middlewares';
|
||||
import { DrizzleContext } from '@drizzle/react-plugin';
|
||||
import { LocalStorage } from 'polyfills/localStorage';
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { Drizzle, generateStore } from '@drizzle/store';
|
||||
|
||||
const storage = new LocalStorage();
|
||||
|
||||
window.ls = new Proxy(storage, {
|
||||
set: (_, prop, value) => {
|
||||
if (LocalStorage.prototype.hasOwnProperty(prop)) {
|
||||
storage[prop] = value;
|
||||
} else {
|
||||
storage.setItem(prop, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
get: (_, name) => {
|
||||
if (LocalStorage.prototype.hasOwnProperty(name)) {
|
||||
return storage[name];
|
||||
}
|
||||
if (storage.values.has(name)) {
|
||||
return storage.getItem(name);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
Drizzle.prototype.deleteAllContracts = function () {
|
||||
Object.keys(this.contracts)
|
||||
.forEach(contractName => this.deleteContract(contractName));
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
const getCommandList = commands => commands
|
||||
.trim()
|
||||
.split(' ')
|
||||
.map(command => command.trim());
|
||||
|
||||
const execute = (listeners, command, data) => {
|
||||
if (listeners.has(command)) {
|
||||
const handlers = listeners.get(command);
|
||||
|
||||
handlers.forEach(handler => handler(data));
|
||||
}
|
||||
};
|
||||
|
||||
const addToListeners = (listeners, commands, handler) => {
|
||||
const commandsList = getCommandList(commands);
|
||||
|
||||
commandsList.forEach(command => {
|
||||
if (!listeners.has(command)) {
|
||||
listeners.set(command, []);
|
||||
}
|
||||
|
||||
const handlers = listeners.get(command);
|
||||
|
||||
handlers.push(handler);
|
||||
});
|
||||
};
|
||||
|
||||
const removeFromListeners = (listeners, commands, handler) => {
|
||||
const commandsList = getCommandList(commands);
|
||||
|
||||
commandsList.forEach(command => {
|
||||
if (listeners.has(command)) {
|
||||
if (!handler) {
|
||||
listeners.delete(command);
|
||||
return;
|
||||
}
|
||||
|
||||
let handlers = listeners.get(command);
|
||||
|
||||
handlers = handlers.filter(element => element !== handler);
|
||||
|
||||
listeners.set(command, handlers);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const removeAllListers = (listeners, command) => listeners.delete(command);
|
||||
|
||||
export const Helpers = {
|
||||
execute,
|
||||
addToListeners,
|
||||
removeFromListeners,
|
||||
removeAllListers
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Helpers } from './helpers';
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
const listeners = new Map();
|
||||
const onceListeners = new Map();
|
||||
|
||||
const on = (commands, handler) => Helpers.addToListeners(listeners, commands, handler);
|
||||
|
||||
const once = (commands, handler) => Helpers.addToListeners(onceListeners, commands, handler);
|
||||
|
||||
const off = (commands, handler) => {
|
||||
Helpers.removeFromListeners(listeners, commands, handler);
|
||||
Helpers.removeFromListeners(onceListeners, commands, handler);
|
||||
};
|
||||
|
||||
const postMessage = (command, value) => vscode.postMessage({ command, value });
|
||||
|
||||
const messageReceived = (event) => {
|
||||
const { command, value: data } = event.data;
|
||||
|
||||
Helpers.execute(listeners, command, data);
|
||||
Helpers.execute(onceListeners, command, data);
|
||||
|
||||
Helpers.removeAllListers(onceListeners, command);
|
||||
};
|
||||
|
||||
window.addEventListener('message', messageReceived, false);
|
||||
|
||||
export const IPCService = {
|
||||
on,
|
||||
once,
|
||||
off,
|
||||
postMessage
|
||||
};
|
|
@ -37,6 +37,7 @@ module.exports = () => {
|
|||
components: path.join(__dirname, './src/components'),
|
||||
constants: path.join(__dirname, './src/constants'),
|
||||
helpers: path.join(__dirname, './src/helpers'),
|
||||
polyfills: path.join(__dirname, './src/polyfills'),
|
||||
services: path.join(__dirname, './src/services'),
|
||||
views: path.join(__dirname, './src/views'),
|
||||
middlewares: path.join(__dirname, './src/middlewares'),
|
||||
|
@ -69,6 +70,19 @@ module.exports = () => {
|
|||
test: [/\.js$/, /\.jsx$/],
|
||||
exclude: /node_modules/,
|
||||
loader: 'eslint-loader'
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'string-replace-loader',
|
||||
options: {
|
||||
search: 'localStorage',
|
||||
replace: 'ls',
|
||||
flags: 'g'
|
||||
},
|
||||
exclude: path.join(__dirname, 'src', 'index.js'),
|
||||
include: [
|
||||
path.resolve(__dirname, 'node_modules')
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
Двоичные данные
images/createConsortium.png
До Ширина: | Высота: | Размер: 94 KiB |
24
package.json
|
@ -5,7 +5,7 @@
|
|||
"publisher": "AzBlockchain",
|
||||
"preview": true,
|
||||
"icon": "images/blockchain-service-logo.png",
|
||||
"version": "0.1.12",
|
||||
"version": "0.1.13",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum"
|
||||
|
@ -16,12 +16,13 @@
|
|||
"homepage": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum/blob/master/README.md",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"vscode": "^1.32.0"
|
||||
"vscode": "^1.36.1"
|
||||
},
|
||||
"keywords": [
|
||||
"azure",
|
||||
"blockchain",
|
||||
"azure",
|
||||
"ethereum",
|
||||
"debuggers",
|
||||
"snippet"
|
||||
],
|
||||
"categories": [
|
||||
|
@ -59,6 +60,21 @@
|
|||
"onDebug"
|
||||
],
|
||||
"contributes": {
|
||||
"configuration": {
|
||||
"title": "Azure Blockchain Development Kit for Ethereum",
|
||||
"properties": {
|
||||
"azureBlockchainService.ignoreLongRunningTaskNotification": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Disable notification on long running tasks."
|
||||
},
|
||||
"azureBlockchainService.openZeppelin.version": {
|
||||
"type": "string",
|
||||
"default": "2.4.0",
|
||||
"scope": "The latest Open Zeppelin version"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "azureBlockchainService.generateMicroservicesWorkflows",
|
||||
|
@ -498,7 +514,7 @@
|
|||
"@types/semver": "^6.0.0",
|
||||
"@types/sinon": "^7.0.11",
|
||||
"@types/uuid": "^3.4.4",
|
||||
"@types/vscode": "^1.32.0",
|
||||
"@types/vscode": "^1.36.1",
|
||||
"copy-webpack-plugin": "^5.0.3",
|
||||
"decache": "^4.5.1",
|
||||
"glob": "^7.1.4",
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#7FBA00" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0z"/>
|
||||
<path opacity="0.15" d="M5,6.056C5,5.473,5.473,5,6.056,5h16.877c-0.037-0.098-0.086-0.191-0.152-0.274L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0H1C0.448,0,0,0.448,0,1v15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
c0.083,0.099,0.189,0.171,0.3,0.231V6.056z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
|
||||
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
|
||||
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<path fill="#68217A" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
|
||||
C46.11,27.138,45.823,27,45.519,27z"/>
|
||||
<path fill="#804998" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
|
||||
C50,32.448,49.552,32,49,32z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M32,32.375c-0.096,0-0.192-0.036-0.266-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
|
||||
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C32.192,32.339,32.096,32.375,32,32.375z"/>
|
||||
<path fill="#DD5900" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
|
||||
C46.11,0.138,45.823,0,45.519,0z"/>
|
||||
<path opacity="0.2" fill="#FFFFFF" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6
|
||||
C50,5.448,49.552,5,49,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M32,5.375c-0.096,0-0.192-0.037-0.266-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
|
||||
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C32.192,5.338,32.096,5.375,32,5.375z"/>
|
||||
<rect x="40" y="18" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path fill="#0072C6" d="M18.519,27H1c-0.552,0-1,0.448-1,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,49.64
|
||||
C4.89,49.868,5.172,50,5.468,50H22c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L19.3,27.375
|
||||
C19.11,27.138,18.823,27,18.519,27z"/>
|
||||
<path fill="#3999C6" d="M22,32H6c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33C23,32.448,22.552,32,22,32
|
||||
z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,50H6c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L9.5,50z"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,37.1,14,37.1 M14,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,36.1,14,36.1L14,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M5,5.375c-0.096,0-0.192-0.037-0.265-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
|
||||
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C5.192,5.338,5.096,5.375,5,5.375z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
|
||||
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
|
||||
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M14,31c-1.103,0-2-0.897-2-2v-2h4v2C16,30.103,15.103,31,14,31z"/>
|
||||
<path fill="#00188F" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,41c0,1.103-0.897,2-2,2h-2v-4h2C30.103,39,31,39.897,31,41z"/>
|
||||
<path fill="#00188F" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
|
||||
<rect x="32" y="40" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<rect x="13" y="32" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M5,32.375c-0.096,0-0.192-0.036-0.265-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
|
||||
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C5.192,32.339,5.096,32.375,5,32.375z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 6.0 KiB |
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#0072C6" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0z"/>
|
||||
<path fill="#3999C6" d="M22,5H6C5.448,5,5,5.448,5,6v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C23,5.448,22.552,5,22,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
|
||||
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
|
||||
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<path fill="#0072C6" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
|
||||
C46.11,27.138,45.823,27,45.519,27z"/>
|
||||
<path fill="#3999C6" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
|
||||
C50,32.448,49.552,32,49,32z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="27.5" x2="32" y2="32"/>
|
||||
<path fill="#0072C6" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
|
||||
C46.11,0.138,45.823,0,45.519,0z"/>
|
||||
<path fill="#3999C6" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C50,5.448,49.552,5,49,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="0.5" x2="32" y2="5"/>
|
||||
<line opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="41" y1="23" x2="41" y2="18"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#00188F" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
|
||||
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
|
||||
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
|
||||
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<path fill="#0072C6" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
|
||||
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
|
||||
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
|
||||
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
|
||||
</g>
|
||||
<path opacity="0.2" fill="#FFFFFF" d="M7.141,45.315l-0.114,2.307l3.742-6.05c-0.732-0.45-1.338-1.118-1.691-1.974
|
||||
c-0.885-2.152,0.142-4.607,2.298-5.491c1.299-0.532,2.702-0.362,3.811,0.321l3.741-6.049l0.065-1.3L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.231,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231L7.141,45.315z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="0.5" y1="0.5" x2="5" y2="5"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
|
||||
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
|
||||
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 5.7 KiB |
|
@ -1,5 +0,0 @@
|
|||
<svg width="32" height="36" viewBox="0 0 32 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 10L15 18.5V35.5L0 27V10Z" fill="white"/>
|
||||
<path d="M32 10L17 18.5V35.5L32 27V10Z" fill="white"/>
|
||||
<path d="M7.42857 4.95833L16 0L23.8571 4.25L31 8.5L16 17L1 8.5L7.42857 4.95833Z" fill="white"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 313 B |
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#0072C6" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0z"/>
|
||||
<path fill="#3999C6" d="M22,5H6C5.448,5,5,5.448,5,6v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C23,5.448,22.552,5,22,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
|
||||
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
|
||||
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<path fill="#0072C6" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
|
||||
C46.11,27.138,45.823,27,45.519,27z"/>
|
||||
<path fill="#3999C6" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
|
||||
C50,32.448,49.552,32,49,32z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="27.5" x2="32" y2="32"/>
|
||||
<path fill="#0072C6" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
|
||||
C46.11,0.138,45.823,0,45.519,0z"/>
|
||||
<path fill="#3999C6" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C50,5.448,49.552,5,49,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="0.5" x2="32" y2="5"/>
|
||||
<line opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="41" y1="23" x2="41" y2="18"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#00188F" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
|
||||
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
|
||||
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
|
||||
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<path fill="#0072C6" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
|
||||
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
|
||||
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
|
||||
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
|
||||
</g>
|
||||
<path opacity="0.2" fill="#FFFFFF" d="M7.141,45.315l-0.114,2.307l3.742-6.05c-0.732-0.45-1.338-1.118-1.691-1.974
|
||||
c-0.885-2.152,0.142-4.607,2.298-5.491c1.299-0.532,2.702-0.362,3.811,0.321l3.741-6.049l0.065-1.3L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.231,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231L7.141,45.315z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="0.5" y1="0.5" x2="5" y2="5"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
|
||||
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
|
||||
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 5.7 KiB |
|
@ -1,83 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#7FBA00" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0z"/>
|
||||
<path opacity="0.15" d="M5,6.056C5,5.473,5.473,5,6.056,5h16.877c-0.037-0.098-0.086-0.191-0.152-0.274L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0H1C0.448,0,0,0.448,0,1v15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
c0.083,0.099,0.189,0.171,0.3,0.231V6.056z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
|
||||
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
|
||||
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<path fill="#68217A" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
|
||||
C46.11,27.138,45.823,27,45.519,27z"/>
|
||||
<path fill="#804998" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
|
||||
C50,32.448,49.552,32,49,32z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M32,32.375c-0.096,0-0.192-0.036-0.266-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
|
||||
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C32.192,32.339,32.096,32.375,32,32.375z"/>
|
||||
<path fill="#DD5900" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
|
||||
C46.11,0.138,45.823,0,45.519,0z"/>
|
||||
<path opacity="0.2" fill="#FFFFFF" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6
|
||||
C50,5.448,49.552,5,49,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M32,5.375c-0.096,0-0.192-0.037-0.266-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
|
||||
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C32.192,5.338,32.096,5.375,32,5.375z"/>
|
||||
<rect x="40" y="18" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path fill="#0072C6" d="M18.519,27H1c-0.552,0-1,0.448-1,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,49.64
|
||||
C4.89,49.868,5.172,50,5.468,50H22c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L19.3,27.375
|
||||
C19.11,27.138,18.823,27,18.519,27z"/>
|
||||
<path fill="#3999C6" d="M22,32H6c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33C23,32.448,22.552,32,22,32
|
||||
z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,50H6c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L9.5,50z"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,37.1,14,37.1 M14,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,36.1,14,36.1L14,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M5,5.375c-0.096,0-0.192-0.037-0.265-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
|
||||
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C5.192,5.338,5.096,5.375,5,5.375z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
|
||||
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
|
||||
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M14,31c-1.103,0-2-0.897-2-2v-2h4v2C16,30.103,15.103,31,14,31z"/>
|
||||
<path fill="#00188F" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,41c0,1.103-0.897,2-2,2h-2v-4h2C30.103,39,31,39.897,31,41z"/>
|
||||
<path fill="#00188F" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
|
||||
<rect x="32" y="40" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<rect x="13" y="32" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M5,32.375c-0.096,0-0.192-0.036-0.265-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
|
||||
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C5.192,32.339,5.096,32.375,5,32.375z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 6.0 KiB |
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#0072C6" d="M38.428,3H4.913C3.856,3,3,3.856,3,4.913v29.916c0,0.448,0.157,0.881,0.443,1.225l8.548,10.258
|
||||
C12.355,46.748,12.893,47,13.461,47h31.626C46.144,47,47,46.144,47,45.087V13.236c0-0.434-0.148-0.856-0.419-1.195l-6.659-8.323
|
||||
C39.559,3.264,39.01,3,38.428,3z"/>
|
||||
<path fill="#3999C6" d="M45.111,13H14.889C13.846,13,13,13.846,13,14.889v30.222C13,46.154,13.846,47,14.889,47h30.222
|
||||
C46.154,47,47,46.154,47,45.111V14.889C47,13.846,46.154,13,45.111,13z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M21.5,47h-6.611C13.846,47,13,46.154,13,45.111V14.889C13,13.846,13.846,13,14.889,13H40.2
|
||||
L21.5,47z"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="29.783" cy="29.783" r="6.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M29.783,22.883c3.804,0,6.9,3.096,6.9,6.9s-3.096,6.9-6.9,6.9s-6.9-3.096-6.9-6.9
|
||||
S25.978,22.883,29.783,22.883 M29.783,21.383c-4.632,0-8.4,3.768-8.4,8.4s3.768,8.4,8.4,8.4s8.4-3.768,8.4-8.4
|
||||
S34.414,21.383,29.783,21.383L29.783,21.383z"/>
|
||||
</g>
|
||||
</g>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="4.5" y1="4.5" x2="13" y2="13"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 1.5 KiB |
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<polygon fill="#804998" points="45.946,26.164 44.054,23.836 29.698,35.5 23.488,20.332 21.089,19.709 4.089,32.709 5.911,35.091
|
||||
21.43,23.224 27.712,38.568 29.911,39.192 29.907,39.116 29.946,39.164 "/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="5" cy="33.9" r="4.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="22" cy="20.9" r="4.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="29" cy="38" r="4.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="45" cy="25" r="4.9"/>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<circle fill="#0072C6" cx="5" cy="33.9" r="4.9"/>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<circle fill="#0072C6" cx="22" cy="20.9" r="4.9"/>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<circle fill="#0072C6" cx="29" cy="38" r="4.9"/>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<circle fill="#0072C6" cx="45" cy="25" r="4.9"/>
|
||||
</g>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -1,83 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#7FBA00" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0z"/>
|
||||
<path opacity="0.15" d="M5,6.056C5,5.473,5.473,5,6.056,5h16.877c-0.037-0.098-0.086-0.191-0.152-0.274L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0H1C0.448,0,0,0.448,0,1v15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
c0.083,0.099,0.189,0.171,0.3,0.231V6.056z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
|
||||
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
|
||||
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<path fill="#68217A" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
|
||||
C46.11,27.138,45.823,27,45.519,27z"/>
|
||||
<path fill="#804998" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
|
||||
C50,32.448,49.552,32,49,32z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M32,32.375c-0.096,0-0.192-0.036-0.266-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
|
||||
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C32.192,32.339,32.096,32.375,32,32.375z"/>
|
||||
<path fill="#DD5900" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
|
||||
C46.11,0.138,45.823,0,45.519,0z"/>
|
||||
<path opacity="0.2" fill="#FFFFFF" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6
|
||||
C50,5.448,49.552,5,49,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M32,5.375c-0.096,0-0.192-0.037-0.266-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
|
||||
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C32.192,5.338,32.096,5.375,32,5.375z"/>
|
||||
<rect x="40" y="18" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path fill="#0072C6" d="M18.519,27H1c-0.552,0-1,0.448-1,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,49.64
|
||||
C4.89,49.868,5.172,50,5.468,50H22c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L19.3,27.375
|
||||
C19.11,27.138,18.823,27,18.519,27z"/>
|
||||
<path fill="#3999C6" d="M22,32H6c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33C23,32.448,22.552,32,22,32
|
||||
z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,50H6c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L9.5,50z"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,37.1,14,37.1 M14,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,36.1,14,36.1L14,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M5,5.375c-0.096,0-0.192-0.037-0.265-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
|
||||
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C5.192,5.338,5.096,5.375,5,5.375z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
|
||||
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
|
||||
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M14,31c-1.103,0-2-0.897-2-2v-2h4v2C16,30.103,15.103,31,14,31z"/>
|
||||
<path fill="#00188F" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,41c0,1.103-0.897,2-2,2h-2v-4h2C30.103,39,31,39.897,31,41z"/>
|
||||
<path fill="#00188F" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
|
||||
<rect x="32" y="40" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<rect x="13" y="32" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M5,32.375c-0.096,0-0.192-0.036-0.265-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
|
||||
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C5.192,32.339,5.096,32.375,5,32.375z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 6.0 KiB |
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#0072C6" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0z"/>
|
||||
<path fill="#3999C6" d="M22,5H6C5.448,5,5,5.448,5,6v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C23,5.448,22.552,5,22,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
|
||||
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
|
||||
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<path fill="#0072C6" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
|
||||
C46.11,27.138,45.823,27,45.519,27z"/>
|
||||
<path fill="#3999C6" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
|
||||
C50,32.448,49.552,32,49,32z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="27.5" x2="32" y2="32"/>
|
||||
<path fill="#0072C6" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
|
||||
C46.11,0.138,45.823,0,45.519,0z"/>
|
||||
<path fill="#3999C6" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C50,5.448,49.552,5,49,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="0.5" x2="32" y2="5"/>
|
||||
<line opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="41" y1="23" x2="41" y2="18"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#00188F" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
|
||||
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
|
||||
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
|
||||
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<path fill="#0072C6" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
|
||||
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
|
||||
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
|
||||
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
|
||||
</g>
|
||||
<path opacity="0.2" fill="#FFFFFF" d="M7.141,45.315l-0.114,2.307l3.742-6.05c-0.732-0.45-1.338-1.118-1.691-1.974
|
||||
c-0.885-2.152,0.142-4.607,2.298-5.491c1.299-0.532,2.702-0.362,3.811,0.321l3.741-6.049l0.065-1.3L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.231,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231L7.141,45.315z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="0.5" y1="0.5" x2="5" y2="5"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
|
||||
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
|
||||
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 5.7 KiB |
|
@ -1,5 +0,0 @@
|
|||
<svg width="32" height="36" viewBox="0 0 32 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 10L15 18.5V35.5L0 27V10Z" fill="black"/>
|
||||
<path d="M32 10L17 18.5V35.5L32 27V10Z" fill="black"/>
|
||||
<path d="M7.42857 4.95833L16 0L23.8571 4.25L31 8.5L16 17L1 8.5L7.42857 4.95833Z" fill="black"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 313 B |
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#0072C6" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0z"/>
|
||||
<path fill="#3999C6" d="M22,5H6C5.448,5,5,5.448,5,6v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C23,5.448,22.552,5,22,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
|
||||
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
|
||||
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<path fill="#0072C6" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
|
||||
C46.11,27.138,45.823,27,45.519,27z"/>
|
||||
<path fill="#3999C6" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
|
||||
C50,32.448,49.552,32,49,32z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="27.5" x2="32" y2="32"/>
|
||||
<path fill="#0072C6" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
|
||||
C46.11,0.138,45.823,0,45.519,0z"/>
|
||||
<path fill="#3999C6" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C50,5.448,49.552,5,49,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="0.5" x2="32" y2="5"/>
|
||||
<line opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="41" y1="23" x2="41" y2="18"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#00188F" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
|
||||
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
|
||||
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
|
||||
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<path fill="#0072C6" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
|
||||
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
|
||||
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
|
||||
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
|
||||
</g>
|
||||
<path opacity="0.2" fill="#FFFFFF" d="M7.141,45.315l-0.114,2.307l3.742-6.05c-0.732-0.45-1.338-1.118-1.691-1.974
|
||||
c-0.885-2.152,0.142-4.607,2.298-5.491c1.299-0.532,2.702-0.362,3.811,0.321l3.741-6.049l0.065-1.3L16.405,26l-0.292,0.334
|
||||
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.231,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
|
||||
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231L7.141,45.315z"/>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="0.5" y1="0.5" x2="5" y2="5"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
|
||||
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
|
||||
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 5.7 KiB |
|
@ -1,83 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#7FBA00" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0z"/>
|
||||
<path opacity="0.15" d="M5,6.056C5,5.473,5.473,5,6.056,5h16.877c-0.037-0.098-0.086-0.191-0.152-0.274L19.3,0.375
|
||||
C19.11,0.138,18.823,0,18.519,0H1C0.448,0,0,0.448,0,1v15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
|
||||
c0.083,0.099,0.189,0.171,0.3,0.231V6.056z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
|
||||
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
|
||||
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<path fill="#68217A" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
|
||||
C46.11,27.138,45.823,27,45.519,27z"/>
|
||||
<path fill="#804998" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
|
||||
C50,32.448,49.552,32,49,32z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M32,32.375c-0.096,0-0.192-0.036-0.266-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
|
||||
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C32.192,32.339,32.096,32.375,32,32.375z"/>
|
||||
<path fill="#DD5900" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
|
||||
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
|
||||
C46.11,0.138,45.823,0,45.519,0z"/>
|
||||
<path opacity="0.2" fill="#FFFFFF" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6
|
||||
C50,5.448,49.552,5,49,5z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M32,5.375c-0.096,0-0.192-0.037-0.266-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
|
||||
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C32.192,5.338,32.096,5.375,32,5.375z"/>
|
||||
<rect x="40" y="18" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path fill="#0072C6" d="M18.519,27H1c-0.552,0-1,0.448-1,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,49.64
|
||||
C4.89,49.868,5.172,50,5.468,50H22c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L19.3,27.375
|
||||
C19.11,27.138,18.823,27,18.519,27z"/>
|
||||
<path fill="#3999C6" d="M22,32H6c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33C23,32.448,22.552,32,22,32
|
||||
z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M9.5,50H6c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L9.5,50z"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="41" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,37.1,14,37.1 M14,36.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,36.1,14,36.1L14,36.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
|
||||
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M5,5.375c-0.096,0-0.192-0.037-0.265-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
|
||||
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C5.192,5.338,5.096,5.375,5,5.375z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
|
||||
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
|
||||
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M14,31c-1.103,0-2-0.897-2-2v-2h4v2C16,30.103,15.103,31,14,31z"/>
|
||||
<path fill="#00188F" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M31,41c0,1.103-0.897,2-2,2h-2v-4h2C30.103,39,31,39.897,31,41z"/>
|
||||
<path fill="#00188F" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
|
||||
<path opacity="0.5" fill="#0072C6" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
|
||||
<rect x="32" y="40" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
|
||||
<rect x="13" y="32" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
|
||||
<path opacity="0.4" fill="#FFFFFF" d="M5,32.375c-0.096,0-0.192-0.036-0.265-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
|
||||
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C5.192,32.339,5.096,32.375,5,32.375z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 6.0 KiB |
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#0072C6" d="M38.428,3H4.913C3.856,3,3,3.856,3,4.913v29.916c0,0.448,0.157,0.881,0.443,1.225l8.548,10.258
|
||||
C12.355,46.748,12.893,47,13.461,47h31.626C46.144,47,47,46.144,47,45.087V13.236c0-0.434-0.148-0.856-0.419-1.195l-6.659-8.323
|
||||
C39.559,3.264,39.01,3,38.428,3z"/>
|
||||
<path fill="#3999C6" d="M45.111,13H14.889C13.846,13,13,13.846,13,14.889v30.222C13,46.154,13.846,47,14.889,47h30.222
|
||||
C46.154,47,47,46.154,47,45.111V14.889C47,13.846,46.154,13,45.111,13z"/>
|
||||
<path opacity="0.25" fill="#FFFFFF" d="M21.5,47h-6.611C13.846,47,13,46.154,13,45.111V14.889C13,13.846,13.846,13,14.889,13H40.2
|
||||
L21.5,47z"/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="29.783" cy="29.783" r="6.9"/>
|
||||
<g opacity="0.8">
|
||||
<path fill="#FFFFFF" d="M29.783,22.883c3.804,0,6.9,3.096,6.9,6.9s-3.096,6.9-6.9,6.9s-6.9-3.096-6.9-6.9
|
||||
S25.978,22.883,29.783,22.883 M29.783,21.383c-4.632,0-8.4,3.768-8.4,8.4s3.768,8.4,8.4,8.4s8.4-3.768,8.4-8.4
|
||||
S34.414,21.383,29.783,21.383L29.783,21.383z"/>
|
||||
</g>
|
||||
</g>
|
||||
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="4.5" y1="4.5" x2="13" y2="13"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 1.5 KiB |
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<polygon fill="#804998" points="45.946,26.164 44.054,23.836 29.698,35.5 23.488,20.332 21.089,19.709 4.089,32.709 5.911,35.091
|
||||
21.43,23.224 27.712,38.568 29.911,39.192 29.907,39.116 29.946,39.164 "/>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="5" cy="33.9" r="4.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="22" cy="20.9" r="4.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="29" cy="38" r="4.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle fill="#00188F" cx="45" cy="25" r="4.9"/>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<circle fill="#0072C6" cx="5" cy="33.9" r="4.9"/>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<circle fill="#0072C6" cx="22" cy="20.9" r="4.9"/>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<circle fill="#0072C6" cx="29" cy="38" r="4.9"/>
|
||||
</g>
|
||||
<g opacity="0.5">
|
||||
<circle fill="#0072C6" cx="45" cy="25" r="4.9"/>
|
||||
</g>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -1,260 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ProgressLocation, QuickPickItem, window } from 'vscode';
|
||||
import { AzureBlockchainServiceClient, IAzureMemberDto, ICreateQuorumMember, ISkuDto } from './ARMBlockchain';
|
||||
import { Constants } from './Constants';
|
||||
import { showInputBox, showQuickPick } from './helpers';
|
||||
import {
|
||||
AzureConsortium,
|
||||
LocationItem,
|
||||
Member,
|
||||
ResourceGroupItem,
|
||||
SkuItem,
|
||||
SubscriptionItem,
|
||||
TransactionNode,
|
||||
} from './Models';
|
||||
import { ConsortiumItem } from './Models/ConsortiumItem';
|
||||
import { ResourceExplorerAndGenerator } from './ResourceExplorerAndGenerator';
|
||||
import { Telemetry } from './TelemetryClient';
|
||||
import { AzureBlockchainServiceValidator } from './validators/AzureBlockchainServiceValidator';
|
||||
|
||||
export class ConsortiumResourceExplorer extends ResourceExplorerAndGenerator {
|
||||
public async selectOrCreateConsortium(childrenFilters?: string[]): Promise<AzureConsortium> {
|
||||
await this.waitForLogin();
|
||||
|
||||
const subscriptionItem = await this.getOrSelectSubscriptionItem();
|
||||
const resourceGroupItem = await this.getOrCreateResourceGroupItem(subscriptionItem);
|
||||
|
||||
return this.getOrCreateConsortiumItem(subscriptionItem, resourceGroupItem, childrenFilters);
|
||||
}
|
||||
|
||||
public async getAccessKeys(consortium: AzureConsortium): Promise<string[]> {
|
||||
await this.waitForLogin();
|
||||
await this._accountApi.waitForFilters();
|
||||
|
||||
const subscriptionId = consortium.getSubscriptionId();
|
||||
const resourceGroup = consortium.getResourceGroup();
|
||||
|
||||
const subscription = this._accountApi.filters
|
||||
.find((filter) => filter.subscription.subscriptionId === subscriptionId);
|
||||
|
||||
if (!subscription) {
|
||||
const error = new Error(Constants.errorMessageStrings.NoSubscriptionFoundClick);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const azureClient = await this.getAzureClient(
|
||||
new SubscriptionItem(consortium.label, subscriptionId, subscription.session),
|
||||
new ResourceGroupItem(resourceGroup),
|
||||
);
|
||||
|
||||
const accessKeys = await azureClient.memberResource.getMemberAccessKeys(consortium.getMemberName());
|
||||
|
||||
return accessKeys.keys.map((key) => key.value);
|
||||
}
|
||||
|
||||
private async getAzureClient(subscriptionItem: SubscriptionItem, resourceGroupItem: ResourceGroupItem)
|
||||
: Promise<AzureBlockchainServiceClient> {
|
||||
return new AzureBlockchainServiceClient(
|
||||
subscriptionItem.session.credentials,
|
||||
subscriptionItem.subscriptionId,
|
||||
resourceGroupItem.label,
|
||||
resourceGroupItem.description,
|
||||
Constants.azureResourceExplorer.requestBaseUri,
|
||||
Constants.azureResourceExplorer.requestApiVersion,
|
||||
{
|
||||
acceptLanguage: Constants.azureResourceExplorer.requestAcceptLanguage,
|
||||
filters: [],
|
||||
generateClientRequestId: true,
|
||||
longRunningOperationRetryTimeout: 30,
|
||||
noRetryPolicy: false,
|
||||
requestOptions: {
|
||||
customHeaders: {},
|
||||
},
|
||||
rpRegistrationRetryTimeout: 30,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private async getOrCreateConsortiumItem(
|
||||
subscriptionItem: SubscriptionItem,
|
||||
resourceGroupItem: ResourceGroupItem,
|
||||
excludedItems?: string[],
|
||||
): Promise<AzureConsortium> {
|
||||
const pick = await showQuickPick(
|
||||
this.getConsortiumItems(subscriptionItem, resourceGroupItem, excludedItems),
|
||||
{ placeHolder: Constants.placeholders.selectConsortium, ignoreFocusOut: true });
|
||||
|
||||
if (pick instanceof ConsortiumItem) {
|
||||
Telemetry.sendEvent('ConsortiumResourceExplorer.getOrCreateConsortiumItem.consortiumItemIsSelected');
|
||||
return this.getAzureConsortium(pick, subscriptionItem, resourceGroupItem);
|
||||
} else {
|
||||
Telemetry.sendEvent('ConsortiumResourceExplorer.getOrCreateConsortiumItem.createConsortiumItemIsSelected');
|
||||
return this.createAzureConsortium(subscriptionItem, resourceGroupItem);
|
||||
}
|
||||
}
|
||||
|
||||
private async getConsortiumItems(
|
||||
subscriptionItem: SubscriptionItem,
|
||||
resourceGroupItem: ResourceGroupItem,
|
||||
excludedItems?: string[],
|
||||
): Promise<QuickPickItem[]> {
|
||||
const items: QuickPickItem[] = [];
|
||||
const createConsortiumItem: QuickPickItem = { label: '$(plus) Create Consortium' };
|
||||
const consortiumItems = await this.loadConsortiumItems(subscriptionItem, resourceGroupItem, excludedItems);
|
||||
|
||||
items.push(createConsortiumItem, ...consortiumItems);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private async loadConsortiumItems(
|
||||
subscriptionItem: SubscriptionItem,
|
||||
resourceGroupItem: ResourceGroupItem,
|
||||
excludedItems: string[] = [],
|
||||
): Promise<ConsortiumItem[]> {
|
||||
const azureClient = await this.getAzureClient(subscriptionItem, resourceGroupItem);
|
||||
const members: IAzureMemberDto[] = await azureClient.memberResource.getListMember();
|
||||
return members
|
||||
.map((member) => new ConsortiumItem(
|
||||
member.properties.consortium,
|
||||
subscriptionItem.subscriptionId,
|
||||
resourceGroupItem.label,
|
||||
member.name,
|
||||
member.properties.dns,
|
||||
))
|
||||
.filter((item) => !excludedItems.includes(item.label))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
}
|
||||
|
||||
private async getAzureConsortium(
|
||||
consortiumItems: ConsortiumItem,
|
||||
subscriptionItem: SubscriptionItem,
|
||||
resourceGroupItem: ResourceGroupItem,
|
||||
): Promise<AzureConsortium> {
|
||||
const azureClient = await this.getAzureClient(subscriptionItem, resourceGroupItem);
|
||||
const transactionNodes = await azureClient
|
||||
.transactionNodeResource
|
||||
.getListTransactionNode(consortiumItems.memberName);
|
||||
const memberItem = new Member(consortiumItems.memberName);
|
||||
|
||||
const azureConsortium = new AzureConsortium(
|
||||
consortiumItems.consortiumName,
|
||||
consortiumItems.subscriptionId,
|
||||
consortiumItems.resourcesGroup,
|
||||
consortiumItems.memberName,
|
||||
consortiumItems.url,
|
||||
);
|
||||
await azureConsortium.setChildren([
|
||||
memberItem,
|
||||
...transactionNodes.map((transactionNode) => {
|
||||
return new TransactionNode(transactionNode.name, transactionNode.properties.dns);
|
||||
}),
|
||||
]);
|
||||
|
||||
return azureConsortium;
|
||||
}
|
||||
|
||||
private async getSkus(
|
||||
client: AzureBlockchainServiceClient,
|
||||
location: LocationItem)
|
||||
: Promise<SkuItem[]> {
|
||||
const skus: ISkuDto[] = await client.skuResource.getListSkus();
|
||||
|
||||
const skuItems: SkuItem[] = [];
|
||||
|
||||
for (const sku of skus) {
|
||||
if (sku.locations.find((element) => element.toLowerCase() === location.description.toLowerCase())) {
|
||||
skuItems.push(new SkuItem(sku.tier, sku.name));
|
||||
}
|
||||
}
|
||||
|
||||
return skuItems;
|
||||
}
|
||||
|
||||
private async createAzureConsortium(subscriptionItem: SubscriptionItem, resourceGroupItem: ResourceGroupItem)
|
||||
: Promise<AzureConsortium> {
|
||||
const azureClient = await this.getAzureClient(subscriptionItem, resourceGroupItem);
|
||||
const { consortiumResource, memberResource } = azureClient;
|
||||
|
||||
const consortiumName = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
prompt: Constants.paletteABSLabels.enterConsortiumName,
|
||||
validateInput: async (name) => {
|
||||
return await window.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title: Constants.informationMessage.consortiumNameValidating,
|
||||
}, async () => {
|
||||
return await AzureBlockchainServiceValidator.validateConsortiumName(name, consortiumResource);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const memberName = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
prompt: Constants.paletteABSLabels.enterMemberName,
|
||||
validateInput: async (name) => {
|
||||
return await window.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title: Constants.informationMessage.memberNameValidating,
|
||||
},
|
||||
async () => await AzureBlockchainServiceValidator.validateMemberName(name, memberResource));
|
||||
},
|
||||
});
|
||||
|
||||
const protocol = await showQuickPick(
|
||||
[{ label: 'Quorum' }],
|
||||
{
|
||||
ignoreFocusOut: true,
|
||||
placeHolder: Constants.paletteABSLabels.selectConsortiumProtocol,
|
||||
},
|
||||
);
|
||||
|
||||
const memberPassword = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
password: true,
|
||||
prompt: Constants.paletteABSLabels.enterMemberPassword,
|
||||
validateInput: AzureBlockchainServiceValidator.validateAccessPassword,
|
||||
});
|
||||
|
||||
const consortiumPassword = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
password: true,
|
||||
prompt: Constants.paletteABSLabels.enterConsortiumManagementPassword,
|
||||
validateInput: AzureBlockchainServiceValidator.validateAccessPassword,
|
||||
});
|
||||
|
||||
const region = await showQuickPick(
|
||||
this.getLocationItems(subscriptionItem),
|
||||
{ placeHolder: Constants.paletteABSLabels.selectConsortiumRegion, ignoreFocusOut: true },
|
||||
);
|
||||
|
||||
const sku = await showQuickPick(
|
||||
this.getSkus(azureClient, region),
|
||||
{ placeHolder: Constants.paletteABSLabels.selectConsortiumSku, ignoreFocusOut: true },
|
||||
);
|
||||
|
||||
const bodyParams: ICreateQuorumMember = {
|
||||
consortiumManagementAccountPassword: memberPassword,
|
||||
consortiumName,
|
||||
consortiumPassword,
|
||||
protocol: protocol.label,
|
||||
region: region.description,
|
||||
sku: {
|
||||
name: sku.description,
|
||||
tier: sku.label,
|
||||
},
|
||||
};
|
||||
|
||||
return window.withProgress({
|
||||
location: ProgressLocation.Window,
|
||||
title: Constants.statusBarMessages.creatingConsortium,
|
||||
}, async () => {
|
||||
await azureClient.consortiumResource.createConsortium(memberName, bodyParams);
|
||||
|
||||
return new AzureConsortium(consortiumName, subscriptionItem.subscriptionId, resourceGroupItem.label, memberName);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { ExtensionContext, extensions } from 'vscode';
|
||||
import { IOZAsset } from './services';
|
||||
import { IOZAsset } from './services/openZeppelin/models';
|
||||
|
||||
const extensionId = 'AzBlockchain.azure-blockchain';
|
||||
const packageJSON = extensions.getExtension(extensionId)!.packageJSON;
|
||||
|
@ -19,10 +19,15 @@ export enum RequiredApps {
|
|||
hdwalletProvider = 'truffle-hdwallet-provider',
|
||||
}
|
||||
|
||||
export enum NotificationOptions {
|
||||
error = 'error',
|
||||
info = 'info',
|
||||
warning = 'warning',
|
||||
}
|
||||
|
||||
export class Constants {
|
||||
public static extensionContext: ExtensionContext;
|
||||
public static temporaryDirectory = '';
|
||||
|
||||
public static extensionName = packageJSON.name;
|
||||
public static extensionVersion = packageJSON.version;
|
||||
public static extensionKey = packageJSON.aiKey;
|
||||
|
@ -44,6 +49,12 @@ export class Constants {
|
|||
hdwalletProvider: 'HDWalletProvider',
|
||||
};
|
||||
|
||||
public static truffleConfigDefaultDirectory = {
|
||||
contracts_build_directory: path.join('./', 'build', 'contracts'),
|
||||
contracts_directory: path.join('./', 'contracts'),
|
||||
migrations_directory: path.join('./', 'migrations'),
|
||||
};
|
||||
|
||||
public static defaultTruffleBox = 'Azure-Samples/Blockchain-Ethereum-Template';
|
||||
public static defaultDebounceTimeout = 300;
|
||||
|
||||
|
@ -201,9 +212,11 @@ export class Constants {
|
|||
},
|
||||
hasDigits: /(?=.*\d)/g,
|
||||
infuraProjectname: /^([a-zA-Z]|\d|\s|[-_:]){3,}$/g,
|
||||
isJsonFile: new RegExp(Constants.contractExtension.json + '$'),
|
||||
isLowerCase: /^[a-z0-9_\-!@$^&()+=?\/<>|[\]{}:.\\~ #`*"'%;,]+$/g,
|
||||
isUrl: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=]+$/igm,
|
||||
lowerCaseLetter: /(?=.*[a-z]).*/g,
|
||||
moduleExportsTemplate: /{(.*)}$/g,
|
||||
// tslint:disable-next-line: max-line-length
|
||||
port: /^([1-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/,
|
||||
specialChars: {
|
||||
|
@ -371,8 +384,10 @@ export class Constants {
|
|||
};
|
||||
|
||||
public static executeCommandMessage = {
|
||||
failedToRunCommand: Constants.getMessageFailedCommand,
|
||||
failedToRunCommand: (command: string) => `Failed to run command - ${command}. More details in output`,
|
||||
failedToRunScript: (scriptPath: string) => `Failed to run script - ${scriptPath}. More details in output`,
|
||||
finishRunningCommand: 'Finished running command',
|
||||
forkingModule: 'Forking script',
|
||||
runningCommand: 'Running command',
|
||||
};
|
||||
|
||||
|
@ -395,9 +410,11 @@ export class Constants {
|
|||
deployingContracts: (destination: string) => {
|
||||
return `Deploying contracts to '${destination}'`;
|
||||
},
|
||||
generatingLogicApp: (appName: string) => `Generating ${appName}!`,
|
||||
};
|
||||
|
||||
public static rpcMethods = {
|
||||
getCode: 'eth_getCode',
|
||||
netListening: 'net_listening',
|
||||
netVersion: 'net_version',
|
||||
};
|
||||
|
@ -430,12 +447,13 @@ export class Constants {
|
|||
BuildContractsDirIsNotExist: Constants.getMessageContractsBuildDirectoryIsNotExist,
|
||||
CompiledContractIsMissing: 'Compiled contract is missing for solidity file.',
|
||||
DirectoryIsNotEmpty: 'Directory is not empty. Open another one?',
|
||||
ErrorWhileExecutingCommand: 'Error while executing command: ',
|
||||
FetchingDeployedBytecodeIsFailed: 'An error occurred while fetching bytecode from network',
|
||||
GetMessageChildAlreadyConnected: Constants.getMessageChildAlreadyConnected,
|
||||
GitIsNotInstalled: 'Git is not installed',
|
||||
InfuraUnauthorized: 'Unauthorized: please sign in with Infura account.',
|
||||
InvalidContract: 'This file is not a valid contract.',
|
||||
InvalidMnemonic: 'Invalid mnemonic',
|
||||
InvalidServiceType: 'Invalid service type.',
|
||||
LoadServiceTreeFailed: 'Load service tree has failed.',
|
||||
MnemonicFileHaveNoText: 'Mnemonic file have no text',
|
||||
NetworkAlreadyExist: Constants.getMessageNetworkAlreadyExist,
|
||||
|
@ -448,6 +466,7 @@ export class Constants {
|
|||
PleaseRenameOldStyleTruffleConfig: 'Please rename file "truffle.js" to "truffle-config.js"',
|
||||
RequiredAppsAreNotInstalled: 'To run command you should install required apps',
|
||||
ThereAreNoMnemonics: 'There are no mnemonics',
|
||||
TruffleConfigHasIncorrectFormat: '"truffle-config.js" has incorrect format',
|
||||
TruffleConfigIsNotExist: 'Truffle configuration file not found',
|
||||
VariableShouldBeDefined: Constants.getMessageVariableShouldBeDefined,
|
||||
WaitForLogin: 'You should sign-in on Azure Portal',
|
||||
|
@ -465,7 +484,7 @@ export class Constants {
|
|||
deployFailed: 'Deploy failed',
|
||||
deploySucceeded: 'Deploy succeeded',
|
||||
detailsButton: 'Details',
|
||||
generatedLogicApp: 'Generated the logic app!',
|
||||
generatedLogicApp: (appName: string) => `Generated the ${appName}!`,
|
||||
infuraAccountSuccessfullyCreated: 'Your Infura account successfully created. Please check you email for complete registration',
|
||||
infuraSignInPrompt: 'Not signed in to Infura account, sign in first.',
|
||||
installButton: 'Install',
|
||||
|
@ -479,6 +498,7 @@ export class Constants {
|
|||
rpcEndpointCopiedToClipboard: 'RPCEndpointAddress copied to clipboard',
|
||||
seeDetailsRequirementsPage: 'Please see details on the Requirements Page',
|
||||
signInButton: 'Sign In',
|
||||
transactionBytecodeWasCopiedToClipboard: 'Transaction Bytecode was copied to clipboard',
|
||||
};
|
||||
|
||||
public static infuraCredentials = {
|
||||
|
@ -520,15 +540,10 @@ export class Constants {
|
|||
Service: 'Service',
|
||||
};
|
||||
|
||||
public static logicApp = {
|
||||
AzureFunction: 'Azure Function',
|
||||
FlowApp: 'Flow App',
|
||||
LogicApp: 'Logic App',
|
||||
output: {
|
||||
AzureFunction: 'generatedAzureFunction',
|
||||
FlowApp: 'generatedFlowApp',
|
||||
LogicApp: 'generatedLogicApp',
|
||||
},
|
||||
public static azureApps = {
|
||||
AzureFunction: { label: 'Azure Function', serviceType: 2, outputDir: 'generatedAzureFunction' },
|
||||
FlowApp: { label: 'Flow App', serviceType: 0, outputDir: 'generatedFlowApp' },
|
||||
LogicApp: { label: 'Logic App', serviceType: 1, outputDir: 'generatedLogicApp'},
|
||||
};
|
||||
|
||||
public static azureResourceExplorer = {
|
||||
|
@ -541,12 +556,19 @@ export class Constants {
|
|||
resourceType: 'blockchainMembers',
|
||||
};
|
||||
|
||||
public static firstOZVersion = '2.3.0';
|
||||
public static allOpenZeppelinVersions = ['2.3.0', '2.4.0'];
|
||||
public static ozVersionUserSettingsKey = 'azureBlockchainService.openZeppelin.version';
|
||||
|
||||
public static openZeppelin = {
|
||||
cancelButtonTitle: 'Cancel',
|
||||
contractsUpgradeIsFailed: 'Upgrade of OpenZeppelin contracts has failed',
|
||||
descriptionDownloadingFailed: 'Description downloading failed',
|
||||
downloadingContractsFromOpenZeppelin: 'Downloading contracts from OpenZeppelin',
|
||||
exploreDownloadedContractsInfo: 'Explore more information about the contracts downloaded',
|
||||
invalidVersionException: 'Invalid version. All OpenZeppelin work will be stopped',
|
||||
moreDetailsButtonTitle: 'More details',
|
||||
newVersionAvailable: 'There is a new version of your OpenZeppelin contracts available. Would you like to download the latest version?',
|
||||
overwriteExistedContracts: 'Overwrite existed contracts',
|
||||
projectFileName: 'project.json',
|
||||
replaceButtonTitle: 'Replace',
|
||||
|
@ -554,6 +576,7 @@ export class Constants {
|
|||
retryDownloading: 'Retry downloading',
|
||||
selectCategoryForDownloading: 'Select category for downloading',
|
||||
skipButtonTitle: 'Skip files',
|
||||
upgradeOpenZeppelin: 'Upgrading OpenZeppelin',
|
||||
hashCalculationFailed(errorMessage: string): string {
|
||||
return `Error while calculating file hash. Message: ${errorMessage}`;
|
||||
},
|
||||
|
@ -583,6 +606,10 @@ export class Constants {
|
|||
fileNow(count: number): string {
|
||||
return `${count} file(s) on OpenZeppelin library now`;
|
||||
},
|
||||
invalidVersionDialog(version: string, location: string, lastVersion: string) {
|
||||
return `There is invalid OpenZeppelin version (${version}) in ${location}. ` +
|
||||
`Do you want to use the latest one (${lastVersion})?`;
|
||||
},
|
||||
};
|
||||
|
||||
public static initialize(context: ExtensionContext) {
|
||||
|
@ -690,10 +717,6 @@ export class Constants {
|
|||
return `Length must be between ${min} and ${max} characters`;
|
||||
}
|
||||
|
||||
private static getMessageFailedCommand(command: string): string {
|
||||
return `Failed to run command - ${command}. More details in output`;
|
||||
}
|
||||
|
||||
private static getMessageInputHasUnresolvedSymbols(unresolvedSymbols: string): string {
|
||||
return `Input value must not have '${unresolvedSymbols}'.`;
|
||||
}
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ChildProcess, spawn } from 'child_process';
|
||||
import { OutputChannel, window } from 'vscode';
|
||||
import { Constants, RequiredApps } from '../Constants';
|
||||
import { shell } from '../helpers';
|
||||
import { Telemetry } from '../TelemetryClient';
|
||||
import { UrlValidator } from '../validators/UrlValidator';
|
||||
import { isGanacheServer, waitGanacheStarted } from './GanacheServiceClient';
|
||||
|
||||
export namespace GanacheService {
|
||||
|
||||
export interface IGanacheProcess {
|
||||
process: ChildProcess;
|
||||
output: OutputChannel;
|
||||
}
|
||||
|
||||
export const ganacheProcesses: { [port: string]: IGanacheProcess } = {};
|
||||
|
||||
export async function startGanacheServer(port: number | string)
|
||||
: Promise<IGanacheProcess | null> {
|
||||
Telemetry.sendEvent('GanacheService.startGanacheServer');
|
||||
if (UrlValidator.validatePort(port)) {
|
||||
Telemetry.sendException(new Error(Constants.ganacheCommandStrings.invalidGanachePort));
|
||||
throw new Error(`${Constants.ganacheCommandStrings.invalidGanachePort}: ${port}.`);
|
||||
}
|
||||
|
||||
if (!isNaN(await shell.findPid(port))) {
|
||||
Telemetry.sendEvent('GanacheService.startGanacheServer.portIsFree', { port: port.toString() });
|
||||
if (await isGanacheServer(port)) {
|
||||
Telemetry.sendEvent('GanacheService.startGanacheServer.isGanacheServer', { port: port.toString() });
|
||||
return null;
|
||||
} else {
|
||||
const error = new Error(Constants.ganacheCommandStrings.cannotStartServer);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const process = spawn('npx', [RequiredApps.ganache, `-p ${port}`], { shell: true });
|
||||
const output = window.createOutputChannel(`${Constants.outputChannel.ganacheCommands}:${port}`);
|
||||
output.show();
|
||||
|
||||
process.stdout.on('data', (data: string | Buffer) => {
|
||||
output.appendLine(data.toString());
|
||||
});
|
||||
|
||||
process.stderr.on('data', (data: string | Buffer) => {
|
||||
output.appendLine(data.toString());
|
||||
});
|
||||
|
||||
process.on('close', () => {
|
||||
delete ganacheProcesses[port];
|
||||
output.dispose();
|
||||
});
|
||||
|
||||
try {
|
||||
await waitGanacheStarted(port, Constants.ganacheRetryAttempts);
|
||||
} catch (error) {
|
||||
Telemetry.sendException(error);
|
||||
process.removeAllListeners();
|
||||
output.dispose();
|
||||
await shell.killPort(port);
|
||||
throw error;
|
||||
}
|
||||
|
||||
Telemetry.sendEvent('GanacheServiceClient.waitGanacheStarted.serverStarted');
|
||||
const ganacheProcess = { process, output };
|
||||
ganacheProcesses[port] = ganacheProcess;
|
||||
return ganacheProcess;
|
||||
}
|
||||
|
||||
export async function stopGanacheServer(port: number | string): Promise<void> {
|
||||
await shell.killPort(port);
|
||||
|
||||
const ganacheProcess = ganacheProcesses[port];
|
||||
if (ganacheProcess) {
|
||||
ganacheProcess.process.removeAllListeners();
|
||||
ganacheProcess.output.dispose();
|
||||
delete ganacheProcesses[port];
|
||||
}
|
||||
}
|
||||
|
||||
export async function dispose(): Promise<void[]> {
|
||||
const shouldBeFree: Array<Promise<void>> = [];
|
||||
|
||||
Object.keys(ganacheProcesses).forEach((port) => {
|
||||
delete ganacheProcesses[port];
|
||||
shouldBeFree.push(shell.killPort(port));
|
||||
});
|
||||
|
||||
return Promise.all(shouldBeFree);
|
||||
}
|
||||
|
||||
export function getPortFromUrl(url: string): string {
|
||||
const result = url.match(/(:\d{2,4})/);
|
||||
return result ? result[0].slice(1) : Constants.defaultLocalhostPort.toString();
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Constants } from '../Constants';
|
||||
import { HttpService } from '../services';
|
||||
import { Telemetry } from '../TelemetryClient';
|
||||
|
||||
export async function isGanacheServer(port: number | string): Promise<boolean> {
|
||||
try {
|
||||
const response = await HttpService.sendRPCRequest(
|
||||
`http://${Constants.localhost}:${port}`,
|
||||
Constants.rpcMethods.netListening);
|
||||
return response && !!response.result || false;
|
||||
} catch (error) {
|
||||
Telemetry.sendException(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function waitGanacheStarted(port: number | string, maxRetries: number = 1): Promise<void> {
|
||||
const retry = async (retries: number) => {
|
||||
if (retries < maxRetries) {
|
||||
if (await isGanacheServer(port)) {
|
||||
return;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, Constants.ganacheRetryTimeout));
|
||||
await retry(retries + 1);
|
||||
} else {
|
||||
const error = new Error(Constants.ganacheCommandStrings.cannotStartServer);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
await retry(0);
|
||||
}
|
|
@ -5,7 +5,7 @@ import * as fs from 'fs-extra';
|
|||
import * as path from 'path';
|
||||
import { Uri, window } from 'vscode';
|
||||
import { Constants } from '../Constants';
|
||||
import { getWorkspaceRoot, TruffleConfiguration } from '../helpers';
|
||||
import { getWorkspaceRoot, showIgnorableNotification, TruffleConfiguration } from '../helpers';
|
||||
import { showInputBox, showQuickPick } from '../helpers/userInteraction';
|
||||
import { ResourceGroupItem, SubscriptionItem } from '../Models/QuickPickItems';
|
||||
import { Output } from '../Output';
|
||||
|
@ -23,48 +23,60 @@ interface ILogicAppData {
|
|||
subscriptionId: string;
|
||||
topicName?: string;
|
||||
workflowType: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface IAzureAppsItem {
|
||||
label: string;
|
||||
serviceType: number;
|
||||
outputDir: string;
|
||||
}
|
||||
|
||||
export class LogicAppGenerator {
|
||||
public async generateMicroservicesWorkflows(filePath?: Uri): Promise<void> {
|
||||
Telemetry.sendEvent('LogicAppGenerator.microservicesWorkflows');
|
||||
this.generateWorkflows(Constants.microservicesWorkflows.Service, filePath);
|
||||
await this.generateWorkflows(Constants.microservicesWorkflows.Service, filePath);
|
||||
}
|
||||
|
||||
public async generateDataPublishingWorkflows(filePath?: Uri): Promise<void> {
|
||||
Telemetry.sendEvent('LogicAppGenerator.dataPublishingWorkflows');
|
||||
this.generateWorkflows(Constants.microservicesWorkflows.Data, filePath);
|
||||
await this.generateWorkflows(Constants.microservicesWorkflows.Data, filePath);
|
||||
}
|
||||
|
||||
public async generateEventPublishingWorkflows(filePath?: Uri): Promise<void> {
|
||||
Telemetry.sendEvent('LogicAppGenerator.eventPublishingWorkflows');
|
||||
this.generateWorkflows(Constants.microservicesWorkflows.Messaging, filePath);
|
||||
await this.generateWorkflows(Constants.microservicesWorkflows.Messaging, filePath);
|
||||
}
|
||||
|
||||
public async generateReportPublishingWorkflows(filePath?: Uri): Promise<void> {
|
||||
Telemetry.sendEvent('LogicAppGenerator.reportPublishingWorkflows');
|
||||
this.generateWorkflows(Constants.microservicesWorkflows.Reporting, filePath);
|
||||
await this.generateWorkflows(Constants.microservicesWorkflows.Reporting, filePath);
|
||||
}
|
||||
|
||||
private async generateWorkflows(workflowType: string, filePath?: Uri): Promise<void> {
|
||||
const filePaths = await this.getContractsPath(filePath);
|
||||
const logicAppData = await this.getLogicAppData(workflowType);
|
||||
for (const file of filePaths) {
|
||||
const contract = await fs.readJson(file, { encoding: 'utf8' });
|
||||
const generatedFiles: any[] = this.getGenerator(contract, logicAppData).GenerateAll();
|
||||
for (const generatedFile of generatedFiles) {
|
||||
await this.writeFile(generatedFile);
|
||||
}
|
||||
}
|
||||
await showIgnorableNotification(
|
||||
Constants.statusBarMessages.generatingLogicApp(logicAppData.label),
|
||||
async () => {
|
||||
for (const file of filePaths) {
|
||||
const contract = await fs.readJson(file, { encoding: 'utf8' });
|
||||
const generatedFiles: any[] = this.getGenerator(contract, logicAppData).GenerateAll();
|
||||
for (const generatedFile of generatedFiles) {
|
||||
await this.writeFile(generatedFile);
|
||||
}
|
||||
}
|
||||
|
||||
window.showInformationMessage(Constants.informationMessage.generatedLogicApp);
|
||||
Telemetry.sendEvent('LogicAppGenerator.generateWorkflows.commandFinished');
|
||||
window.showInformationMessage(Constants.informationMessage.generatedLogicApp(logicAppData.label));
|
||||
Telemetry.sendEvent('LogicAppGenerator.generateWorkflows.commandFinished');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private async getContractsPath(filePath?: Uri): Promise<string[]> {
|
||||
const truffleConfigPath = TruffleConfiguration.getTruffleConfigUri();
|
||||
const truffleConfig = new TruffleConfiguration.TruffleConfig(truffleConfigPath);
|
||||
const configuration = truffleConfig.getConfiguration();
|
||||
const configuration = await truffleConfig.getConfiguration();
|
||||
const buildDir = path.join(getWorkspaceRoot()!, configuration.contracts_build_directory);
|
||||
const files: string[] = [];
|
||||
|
||||
|
@ -102,15 +114,15 @@ export class LogicAppGenerator {
|
|||
}
|
||||
|
||||
private async getLogicAppData(workflowType: string): Promise<ILogicAppData> {
|
||||
const serviceType = await this.getServiceType(workflowType);
|
||||
const outputDir = await this.getOutputDir(serviceType);
|
||||
const azureAppItem: IAzureAppsItem = await this.getAzureAppItem(workflowType);
|
||||
const contractAddress = await showInputBox({ ignoreFocusOut: true, value: 'contract address' });
|
||||
const [subscriptionItem, resourceGroupItem] = await this.selectSubscriptionAndResourceGroup();
|
||||
const logicAppData: ILogicAppData = {
|
||||
contractAddress,
|
||||
outputDir,
|
||||
label: azureAppItem.label,
|
||||
outputDir: path.join(getWorkspaceRoot()!, azureAppItem.outputDir),
|
||||
resourceGroup: resourceGroupItem.description,
|
||||
serviceType,
|
||||
serviceType: azureAppItem.serviceType,
|
||||
subscriptionId: subscriptionItem.subscriptionId,
|
||||
workflowType,
|
||||
};
|
||||
|
@ -157,34 +169,14 @@ export class LogicAppGenerator {
|
|||
return [subscriptionItem, resourceGroupItem];
|
||||
}
|
||||
|
||||
private async getServiceType(workflowType: string): Promise<number> {
|
||||
const items = [
|
||||
{ label: Constants.logicApp.LogicApp, serviceType: 1 },
|
||||
{ label: Constants.logicApp.FlowApp, serviceType: 0 },
|
||||
];
|
||||
private async getAzureAppItem(workflowType: string): Promise<IAzureAppsItem> {
|
||||
const items = [Constants.azureApps.LogicApp, Constants.azureApps.FlowApp ];
|
||||
|
||||
if (workflowType === Constants.microservicesWorkflows.Service) {
|
||||
items.push({ label: Constants.logicApp.AzureFunction, serviceType: 2 });
|
||||
items.push(Constants.azureApps.AzureFunction);
|
||||
}
|
||||
|
||||
const item = await showQuickPick(items, { ignoreFocusOut: true });
|
||||
return item.serviceType;
|
||||
}
|
||||
|
||||
private getOutputDir(serviceType: int): string {
|
||||
switch (serviceType) {
|
||||
case 0:
|
||||
return path.join(getWorkspaceRoot()!, Constants.logicApp.output.FlowApp);
|
||||
case 1:
|
||||
return path.join(getWorkspaceRoot()!, Constants.logicApp.output.LogicApp);
|
||||
case 2:
|
||||
return path.join(getWorkspaceRoot()!, Constants.logicApp.output.AzureFunction);
|
||||
default: {
|
||||
const error = new Error(Constants.errorMessageStrings.InvalidServiceType);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return await showQuickPick(items, { ignoreFocusOut: true });
|
||||
}
|
||||
|
||||
private async getMessagingType(): Promise<number> {
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import * as fs from 'fs';
|
||||
import { Memento } from 'vscode';
|
||||
import { Constants } from '../Constants';
|
||||
|
||||
export class MnemonicRepository {
|
||||
|
||||
public static initialize(globalState: Memento): void {
|
||||
MnemonicRepository.globalState = globalState;
|
||||
}
|
||||
|
||||
public static getMnemonic(filePath: string): string {
|
||||
return fs.readFileSync(filePath).toString().trim();
|
||||
}
|
||||
|
||||
public static getAllMnemonicPaths(): string[] {
|
||||
return MnemonicRepository.globalState.get(Constants.mnemonicConstants.mnemonicStorage) as string[] || [];
|
||||
}
|
||||
|
||||
public static getExistedMnemonicPaths(): string[] {
|
||||
return MnemonicRepository.getAllMnemonicPaths().filter((path) => fs.existsSync(path));
|
||||
}
|
||||
|
||||
public static saveMnemonicPath(filePath: string): void {
|
||||
const storage = MnemonicRepository.globalState.get(Constants.mnemonicConstants.mnemonicStorage) as string[] || [];
|
||||
storage.push(filePath);
|
||||
MnemonicRepository.globalState.update(Constants.mnemonicConstants.mnemonicStorage, storage);
|
||||
}
|
||||
|
||||
public static MaskMnemonic(mnemonic: string) {
|
||||
return mnemonic
|
||||
? `${mnemonic.slice(0, 3)} ... ${mnemonic.slice(-3)}`
|
||||
: Constants.placeholders.emptyLineText;
|
||||
}
|
||||
|
||||
private static globalState: Memento;
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ConsortiumResourceExplorer } from '../ConsortiumResourceExplorer';
|
||||
import { Constants } from '../Constants';
|
||||
import { TruffleConfiguration } from '../helpers';
|
||||
import { ItemType } from './ItemType';
|
||||
import { ProtectedConsortium } from './ProtectedConsortium';
|
||||
|
||||
export class AzureConsortium extends ProtectedConsortium {
|
||||
private readonly subscriptionId: string;
|
||||
private readonly resourcesGroup: string;
|
||||
private readonly memberName: string;
|
||||
|
||||
constructor(
|
||||
consortiumName: string,
|
||||
subscriptionId: string,
|
||||
resourcesGroup: string,
|
||||
memberName: string,
|
||||
url?: string,
|
||||
) {
|
||||
super(ItemType.AZURE_CONSORTIUM, consortiumName);
|
||||
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.resourcesGroup = resourcesGroup;
|
||||
this.memberName = memberName;
|
||||
|
||||
if (url) {
|
||||
this.addUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
|
||||
const network = await super.getTruffleNetwork();
|
||||
|
||||
network.options.gasPrice = 0;
|
||||
network.options.gas = 0;
|
||||
|
||||
return network;
|
||||
}
|
||||
|
||||
public getSubscriptionId(): string {
|
||||
return this.subscriptionId;
|
||||
}
|
||||
|
||||
public getResourceGroup(): string {
|
||||
return this.resourcesGroup;
|
||||
}
|
||||
|
||||
public getMemberName(): string {
|
||||
return this.memberName;
|
||||
}
|
||||
|
||||
public async getRPCAddress(): Promise<string> {
|
||||
const url = this.getUrls()[0];
|
||||
if (!url) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!url.port) {
|
||||
url.port = `${Constants.defaultAzureBSPort}`;
|
||||
}
|
||||
|
||||
const consortiumResourceExplorer = new ConsortiumResourceExplorer();
|
||||
const keys = await consortiumResourceExplorer.getAccessKeys(this);
|
||||
return keys ? `${url.origin}/${keys[0]}` : url.origin;
|
||||
}
|
||||
|
||||
public toJSON(): { [p: string]: any } {
|
||||
const obj = super.toJSON();
|
||||
|
||||
obj.subscriptionId = this.subscriptionId;
|
||||
obj.resourcesGroup = this.resourcesGroup;
|
||||
obj.memberName = this.memberName;
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ExtensionItem } from './ExtensionItem';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
export class Command extends ExtensionItem {
|
||||
constructor(label: string, commandName: string, args?: any[]) {
|
||||
super(ItemType.COMMAND, `-> ${label}`);
|
||||
|
||||
this.command = {
|
||||
arguments: args,
|
||||
command: commandName,
|
||||
title: `-> ${label}`,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { URL } from 'url';
|
||||
import { Constants } from '../Constants';
|
||||
import { TruffleConfiguration } from '../helpers';
|
||||
import { ExtensionItem } from './ExtensionItem';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
const protocolRegExp = new RegExp('^(' +
|
||||
Constants.networkProtocols.http + '|' +
|
||||
Constants.networkProtocols.https + '|' +
|
||||
Constants.networkProtocols.ftp + '|' +
|
||||
Constants.networkProtocols.file +
|
||||
').*', 'i');
|
||||
|
||||
export abstract class Consortium extends ExtensionItem {
|
||||
private readonly urls: URL[];
|
||||
private consortiumId: number;
|
||||
|
||||
protected constructor(itemType: ItemType, consortiumName: string, description?: string) {
|
||||
super(itemType, consortiumName, description);
|
||||
|
||||
this.contextValue = Constants.contextValue.consortium;
|
||||
this.iconPath = Constants.icons.consortium;
|
||||
|
||||
this.urls = [];
|
||||
this.consortiumId = + Date.now();
|
||||
}
|
||||
|
||||
public addUrl(url: URL | string) {
|
||||
if (typeof url === 'string') {
|
||||
if (!url.match(protocolRegExp)) {
|
||||
url = `${this.defaultProtocol()}${url}`;
|
||||
}
|
||||
|
||||
url = new URL(url);
|
||||
}
|
||||
|
||||
this.urls.push(url);
|
||||
}
|
||||
|
||||
public addUrls(urls: URL[] | string[]) {
|
||||
urls.forEach((url: URL | string) => this.addUrl(url));
|
||||
}
|
||||
|
||||
public getUrls(): URL[] {
|
||||
return this.urls;
|
||||
}
|
||||
|
||||
public toJSON(): { [key: string]: any } {
|
||||
const obj = super.toJSON();
|
||||
obj.urls = this.urls.map((url) => url.toString());
|
||||
obj.consortiumId = this.consortiumId;
|
||||
return obj;
|
||||
}
|
||||
|
||||
public async getRPCAddress(): Promise<string> {
|
||||
if (this.urls.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const url = this.urls[0];
|
||||
return url.pathname === '/' ? url.origin : `${url.origin}/${url.pathname}`;
|
||||
}
|
||||
|
||||
public getConsortiumId(): number {
|
||||
return this.consortiumId;
|
||||
}
|
||||
|
||||
public setConsortiumId(id: number): void {
|
||||
this.consortiumId = id;
|
||||
}
|
||||
|
||||
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
|
||||
return {
|
||||
name: this.label,
|
||||
options: {
|
||||
consortium_id: this.getConsortiumId(),
|
||||
network_id: '*',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected defaultProtocol(): string {
|
||||
return Constants.networkProtocols.https;
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { QuickPickItem } from 'vscode';
|
||||
|
||||
export class ConsortiumItem implements QuickPickItem {
|
||||
public readonly consortiumName: string;
|
||||
public readonly memberName: string;
|
||||
public readonly resourcesGroup: string;
|
||||
public readonly subscriptionId: string;
|
||||
public readonly url?: string;
|
||||
|
||||
public readonly label: string;
|
||||
|
||||
constructor(
|
||||
consortiumName: string,
|
||||
subscriptionId: string,
|
||||
resourcesGroup: string,
|
||||
memberName: string,
|
||||
url?: string,
|
||||
) {
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.resourcesGroup = resourcesGroup;
|
||||
this.memberName = memberName;
|
||||
this.url = url;
|
||||
this.consortiumName = consortiumName;
|
||||
|
||||
this.label = consortiumName;
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { commands, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||
import { Constants } from '../Constants';
|
||||
import { Telemetry } from '../TelemetryClient';
|
||||
import { IExtensionItem } from './IExtensionItem';
|
||||
import { ItemType } from './ItemType';
|
||||
import Timeout = NodeJS.Timeout;
|
||||
|
||||
export abstract class ExtensionItem extends TreeItem implements IExtensionItem {
|
||||
protected static timeoutID: NodeJS.Timeout | undefined;
|
||||
protected children: IExtensionItem[];
|
||||
protected parent: IExtensionItem | null;
|
||||
|
||||
protected constructor(
|
||||
public readonly itemType: ItemType,
|
||||
public readonly label: string,
|
||||
public readonly description?: string,
|
||||
) {
|
||||
super(label);
|
||||
|
||||
this.children = [];
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
public getParent(): IExtensionItem | null {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
public getChildren(): IExtensionItem[] {
|
||||
return this.children;
|
||||
}
|
||||
|
||||
public addParent(parent: IExtensionItem): void {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public addChild(child: IExtensionItem): void {
|
||||
if (this.children.some((_child) => _child.label === child.label)) {
|
||||
Telemetry.sendException(new Error(Constants.errorMessageStrings.GetMessageChildAlreadyConnected(
|
||||
Telemetry.obfuscate(child.label || ''),
|
||||
)));
|
||||
throw new Error(Constants.errorMessageStrings.GetMessageChildAlreadyConnected(child.label || ''));
|
||||
}
|
||||
|
||||
child.addParent(this);
|
||||
this.children.push(child);
|
||||
|
||||
this.collapse();
|
||||
return this.refreshTree();
|
||||
}
|
||||
|
||||
public removeChild(child: IExtensionItem): void {
|
||||
this.children = this.children.filter((_child) => _child !== child);
|
||||
|
||||
this.collapse();
|
||||
return this.refreshTree();
|
||||
}
|
||||
|
||||
public setChildren(children: IExtensionItem[]): void {
|
||||
this.children = children;
|
||||
this.children.forEach((child) => child.addParent(this));
|
||||
|
||||
this.collapse();
|
||||
return this.refreshTree();
|
||||
}
|
||||
|
||||
public toJSON(): { [key: string]: any } {
|
||||
return {
|
||||
children: this.children,
|
||||
description: this.description,
|
||||
itemType: this.itemType,
|
||||
label: this.label,
|
||||
};
|
||||
}
|
||||
|
||||
private collapse() {
|
||||
if (this.children.length > 0) {
|
||||
Telemetry.sendEvent('ExtensionItem.collapse.childrenLengthGreaterThanZero');
|
||||
this.collapsibleState = TreeItemCollapsibleState.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private refreshTree(): void {
|
||||
clearTimeout(ExtensionItem.timeoutID as Timeout);
|
||||
ExtensionItem.timeoutID = setTimeout(async () => {
|
||||
try {
|
||||
await commands.executeCommand('azureBlockchainService.refresh');
|
||||
} catch (error) {
|
||||
Telemetry.sendException(error);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TreeItem } from 'vscode';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
export interface IExtensionItem extends TreeItem {
|
||||
itemType: ItemType;
|
||||
|
||||
getParent(): IExtensionItem | null;
|
||||
getChildren(): IExtensionItem[];
|
||||
addParent(parent: IExtensionItem): void;
|
||||
addChild(child: IExtensionItem): void;
|
||||
removeChild(child: IExtensionItem): void;
|
||||
setChildren(children: IExtensionItem[]): void;
|
||||
toJSON(): { [key: string]: any };
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ExtensionItem } from './ExtensionItem';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
export class Info extends ExtensionItem {
|
||||
constructor(label: string, description?: string) {
|
||||
super(ItemType.INFO, label, description);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { AzureConsortium } from '../AzureConsortium';
|
||||
import { ConsortiumItemCreator } from './ConsortiumItemCreator';
|
||||
|
||||
export class AzureConsortiumItemCreator extends ConsortiumItemCreator {
|
||||
protected getRequiredFields(): Array<{ fieldName: string, type: string }> {
|
||||
const requiredFields = super.getRequiredFields();
|
||||
requiredFields.push(...[
|
||||
{ fieldName: 'subscriptionId', type: 'string' },
|
||||
{ fieldName: 'resourcesGroup', type: 'string' },
|
||||
{ fieldName: 'memberName', type: 'string' },
|
||||
]);
|
||||
|
||||
return requiredFields;
|
||||
}
|
||||
|
||||
protected getAdditionalConstructorArguments(obj: { [key: string]: any }): any[] {
|
||||
const { memberName, resourcesGroup, subscriptionId } = obj;
|
||||
return [
|
||||
subscriptionId,
|
||||
resourcesGroup,
|
||||
memberName,
|
||||
];
|
||||
}
|
||||
|
||||
protected createConsortium(consortiumName: string, subscriptionId: string, resourcesGroup: string, memberName: string)
|
||||
: AzureConsortium {
|
||||
return new AzureConsortium(consortiumName, subscriptionId, resourcesGroup, memberName);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Consortium } from '../Consortium';
|
||||
import { ItemCreator } from './ItemCreator';
|
||||
|
||||
export abstract class ConsortiumItemCreator extends ItemCreator {
|
||||
protected createFromObject(obj: { [key: string]: any }): Consortium {
|
||||
const { label, consortiumId, urls } = obj;
|
||||
const args = this.getAdditionalConstructorArguments(obj);
|
||||
|
||||
const consortium = this.createConsortium(label, ...args);
|
||||
|
||||
consortium.addUrls(urls);
|
||||
consortium.setConsortiumId(consortiumId);
|
||||
|
||||
return consortium;
|
||||
}
|
||||
|
||||
protected getRequiredFields(): Array<{ fieldName: string, type: string }> {
|
||||
const requiredFields = super.getRequiredFields();
|
||||
requiredFields.push(...[
|
||||
{ fieldName: 'urls', type: 'array' },
|
||||
{ fieldName: 'consortiumId', type: 'number' },
|
||||
]);
|
||||
|
||||
return requiredFields;
|
||||
}
|
||||
|
||||
protected abstract getAdditionalConstructorArguments(obj: { [key: string]: any }): any[];
|
||||
protected abstract createConsortium(consortiumName: string, ...args: any[]): Consortium;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Info } from '../Info';
|
||||
import { ItemCreator } from './ItemCreator';
|
||||
|
||||
export class InfoItemCreator extends ItemCreator {
|
||||
protected createFromObject(obj: { [key: string]: any }): Info {
|
||||
const { label, description } = obj;
|
||||
|
||||
return new Info(label, description);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { LocalNetworkConsortium } from '../LocalNetworkConsortium';
|
||||
import { ConsortiumItemCreator } from './ConsortiumItemCreator';
|
||||
|
||||
export class LocalNetworkConsortiumItemCreator extends ConsortiumItemCreator {
|
||||
protected getAdditionalConstructorArguments(): any[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected createConsortium(consortiumName: string): LocalNetworkConsortium {
|
||||
return new LocalNetworkConsortium(consortiumName);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { MainNetworkConsortium } from '../MainNetworkConsortium';
|
||||
import { ConsortiumItemCreator } from './ConsortiumItemCreator';
|
||||
|
||||
export class MainNetworkConsortiumItemCreator extends ConsortiumItemCreator {
|
||||
protected getAdditionalConstructorArguments(): any[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected createConsortium(consortiumName: string): MainNetworkConsortium {
|
||||
return new MainNetworkConsortium(consortiumName);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Network } from '../Network';
|
||||
import { ItemCreator } from './ItemCreator';
|
||||
|
||||
export class NetworkItemCreator extends ItemCreator {
|
||||
protected createFromObject(obj: { [key: string]: any }): Network {
|
||||
const { label, itemType } = obj;
|
||||
|
||||
return new Network(label, itemType);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TestNetworkConsortium } from '../TestNetworkConsortium';
|
||||
import { ConsortiumItemCreator } from './ConsortiumItemCreator';
|
||||
|
||||
export class TestNetworkConsortiumItemCreator extends ConsortiumItemCreator {
|
||||
protected getAdditionalConstructorArguments(): any[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected createConsortium(consortiumName: string): TestNetworkConsortium {
|
||||
return new TestNetworkConsortium(consortiumName);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TransactionNode } from '../TransactionNode';
|
||||
import { ItemCreator } from './ItemCreator';
|
||||
|
||||
export class TransactionNodeItemCreator extends ItemCreator {
|
||||
protected createFromObject(obj: { [key: string]: any }): TransactionNode {
|
||||
const { label, dns } = obj;
|
||||
|
||||
return new TransactionNode(label, dns);
|
||||
}
|
||||
|
||||
protected getRequiredFields(): Array<{ fieldName: string, type: string }> {
|
||||
const requiredFields = super.getRequiredFields();
|
||||
|
||||
return requiredFields.concat({ fieldName: 'dns', type: 'string' });
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Constants } from '../Constants';
|
||||
import { TruffleConfiguration } from '../helpers';
|
||||
import { Consortium } from './Consortium';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
export class LocalNetworkConsortium extends Consortium {
|
||||
constructor(consortiumName: string, url?: string) {
|
||||
super(ItemType.LOCAL_CONSORTIUM, consortiumName);
|
||||
|
||||
if (url) {
|
||||
this.addUrl(url);
|
||||
}
|
||||
|
||||
this.contextValue = Constants.contextValue.localConsortium;
|
||||
}
|
||||
|
||||
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
|
||||
const network = await super.getTruffleNetwork();
|
||||
|
||||
const url = this.getUrls()[0];
|
||||
network.options.host = url.hostname || Constants.localhost;
|
||||
network.options.port = parseInt(url.port, 10) || Constants.defaultLocalhostPort;
|
||||
|
||||
return network;
|
||||
}
|
||||
|
||||
public async getPort(): Promise<number | undefined> {
|
||||
const network = await this.getTruffleNetwork();
|
||||
|
||||
return network.options.port;
|
||||
}
|
||||
|
||||
protected defaultProtocol(): string {
|
||||
return Constants.networkProtocols.http;
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { QuickPickItem } from 'vscode';
|
||||
|
||||
export class LocationItem implements QuickPickItem {
|
||||
public readonly label: string;
|
||||
public readonly description: string;
|
||||
|
||||
constructor(label?: string, description?: string) {
|
||||
this.label = label || '';
|
||||
this.description = description || '';
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TruffleConfiguration } from '../helpers';
|
||||
import { ItemType } from './ItemType';
|
||||
import { NetworkConsortium } from './NetworkConsortium';
|
||||
|
||||
export class MainNetworkConsortium extends NetworkConsortium {
|
||||
constructor(consortiumName: string, url?: string) {
|
||||
super(ItemType.ETHEREUM_MAIN_CONSORTIUM, consortiumName);
|
||||
|
||||
if (url) {
|
||||
this.addUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
|
||||
const network = await super.getTruffleNetwork();
|
||||
|
||||
network.options.network_id = 1;
|
||||
|
||||
return network;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Constants } from '../Constants';
|
||||
import { ExtensionItem } from './ExtensionItem';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
export class Member extends ExtensionItem {
|
||||
constructor(memberName: string) {
|
||||
super(ItemType.MEMBER, memberName);
|
||||
|
||||
this.contextValue = Constants.contextValue.member;
|
||||
this.iconPath = Constants.icons.member;
|
||||
}
|
||||
|
||||
public toJSON(): { [p: string]: any } {
|
||||
return super.toJSON();
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Constants } from '../Constants';
|
||||
import { ExtensionItem } from './ExtensionItem';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
export class Network extends ExtensionItem {
|
||||
constructor(
|
||||
networkName: string,
|
||||
itemType: ItemType.AZURE_BLOCKCHAIN | ItemType.LOCAL_NETWORK |
|
||||
ItemType.ETHEREUM_TEST_NETWORK | ItemType.ETHEREUM_MAIN_NETWORK,
|
||||
) {
|
||||
super(itemType, networkName);
|
||||
|
||||
this.contextValue = Constants.contextValue.blockchainService;
|
||||
this.iconPath = Constants.icons.blockchainService;
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Constants } from '../Constants';
|
||||
import { showInputBox, TruffleConfiguration } from '../helpers';
|
||||
import { ItemType } from './ItemType';
|
||||
import { ProtectedConsortium } from './ProtectedConsortium';
|
||||
|
||||
export abstract class NetworkConsortium extends ProtectedConsortium {
|
||||
|
||||
protected constructor(itemType: ItemType, consortiumName: string, description?: string) {
|
||||
super(itemType, consortiumName, description);
|
||||
}
|
||||
|
||||
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
|
||||
const network = await super.getTruffleNetwork();
|
||||
|
||||
network.options.gasPrice = await this.getGasPrice();
|
||||
network.options.gas = await this.getGasLimit();
|
||||
|
||||
return network;
|
||||
}
|
||||
|
||||
protected async getGasPrice(): Promise<number> {
|
||||
const value = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
prompt: Constants.paletteABSLabels.valueOrDefault(
|
||||
Constants.propertyLabels.gasPrice,
|
||||
Constants.defaultContractSettings.gasPrice),
|
||||
validateInput: this.validation,
|
||||
});
|
||||
|
||||
if (!value) {
|
||||
return Constants.defaultContractSettings.gasPrice;
|
||||
} else {
|
||||
return Number(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected async getGasLimit(): Promise<number> {
|
||||
const value = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
prompt: Constants.paletteABSLabels.valueOrDefault(
|
||||
Constants.propertyLabels.gasLimit,
|
||||
Constants.defaultContractSettings.gasLimit),
|
||||
validateInput: this.validation,
|
||||
});
|
||||
|
||||
if (!value) {
|
||||
return Constants.defaultContractSettings.gasLimit;
|
||||
} else {
|
||||
return Number.parseInt(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private validation(value: string): string | undefined {
|
||||
return value && !value.match(new RegExp(/^\d+$/g)) ?
|
||||
Constants.validationMessages.valueShouldBeNumberOrEmpty :
|
||||
undefined;
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Constants } from '../Constants';
|
||||
import { saveTextInFile, showInputBox, showQuickPick, TruffleConfiguration } from '../helpers';
|
||||
import { MnemonicRepository } from '../MnemonicService/MnemonicRepository';
|
||||
import { Consortium } from './Consortium';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
export abstract class ProtectedConsortium extends Consortium {
|
||||
|
||||
protected constructor(itemType: ItemType, consortiumName: string, description?: string) {
|
||||
super(itemType, consortiumName, description);
|
||||
}
|
||||
|
||||
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
|
||||
const truffleConfigPath = TruffleConfiguration.getTruffleConfigUri();
|
||||
const config = new TruffleConfiguration.TruffleConfig(truffleConfigPath);
|
||||
const network = await super.getTruffleNetwork();
|
||||
const targetURL = await this.getRPCAddress();
|
||||
const mnemonic = await this.getMnemonic();
|
||||
await config.importPackage('fs', 'fs');
|
||||
|
||||
network.options.provider = {
|
||||
mnemonic: mnemonic.path,
|
||||
url: `${targetURL}`,
|
||||
};
|
||||
|
||||
return network;
|
||||
}
|
||||
|
||||
private async getMnemonic(): Promise<{mnemonic: string, path: string}> {
|
||||
|
||||
const mnemonicOptions = [
|
||||
{
|
||||
cmd: async () => {
|
||||
const mnemonic = await TruffleConfiguration.generateMnemonic();
|
||||
const path = await this.saveMnemonicFile(mnemonic);
|
||||
return {mnemonic, path};
|
||||
},
|
||||
label: Constants.placeholders.generateMnemonic,
|
||||
},
|
||||
{
|
||||
cmd: async () => {
|
||||
const mnemonic = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
placeHolder: Constants.placeholders.pasteMnemonic,
|
||||
});
|
||||
const path = await this.saveMnemonicFile(mnemonic);
|
||||
return {mnemonic, path};
|
||||
},
|
||||
label: Constants.placeholders.pasteMnemonic,
|
||||
},
|
||||
];
|
||||
|
||||
const savedMnemonics = MnemonicRepository.getExistedMnemonicPaths()
|
||||
.map((path) => {
|
||||
const mnemonic = MnemonicRepository.getMnemonic(path);
|
||||
const label = MnemonicRepository.MaskMnemonic(mnemonic);
|
||||
return {
|
||||
cmd: async () => ({mnemonic, path}),
|
||||
detail: path,
|
||||
label,
|
||||
};
|
||||
});
|
||||
|
||||
mnemonicOptions.push(...savedMnemonics);
|
||||
|
||||
return await (await showQuickPick(
|
||||
mnemonicOptions,
|
||||
{ placeHolder: Constants.placeholders.setupMnemonic, ignoreFocusOut: true })).cmd();
|
||||
}
|
||||
|
||||
private async saveMnemonicFile(mnemonic: string): Promise<string> {
|
||||
const path = await saveTextInFile(
|
||||
mnemonic,
|
||||
'',
|
||||
{ Files: [Constants.mnemonicConstants.fileExt]});
|
||||
MnemonicRepository.saveMnemonicPath(path);
|
||||
return path;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { QuickPickItem } from 'vscode';
|
||||
|
||||
export class NetworkForContractItem implements QuickPickItem {
|
||||
public readonly label: string;
|
||||
public readonly host: string;
|
||||
public readonly contractAddress: string;
|
||||
|
||||
constructor(label: string, host: string, contractAddress: string) {
|
||||
this.label = label;
|
||||
this.host = host;
|
||||
this.contractAddress = contractAddress;
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { QuickPickItem } from 'vscode';
|
||||
|
||||
export class ResourceGroupItem implements QuickPickItem {
|
||||
public readonly label: string;
|
||||
public readonly description: string;
|
||||
|
||||
constructor(label?: string, location?: string) {
|
||||
this.label = label || '';
|
||||
this.description = location || '';
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { QuickPickItem } from 'vscode';
|
||||
|
||||
export class SkuItem implements QuickPickItem {
|
||||
public readonly label: string;
|
||||
public readonly description: string;
|
||||
|
||||
constructor(tier: string, name: string) {
|
||||
this.label = tier;
|
||||
this.description = name;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { QuickPickItem } from 'vscode';
|
||||
import { AzureSession } from '../azure-account.api';
|
||||
|
||||
export class SubscriptionItem implements QuickPickItem {
|
||||
public readonly label: string;
|
||||
public readonly description: string;
|
||||
public readonly session: AzureSession;
|
||||
public readonly subscriptionId: string;
|
||||
|
||||
constructor(label: string, subscriptionId: string, session: AzureSession) {
|
||||
this.label = label;
|
||||
this.description = subscriptionId;
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.session = session;
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TruffleConfiguration } from '../helpers';
|
||||
import { ItemType } from './ItemType';
|
||||
import { NetworkConsortium } from './NetworkConsortium';
|
||||
|
||||
export class TestNetworkConsortium extends NetworkConsortium {
|
||||
constructor(consortiumName: string, url?: string) {
|
||||
super(ItemType.ETHEREUM_TEST_CONSORTIUM, consortiumName);
|
||||
|
||||
if (url) {
|
||||
this.addUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
|
||||
const network = await super.getTruffleNetwork();
|
||||
const targetURL = network.options.provider!.url;
|
||||
|
||||
network.options.network_id = this.getNetworkId(targetURL!);
|
||||
|
||||
return network;
|
||||
}
|
||||
|
||||
/**
|
||||
* https://ethereum.stackexchange.com/questions/17051/how-to-select-a-network-id-or-is-there-a-list-of-network-ids
|
||||
*/
|
||||
private getNetworkId(host: string): number | string {
|
||||
host = host.toLowerCase();
|
||||
if (host.includes('ropsten')) {
|
||||
return 3;
|
||||
} else if (host.includes('rinkeby')) {
|
||||
return 4;
|
||||
} else if (host.includes('kovan')) {
|
||||
return 42;
|
||||
} else if (host.includes('goerli')) {
|
||||
return 5;
|
||||
} else if (host.includes('kotti')) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
return '*';
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Constants } from '../Constants';
|
||||
import { ExtensionItem } from './ExtensionItem';
|
||||
import { ItemType } from './ItemType';
|
||||
|
||||
export class TransactionNode extends ExtensionItem {
|
||||
private readonly dns: string;
|
||||
|
||||
constructor(transactionNodeName: string, dns: string) {
|
||||
super(ItemType.TRANSACTION_NODE, transactionNodeName);
|
||||
|
||||
this.contextValue = Constants.contextValue.transactionNode;
|
||||
this.iconPath = Constants.icons.transactionNode;
|
||||
|
||||
this.dns = dns;
|
||||
}
|
||||
|
||||
public toJSON(): { [p: string]: any } {
|
||||
const obj = super.toJSON();
|
||||
obj.dns = this.dns;
|
||||
return obj;
|
||||
}
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ResourceManagementClient, SubscriptionClient } from 'azure-arm-resource';
|
||||
import { commands, extensions, ProgressLocation, QuickPickItem, window } from 'vscode';
|
||||
import { AzureAccount } from './azure-account.api';
|
||||
import { Constants } from './Constants';
|
||||
import { showInputBox, showQuickPick } from './helpers';
|
||||
import { LocationItem, ResourceGroupItem, SubscriptionItem } from './Models';
|
||||
import { Telemetry } from './TelemetryClient';
|
||||
import { AzureBlockchainServiceValidator } from './validators/AzureBlockchainServiceValidator';
|
||||
|
||||
interface ICachedLocationItems {
|
||||
locationItems: LocationItem[];
|
||||
providerLocationItems: LocationItem[];
|
||||
}
|
||||
|
||||
export class ResourceExplorerAndGenerator {
|
||||
private static cache: { [subscriptionId: string]: ICachedLocationItems } = {};
|
||||
|
||||
protected readonly _accountApi: AzureAccount;
|
||||
|
||||
constructor() {
|
||||
this._accountApi = extensions.getExtension<AzureAccount>('ms-vscode.azure-account')!.exports;
|
||||
}
|
||||
|
||||
protected async getOrSelectSubscriptionItem(): Promise<SubscriptionItem> {
|
||||
return showQuickPick(
|
||||
await this.getSubscriptionItems(),
|
||||
{ placeHolder: Constants.placeholders.selectSubscription, ignoreFocusOut: true },
|
||||
);
|
||||
}
|
||||
|
||||
protected async getOrCreateResourceGroupItem(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem> {
|
||||
const pick = await showQuickPick(
|
||||
this.getResourceGroupItems(subscriptionItem),
|
||||
{ placeHolder: Constants.placeholders.selectResourceGroup, ignoreFocusOut: true },
|
||||
);
|
||||
|
||||
if (pick instanceof ResourceGroupItem) {
|
||||
Telemetry.sendEvent('ResourceExplorerAndGenerator.getOrCreateResourceGroupItem.itemIsResourceGroupItem');
|
||||
return pick;
|
||||
} else {
|
||||
Telemetry.sendEvent('ResourceExplorerAndGenerator.getOrCreateResourceGroupItem.createResourceGroupItemSelected');
|
||||
return this.createResourceGroup(subscriptionItem);
|
||||
}
|
||||
}
|
||||
|
||||
protected async getLocationItems(subscriptionItem: SubscriptionItem): Promise<LocationItem[]> {
|
||||
const cachedLocationItems = await this.getCachedLocationItems(subscriptionItem);
|
||||
const locationItems = cachedLocationItems.locationItems;
|
||||
const providerLocationItems = cachedLocationItems.providerLocationItems;
|
||||
return providerLocationItems.length !== 0 ? providerLocationItems : locationItems;
|
||||
}
|
||||
|
||||
protected async waitForLogin(): Promise<boolean> {
|
||||
let result = await this._accountApi.waitForLogin();
|
||||
if (!result) {
|
||||
await commands.executeCommand('azure-account.askForLogin');
|
||||
result = await this._accountApi.waitForLogin();
|
||||
if (!result) {
|
||||
const error = new Error(Constants.errorMessageStrings.WaitForLogin);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async getSubscriptionItems(): Promise<SubscriptionItem[]> {
|
||||
await this._accountApi.waitForFilters();
|
||||
|
||||
const subscriptionItems = this._accountApi.filters
|
||||
.map((filter) => new SubscriptionItem(
|
||||
filter.subscription.displayName || '',
|
||||
filter.subscription.subscriptionId || '',
|
||||
filter.session,
|
||||
));
|
||||
|
||||
if (subscriptionItems.length === 0) {
|
||||
const error = new Error(Constants.errorMessageStrings.NoSubscriptionFoundClick);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return subscriptionItems;
|
||||
}
|
||||
|
||||
private async getResourceGroupItems(subscriptionItem: SubscriptionItem): Promise<QuickPickItem[]> {
|
||||
const createGroupItem: QuickPickItem = { label: '$(plus) Create Resource Group' };
|
||||
const items: QuickPickItem[] = [];
|
||||
const resourceManagementClient = await this.getResourceClient(subscriptionItem);
|
||||
const resourceGroups = await resourceManagementClient.resourceGroups.list();
|
||||
const cachedLocationItems = await this.getCachedLocationItems(subscriptionItem);
|
||||
const locationItems = cachedLocationItems.locationItems;
|
||||
const resourceItems = resourceGroups.map((resourceGroup) => {
|
||||
const location = locationItems.find((locationItem) => locationItem.description === resourceGroup.location);
|
||||
return new ResourceGroupItem(
|
||||
resourceGroup.name,
|
||||
location ? location.description : resourceGroup.location,
|
||||
);
|
||||
});
|
||||
|
||||
items.push(createGroupItem);
|
||||
items.push(...resourceItems);
|
||||
return items;
|
||||
}
|
||||
|
||||
private async getSubscriptionClient(subscriptionItem: SubscriptionItem)
|
||||
: Promise<SubscriptionClient.SubscriptionClient> {
|
||||
return new SubscriptionClient.SubscriptionClient(
|
||||
subscriptionItem.session.credentials,
|
||||
subscriptionItem.session.environment.resourceManagerEndpointUrl,
|
||||
);
|
||||
}
|
||||
|
||||
private async getResourceClient(subscriptionItem: SubscriptionItem)
|
||||
: Promise<ResourceManagementClient.ResourceManagementClient> {
|
||||
return new ResourceManagementClient.ResourceManagementClient(
|
||||
subscriptionItem.session.credentials,
|
||||
subscriptionItem.subscriptionId,
|
||||
subscriptionItem.session.environment.resourceManagerEndpointUrl,
|
||||
);
|
||||
}
|
||||
|
||||
private async createResourceGroup(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem> {
|
||||
const { resourceGroups } = await this.getResourceClient(subscriptionItem);
|
||||
|
||||
const resourceGroupName = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
placeHolder: Constants.placeholders.resourceGroupName,
|
||||
prompt: Constants.paletteABSLabels.provideResourceGroupName,
|
||||
validateInput: (name) => AzureBlockchainServiceValidator.validateResourceGroupName(name, resourceGroups),
|
||||
});
|
||||
|
||||
const locationItem = await showQuickPick(
|
||||
this.getLocationItems(subscriptionItem),
|
||||
{ placeHolder: Constants.placeholders.selectRgLocation, ignoreFocusOut: true },
|
||||
);
|
||||
|
||||
return window.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title: `Creating resource group '${resourceGroupName}'`,
|
||||
}, async () => {
|
||||
if (subscriptionItem.subscriptionId === undefined) {
|
||||
const error = new Error(Constants.errorMessageStrings.NoSubscriptionFound);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
} else {
|
||||
Telemetry.sendEvent('ResourceExplorerAndGenerator.createResourceGroup.withProgress.subscriptionIdIsDefined');
|
||||
const resourceManagementClient = await this.getResourceClient(subscriptionItem);
|
||||
const resourceGroup = await resourceManagementClient.resourceGroups.createOrUpdate(
|
||||
resourceGroupName,
|
||||
{ location: locationItem.description },
|
||||
);
|
||||
return new ResourceGroupItem(resourceGroup.name, resourceGroup.location);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async getCachedLocationItems(subscriptionItem: SubscriptionItem): Promise<ICachedLocationItems> {
|
||||
const cache = ResourceExplorerAndGenerator.cache;
|
||||
|
||||
if (cache[subscriptionItem.subscriptionId]) {
|
||||
return cache[subscriptionItem.subscriptionId];
|
||||
}
|
||||
|
||||
const subscriptionClient = await this.getSubscriptionClient(subscriptionItem);
|
||||
const resourceManagementClient = await this.getResourceClient(subscriptionItem);
|
||||
const locations = await subscriptionClient.subscriptions.listLocations(subscriptionItem.subscriptionId);
|
||||
const blockchain = await resourceManagementClient.providers.get(Constants.azureResourceExplorer.providerName);
|
||||
const locationItems = locations.map((location) => new LocationItem(location.displayName, location.name));
|
||||
const providerLocationItems: LocationItem[] = [];
|
||||
const blockchainMember = blockchain.resourceTypes && blockchain.resourceTypes.find((resourceType) => {
|
||||
return resourceType.resourceType === Constants.azureResourceExplorer.resourceType;
|
||||
});
|
||||
|
||||
if (blockchainMember && blockchainMember.locations) {
|
||||
providerLocationItems.push(...locationItems
|
||||
.filter((item) => blockchainMember.locations!.includes(item.label))
|
||||
.sort((a, b) => a.label.localeCompare(b.label)));
|
||||
}
|
||||
|
||||
const cachedLocationItems = {
|
||||
locationItems,
|
||||
providerLocationItems,
|
||||
};
|
||||
|
||||
cache[subscriptionItem.subscriptionId] = cachedLocationItems;
|
||||
|
||||
return cachedLocationItems;
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Command } from '../Models';
|
||||
import { ExtensionView } from './ExtensionView';
|
||||
|
||||
export class CommandView extends ExtensionView<Command> {
|
||||
constructor(commandItem: Command) {
|
||||
super(commandItem);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Consortium } from '../Models';
|
||||
import { ExtensionView } from './ExtensionView';
|
||||
|
||||
export class ConsortiumView extends ExtensionView<Consortium> {
|
||||
constructor(consortiumItem: Consortium) {
|
||||
super(consortiumItem);
|
||||
}
|
||||
|
||||
public async getRPCAddress(): Promise<string> {
|
||||
return this.extensionItem.getRPCAddress();
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Info } from '../Models';
|
||||
import { ExtensionView } from './ExtensionView';
|
||||
|
||||
export class InfoView extends ExtensionView<Info> {
|
||||
constructor(infoItem: Info) {
|
||||
super(infoItem);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Network } from '../Models';
|
||||
import { ExtensionView } from './ExtensionView';
|
||||
|
||||
export class NetworkView extends ExtensionView<Network> {
|
||||
constructor(networkItem: Network) {
|
||||
super(networkItem);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TransactionNode } from '../Models';
|
||||
import { ExtensionView } from './ExtensionView';
|
||||
|
||||
export class TransactionNodeView extends ExtensionView<TransactionNode> {
|
||||
constructor(transactionNodeItem: TransactionNode) {
|
||||
super(transactionNodeItem);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Command } from '../../Models';
|
||||
import { CommandView } from '../CommandView';
|
||||
import { ViewCreator } from './ViewCreator';
|
||||
|
||||
export class CommandViewCreator extends ViewCreator {
|
||||
public create(commandItem: Command): CommandView {
|
||||
return new CommandView(commandItem);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Consortium } from '../../Models';
|
||||
import { ConsortiumView } from '../ConsortiumView';
|
||||
import { ViewCreator } from './ViewCreator';
|
||||
|
||||
export class ConsortiumViewCreator extends ViewCreator {
|
||||
public create(consortiumItem: Consortium): ConsortiumView {
|
||||
return new ConsortiumView(consortiumItem);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Info } from '../../Models';
|
||||
import { InfoView } from '../InfoView';
|
||||
import { ViewCreator } from './ViewCreator';
|
||||
|
||||
export class InfoViewCreator extends ViewCreator {
|
||||
public create(infoItem: Info): InfoView {
|
||||
return new InfoView(infoItem);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Network } from '../../Models';
|
||||
import { NetworkView } from '../NetworkView';
|
||||
import { ViewCreator } from './ViewCreator';
|
||||
|
||||
export class NetworkViewCreator extends ViewCreator {
|
||||
public create(networkItem: Network): NetworkView {
|
||||
return new NetworkView(networkItem);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TransactionNode } from '../../Models';
|
||||
import { TransactionNodeView } from '../TransactionNodeView';
|
||||
import { ViewCreator } from './ViewCreator';
|
||||
|
||||
export class TransactionNodeViewCreator extends ViewCreator {
|
||||
public create(transactionNodeItem: TransactionNode): TransactionNodeView {
|
||||
return new TransactionNodeView(transactionNodeItem);
|
||||
}
|
||||
}
|
|
@ -1,228 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ConsortiumResourceExplorer } from '../ConsortiumResourceExplorer';
|
||||
import { Constants } from '../Constants';
|
||||
import { GanacheService } from '../GanacheService/GanacheService';
|
||||
import { showInputBox, showQuickPick } from '../helpers';
|
||||
import { findPid } from '../helpers/shell';
|
||||
import {
|
||||
AzureConsortium,
|
||||
Consortium,
|
||||
ItemType,
|
||||
LocalNetworkConsortium,
|
||||
MainNetworkConsortium,
|
||||
Network,
|
||||
TestNetworkConsortium,
|
||||
} from '../Models';
|
||||
import { Telemetry } from '../TelemetryClient';
|
||||
import { ConsortiumTreeManager } from '../treeService/ConsortiumTreeManager';
|
||||
import { UrlValidator } from '../validators/UrlValidator';
|
||||
import { ConsortiumView } from '../ViewItems';
|
||||
|
||||
interface IConsortiumDestination {
|
||||
cmd: (network?: Network) => Promise<Consortium>;
|
||||
itemType: ItemType;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export namespace ConsortiumCommands {
|
||||
export async function createConsortium(consortiumTreeManager: ConsortiumTreeManager): Promise<Consortium> {
|
||||
Telemetry.sendEvent('ConsortiumCommands.createConsortium.commandStarted');
|
||||
const createConsortiumDestination: IConsortiumDestination[] = [
|
||||
{
|
||||
cmd: selectOrCreateConsortium,
|
||||
itemType: ItemType.AZURE_BLOCKCHAIN,
|
||||
label: Constants.uiCommandStrings.CreateConsortiumAzureBlockchainService,
|
||||
},
|
||||
];
|
||||
|
||||
const consortium = await execute(createConsortiumDestination, consortiumTreeManager, false);
|
||||
Telemetry.sendEvent('ConsortiumCommands.createConsortium.commandFinished');
|
||||
return consortium;
|
||||
}
|
||||
|
||||
export async function connectConsortium(consortiumTreeManager: ConsortiumTreeManager): Promise<Consortium> {
|
||||
Telemetry.sendEvent('ConsortiumCommands.connectConsortium.commandStarted');
|
||||
const connectConsortiumDestination: IConsortiumDestination[] = [
|
||||
{
|
||||
cmd: connectLocalNetwork,
|
||||
itemType: ItemType.LOCAL_NETWORK,
|
||||
label: Constants.uiCommandStrings.ConnectConsortiumLocalGanache,
|
||||
},
|
||||
{
|
||||
cmd: selectOrCreateConsortium,
|
||||
itemType: ItemType.AZURE_BLOCKCHAIN,
|
||||
label: Constants.uiCommandStrings.ConnectConsortiumAzureBlockchainService,
|
||||
},
|
||||
{
|
||||
cmd: connectToEthereumTestnet,
|
||||
itemType: ItemType.ETHEREUM_TEST_NETWORK,
|
||||
label: Constants.uiCommandStrings.ConnectConsortiumTestEthereum,
|
||||
},
|
||||
{
|
||||
cmd: connectToPublicNetwork,
|
||||
itemType: ItemType.ETHEREUM_MAIN_NETWORK,
|
||||
label: Constants.uiCommandStrings.ConnectConsortiumPublicEthereum,
|
||||
},
|
||||
];
|
||||
|
||||
const consortium = await execute(connectConsortiumDestination, consortiumTreeManager);
|
||||
Telemetry.sendEvent('ConsortiumCommands.connectConsortium.commandFinished');
|
||||
return consortium;
|
||||
}
|
||||
|
||||
export async function disconnectConsortium(consortiumTreeManager: ConsortiumTreeManager, viewItem: ConsortiumView)
|
||||
: Promise<void> {
|
||||
Telemetry.sendEvent('ConsortiumCommands.disconnectConsortium.commandStarted');
|
||||
if (viewItem.extensionItem instanceof LocalNetworkConsortium) {
|
||||
Telemetry.sendEvent('ConsortiumCommands.disconnectConsortium.localNetworkConsortiumSelected');
|
||||
const port = await viewItem.extensionItem.getPort();
|
||||
|
||||
if (port) {
|
||||
Telemetry.sendEvent('ConsortiumCommands.disconnectConsortium.portDefined');
|
||||
await GanacheService.stopGanacheServer(port);
|
||||
}
|
||||
}
|
||||
|
||||
const consortiumView = await consortiumTreeManager.removeItem(viewItem.extensionItem);
|
||||
Telemetry.sendEvent('ConsortiumCommands.disconnectConsortium.commandFinished');
|
||||
return consortiumView;
|
||||
}
|
||||
}
|
||||
|
||||
async function execute(
|
||||
consortiumDestination: IConsortiumDestination[],
|
||||
consortiumTreeManager: ConsortiumTreeManager,
|
||||
addChild: boolean = true,
|
||||
): Promise<Consortium> {
|
||||
const destination = await selectDestination(consortiumDestination);
|
||||
const networkItem = await getNetwork(consortiumTreeManager, destination.itemType);
|
||||
const consortiumItem = await destination.cmd(networkItem);
|
||||
|
||||
if (addChild) {
|
||||
Telemetry.sendEvent('ConsortiumCommands.execute.addChild');
|
||||
await networkItem.addChild(consortiumItem);
|
||||
}
|
||||
|
||||
Telemetry.sendEvent(
|
||||
'ConsortiumCommands.execute.newConsortiumItem',
|
||||
{
|
||||
ruri: Telemetry.obfuscate((consortiumItem.resourceUri || '').toString()),
|
||||
type: Telemetry.obfuscate(consortiumItem.itemType.toString()),
|
||||
urls: Telemetry.obfuscate(JSON.stringify(consortiumItem.getUrls())),
|
||||
});
|
||||
return consortiumItem;
|
||||
}
|
||||
|
||||
function getConnectedAbsConsortia(networkItem: Network): string[] {
|
||||
return networkItem
|
||||
.getChildren()
|
||||
.filter((e) => e.label)
|
||||
.map((e) => e.label) as string[];
|
||||
}
|
||||
|
||||
async function selectDestination(consortiumDestination: IConsortiumDestination[]): Promise<IConsortiumDestination> {
|
||||
return showQuickPick(
|
||||
consortiumDestination,
|
||||
{
|
||||
ignoreFocusOut: true,
|
||||
placeHolder: Constants.placeholders.selectDestination,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async function getNetwork(consortiumTreeManager: ConsortiumTreeManager, itemType: ItemType): Promise<Network> {
|
||||
const networkItem = consortiumTreeManager.getItem(itemType) as Network;
|
||||
|
||||
if (networkItem === undefined) {
|
||||
const error = new Error(Constants.errorMessageStrings.ActionAborted);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return networkItem;
|
||||
}
|
||||
|
||||
async function selectOrCreateConsortium(network?: Network): Promise<AzureConsortium> {
|
||||
const excludedItems = network ? getConnectedAbsConsortia(network) : [];
|
||||
const azureResourceExplorer = new ConsortiumResourceExplorer();
|
||||
return azureResourceExplorer.selectOrCreateConsortium(excludedItems);
|
||||
}
|
||||
|
||||
async function connectLocalNetwork(network?: Network): Promise<LocalNetworkConsortium> {
|
||||
|
||||
const ports = await getExistingLocalPorts(network);
|
||||
|
||||
const port = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
prompt: Constants.paletteABSLabels.enterLocalNetworkLocation,
|
||||
validateInput: async (value: string) => {
|
||||
|
||||
const validationError = UrlValidator.validatePort(value);
|
||||
if (validationError) {
|
||||
return validationError;
|
||||
}
|
||||
|
||||
if (ports.some((existPort) => existPort === value)) {
|
||||
return Constants.validationMessages.networkAlreadyExists;
|
||||
}
|
||||
|
||||
if (!isNaN(await findPid(value))) {
|
||||
return Constants.validationMessages.portAlreadyInUse;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
await GanacheService.startGanacheServer(port);
|
||||
|
||||
const label = `${Constants.localhostName}:${port}`;
|
||||
const url = `${Constants.networkProtocols.http}${Constants.localhost}:${port}`;
|
||||
return new LocalNetworkConsortium(label, url);
|
||||
}
|
||||
|
||||
async function connectToEthereumTestnet(): Promise<TestNetworkConsortium> {
|
||||
const consortiumName = await getConsortiumName();
|
||||
const url = await getConsortiumUrl();
|
||||
|
||||
return new TestNetworkConsortium(consortiumName, url);
|
||||
}
|
||||
|
||||
async function connectToPublicNetwork(): Promise<MainNetworkConsortium> {
|
||||
const consortiumName = await getConsortiumName();
|
||||
const url = await getConsortiumUrl();
|
||||
|
||||
return new MainNetworkConsortium(consortiumName, url);
|
||||
}
|
||||
|
||||
async function getConsortiumName() {
|
||||
return showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
prompt: Constants.paletteABSLabels.enterConsortiumName,
|
||||
validateInput: (value: string) => {
|
||||
if (!value) {
|
||||
return Constants.validationMessages.valueCannotBeEmpty;
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function getConsortiumUrl() {
|
||||
return showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
prompt: Constants.paletteABSLabels.enterNetworkLocation,
|
||||
validateInput: (value: string) => {
|
||||
return UrlValidator.validateHostUrl(value);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function getExistingLocalPorts(network?: Network): Promise<string[]> {
|
||||
const localNetworks = network ? await network.getChildren() : [];
|
||||
return await Promise.all((localNetworks as LocalNetworkConsortium[])
|
||||
.map(async (item) => `${await item.getPort()}`));
|
||||
}
|
|
@ -4,102 +4,126 @@
|
|||
import open = require('open');
|
||||
import { ProgressLocation, window } from 'vscode';
|
||||
import { Constants } from '../Constants';
|
||||
import { showQuickPick } from '../helpers';
|
||||
import { openZeppelinHelper, showQuickPick } from '../helpers';
|
||||
import { Output } from '../Output';
|
||||
import {
|
||||
IOZAsset,
|
||||
IOZContractCategory,
|
||||
OpenZeppelinMigrationsService,
|
||||
OpenZeppelinService,
|
||||
PromiseState,
|
||||
} from '../services';
|
||||
import { OpenZeppelinMigrationsService, OpenZeppelinService } from '../services';
|
||||
import { IOZAsset, IOZContractCategory, PromiseState } from '../services/openZeppelin/models';
|
||||
import { Telemetry } from '../TelemetryClient';
|
||||
|
||||
export namespace OpenZeppelinCommands {
|
||||
export async function addCategory(): Promise<void> {
|
||||
Telemetry.sendEvent('OpenZeppelinCommands.addCategory');
|
||||
const categories = OpenZeppelinService.getCategories();
|
||||
|
||||
const currentOZVersion = await openZeppelinHelper.tryGetCurrentOpenZeppelinVersionAsync();
|
||||
const manifest = await openZeppelinHelper.createManifestAsync(currentOZVersion);
|
||||
const categories = await manifest.getCategories();
|
||||
const category = await selectCategory(categories);
|
||||
|
||||
Telemetry.sendEvent('OpenZeppelinCommands.addCategory.selected', { name: category.name });
|
||||
const fullAssetWithDependencies = OpenZeppelinService.collectAssetsWithDependencies(category.assets);
|
||||
|
||||
const baseUrl = manifest.getBaseUrlToContractsSource();
|
||||
const fullAssetWithDependencies = manifest.collectAssetsWithDependencies(category.assets);
|
||||
Output.outputLine(
|
||||
Constants.outputChannel.azureBlockchain,
|
||||
Constants.openZeppelin.categoryWillDownloaded(category.name),
|
||||
);
|
||||
const assetsStatuses = OpenZeppelinService.getAssetsStatus(fullAssetWithDependencies);
|
||||
const assetsStatuses = await OpenZeppelinService.getAssetsStatus(fullAssetWithDependencies);
|
||||
Output.outputLine(
|
||||
Constants.outputChannel.azureBlockchain,
|
||||
Constants.openZeppelin.fileNow(assetsStatuses.existing.length),
|
||||
);
|
||||
|
||||
if (assetsStatuses.existing.length > 0) {
|
||||
const answer = await window.showInformationMessage(
|
||||
Constants.openZeppelin.alreadyExisted(assetsStatuses.existing),
|
||||
Constants.openZeppelin.replaceButtonTitle,
|
||||
Constants.openZeppelin.skipButtonTitle,
|
||||
);
|
||||
const downloadedAssets
|
||||
= await downloadOZFiles(baseUrl, assetsStatuses.existing, assetsStatuses.missing, fullAssetWithDependencies);
|
||||
|
||||
await OpenZeppelinService.updateProjectJsonAsync(manifest.getVersion(), category, downloadedAssets);
|
||||
|
||||
openDocumentationUrl(manifest.getCategoryApiDocumentationUrl(category));
|
||||
|
||||
Telemetry.sendEvent('OpenZeppelinCommands.addCategory.overwriteExistedDialog', { name: answer || '' });
|
||||
if (answer === Constants.openZeppelin.replaceButtonTitle) {
|
||||
Output.outputLine(
|
||||
Constants.outputChannel.azureBlockchain,
|
||||
Constants.openZeppelin.overwriteExistedContracts,
|
||||
);
|
||||
await downloadFileSetWithProgress(fullAssetWithDependencies, true);
|
||||
} else {
|
||||
await downloadFileSetWithProgress(assetsStatuses.missing, false);
|
||||
}
|
||||
} else {
|
||||
await downloadFileSetWithProgress(fullAssetWithDependencies, false);
|
||||
}
|
||||
openDocumentationUrl(category);
|
||||
Telemetry.sendEvent('OpenZeppelinCommands.addCategory.generateMigrations');
|
||||
await OpenZeppelinMigrationsService.generateMigrations(await OpenZeppelinService.getAllDownloadedAssets());
|
||||
await OpenZeppelinMigrationsService.generateMigrations(await OpenZeppelinService.getAllDownloadedAssetsAsync());
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadFileSetWithProgress(assets: IOZAsset[], overwrite: boolean = false): Promise<void> {
|
||||
async function downloadOZFiles(
|
||||
baseUrl: string,
|
||||
existing: IOZAsset[],
|
||||
missing: IOZAsset[],
|
||||
fullAssetWithDependencies: IOZAsset[])
|
||||
: Promise<IOZAsset[]> {
|
||||
let downloadedAssets: IOZAsset[];
|
||||
|
||||
if (existing.length > 0) {
|
||||
const answer = await window.showInformationMessage(
|
||||
Constants.openZeppelin.alreadyExisted(existing),
|
||||
Constants.openZeppelin.replaceButtonTitle,
|
||||
Constants.openZeppelin.skipButtonTitle,
|
||||
);
|
||||
|
||||
Telemetry.sendEvent('OpenZeppelinCommands.downloadOZFiles.overwriteExistedDialog', { name: answer || '' });
|
||||
if (answer === Constants.openZeppelin.replaceButtonTitle) {
|
||||
Output.outputLine(
|
||||
Constants.outputChannel.azureBlockchain,
|
||||
Constants.openZeppelin.overwriteExistedContracts,
|
||||
);
|
||||
downloadedAssets = await downloadFileSetWithProgress(baseUrl, fullAssetWithDependencies, true);
|
||||
} else {
|
||||
downloadedAssets = await downloadFileSetWithProgress(baseUrl, missing, false);
|
||||
}
|
||||
} else {
|
||||
downloadedAssets = await downloadFileSetWithProgress(baseUrl, fullAssetWithDependencies, false);
|
||||
}
|
||||
|
||||
if (downloadedAssets.length) {
|
||||
window.showInformationMessage(Constants.openZeppelin.wereDownloaded(downloadedAssets.length));
|
||||
}
|
||||
|
||||
return downloadedAssets;
|
||||
}
|
||||
|
||||
async function downloadFileSetWithProgress(
|
||||
baseUri: string,
|
||||
assets: IOZAsset[],
|
||||
overwrite: boolean = false)
|
||||
: Promise<IOZAsset[]> {
|
||||
return window.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title: Constants.openZeppelin.downloadingContractsFromOpenZeppelin,
|
||||
}, async () => downloadFileSet(assets, overwrite),
|
||||
);
|
||||
}
|
||||
}, async () => downloadFileSet(assets));
|
||||
|
||||
async function downloadFileSet(assets: IOZAsset[], overwrite: boolean): Promise<void> {
|
||||
const results = await OpenZeppelinService.downloadFiles(assets, overwrite);
|
||||
async function downloadFileSet(_assets: IOZAsset[])
|
||||
: Promise<IOZAsset[]> {
|
||||
const results = await OpenZeppelinService.downloadAssetsAsync(baseUri, _assets, overwrite);
|
||||
|
||||
const downloaded = results
|
||||
.filter((result) => result.state === PromiseState.fulfilled)
|
||||
.map((result) => result.asset);
|
||||
let downloaded = results
|
||||
.filter((result) => result.state === PromiseState.fulfilled)
|
||||
.map((result) => result.asset);
|
||||
|
||||
const rejected = results
|
||||
.filter((result) => result.state === PromiseState.rejected)
|
||||
.map((result) => result.asset);
|
||||
Telemetry.sendEvent(
|
||||
'OpenZeppelinCommands.downloadFileSet.result',
|
||||
{ downloadedCount: downloaded.length.toString(), rejectedCount: rejected.length.toString() },
|
||||
);
|
||||
|
||||
if (downloaded.length > 0) {
|
||||
await OpenZeppelinService.addAssetsToProjectJson(downloaded);
|
||||
window.showInformationMessage(Constants.openZeppelin.wereDownloaded(downloaded.length));
|
||||
}
|
||||
|
||||
if (rejected.length > 0) {
|
||||
const answer = await window.showErrorMessage(
|
||||
Constants.openZeppelin.wereNotDownloaded(rejected.length),
|
||||
Constants.openZeppelin.retryButtonTitle,
|
||||
Constants.openZeppelin.cancelButtonTitle,
|
||||
const rejected = results
|
||||
.filter((result) => result.state === PromiseState.rejected)
|
||||
.map((result) => result.asset);
|
||||
Telemetry.sendEvent(
|
||||
'OpenZeppelinCommands.downloadFileSet.result',
|
||||
{ downloadedCount: downloaded.length.toString(), rejectedCount: rejected.length.toString() },
|
||||
);
|
||||
if (answer === Constants.openZeppelin.retryButtonTitle) {
|
||||
Output.outputLine(
|
||||
Constants.outputChannel.azureBlockchain,
|
||||
Constants.openZeppelin.retryDownloading,
|
||||
|
||||
if (rejected.length > 0) {
|
||||
const answer = await window.showErrorMessage(
|
||||
Constants.openZeppelin.wereNotDownloaded(rejected.length),
|
||||
Constants.openZeppelin.retryButtonTitle,
|
||||
Constants.openZeppelin.cancelButtonTitle,
|
||||
);
|
||||
Telemetry.sendEvent('OpenZeppelinCommands.downloadFileSet.retry', { assetsCount: rejected.length.toString() });
|
||||
await downloadFileSet(rejected, overwrite);
|
||||
if (answer === Constants.openZeppelin.retryButtonTitle) {
|
||||
Output.outputLine(
|
||||
Constants.outputChannel.azureBlockchain,
|
||||
Constants.openZeppelin.retryDownloading,
|
||||
);
|
||||
Telemetry.sendEvent('OpenZeppelinCommands.downloadFileSet.retry', { assetsCount: rejected.length.toString() });
|
||||
downloaded = downloaded.concat(await downloadFileSet(rejected));
|
||||
}
|
||||
}
|
||||
|
||||
return downloaded;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,8 +142,7 @@ async function selectCategory(categories: IOZContractCategory[]): Promise<IOZCon
|
|||
);
|
||||
}
|
||||
|
||||
async function openDocumentationUrl(category: IOZContractCategory): Promise<void> {
|
||||
const documentationUrl = OpenZeppelinService.getCategoryApiDocumentationUrl(category);
|
||||
async function openDocumentationUrl(documentationUrl?: string): Promise<void> {
|
||||
if (!documentationUrl) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import * as fs from 'fs-extra';
|
||||
import { ProgressLocation, Uri, window, workspace } from 'vscode';
|
||||
import { Uri, window, workspace } from 'vscode';
|
||||
import { Constants, RequiredApps } from '../Constants';
|
||||
import {
|
||||
gitHelper,
|
||||
outputCommandHelper,
|
||||
required,
|
||||
showIgnorableNotification,
|
||||
showInputBox,
|
||||
showOpenFolderDialog,
|
||||
showQuickPick,
|
||||
|
@ -79,36 +80,38 @@ async function chooseNewProjectDir(): Promise<string> {
|
|||
|
||||
async function createNewEmptyProject(projectPath: string): Promise<void> {
|
||||
Telemetry.sendEvent('ProjectCommands.createNewEmptyProject.baseProject');
|
||||
return window.withProgress({
|
||||
location: ProgressLocation.Window,
|
||||
title: Constants.statusBarMessages.creatingProject,
|
||||
}, async () => {
|
||||
return createProject(projectPath, Constants.defaultTruffleBox);
|
||||
});
|
||||
|
||||
return createProject(projectPath, Constants.defaultTruffleBox);
|
||||
}
|
||||
|
||||
async function createProjectFromTruffleBox(projectPath: string): Promise<void> {
|
||||
Telemetry.sendEvent('ProjectCommands.createProjectFromTruffleBox.customProject');
|
||||
const truffleBoxName = await getTruffleBoxName();
|
||||
await createProject(projectPath, truffleBoxName);
|
||||
|
||||
return createProject(projectPath, truffleBoxName);
|
||||
}
|
||||
|
||||
async function createProject(projectPath: string, truffleBoxName: string): Promise<void> {
|
||||
try {
|
||||
Telemetry.sendEvent('ProjectCommands.createProject.unbox', { truffleBoxName });
|
||||
await outputCommandHelper.executeCommand(projectPath, 'npx', RequiredApps.truffle, 'unbox', truffleBoxName);
|
||||
await showIgnorableNotification(
|
||||
Constants.statusBarMessages.creatingProject,
|
||||
async () => {
|
||||
try {
|
||||
Telemetry.sendEvent('ProjectCommands.createProject.unbox', { truffleBoxName });
|
||||
await outputCommandHelper.executeCommand(projectPath, 'npx', RequiredApps.truffle, 'unbox', truffleBoxName);
|
||||
|
||||
TruffleConfiguration.checkTruffleConfigNaming(projectPath);
|
||||
workspace.updateWorkspaceFolders(
|
||||
0,
|
||||
workspace.workspaceFolders ? workspace.workspaceFolders.length : null,
|
||||
{ uri: Uri.file(projectPath) });
|
||||
TruffleConfiguration.checkTruffleConfigNaming(projectPath);
|
||||
workspace.updateWorkspaceFolders(
|
||||
0,
|
||||
workspace.workspaceFolders ? workspace.workspaceFolders.length : null,
|
||||
{ uri: Uri.file(projectPath) });
|
||||
|
||||
} catch (error) {
|
||||
fs.emptyDirSync(projectPath);
|
||||
Telemetry.sendException(new Error(Constants.errorMessageStrings.NewProjectCreationFailed));
|
||||
throw new Error(`${Constants.errorMessageStrings.NewProjectCreationFailed} ${error.message}`);
|
||||
}
|
||||
} catch (error) {
|
||||
fs.emptyDirSync(projectPath);
|
||||
Telemetry.sendException(new Error(Constants.errorMessageStrings.NewProjectCreationFailed));
|
||||
throw new Error(`${Constants.errorMessageStrings.NewProjectCreationFailed} ${error.message}`);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async function getTruffleBoxName(): Promise<string> {
|
||||
|
|
|
@ -6,24 +6,35 @@ import * as fs from 'fs-extra';
|
|||
// @ts-ignore
|
||||
import * as hdkey from 'hdkey';
|
||||
import * as path from 'path';
|
||||
import { ProgressLocation, QuickPickItem, Uri, window } from 'vscode';
|
||||
import { QuickPickItem, Uri, window } from 'vscode';
|
||||
import { Constants, RequiredApps } from '../Constants';
|
||||
import {
|
||||
getWorkspaceRoot,
|
||||
openZeppelinHelper,
|
||||
outputCommandHelper,
|
||||
required,
|
||||
showConfirmPaidOperationDialog,
|
||||
showIgnorableNotification,
|
||||
showQuickPick,
|
||||
TruffleConfig,
|
||||
TruffleConfiguration,
|
||||
vscodeEnvironment,
|
||||
} from '../helpers';
|
||||
import { IDeployDestination, ItemType } from '../Models';
|
||||
import { NetworkForContractItem } from '../Models/QuickPickItems/NetworkForContractItem';
|
||||
import { LocalService } from '../Models/TreeItems';
|
||||
import { Project } from '../Models/TreeItems';
|
||||
import { Output } from '../Output';
|
||||
import { ContractDB, GanacheService, MnemonicRepository, OpenZeppelinService, TreeManager } from '../services';
|
||||
import { OZContractValidated } from '../services/openZeppelin/OpenZeppelinService';
|
||||
import {
|
||||
ContractDB,
|
||||
ContractInstanceWithMetadata,
|
||||
ContractService,
|
||||
GanacheService,
|
||||
MnemonicRepository,
|
||||
OpenZeppelinService,
|
||||
TreeManager,
|
||||
} from '../services';
|
||||
import { OZContractValidated } from '../services/openZeppelin/models';
|
||||
import { Telemetry } from '../TelemetryClient';
|
||||
import { ProjectView } from '../ViewItems';
|
||||
import { ServiceCommands } from './ServiceCommands';
|
||||
|
@ -47,17 +58,18 @@ interface IExtendedQuickPickItem extends QuickPickItem {
|
|||
export namespace TruffleCommands {
|
||||
export async function buildContracts(): Promise<void> {
|
||||
Telemetry.sendEvent('TruffleCommands.buildContracts.commandStarted');
|
||||
await window.withProgress({
|
||||
location: ProgressLocation.Window,
|
||||
title: Constants.statusBarMessages.buildingContracts,
|
||||
}, async () => {
|
||||
if (!await required.checkAppsSilent(RequiredApps.truffle)) {
|
||||
Telemetry.sendEvent('TruffleCommands.buildContracts.truffleInstallation');
|
||||
await required.installTruffle(required.Scope.locally);
|
||||
}
|
||||
await showIgnorableNotification(
|
||||
Constants.statusBarMessages.buildingContracts,
|
||||
async () => {
|
||||
if (!await required.checkAppsSilent(RequiredApps.truffle)) {
|
||||
Telemetry.sendEvent('TruffleCommands.buildContracts.truffleInstallation');
|
||||
await required.installTruffle(required.Scope.locally);
|
||||
}
|
||||
|
||||
await outputCommandHelper.executeCommand(getWorkspaceRoot(), 'npx', RequiredApps.truffle, 'compile');
|
||||
},
|
||||
);
|
||||
|
||||
await outputCommandHelper.executeCommand(getWorkspaceRoot(), 'npx', RequiredApps.truffle, 'compile');
|
||||
});
|
||||
Telemetry.sendEvent('TruffleCommands.buildContracts.commandFinished');
|
||||
}
|
||||
|
||||
|
@ -89,8 +101,7 @@ export namespace TruffleCommands {
|
|||
{ url: Telemetry.obfuscate(command.description || '') },
|
||||
);
|
||||
|
||||
await validateOpenZeppelinContracts();
|
||||
|
||||
await checkOpenZeppelinIfUsed();
|
||||
await command.cmd();
|
||||
|
||||
Telemetry.sendEvent('TruffleCommands.deployContracts.commandFinished');
|
||||
|
@ -114,9 +125,39 @@ export namespace TruffleCommands {
|
|||
|
||||
export async function writeDeployedBytecodeToBuffer(uri: Uri): Promise<void> {
|
||||
Telemetry.sendEvent('TruffleCommands.writeBytecodeToBuffer.commandStarted');
|
||||
const contract = await readCompiledContract(uri);
|
||||
|
||||
await vscodeEnvironment.writeToClipboard(contract[Constants.contractProperties.deployedBytecode]);
|
||||
ensureFileIsContractJson(uri.fsPath);
|
||||
|
||||
const contractInstances = await ContractDB.getContractInstances(
|
||||
path.basename(uri.fsPath, Constants.contractExtension.json)) as ContractInstanceWithMetadata[];
|
||||
const contractInstancesWithNetworkInfo = contractInstances.filter((contractIns) => {
|
||||
return contractIns.network.name !== undefined && !!contractIns.provider && !!contractIns.address;
|
||||
});
|
||||
|
||||
if (!contractInstancesWithNetworkInfo.length) {
|
||||
window.showInformationMessage(Constants.informationMessage.contractNotDeployed);
|
||||
return;
|
||||
}
|
||||
|
||||
const networkQuickPickItems = contractInstancesWithNetworkInfo.map((contractIns) =>
|
||||
new NetworkForContractItem(contractIns.network.name!, contractIns.provider!.host, contractIns.address!));
|
||||
const networkItem = await showQuickPick(
|
||||
networkQuickPickItems,
|
||||
{ placeHolder: 'Select a network', ignoreFocusOut: true },
|
||||
);
|
||||
|
||||
try {
|
||||
const deployedBytecode =
|
||||
await ContractService.getDeployedBytecodeByAddress(networkItem.host, networkItem.contractAddress);
|
||||
|
||||
window.showInformationMessage(Constants.informationMessage.transactionBytecodeWasCopiedToClipboard);
|
||||
|
||||
await vscodeEnvironment.writeToClipboard(deployedBytecode);
|
||||
} catch (ex) {
|
||||
Telemetry.sendException(ex);
|
||||
window.showErrorMessage(Constants.errorMessageStrings.FetchingDeployedBytecodeIsFailed);
|
||||
}
|
||||
|
||||
Telemetry.sendEvent('TruffleCommands.writeBytecodeToBuffer.commandFinished');
|
||||
}
|
||||
|
||||
|
@ -179,6 +220,17 @@ export namespace TruffleCommands {
|
|||
}
|
||||
}
|
||||
|
||||
async function checkOpenZeppelinIfUsed(): Promise<void> {
|
||||
if (OpenZeppelinService.projectJsonExists()) {
|
||||
if (await openZeppelinHelper.shouldUpgradeOpenZeppelinAsync()) {
|
||||
await openZeppelinHelper.upgradeOpenZeppelinContractsAsync();
|
||||
await openZeppelinHelper.upgradeOpenZeppelinUserSettingsAsync();
|
||||
}
|
||||
|
||||
await validateOpenZeppelinContracts();
|
||||
}
|
||||
}
|
||||
|
||||
function removeDuplicateNetworks(deployDestinations: IDeployDestinationItem[]): IDeployDestinationItem[] {
|
||||
return deployDestinations.filter((destination, index, destinations) => {
|
||||
return destinations.findIndex((dest) => dest.label === destination.label) === index;
|
||||
|
@ -208,7 +260,7 @@ async function installRequiredDependencies(): Promise<void> {
|
|||
}
|
||||
|
||||
async function validateOpenZeppelinContracts(): Promise<void> {
|
||||
const validatedContracts = await OpenZeppelinService.validateContracts();
|
||||
const validatedContracts = await OpenZeppelinService.validateContractsAsync();
|
||||
validatedContracts.forEach((ozContract: OZContractValidated) => {
|
||||
if (ozContract.isExistedOnDisk) {
|
||||
Output.outputLine('', ozContract.isHashValid
|
||||
|
@ -396,29 +448,29 @@ async function createNetwork(getTruffleNetwork: () => Promise<TruffleConfigurati
|
|||
}
|
||||
|
||||
async function deployToNetwork(networkName: string, truffleConfigPath: string): Promise<void> {
|
||||
return window.withProgress({
|
||||
location: ProgressLocation.Window,
|
||||
title: Constants.statusBarMessages.deployingContracts(networkName),
|
||||
}, async () => {
|
||||
const workspaceRoot = path.dirname(truffleConfigPath);
|
||||
await showIgnorableNotification(
|
||||
Constants.statusBarMessages.deployingContracts(networkName),
|
||||
async () => {
|
||||
const workspaceRoot = path.dirname(truffleConfigPath);
|
||||
|
||||
await fs.ensureDir(workspaceRoot);
|
||||
await fs.ensureDir(workspaceRoot);
|
||||
|
||||
try {
|
||||
await installRequiredDependencies();
|
||||
await outputCommandHelper.executeCommand(
|
||||
workspaceRoot,
|
||||
'npx',
|
||||
RequiredApps.truffle, 'migrate', '--reset', '--network', networkName,
|
||||
);
|
||||
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deploySucceeded);
|
||||
} catch (error) {
|
||||
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deployFailed);
|
||||
throw error;
|
||||
}
|
||||
try {
|
||||
await installRequiredDependencies();
|
||||
await outputCommandHelper.executeCommand(
|
||||
workspaceRoot,
|
||||
'npx',
|
||||
RequiredApps.truffle, 'migrate', '--reset', '--network', networkName,
|
||||
);
|
||||
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deploySucceeded);
|
||||
} catch (error) {
|
||||
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deployFailed);
|
||||
throw error;
|
||||
}
|
||||
|
||||
await ContractDB.updateContracts();
|
||||
});
|
||||
await ContractDB.updateContracts();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async function deployToLocalGanache(networkName: string, truffleConfigPath: string, port: number): Promise<void> {
|
||||
|
@ -433,13 +485,16 @@ async function deployToMainNetwork(networkName: string, truffleConfigPath: strin
|
|||
}
|
||||
|
||||
async function readCompiledContract(uri: Uri): Promise<any> {
|
||||
if (path.extname(uri.fsPath) !== Constants.contractExtension.json) {
|
||||
const error = new Error(Constants.errorMessageStrings.InvalidContract);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
ensureFileIsContractJson(uri.fsPath);
|
||||
const data = fs.readFileSync(uri.fsPath, null);
|
||||
|
||||
return JSON.parse(data.toString());
|
||||
}
|
||||
|
||||
function ensureFileIsContractJson(filePath: string) {
|
||||
if (path.extname(filePath) !== Constants.contractExtension.json) {
|
||||
const error = new Error(Constants.errorMessageStrings.InvalidContract);
|
||||
Telemetry.sendException(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,32 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as cp from 'child_process';
|
||||
import * as os from 'os';
|
||||
|
||||
// The same implementation as in helpers/truffleConfig.ts
|
||||
// The same implementation as in helpers/command.ts
|
||||
// The difference is that all code which uses 'vscode' module is removed.
|
||||
// TODO: think how to reuse code
|
||||
interface IForkMessage {
|
||||
command: string;
|
||||
message?: string;
|
||||
batch?: {
|
||||
index: number;
|
||||
done: boolean;
|
||||
message: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ICommandResult {
|
||||
code: number;
|
||||
cmdOutput: string;
|
||||
cmdOutputIncludingStderr: string;
|
||||
code: number;
|
||||
cmdOutput: string;
|
||||
cmdOutputIncludingStderr: string;
|
||||
messages?: Array<{[key: string]: any}>;
|
||||
}
|
||||
|
||||
export interface ICommandExecute {
|
||||
childProcess: cp.ChildProcess;
|
||||
result: Promise<ICommandResult>;
|
||||
}
|
||||
|
||||
export async function executeCommand(
|
||||
|
@ -18,7 +37,7 @@ export async function executeCommand(
|
|||
const result: ICommandResult = await tryExecuteCommand(workingDirectory, commands, ...args);
|
||||
|
||||
if (result.code !== 0) {
|
||||
throw new Error('Error while executin command: ' + commands.concat(' ', ...args.join(' ')));
|
||||
throw new Error('Error while execution command: ' + commands.concat(' ', ...args.join(' ')));
|
||||
}
|
||||
|
||||
return result.cmdOutput;
|
||||
|
@ -54,3 +73,77 @@ async function tryExecuteCommand(workingDirectory: string | undefined, commands:
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function executeCommandInFork(workingDirectory: string | undefined, modulePath: string, ...args: string[])
|
||||
: Promise<string> {
|
||||
const result: ICommandResult = await tryExecuteCommandInFork(workingDirectory, modulePath, ...args);
|
||||
|
||||
if (result.code !== 0) {
|
||||
throw new Error(`Failed to run script - ${modulePath}. More details in output`);
|
||||
}
|
||||
|
||||
return result.cmdOutput;
|
||||
}
|
||||
|
||||
export function forkProcess(workingDirectory: string | undefined, modulePath: string, args: string[]): cp.ChildProcess {
|
||||
const options: cp.ForkOptions = { cwd: workingDirectory || os.tmpdir(), silent: true };
|
||||
return cp.fork(modulePath, args, options);
|
||||
}
|
||||
|
||||
export async function tryExecuteCommandInFork(
|
||||
workingDirectory: string | undefined,
|
||||
modulePath: string,
|
||||
...args: string[]
|
||||
): Promise<ICommandResult> {
|
||||
const { result } = tryExecuteCommandInForkAsync(workingDirectory, modulePath, ...args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function tryExecuteCommandInForkAsync(
|
||||
workingDirectory: string | undefined,
|
||||
modulePath: string,
|
||||
...args: string[]
|
||||
): ICommandExecute {
|
||||
let cmdOutput: string = '';
|
||||
let cmdOutputIncludingStderr: string = '';
|
||||
const messages: Array<string | object> = [];
|
||||
const batches: {[key: string]: string[]} = {};
|
||||
|
||||
const childProcess = forkProcess(workingDirectory, modulePath, args);
|
||||
const result = new Promise((resolve: (res: any) => void, reject: (error: Error) => void): void => {
|
||||
childProcess.stdout.on('data', (data: string | Buffer) => {
|
||||
data = data.toString();
|
||||
cmdOutput = cmdOutput.concat(data);
|
||||
cmdOutputIncludingStderr = cmdOutputIncludingStderr.concat(data);
|
||||
});
|
||||
|
||||
childProcess.stderr.on('data', (data: string | Buffer) => {
|
||||
data = data.toString();
|
||||
cmdOutputIncludingStderr = cmdOutputIncludingStderr.concat(data);
|
||||
});
|
||||
|
||||
childProcess.on('message', (message: IForkMessage) => {
|
||||
if (message.batch) {
|
||||
batches[message.command] = batches[message.command] || [];
|
||||
batches[message.command][message.batch.index] = message.batch.message;
|
||||
if (message.batch.done) {
|
||||
messages.push({command: message.command, message: batches[message.command].join('')});
|
||||
}
|
||||
} else {
|
||||
messages.push(message);
|
||||
}
|
||||
|
||||
const data = JSON.stringify(message);
|
||||
cmdOutput = cmdOutput.concat(data);
|
||||
cmdOutputIncludingStderr = cmdOutputIncludingStderr.concat(data);
|
||||
});
|
||||
|
||||
childProcess.on('error', reject);
|
||||
childProcess.on('exit', (code: number) => {
|
||||
resolve({ cmdOutput, cmdOutputIncludingStderr, code, messages });
|
||||
});
|
||||
});
|
||||
|
||||
return { childProcess, result };
|
||||
}
|
||||
|
|
|
@ -1,39 +1,42 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
DebugAdapterDescriptor,
|
||||
DebugAdapterDescriptorFactory,
|
||||
DebugAdapterExecutable,
|
||||
DebugAdapterServer,
|
||||
DebugSession,
|
||||
ProviderResult,
|
||||
DebugAdapterDescriptor,
|
||||
DebugAdapterDescriptorFactory,
|
||||
DebugAdapterExecutable,
|
||||
DebugAdapterServer,
|
||||
DebugSession,
|
||||
ProviderResult,
|
||||
} from 'vscode';
|
||||
|
||||
import * as Net from 'net';
|
||||
import { SolidityDebugSession } from '../debugSession';
|
||||
|
||||
export default class TruffleDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory {
|
||||
private _server?: Net.Server;
|
||||
private _server?: Net.Server;
|
||||
|
||||
public createDebugAdapterDescriptor(
|
||||
_session: DebugSession,
|
||||
_executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor> {
|
||||
public createDebugAdapterDescriptor(
|
||||
_session: DebugSession,
|
||||
_executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor> {
|
||||
|
||||
if (!this._server) {
|
||||
// start listening on a random port
|
||||
this._server = Net.createServer((socket) => {
|
||||
const debugSession = new SolidityDebugSession();
|
||||
debugSession.setRunAsServer(true);
|
||||
debugSession.start(socket as NodeJS.ReadableStream, socket);
|
||||
}).listen(0);
|
||||
}
|
||||
|
||||
// make VS Code connect to debug server
|
||||
const address: any = this._server.address();
|
||||
return new DebugAdapterServer(address.port);
|
||||
if (!this._server) {
|
||||
// start listening on a random port
|
||||
this._server = Net.createServer((socket) => {
|
||||
const debugSession = new SolidityDebugSession();
|
||||
debugSession.setRunAsServer(true);
|
||||
debugSession.start(socket as NodeJS.ReadableStream, socket);
|
||||
}).listen(0);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
if (this._server) {
|
||||
this._server.close();
|
||||
}
|
||||
// make VS Code connect to debug server
|
||||
const address: any = this._server.address();
|
||||
return new DebugAdapterServer(address.port);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
if (this._server) {
|
||||
this._server.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
CancellationToken,
|
||||
DebugConfiguration,
|
||||
DebugConfigurationProvider,
|
||||
ProviderResult,
|
||||
WorkspaceFolder,
|
||||
CancellationToken,
|
||||
DebugConfiguration,
|
||||
DebugConfigurationProvider,
|
||||
ProviderResult,
|
||||
WorkspaceFolder,
|
||||
} from 'vscode';
|
||||
|
||||
export default class TruffleDebuggerConfigurationProvider implements DebugConfigurationProvider {
|
||||
/**
|
||||
* Massage a debug configuration just before a debug session is being launched,
|
||||
* e.g. add all missing attributes to the debug configuration.
|
||||
*/
|
||||
public resolveDebugConfiguration(
|
||||
_folder: WorkspaceFolder | undefined,
|
||||
config: DebugConfiguration,
|
||||
_token?: CancellationToken): ProviderResult<DebugConfiguration> {
|
||||
return config;
|
||||
}
|
||||
/**
|
||||
* Massage a debug configuration just before a debug session is being launched,
|
||||
* e.g. add all missing attributes to the debug configuration.
|
||||
*/
|
||||
public resolveDebugConfiguration(
|
||||
_folder: WorkspaceFolder | undefined,
|
||||
config: DebugConfiguration,
|
||||
_token?: CancellationToken): ProviderResult<DebugConfiguration> {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { debug, ExtensionContext } from 'vscode';
|
||||
import { DEBUG_TYPE, EMBED_DEBUG_ADAPTER } from '../constants/debugAdapter';
|
||||
import DebugAdapterTrackerFactory from '../debugAdapterTracker/debugAdapterTrackerFactory';
|
||||
|
@ -5,18 +8,18 @@ import DebugAdapterDescriptorFactory from './debugAdapterDescriptorFactory';
|
|||
import DebuggerConfigurationProvider from './debugConfigurationProvider';
|
||||
|
||||
export class DebuggerConfiguration {
|
||||
public static initialize(context: ExtensionContext) {
|
||||
const debugConfigProvider = new DebuggerConfigurationProvider();
|
||||
context.subscriptions.push(debug.registerDebugConfigurationProvider(DEBUG_TYPE, debugConfigProvider));
|
||||
public static initialize(context: ExtensionContext) {
|
||||
const debugConfigProvider = new DebuggerConfigurationProvider();
|
||||
context.subscriptions.push(debug.registerDebugConfigurationProvider(DEBUG_TYPE, debugConfigProvider));
|
||||
|
||||
if (EMBED_DEBUG_ADAPTER) {
|
||||
const factory = new DebugAdapterDescriptorFactory();
|
||||
context.subscriptions.push(debug.registerDebugAdapterDescriptorFactory(DEBUG_TYPE, factory));
|
||||
context.subscriptions.push(factory);
|
||||
}
|
||||
|
||||
const debugAdapterTrackerFactory = new DebugAdapterTrackerFactory();
|
||||
const trackerFactory = debug.registerDebugAdapterTrackerFactory(DEBUG_TYPE, debugAdapterTrackerFactory);
|
||||
context.subscriptions.push(trackerFactory);
|
||||
if (EMBED_DEBUG_ADAPTER) {
|
||||
const factory = new DebugAdapterDescriptorFactory();
|
||||
context.subscriptions.push(debug.registerDebugAdapterDescriptorFactory(DEBUG_TYPE, factory));
|
||||
context.subscriptions.push(factory);
|
||||
}
|
||||
|
||||
const debugAdapterTrackerFactory = new DebugAdapterTrackerFactory();
|
||||
const trackerFactory = debug.registerDebugAdapterTrackerFactory(DEBUG_TYPE, debugAdapterTrackerFactory);
|
||||
context.subscriptions.push(trackerFactory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import * as crypto from 'crypto';
|
|||
import * as ESTree from 'estree';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { tryExecuteCommandInFork } from './cmdCommandExecutor';
|
||||
|
||||
export namespace ConfigurationReader {
|
||||
const notAllowedSymbols = new RegExp(
|
||||
|
@ -203,11 +204,11 @@ export namespace ConfigurationReader {
|
|||
}
|
||||
}
|
||||
|
||||
public getConfiguration(): IConfiguration {
|
||||
const moduleExports = getModuleExportsObjectExpression(this.ast);
|
||||
public async getConfiguration(workingDirectory: string): Promise<IConfiguration> {
|
||||
const truffleConfig = await getTruffleMetadata(workingDirectory);
|
||||
|
||||
if (moduleExports) {
|
||||
return astToConfiguration(moduleExports);
|
||||
if (truffleConfig) {
|
||||
return jsonToConfiguration(truffleConfig);
|
||||
}
|
||||
|
||||
return getDefaultConfiguration();
|
||||
|
@ -245,6 +246,23 @@ export namespace ConfigurationReader {
|
|||
}
|
||||
}
|
||||
|
||||
async function getTruffleMetadata(workingDirectory: string): Promise<IConfiguration> {
|
||||
const truffleConfigTemplatePath = typeof(IS_BUNDLE_TIME) === 'undefined' || IS_BUNDLE_TIME === false
|
||||
? path.join(__dirname, '..', 'helpers', 'checkTruffleConfigTemplate.js')
|
||||
: path.join(__dirname, 'checkTruffleConfigTemplate.js');
|
||||
const truffleConfigPath =
|
||||
path.relative(path.dirname(truffleConfigTemplatePath), path.join(workingDirectory, 'truffle-config.js'));
|
||||
|
||||
const result = await tryExecuteCommandInFork(workingDirectory, truffleConfigTemplatePath, truffleConfigPath);
|
||||
const truffleConfigObject = result.messages!.find((message) => message.command === 'truffleConfig');
|
||||
|
||||
if (!truffleConfigObject || !truffleConfigObject.message) {
|
||||
throw new Error('"truffle-config.js" has incorrect format');
|
||||
}
|
||||
|
||||
return JSON.parse(truffleConfigObject.message);
|
||||
}
|
||||
|
||||
function getDefaultConfiguration(): IConfiguration {
|
||||
return {
|
||||
contracts_build_directory: path.join('./', 'build', 'contracts'),
|
||||
|
@ -463,35 +481,29 @@ export namespace ConfigurationReader {
|
|||
};
|
||||
}
|
||||
|
||||
function astToConfiguration(node: ESTree.ObjectExpression): IConfiguration {
|
||||
const configuration = getDefaultConfiguration();
|
||||
function jsonToConfiguration(truffleConfig: {[key: string]: any}): IConfiguration {
|
||||
const { contracts_directory, contracts_build_directory, migrations_directory }
|
||||
= getDefaultConfiguration();
|
||||
|
||||
const contractsDir = findProperty(node, 'contracts_directory');
|
||||
if (contractsDir && contractsDir.value.type === 'Literal' &&
|
||||
typeof contractsDir.value.value === 'string' && contractsDir.value.value) {
|
||||
configuration.contracts_directory = contractsDir.value.value;
|
||||
truffleConfig.contracts_directory = truffleConfig.contracts_directory || contracts_directory;
|
||||
truffleConfig.contracts_build_directory = truffleConfig.contracts_build_directory || contracts_build_directory;
|
||||
truffleConfig.migrations_directory = truffleConfig.migrations_directory || migrations_directory;
|
||||
|
||||
const arrayNetwork: INetwork[] = [];
|
||||
|
||||
if (truffleConfig.networks) {
|
||||
// Networks are not used yet in the code
|
||||
Object.entries(truffleConfig.networks).forEach(([key, value]) => {
|
||||
arrayNetwork.push({
|
||||
name: key,
|
||||
options: value as INetworkOption,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const contractsBuildDir = findProperty(node, 'contracts_build_directory');
|
||||
if (contractsBuildDir && contractsBuildDir.value.type === 'Literal' &&
|
||||
typeof contractsBuildDir.value.value === 'string' && contractsBuildDir.value.value) {
|
||||
configuration.contracts_build_directory = contractsBuildDir.value.value;
|
||||
}
|
||||
truffleConfig.networks = arrayNetwork;
|
||||
|
||||
const migrationsDir = findProperty(node, 'migrations_directory');
|
||||
if (migrationsDir && migrationsDir.value.type === 'Literal' &&
|
||||
typeof migrationsDir.value.value === 'string' && migrationsDir.value.value) {
|
||||
configuration.migrations_directory = migrationsDir.value.value;
|
||||
}
|
||||
|
||||
const networks = findProperty(node, 'networks');
|
||||
if (networks && networks.value.type === 'ObjectExpression') {
|
||||
configuration.networks = astToNetworks(networks.value);
|
||||
}
|
||||
|
||||
// TODO: compilers
|
||||
|
||||
return configuration;
|
||||
return truffleConfig as IConfiguration;
|
||||
}
|
||||
|
||||
function astToNetworks(node: ESTree.ObjectExpression): INetwork[] {
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export const CONTRACT_JSON_EXTENSION = '.json';
|
||||
export const CONTRACT_JSON_ENCODING = 'utf-8';
|
||||
|
|
|
@ -1,39 +1,42 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export const EVENT_TYPES = {
|
||||
breakpointValidated: 'breakpointValidated',
|
||||
end: 'end',
|
||||
launched: 'launched',
|
||||
stopOnBreakpoint: 'stopOnBreakpoint',
|
||||
stopOnEntry: 'stopOnEntry',
|
||||
stopOnException: 'stopOnException',
|
||||
stopOnStepIn: 'stopOnStepIn',
|
||||
stopOnStepOut: 'stopOnStepOut',
|
||||
stopOnStepOver: 'stopOnStepOver',
|
||||
stopped: 'stopped',
|
||||
breakpointValidated: 'breakpointValidated',
|
||||
end: 'end',
|
||||
launched: 'launched',
|
||||
stopOnBreakpoint: 'stopOnBreakpoint',
|
||||
stopOnEntry: 'stopOnEntry',
|
||||
stopOnException: 'stopOnException',
|
||||
stopOnStepIn: 'stopOnStepIn',
|
||||
stopOnStepOut: 'stopOnStepOut',
|
||||
stopOnStepOver: 'stopOnStepOver',
|
||||
stopped: 'stopped',
|
||||
};
|
||||
|
||||
export const EVENT_REASONS = {
|
||||
breakpoint: 'breakpoint',
|
||||
changed: 'changed',
|
||||
entry: 'entry',
|
||||
exception: 'exception',
|
||||
stepIn: 'stepin',
|
||||
stepOut: 'stepout',
|
||||
stepOver: 'step',
|
||||
breakpoint: 'breakpoint',
|
||||
changed: 'changed',
|
||||
entry: 'entry',
|
||||
exception: 'exception',
|
||||
stepIn: 'stepin',
|
||||
stepOut: 'stepout',
|
||||
stepOver: 'step',
|
||||
};
|
||||
|
||||
// we don't support multiple threads, so we can use a hardcoded ID for the default thread
|
||||
export const MAIN_THREAD = {
|
||||
id: 1,
|
||||
name: 'thread 1',
|
||||
id: 1,
|
||||
name: 'thread 1',
|
||||
};
|
||||
|
||||
export const EVALUATE_REQUEST_TYPES = {
|
||||
hover: 'hover',
|
||||
watch: 'watch',
|
||||
hover: 'hover',
|
||||
watch: 'watch',
|
||||
};
|
||||
|
||||
export const DEBUG_TYPE = 'truffle';
|
||||
|
||||
export const EMBED_DEBUG_ADAPTER = !!(typeof(IS_BUNDLE_TIME) === 'undefined');
|
||||
export const EMBED_DEBUG_ADAPTER = typeof (IS_BUNDLE_TIME) === 'undefined' || IS_BUNDLE_TIME === false;
|
||||
|
||||
export const ERROR_MESSAGE_ID = 1;
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export const GET_INSTRUCTIONS = 'requestInstructions';
|
||||
export const GET_CURRENT_INSTRUCTION = 'requestCurrentInstruction';
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export const TRANSACTION_NUMBER_TO_SHOW = 5;
|
||||
export const TRANSACTION_DEFAULT_METHOD_NAME = 'constructor';
|
||||
export const LAST_BLOCK_QUERY = 'latest';
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export const TRUFFLE_CONFIG_NAME = 'truffle-config.js';
|
||||
export const TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE = 'development';
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
const VARIABLE_REFERANCE = {
|
||||
all: 1,
|
||||
dynamicVariables: 2,
|
||||
all: 1,
|
||||
dynamicVariables: 2,
|
||||
};
|
||||
|
||||
export const SCOPES = {
|
||||
all: {
|
||||
name: 'All',
|
||||
ref: VARIABLE_REFERANCE.all,
|
||||
},
|
||||
dynamicVariables: {
|
||||
ref: VARIABLE_REFERANCE.dynamicVariables,
|
||||
},
|
||||
all: {
|
||||
name: 'All',
|
||||
ref: VARIABLE_REFERANCE.all,
|
||||
},
|
||||
dynamicVariables: {
|
||||
ref: VARIABLE_REFERANCE.dynamicVariables,
|
||||
},
|
||||
};
|
||||
|
||||
export const OBJECT_VARIABLE_DISPLAY_NAME = 'Object';
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { CONTRACT_JSON_ENCODING } from '../constants/contractJson';
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { DebugNetwork } from '../debugNetwork';
|
||||
import { sortFilePaths } from '../helpers';
|
||||
import { IContractJsonModel } from '../models/IContractJsonModel';
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { DebugAdapterTracker, DebugSession, window } from 'vscode';
|
||||
import InstructionView from '../instructionsView/instructionView';
|
||||
|
||||
|
@ -6,50 +9,50 @@ import { GET_CURRENT_INSTRUCTION, GET_INSTRUCTIONS } from '../constants/debugSes
|
|||
import { IInstruction } from '../models/IInstruction';
|
||||
|
||||
export default class SolidityDebugAdapterTracker implements DebugAdapterTracker {
|
||||
private session: DebugSession;
|
||||
private instructionView: InstructionView;
|
||||
private session: DebugSession;
|
||||
private instructionView: InstructionView;
|
||||
|
||||
constructor(session: DebugSession) {
|
||||
this.session = session;
|
||||
this.instructionView = new InstructionView();
|
||||
}
|
||||
constructor(session: DebugSession) {
|
||||
this.session = session;
|
||||
this.instructionView = new InstructionView();
|
||||
}
|
||||
|
||||
public onDidSendMessage(message: any): void {
|
||||
if (message.success === false) {
|
||||
window.showErrorMessage('Error occured in debug mode: ' + message.body.error.format);
|
||||
return;
|
||||
}
|
||||
switch (message.event) {
|
||||
case EVENT_TYPES.launched: // init instructions after launch
|
||||
this.requestForInstructions();
|
||||
return;
|
||||
case EVENT_TYPES.stopped: // get current instruction on every stop event
|
||||
this.requestForCurrentInstruction();
|
||||
return;
|
||||
}
|
||||
switch (message.command) {
|
||||
case GET_INSTRUCTIONS:
|
||||
this.updateInstructionView(message.body.instructions);
|
||||
return;
|
||||
case GET_CURRENT_INSTRUCTION:
|
||||
this.revealInstruction(message.body.currentInstruction);
|
||||
return;
|
||||
}
|
||||
public onDidSendMessage(message: any): void {
|
||||
if (message.success === false) {
|
||||
window.showErrorMessage('Error occured in debug mode: ' + message.body.error.format);
|
||||
return;
|
||||
}
|
||||
switch (message.event) {
|
||||
case EVENT_TYPES.launched: // init instructions after launch
|
||||
this.requestForInstructions();
|
||||
return;
|
||||
case EVENT_TYPES.stopped: // get current instruction on every stop event
|
||||
this.requestForCurrentInstruction();
|
||||
return;
|
||||
}
|
||||
switch (message.command) {
|
||||
case GET_INSTRUCTIONS:
|
||||
this.updateInstructionView(message.body.instructions);
|
||||
return;
|
||||
case GET_CURRENT_INSTRUCTION:
|
||||
this.revealInstruction(message.body.currentInstruction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private requestForInstructions() {
|
||||
this.session.customRequest(GET_INSTRUCTIONS);
|
||||
}
|
||||
private requestForInstructions() {
|
||||
this.session.customRequest(GET_INSTRUCTIONS);
|
||||
}
|
||||
|
||||
private requestForCurrentInstruction() {
|
||||
this.session.customRequest(GET_CURRENT_INSTRUCTION);
|
||||
}
|
||||
private requestForCurrentInstruction() {
|
||||
this.session.customRequest(GET_CURRENT_INSTRUCTION);
|
||||
}
|
||||
|
||||
private updateInstructionView(instructions: IInstruction[]) {
|
||||
this.instructionView.update(instructions);
|
||||
}
|
||||
private updateInstructionView(instructions: IInstruction[]) {
|
||||
this.instructionView.update(instructions);
|
||||
}
|
||||
|
||||
private revealInstruction(instruction: IInstruction) {
|
||||
this.instructionView.revealInstruction(instruction);
|
||||
}
|
||||
private revealInstruction(instruction: IInstruction) {
|
||||
this.instructionView.revealInstruction(instruction);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
DebugAdapterTracker,
|
||||
DebugAdapterTrackerFactory,
|
||||
DebugSession,
|
||||
ProviderResult,
|
||||
DebugAdapterTracker,
|
||||
DebugAdapterTrackerFactory,
|
||||
DebugSession,
|
||||
ProviderResult,
|
||||
} from 'vscode';
|
||||
import SolidityDebugAdapterTracker from './debugAdapterTracker';
|
||||
|
||||
export default class SolidityDebugAdapterTrackerFactory implements DebugAdapterTrackerFactory {
|
||||
public createDebugAdapterTracker(session: DebugSession): ProviderResult<DebugAdapterTracker> {
|
||||
return new SolidityDebugAdapterTracker(session);
|
||||
}
|
||||
public createDebugAdapterTracker(session: DebugSession): ProviderResult<DebugAdapterTracker> {
|
||||
return new SolidityDebugAdapterTracker(session);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,95 +1,105 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as path from 'path';
|
||||
import { executeCommand } from './cmdCommandExecutor';
|
||||
import { ConfigurationReader } from './configurationReader';
|
||||
import { TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE, TRUFFLE_CONFIG_NAME } from './constants/truffleConfig';
|
||||
|
||||
export class DebugNetwork {
|
||||
public workingDirectory: string;
|
||||
private _basedConfig: ConfigurationReader.TruffleConfig | undefined;
|
||||
private _truffleConfiguration: ConfigurationReader.IConfiguration | undefined;
|
||||
private _networkForDebug: ConfigurationReader.INetwork | undefined;
|
||||
constructor(truffleConfigDirectory: string) {
|
||||
this.workingDirectory = truffleConfigDirectory;
|
||||
}
|
||||
public workingDirectory: string;
|
||||
private _basedConfig: ConfigurationReader.TruffleConfig | undefined;
|
||||
private _truffleConfiguration: ConfigurationReader.IConfiguration | undefined;
|
||||
private _networkForDebug: ConfigurationReader.INetwork | undefined;
|
||||
constructor(truffleConfigDirectory: string) {
|
||||
this.workingDirectory = truffleConfigDirectory;
|
||||
}
|
||||
|
||||
public async load(): Promise<void> {
|
||||
this._basedConfig =
|
||||
new ConfigurationReader.TruffleConfig(path.join(this.workingDirectory, TRUFFLE_CONFIG_NAME));
|
||||
this._truffleConfiguration = this.loadConfiguration();
|
||||
this._networkForDebug = await this.loadNetworkForDebug();
|
||||
}
|
||||
public async load(): Promise<void> {
|
||||
this._basedConfig =
|
||||
new ConfigurationReader.TruffleConfig(path.join(this.workingDirectory, TRUFFLE_CONFIG_NAME));
|
||||
this._truffleConfiguration = await this.loadConfiguration();
|
||||
this._networkForDebug = await this.loadNetworkForDebug();
|
||||
}
|
||||
|
||||
public getTruffleConfiguration() {
|
||||
return this._truffleConfiguration;
|
||||
}
|
||||
public getTruffleConfiguration() {
|
||||
return this._truffleConfiguration;
|
||||
}
|
||||
|
||||
public getNetwork() {
|
||||
return this._networkForDebug;
|
||||
}
|
||||
public getNetwork() {
|
||||
return this._networkForDebug;
|
||||
}
|
||||
|
||||
// Port and host are defined
|
||||
public isLocalNetwork() {
|
||||
if (!this._networkForDebug || !this._networkForDebug.options) {
|
||||
throw new Error('Network is not defined. Try to call this.load()');
|
||||
}
|
||||
const options = this._networkForDebug.options;
|
||||
return !!(options.host && options.port);
|
||||
// Port and host are defined
|
||||
public isLocalNetwork() {
|
||||
if (!this._networkForDebug || !this._networkForDebug.options) {
|
||||
throw new Error('Network is not defined. Try to call this.load()');
|
||||
}
|
||||
const options = this._networkForDebug.options;
|
||||
return !!(options.host && options.port);
|
||||
}
|
||||
|
||||
private loadConfiguration(): ConfigurationReader.IConfiguration {
|
||||
const configuration = this._basedConfig!.getConfiguration();
|
||||
configuration.contracts_build_directory =
|
||||
path.join(this.workingDirectory, configuration.contracts_build_directory);
|
||||
configuration.contracts_directory =
|
||||
path.join(this.workingDirectory, configuration.contracts_directory);
|
||||
configuration.migrations_directory =
|
||||
path.join(this.workingDirectory, configuration.migrations_directory);
|
||||
return configuration;
|
||||
}
|
||||
private async loadConfiguration(): Promise<ConfigurationReader.IConfiguration> {
|
||||
const configuration = await this._basedConfig!.getConfiguration(this.workingDirectory);
|
||||
|
||||
private async loadNetworkForDebug(): Promise<ConfigurationReader.INetwork> {
|
||||
const networks = this._basedConfig!.getNetworks();
|
||||
const networkForDebug = networks
|
||||
.find((n) => n.name === TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
|
||||
if (!this.isNetworkForDebugValid(networkForDebug)) {
|
||||
const provider = await this.getProviderByResolvingConfig(TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
|
||||
if (provider.url) {
|
||||
networkForDebug!.options.provider = {
|
||||
url: provider.url,
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Truffle config is not properly defined.
|
||||
return {
|
||||
contracts_build_directory: this.relativeToAbsolutePath(configuration.contracts_build_directory),
|
||||
contracts_directory: this.relativeToAbsolutePath(configuration.contracts_directory),
|
||||
migrations_directory: this.relativeToAbsolutePath(configuration.migrations_directory),
|
||||
};
|
||||
}
|
||||
|
||||
private async loadNetworkForDebug(): Promise<ConfigurationReader.INetwork> {
|
||||
const networks = this._basedConfig!.getNetworks();
|
||||
const networkForDebug = networks
|
||||
.find((n) => n.name === TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
|
||||
if (!this.isNetworkForDebugValid(networkForDebug)) {
|
||||
const provider = await this.getProviderByResolvingConfig(TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
|
||||
if (provider.url) {
|
||||
networkForDebug!.options.provider = {
|
||||
url: provider.url,
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Truffle config is not properly defined.
|
||||
Please create ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network,
|
||||
set host+port, or hdwallet/http/websocket provider.`);
|
||||
}
|
||||
}
|
||||
|
||||
return networkForDebug!;
|
||||
}
|
||||
}
|
||||
|
||||
private isNetworkForDebugValid(networkForDebug: ConfigurationReader.INetwork | undefined): boolean {
|
||||
if (!networkForDebug || !networkForDebug.options) {
|
||||
throw new Error(`No ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network in the truffle config`);
|
||||
}
|
||||
return networkForDebug!;
|
||||
}
|
||||
|
||||
if (networkForDebug.options.host && networkForDebug.options.port) {
|
||||
return true;
|
||||
}
|
||||
// truffle-config helper can read only hdwallet provider
|
||||
const isHdWalletProvider = !!networkForDebug.options.provider;
|
||||
if (isHdWalletProvider) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
private isNetworkForDebugValid(networkForDebug: ConfigurationReader.INetwork | undefined): boolean {
|
||||
if (!networkForDebug || !networkForDebug.options) {
|
||||
throw new Error(`No ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network in the truffle config`);
|
||||
}
|
||||
|
||||
private async getProviderByResolvingConfig(network: string) {
|
||||
// use truffle exec web3ProviderResolver.js to solve http- or websocket- web3 provider
|
||||
const truffleConfigReaderPath = path.join(__dirname, 'web3ProviderResolver.js');
|
||||
const args = [ 'truffle', 'exec', truffleConfigReaderPath, '--network', network ];
|
||||
const result = await executeCommand(this.workingDirectory, 'npx', ...args);
|
||||
const providerJson = result.split('provider%=')[1];
|
||||
return JSON.parse(providerJson);
|
||||
if (networkForDebug.options.host && networkForDebug.options.port) {
|
||||
return true;
|
||||
}
|
||||
// truffle-config helper can read only hdwallet provider
|
||||
const isHdWalletProvider = !!networkForDebug.options.provider;
|
||||
if (isHdWalletProvider) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async getProviderByResolvingConfig(network: string) {
|
||||
// use truffle exec web3ProviderResolver.js to solve http- or websocket- web3 provider
|
||||
const truffleConfigReaderPath = path.join(__dirname, 'web3ProviderResolver.js');
|
||||
const args = ['truffle', 'exec', truffleConfigReaderPath, '--network', network];
|
||||
const result = await executeCommand(this.workingDirectory, 'npx', ...args);
|
||||
const providerJson = result.split('provider%=')[1];
|
||||
return JSON.parse(providerJson);
|
||||
}
|
||||
|
||||
private relativeToAbsolutePath(directory: string) {
|
||||
if (directory && path.isAbsolute(directory)) {
|
||||
return directory;
|
||||
}
|
||||
|
||||
return path.join(this.workingDirectory, directory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,52 +1,55 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { IInstruction } from '../models/IInstruction';
|
||||
import InstructionTreeNode from './instructionTreeNode';
|
||||
|
||||
export default class InstructionDataManager {
|
||||
private instructionObject: any = {};
|
||||
private instructionObject: any = {};
|
||||
|
||||
public load(instructions: IInstruction[]) {
|
||||
this.instructionObject = this.mapInstructionsArrayToObject(instructions);
|
||||
public load(instructions: IInstruction[]) {
|
||||
this.instructionObject = this.mapInstructionsArrayToObject(instructions);
|
||||
}
|
||||
|
||||
public getChidren(element?: InstructionTreeNode): string[] {
|
||||
if (!element) {
|
||||
return Object.keys(this.instructionObject).map((k) => k);
|
||||
}
|
||||
|
||||
public getChidren(element?: InstructionTreeNode): string[] {
|
||||
if (!element) {
|
||||
return Object.keys(this.instructionObject).map((k) => k);
|
||||
}
|
||||
|
||||
const item = this.getItemByPath(element.getPaths());
|
||||
if (item === undefined) {
|
||||
return [];
|
||||
}
|
||||
return Object.keys(item);
|
||||
const item = this.getItemByPath(element.getPaths());
|
||||
if (item === undefined) {
|
||||
return [];
|
||||
}
|
||||
return Object.keys(item);
|
||||
}
|
||||
|
||||
public getItem(element: InstructionTreeNode): any {
|
||||
return this.getItemByPath(element.getPaths());
|
||||
}
|
||||
|
||||
public getItemParent(element: InstructionTreeNode): any {
|
||||
return this.getItemByPath(element.getParentPaths());
|
||||
}
|
||||
|
||||
// Map from array to object in order to used in view
|
||||
// [{pc:1,op: ''},{pc:2,op:''}] ==> { 1:{pc:1,op:''}, 2:{pc:2,op:''}}
|
||||
private mapInstructionsArrayToObject(steps: IInstruction[]): any {
|
||||
const res: any = {};
|
||||
steps.forEach((s) => {
|
||||
res[s.pc] = s;
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private getItemByPath(paths: string[]): any {
|
||||
if (paths.length === 0) {
|
||||
return void 0;
|
||||
}
|
||||
let item = this.instructionObject;
|
||||
paths.forEach((key) => {
|
||||
item = item[key];
|
||||
});
|
||||
return item;
|
||||
public getItem(element: InstructionTreeNode): any {
|
||||
return this.getItemByPath(element.getPaths());
|
||||
}
|
||||
|
||||
public getItemParent(element: InstructionTreeNode): any {
|
||||
return this.getItemByPath(element.getParentPaths());
|
||||
}
|
||||
|
||||
// Map from array to object in order to used in view
|
||||
// [{pc:1,op: ''},{pc:2,op:''}] ==> { 1:{pc:1,op:''}, 2:{pc:2,op:''}}
|
||||
private mapInstructionsArrayToObject(steps: IInstruction[]): any {
|
||||
const res: any = {};
|
||||
steps.forEach((s) => {
|
||||
res[s.pc] = s;
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private getItemByPath(paths: string[]): any {
|
||||
if (paths.length === 0) {
|
||||
return void 0;
|
||||
}
|
||||
let item = this.instructionObject;
|
||||
paths.forEach((key) => {
|
||||
item = item[key];
|
||||
});
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,57 +1,60 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Event, EventEmitter, ProviderResult, TreeDataProvider, TreeItem, TreeItemCollapsibleState } from 'vscode';
|
||||
import { IInstruction } from '../models/IInstruction';
|
||||
import InstructionDataManager from './instructionDataManager';
|
||||
import InstructionTreeNode from './instructionTreeNode';
|
||||
|
||||
export default class InstructionDataProvider implements TreeDataProvider<InstructionTreeNode> {
|
||||
public _onDidChangeTreeData: EventEmitter<InstructionTreeNode> = new EventEmitter<InstructionTreeNode>();
|
||||
public readonly onDidChangeTreeData: Event<InstructionTreeNode> = this._onDidChangeTreeData.event;
|
||||
public _onDidChangeTreeData: EventEmitter<InstructionTreeNode> = new EventEmitter<InstructionTreeNode>();
|
||||
public readonly onDidChangeTreeData: Event<InstructionTreeNode> = this._onDidChangeTreeData.event;
|
||||
|
||||
private instructionDataManager: InstructionDataManager;
|
||||
private instructionDataManager: InstructionDataManager;
|
||||
|
||||
constructor(instructionDataManager: InstructionDataManager) {
|
||||
this.instructionDataManager = instructionDataManager;
|
||||
}
|
||||
constructor(instructionDataManager: InstructionDataManager) {
|
||||
this.instructionDataManager = instructionDataManager;
|
||||
}
|
||||
|
||||
public refresh(newInstructions: IInstruction[]) {
|
||||
this.instructionDataManager.load(newInstructions);
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
public refresh(newInstructions: IInstruction[]) {
|
||||
this.instructionDataManager.load(newInstructions);
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
||||
public getChildren(element?: InstructionTreeNode): ProviderResult<InstructionTreeNode[]> {
|
||||
const items = this.instructionDataManager.getChidren(element);
|
||||
return items.map((e) => new InstructionTreeNode(e, element));
|
||||
}
|
||||
public getChildren(element?: InstructionTreeNode): ProviderResult<InstructionTreeNode[]> {
|
||||
const items = this.instructionDataManager.getChidren(element);
|
||||
return items.map((e) => new InstructionTreeNode(e, element));
|
||||
}
|
||||
|
||||
public getTreeItem(element: InstructionTreeNode): TreeItem {
|
||||
const item = this.instructionDataManager.getItem(element);
|
||||
const isSpecificObjectValueType = this.isSpecificObjectValueType(item);
|
||||
const collapsibleState = isSpecificObjectValueType
|
||||
? TreeItemCollapsibleState.Collapsed
|
||||
: TreeItemCollapsibleState.None;
|
||||
public getTreeItem(element: InstructionTreeNode): TreeItem {
|
||||
const item = this.instructionDataManager.getItem(element);
|
||||
const isSpecificObjectValueType = this.isSpecificObjectValueType(item);
|
||||
const collapsibleState = isSpecificObjectValueType
|
||||
? TreeItemCollapsibleState.Collapsed
|
||||
: TreeItemCollapsibleState.None;
|
||||
|
||||
return {
|
||||
collapsibleState,
|
||||
id: element.getId(),
|
||||
label: this.generateTreeItemLabel(element.getKey(), item, isSpecificObjectValueType),
|
||||
};
|
||||
}
|
||||
return {
|
||||
collapsibleState,
|
||||
id: element.getId(),
|
||||
label: this.generateTreeItemLabel(element.getKey(), item, isSpecificObjectValueType),
|
||||
};
|
||||
}
|
||||
|
||||
public getParent(element: InstructionTreeNode): ProviderResult<InstructionTreeNode> {
|
||||
return element.getParent();
|
||||
}
|
||||
public getParent(element: InstructionTreeNode): ProviderResult<InstructionTreeNode> {
|
||||
return element.getParent();
|
||||
}
|
||||
|
||||
private generateTreeItemLabel(treeItemKey: string, treeItemValue: any, isSpecificObjectValueType: boolean) {
|
||||
return isSpecificObjectValueType
|
||||
? treeItemKey
|
||||
: `${treeItemKey}: ${JSON.stringify(treeItemValue)}`;
|
||||
}
|
||||
private generateTreeItemLabel(treeItemKey: string, treeItemValue: any, isSpecificObjectValueType: boolean) {
|
||||
return isSpecificObjectValueType
|
||||
? treeItemKey
|
||||
: `${treeItemKey}: ${JSON.stringify(treeItemValue)}`;
|
||||
}
|
||||
|
||||
// TODO: refactroign - same method in variablesHandler
|
||||
private isSpecificObjectValueType(item: any) {
|
||||
return !Array.isArray(item)
|
||||
&& item !== null
|
||||
&& item !== undefined
|
||||
&& typeof(item) === 'object';
|
||||
}
|
||||
// TODO: refactroign - same method in variablesHandler
|
||||
private isSpecificObjectValueType(item: any) {
|
||||
return !Array.isArray(item)
|
||||
&& item !== null
|
||||
&& item !== undefined
|
||||
&& typeof (item) === 'object';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +1,48 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { IInstruction } from '../models/IInstruction';
|
||||
|
||||
export default class InstructionTreeNode {
|
||||
private key: string;
|
||||
private path: string;
|
||||
private parent?: InstructionTreeNode;
|
||||
private key: string;
|
||||
private path: string;
|
||||
private parent?: InstructionTreeNode;
|
||||
|
||||
constructor(key?: string, parent?: InstructionTreeNode, instructionData?: IInstruction) {
|
||||
if (!key && (!instructionData || (!instructionData.pc && instructionData.pc !== 0))) {
|
||||
throw new Error('Incorrect input params');
|
||||
}
|
||||
|
||||
const nodeKey = instructionData
|
||||
? instructionData.pc.toString()
|
||||
: (key || '');
|
||||
this.key = nodeKey;
|
||||
this.parent = parent;
|
||||
this.path = this.generatePath(nodeKey, parent);
|
||||
constructor(key?: string, parent?: InstructionTreeNode, instructionData?: IInstruction) {
|
||||
if (!key && (!instructionData || (!instructionData.pc && instructionData.pc !== 0))) {
|
||||
throw new Error('Incorrect input params');
|
||||
}
|
||||
|
||||
public getId(): string {
|
||||
return this.path;
|
||||
}
|
||||
const nodeKey = instructionData
|
||||
? instructionData.pc.toString()
|
||||
: (key || '');
|
||||
this.key = nodeKey;
|
||||
this.parent = parent;
|
||||
this.path = this.generatePath(nodeKey, parent);
|
||||
}
|
||||
|
||||
public getKey(): string {
|
||||
return this.key;
|
||||
}
|
||||
public getId(): string {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public getParent(): InstructionTreeNode | undefined {
|
||||
return this.parent;
|
||||
}
|
||||
public getKey(): string {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public getParentPaths(): string[] {
|
||||
return this.path.split(/\//).slice(1, this.path.length - 1); // not take first empty element and last
|
||||
}
|
||||
public getParent(): InstructionTreeNode | undefined {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
public getPaths(): string[] {
|
||||
return this.path.split(/\//).slice(1); // not take first empty element
|
||||
}
|
||||
public getParentPaths(): string[] {
|
||||
return this.path.split(/\//).slice(1, this.path.length - 1); // not take first empty element and last
|
||||
}
|
||||
|
||||
private generatePath(key: string, parent?: InstructionTreeNode) {
|
||||
const parentPath = parent ? parent.path : '';
|
||||
return `${parentPath}/${key}`;
|
||||
}
|
||||
public getPaths(): string[] {
|
||||
return this.path.split(/\//).slice(1); // not take first empty element
|
||||
}
|
||||
|
||||
private generatePath(key: string, parent?: InstructionTreeNode) {
|
||||
const parentPath = parent ? parent.path : '';
|
||||
return `${parentPath}/${key}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TreeView, window } from 'vscode';
|
||||
import { IInstruction } from '../models/IInstruction';
|
||||
import InstructionDataManager from './instructionDataManager';
|
||||
|
@ -7,23 +10,23 @@ import InstructionTreeNode from './instructionTreeNode';
|
|||
const INSTRUCTION_VIEW_ID = 'InstructionView';
|
||||
|
||||
export default class InstructionView {
|
||||
private view: TreeView<InstructionTreeNode>;
|
||||
private dataProvider: InstructionDataProvider;
|
||||
constructor() {
|
||||
const dataManager = new InstructionDataManager();
|
||||
this.dataProvider = new InstructionDataProvider(dataManager);
|
||||
this.view = window.createTreeView(INSTRUCTION_VIEW_ID,
|
||||
{ treeDataProvider: this.dataProvider, showCollapseAll: true });
|
||||
}
|
||||
private view: TreeView<InstructionTreeNode>;
|
||||
private dataProvider: InstructionDataProvider;
|
||||
constructor() {
|
||||
const dataManager = new InstructionDataManager();
|
||||
this.dataProvider = new InstructionDataProvider(dataManager);
|
||||
this.view = window.createTreeView(INSTRUCTION_VIEW_ID,
|
||||
{ treeDataProvider: this.dataProvider, showCollapseAll: true });
|
||||
}
|
||||
|
||||
public update(newInstructions: IInstruction[]) {
|
||||
this.dataProvider.refresh(newInstructions);
|
||||
}
|
||||
public update(newInstructions: IInstruction[]) {
|
||||
this.dataProvider.refresh(newInstructions);
|
||||
}
|
||||
|
||||
public revealInstruction(instruction: IInstruction) {
|
||||
if (this.view.visible) {
|
||||
const treeNode = new InstructionTreeNode(undefined, undefined, instruction);
|
||||
this.view.reveal(treeNode, { focus: true, select: true, expand: true });
|
||||
}
|
||||
public revealInstruction(instruction: IInstruction) {
|
||||
if (this.view.visible) {
|
||||
const treeNode = new InstructionTreeNode(undefined, undefined, instruction);
|
||||
this.view.reveal(treeNode, { focus: true, select: true, expand: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export interface ICallInfo {
|
||||
column: number;
|
||||
file: string;
|
||||
line: number;
|
||||
method: string;
|
||||
column: number;
|
||||
file: string;
|
||||
line: number;
|
||||
method: string;
|
||||
}
|
||||
|
|