Merge pull request #27 from microsoft/caleteet-0113-updates

Updates from release v0.1.13
This commit is contained in:
Chris Segura 2020-01-09 19:12:53 -08:00 коммит произвёл GitHub
Родитель 46145a5fdd e7a86bd639
Коммит 1a28f904f4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
171 изменённых файлов: 7205 добавлений и 5419 удалений

7
.vscode/extensions.json поставляемый Normal file
Просмотреть файл

@ -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"
]
}

62
.vscode/launch.json поставляемый Normal file
Просмотреть файл

@ -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" ]
}
]
}

26
.vscode/settings.json поставляемый Normal file
Просмотреть файл

@ -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
}

73
.vscode/tasks.json поставляемый Normal file
Просмотреть файл

@ -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/extension.js
!out/src/debugger.js !out/src/debugger.js
!out/src/web3ProviderResolver.js !out/src/web3ProviderResolver.js
!out/src/checkTruffleConfigTemplate.js
src/** src/**
test/** test/**
.editorconfig .editorconfig

Просмотреть файл

@ -2,7 +2,24 @@
All notable changes to the "azure blockchain" extension will be documented in this file. 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 ## 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 - Bumped HD wallet provider to latest Truffle version
- Minimized output channel logs - Minimized output channel logs
- Fixed output channel issue which shows JavaScript object after contract migration - 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 ## 0.1.10
@ -55,14 +72,14 @@ All notable changes to the "azure blockchain" extension will be documented in th
## 0.1.5 ## 0.1.5
- Backend test coverage - Backend test coverage
- Cleanup of packaging output, optimization - Cleanup of packaging output, optimization
- Truffle installation fails on new installs fix - Truffle installation fails on new installs fix
- Improved support for multiple ganache instances - Improved support for multiple ganache instances
- Preflight validation for ABS deployments - Preflight validation for ABS deployments
- Cleanup of code generation output - Cleanup of code generation output
- Ganache commands cleanup - Ganache commands cleanup
- Add command to export private key from mnemonic - Add command to export private key from mnemonic
- Better error handling ABS deployments - Better error handling ABS deployments
## 0.1.4 ## 0.1.4
@ -83,7 +100,6 @@ All notable changes to the "azure blockchain" extension will be documented in th
- Updated menu options - Updated menu options
## 0.1.0 ## 0.1.0
- Initial release - Initial release

Просмотреть файл

@ -15,7 +15,7 @@ Azure Blockchain Development Kit simplifies how you create, connect to, build an
- Supported Operating Systems - Supported Operating Systems
- Windows 10 - Windows 10
- Mac OSX - Mac OSX
- VS Code 1.32.0 (or greater) - VS Code 1.36.1 (or greater)
- Python 2.7.15 - Python 2.7.15
- Node 10.15.x - Node 10.15.x
- Git 2.10.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. 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.` `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 ## 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: 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 ## Build your Solidity Contract

Просмотреть файл

@ -11,45 +11,47 @@
"lint:fix": "npm run lint -- --fix" "lint:fix": "npm run lint -- --fix"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.5.5", "@babel/core": "^7.7.7",
"@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-proposal-object-rest-spread": "^7.5.5", "@babel/plugin-proposal-object-rest-spread": "^7.7.7",
"@babel/plugin-syntax-bigint": "^7.4.4", "@babel/plugin-syntax-bigint": "^7.7.4",
"@babel/plugin-transform-runtime": "^7.5.5", "@babel/plugin-transform-runtime": "^7.7.6",
"@babel/preset-env": "^7.5.5", "@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.7.4",
"@babel/runtime": "^7.5.5", "@babel/runtime": "^7.7.7",
"babel-eslint": "^10.0.2", "babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
"cross-env": "^5.2.0", "cross-env": "^6.0.3",
"css-loader": "^3.1.0", "css-loader": "^3.4.0",
"eslint": "^6.1.0", "eslint": "^6.8.0",
"eslint-config-airbnb": "^17.1.1", "eslint-config-airbnb": "^18.0.1",
"eslint-loader": "^2.2.1", "eslint-loader": "^3.0.3",
"eslint-plugin-import": "^2.18.2", "eslint-plugin-import": "^2.19.1",
"eslint-plugin-jest": "^22.14.0", "eslint-plugin-jest": "^23.2.0",
"eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.14.3", "eslint-plugin-react": "^7.17.0",
"file-loader": "^4.1.0", "eslint-plugin-react-hooks": "^2.3.0",
"file-loader": "^5.0.2",
"html-loader": "^0.5.5", "html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"less": "^3.9.0", "less": "^3.10.3",
"less-loader": "^5.0.0", "less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.8.0", "mini-css-extract-plugin": "^0.9.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"style-loader": "^0.23.1", "string-replace-loader": "^2.2.0",
"url-loader": "^2.1.0", "style-loader": "^1.1.2",
"webpack": "^4.38.0", "url-loader": "^3.0.0",
"webpack-cli": "^3.3.6" "webpack": "^4.41.5",
"webpack-cli": "^3.3.10"
}, },
"dependencies": { "dependencies": {
"@drizzle/react-components": "^1.5.1", "@drizzle/react-components": "^1.5.1",
"@drizzle/react-plugin": "^1.5.1", "@drizzle/react-plugin": "^1.5.1",
"@drizzle/store": "^1.5.1", "@drizzle/store": "^1.5.1",
"@material-ui/core": "^4.2.1", "@material-ui/core": "^4.8.2",
"@material-ui/icons": "^4.2.1", "@material-ui/icons": "^4.5.1",
"@truffle/hdwallet-provider": "^1.0.23", "@truffle/hdwallet-provider": "^1.0.28",
"react": "^16.10.2", "react": "^16.12.0",
"react-dom": "^16.10.2" "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 App from './App';
import { contractEventNotifier } from 'middlewares'; import { contractEventNotifier } from 'middlewares';
import { DrizzleContext } from '@drizzle/react-plugin'; import { DrizzleContext } from '@drizzle/react-plugin';
import { LocalStorage } from 'polyfills/localStorage';
import React from 'react'; import React from 'react';
import { render } from 'react-dom'; import { render } from 'react-dom';
import { Drizzle, generateStore } from '@drizzle/store'; 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 () { Drizzle.prototype.deleteAllContracts = function () {
Object.keys(this.contracts) Object.keys(this.contracts)
.forEach(contractName => this.deleteContract(contractName)); .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'), components: path.join(__dirname, './src/components'),
constants: path.join(__dirname, './src/constants'), constants: path.join(__dirname, './src/constants'),
helpers: path.join(__dirname, './src/helpers'), helpers: path.join(__dirname, './src/helpers'),
polyfills: path.join(__dirname, './src/polyfills'),
services: path.join(__dirname, './src/services'), services: path.join(__dirname, './src/services'),
views: path.join(__dirname, './src/views'), views: path.join(__dirname, './src/views'),
middlewares: path.join(__dirname, './src/middlewares'), middlewares: path.join(__dirname, './src/middlewares'),
@ -69,6 +70,19 @@ module.exports = () => {
test: [/\.js$/, /\.jsx$/], test: [/\.js$/, /\.jsx$/],
exclude: /node_modules/, exclude: /node_modules/,
loader: 'eslint-loader' 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

Просмотреть файл

@ -5,7 +5,7 @@
"publisher": "AzBlockchain", "publisher": "AzBlockchain",
"preview": true, "preview": true,
"icon": "images/blockchain-service-logo.png", "icon": "images/blockchain-service-logo.png",
"version": "0.1.12", "version": "0.1.13",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum" "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", "homepage": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum/blob/master/README.md",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"vscode": "^1.32.0" "vscode": "^1.36.1"
}, },
"keywords": [ "keywords": [
"azure",
"blockchain", "blockchain",
"azure",
"ethereum", "ethereum",
"debuggers",
"snippet" "snippet"
], ],
"categories": [ "categories": [
@ -59,6 +60,21 @@
"onDebug" "onDebug"
], ],
"contributes": { "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": [ "commands": [
{ {
"command": "azureBlockchainService.generateMicroservicesWorkflows", "command": "azureBlockchainService.generateMicroservicesWorkflows",
@ -498,7 +514,7 @@
"@types/semver": "^6.0.0", "@types/semver": "^6.0.0",
"@types/sinon": "^7.0.11", "@types/sinon": "^7.0.11",
"@types/uuid": "^3.4.4", "@types/uuid": "^3.4.4",
"@types/vscode": "^1.32.0", "@types/vscode": "^1.36.1",
"copy-webpack-plugin": "^5.0.3", "copy-webpack-plugin": "^5.0.3",
"decache": "^4.5.1", "decache": "^4.5.1",
"glob": "^7.1.4", "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 os from 'os';
import * as path from 'path'; import * as path from 'path';
import { ExtensionContext, extensions } from 'vscode'; import { ExtensionContext, extensions } from 'vscode';
import { IOZAsset } from './services'; import { IOZAsset } from './services/openZeppelin/models';
const extensionId = 'AzBlockchain.azure-blockchain'; const extensionId = 'AzBlockchain.azure-blockchain';
const packageJSON = extensions.getExtension(extensionId)!.packageJSON; const packageJSON = extensions.getExtension(extensionId)!.packageJSON;
@ -19,10 +19,15 @@ export enum RequiredApps {
hdwalletProvider = 'truffle-hdwallet-provider', hdwalletProvider = 'truffle-hdwallet-provider',
} }
export enum NotificationOptions {
error = 'error',
info = 'info',
warning = 'warning',
}
export class Constants { export class Constants {
public static extensionContext: ExtensionContext; public static extensionContext: ExtensionContext;
public static temporaryDirectory = ''; public static temporaryDirectory = '';
public static extensionName = packageJSON.name; public static extensionName = packageJSON.name;
public static extensionVersion = packageJSON.version; public static extensionVersion = packageJSON.version;
public static extensionKey = packageJSON.aiKey; public static extensionKey = packageJSON.aiKey;
@ -44,6 +49,12 @@ export class Constants {
hdwalletProvider: 'HDWalletProvider', 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 defaultTruffleBox = 'Azure-Samples/Blockchain-Ethereum-Template';
public static defaultDebounceTimeout = 300; public static defaultDebounceTimeout = 300;
@ -201,9 +212,11 @@ export class Constants {
}, },
hasDigits: /(?=.*\d)/g, hasDigits: /(?=.*\d)/g,
infuraProjectname: /^([a-zA-Z]|\d|\s|[-_:]){3,}$/g, infuraProjectname: /^([a-zA-Z]|\d|\s|[-_:]){3,}$/g,
isJsonFile: new RegExp(Constants.contractExtension.json + '$'),
isLowerCase: /^[a-z0-9_\-!@$^&()+=?\/<>|[\]{}:.\\~ #`*"'%;,]+$/g, isLowerCase: /^[a-z0-9_\-!@$^&()+=?\/<>|[\]{}:.\\~ #`*"'%;,]+$/g,
isUrl: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=]+$/igm, isUrl: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=]+$/igm,
lowerCaseLetter: /(?=.*[a-z]).*/g, lowerCaseLetter: /(?=.*[a-z]).*/g,
moduleExportsTemplate: /{(.*)}$/g,
// tslint:disable-next-line: max-line-length // 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])$/, 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: { specialChars: {
@ -371,8 +384,10 @@ export class Constants {
}; };
public static executeCommandMessage = { 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', finishRunningCommand: 'Finished running command',
forkingModule: 'Forking script',
runningCommand: 'Running command', runningCommand: 'Running command',
}; };
@ -395,9 +410,11 @@ export class Constants {
deployingContracts: (destination: string) => { deployingContracts: (destination: string) => {
return `Deploying contracts to '${destination}'`; return `Deploying contracts to '${destination}'`;
}, },
generatingLogicApp: (appName: string) => `Generating ${appName}!`,
}; };
public static rpcMethods = { public static rpcMethods = {
getCode: 'eth_getCode',
netListening: 'net_listening', netListening: 'net_listening',
netVersion: 'net_version', netVersion: 'net_version',
}; };
@ -430,12 +447,13 @@ export class Constants {
BuildContractsDirIsNotExist: Constants.getMessageContractsBuildDirectoryIsNotExist, BuildContractsDirIsNotExist: Constants.getMessageContractsBuildDirectoryIsNotExist,
CompiledContractIsMissing: 'Compiled contract is missing for solidity file.', CompiledContractIsMissing: 'Compiled contract is missing for solidity file.',
DirectoryIsNotEmpty: 'Directory is not empty. Open another one?', 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, GetMessageChildAlreadyConnected: Constants.getMessageChildAlreadyConnected,
GitIsNotInstalled: 'Git is not installed', GitIsNotInstalled: 'Git is not installed',
InfuraUnauthorized: 'Unauthorized: please sign in with Infura account.', InfuraUnauthorized: 'Unauthorized: please sign in with Infura account.',
InvalidContract: 'This file is not a valid contract.', InvalidContract: 'This file is not a valid contract.',
InvalidMnemonic: 'Invalid mnemonic', InvalidMnemonic: 'Invalid mnemonic',
InvalidServiceType: 'Invalid service type.',
LoadServiceTreeFailed: 'Load service tree has failed.', LoadServiceTreeFailed: 'Load service tree has failed.',
MnemonicFileHaveNoText: 'Mnemonic file have no text', MnemonicFileHaveNoText: 'Mnemonic file have no text',
NetworkAlreadyExist: Constants.getMessageNetworkAlreadyExist, NetworkAlreadyExist: Constants.getMessageNetworkAlreadyExist,
@ -448,6 +466,7 @@ export class Constants {
PleaseRenameOldStyleTruffleConfig: 'Please rename file "truffle.js" to "truffle-config.js"', PleaseRenameOldStyleTruffleConfig: 'Please rename file "truffle.js" to "truffle-config.js"',
RequiredAppsAreNotInstalled: 'To run command you should install required apps', RequiredAppsAreNotInstalled: 'To run command you should install required apps',
ThereAreNoMnemonics: 'There are no mnemonics', ThereAreNoMnemonics: 'There are no mnemonics',
TruffleConfigHasIncorrectFormat: '"truffle-config.js" has incorrect format',
TruffleConfigIsNotExist: 'Truffle configuration file not found', TruffleConfigIsNotExist: 'Truffle configuration file not found',
VariableShouldBeDefined: Constants.getMessageVariableShouldBeDefined, VariableShouldBeDefined: Constants.getMessageVariableShouldBeDefined,
WaitForLogin: 'You should sign-in on Azure Portal', WaitForLogin: 'You should sign-in on Azure Portal',
@ -465,7 +484,7 @@ export class Constants {
deployFailed: 'Deploy failed', deployFailed: 'Deploy failed',
deploySucceeded: 'Deploy succeeded', deploySucceeded: 'Deploy succeeded',
detailsButton: 'Details', 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', infuraAccountSuccessfullyCreated: 'Your Infura account successfully created. Please check you email for complete registration',
infuraSignInPrompt: 'Not signed in to Infura account, sign in first.', infuraSignInPrompt: 'Not signed in to Infura account, sign in first.',
installButton: 'Install', installButton: 'Install',
@ -479,6 +498,7 @@ export class Constants {
rpcEndpointCopiedToClipboard: 'RPCEndpointAddress copied to clipboard', rpcEndpointCopiedToClipboard: 'RPCEndpointAddress copied to clipboard',
seeDetailsRequirementsPage: 'Please see details on the Requirements Page', seeDetailsRequirementsPage: 'Please see details on the Requirements Page',
signInButton: 'Sign In', signInButton: 'Sign In',
transactionBytecodeWasCopiedToClipboard: 'Transaction Bytecode was copied to clipboard',
}; };
public static infuraCredentials = { public static infuraCredentials = {
@ -520,15 +540,10 @@ export class Constants {
Service: 'Service', Service: 'Service',
}; };
public static logicApp = { public static azureApps = {
AzureFunction: 'Azure Function', AzureFunction: { label: 'Azure Function', serviceType: 2, outputDir: 'generatedAzureFunction' },
FlowApp: 'Flow App', FlowApp: { label: 'Flow App', serviceType: 0, outputDir: 'generatedFlowApp' },
LogicApp: 'Logic App', LogicApp: { label: 'Logic App', serviceType: 1, outputDir: 'generatedLogicApp'},
output: {
AzureFunction: 'generatedAzureFunction',
FlowApp: 'generatedFlowApp',
LogicApp: 'generatedLogicApp',
},
}; };
public static azureResourceExplorer = { public static azureResourceExplorer = {
@ -541,12 +556,19 @@ export class Constants {
resourceType: 'blockchainMembers', 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 = { public static openZeppelin = {
cancelButtonTitle: 'Cancel', cancelButtonTitle: 'Cancel',
contractsUpgradeIsFailed: 'Upgrade of OpenZeppelin contracts has failed',
descriptionDownloadingFailed: 'Description downloading failed', descriptionDownloadingFailed: 'Description downloading failed',
downloadingContractsFromOpenZeppelin: 'Downloading contracts from OpenZeppelin', downloadingContractsFromOpenZeppelin: 'Downloading contracts from OpenZeppelin',
exploreDownloadedContractsInfo: 'Explore more information about the contracts downloaded', exploreDownloadedContractsInfo: 'Explore more information about the contracts downloaded',
invalidVersionException: 'Invalid version. All OpenZeppelin work will be stopped',
moreDetailsButtonTitle: 'More details', 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', overwriteExistedContracts: 'Overwrite existed contracts',
projectFileName: 'project.json', projectFileName: 'project.json',
replaceButtonTitle: 'Replace', replaceButtonTitle: 'Replace',
@ -554,6 +576,7 @@ export class Constants {
retryDownloading: 'Retry downloading', retryDownloading: 'Retry downloading',
selectCategoryForDownloading: 'Select category for downloading', selectCategoryForDownloading: 'Select category for downloading',
skipButtonTitle: 'Skip files', skipButtonTitle: 'Skip files',
upgradeOpenZeppelin: 'Upgrading OpenZeppelin',
hashCalculationFailed(errorMessage: string): string { hashCalculationFailed(errorMessage: string): string {
return `Error while calculating file hash. Message: ${errorMessage}`; return `Error while calculating file hash. Message: ${errorMessage}`;
}, },
@ -583,6 +606,10 @@ export class Constants {
fileNow(count: number): string { fileNow(count: number): string {
return `${count} file(s) on OpenZeppelin library now`; 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) { public static initialize(context: ExtensionContext) {
@ -690,10 +717,6 @@ export class Constants {
return `Length must be between ${min} and ${max} characters`; 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 { private static getMessageInputHasUnresolvedSymbols(unresolvedSymbols: string): string {
return `Input value must not have '${unresolvedSymbols}'.`; 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 * as path from 'path';
import { Uri, window } from 'vscode'; import { Uri, window } from 'vscode';
import { Constants } from '../Constants'; import { Constants } from '../Constants';
import { getWorkspaceRoot, TruffleConfiguration } from '../helpers'; import { getWorkspaceRoot, showIgnorableNotification, TruffleConfiguration } from '../helpers';
import { showInputBox, showQuickPick } from '../helpers/userInteraction'; import { showInputBox, showQuickPick } from '../helpers/userInteraction';
import { ResourceGroupItem, SubscriptionItem } from '../Models/QuickPickItems'; import { ResourceGroupItem, SubscriptionItem } from '../Models/QuickPickItems';
import { Output } from '../Output'; import { Output } from '../Output';
@ -23,48 +23,60 @@ interface ILogicAppData {
subscriptionId: string; subscriptionId: string;
topicName?: string; topicName?: string;
workflowType: string; workflowType: string;
label: string;
}
interface IAzureAppsItem {
label: string;
serviceType: number;
outputDir: string;
} }
export class LogicAppGenerator { export class LogicAppGenerator {
public async generateMicroservicesWorkflows(filePath?: Uri): Promise<void> { public async generateMicroservicesWorkflows(filePath?: Uri): Promise<void> {
Telemetry.sendEvent('LogicAppGenerator.microservicesWorkflows'); Telemetry.sendEvent('LogicAppGenerator.microservicesWorkflows');
this.generateWorkflows(Constants.microservicesWorkflows.Service, filePath); await this.generateWorkflows(Constants.microservicesWorkflows.Service, filePath);
} }
public async generateDataPublishingWorkflows(filePath?: Uri): Promise<void> { public async generateDataPublishingWorkflows(filePath?: Uri): Promise<void> {
Telemetry.sendEvent('LogicAppGenerator.dataPublishingWorkflows'); Telemetry.sendEvent('LogicAppGenerator.dataPublishingWorkflows');
this.generateWorkflows(Constants.microservicesWorkflows.Data, filePath); await this.generateWorkflows(Constants.microservicesWorkflows.Data, filePath);
} }
public async generateEventPublishingWorkflows(filePath?: Uri): Promise<void> { public async generateEventPublishingWorkflows(filePath?: Uri): Promise<void> {
Telemetry.sendEvent('LogicAppGenerator.eventPublishingWorkflows'); Telemetry.sendEvent('LogicAppGenerator.eventPublishingWorkflows');
this.generateWorkflows(Constants.microservicesWorkflows.Messaging, filePath); await this.generateWorkflows(Constants.microservicesWorkflows.Messaging, filePath);
} }
public async generateReportPublishingWorkflows(filePath?: Uri): Promise<void> { public async generateReportPublishingWorkflows(filePath?: Uri): Promise<void> {
Telemetry.sendEvent('LogicAppGenerator.reportPublishingWorkflows'); 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> { private async generateWorkflows(workflowType: string, filePath?: Uri): Promise<void> {
const filePaths = await this.getContractsPath(filePath); const filePaths = await this.getContractsPath(filePath);
const logicAppData = await this.getLogicAppData(workflowType); const logicAppData = await this.getLogicAppData(workflowType);
for (const file of filePaths) { await showIgnorableNotification(
const contract = await fs.readJson(file, { encoding: 'utf8' }); Constants.statusBarMessages.generatingLogicApp(logicAppData.label),
const generatedFiles: any[] = this.getGenerator(contract, logicAppData).GenerateAll(); async () => {
for (const generatedFile of generatedFiles) { for (const file of filePaths) {
await this.writeFile(generatedFile); 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); window.showInformationMessage(Constants.informationMessage.generatedLogicApp(logicAppData.label));
Telemetry.sendEvent('LogicAppGenerator.generateWorkflows.commandFinished'); Telemetry.sendEvent('LogicAppGenerator.generateWorkflows.commandFinished');
},
);
} }
private async getContractsPath(filePath?: Uri): Promise<string[]> { private async getContractsPath(filePath?: Uri): Promise<string[]> {
const truffleConfigPath = TruffleConfiguration.getTruffleConfigUri(); const truffleConfigPath = TruffleConfiguration.getTruffleConfigUri();
const truffleConfig = new TruffleConfiguration.TruffleConfig(truffleConfigPath); 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 buildDir = path.join(getWorkspaceRoot()!, configuration.contracts_build_directory);
const files: string[] = []; const files: string[] = [];
@ -102,15 +114,15 @@ export class LogicAppGenerator {
} }
private async getLogicAppData(workflowType: string): Promise<ILogicAppData> { private async getLogicAppData(workflowType: string): Promise<ILogicAppData> {
const serviceType = await this.getServiceType(workflowType); const azureAppItem: IAzureAppsItem = await this.getAzureAppItem(workflowType);
const outputDir = await this.getOutputDir(serviceType);
const contractAddress = await showInputBox({ ignoreFocusOut: true, value: 'contract address' }); const contractAddress = await showInputBox({ ignoreFocusOut: true, value: 'contract address' });
const [subscriptionItem, resourceGroupItem] = await this.selectSubscriptionAndResourceGroup(); const [subscriptionItem, resourceGroupItem] = await this.selectSubscriptionAndResourceGroup();
const logicAppData: ILogicAppData = { const logicAppData: ILogicAppData = {
contractAddress, contractAddress,
outputDir, label: azureAppItem.label,
outputDir: path.join(getWorkspaceRoot()!, azureAppItem.outputDir),
resourceGroup: resourceGroupItem.description, resourceGroup: resourceGroupItem.description,
serviceType, serviceType: azureAppItem.serviceType,
subscriptionId: subscriptionItem.subscriptionId, subscriptionId: subscriptionItem.subscriptionId,
workflowType, workflowType,
}; };
@ -157,34 +169,14 @@ export class LogicAppGenerator {
return [subscriptionItem, resourceGroupItem]; return [subscriptionItem, resourceGroupItem];
} }
private async getServiceType(workflowType: string): Promise<number> { private async getAzureAppItem(workflowType: string): Promise<IAzureAppsItem> {
const items = [ const items = [Constants.azureApps.LogicApp, Constants.azureApps.FlowApp ];
{ label: Constants.logicApp.LogicApp, serviceType: 1 },
{ label: Constants.logicApp.FlowApp, serviceType: 0 },
];
if (workflowType === Constants.microservicesWorkflows.Service) { 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 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;
}
}
} }
private async getMessagingType(): Promise<number> { 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 open = require('open');
import { ProgressLocation, window } from 'vscode'; import { ProgressLocation, window } from 'vscode';
import { Constants } from '../Constants'; import { Constants } from '../Constants';
import { showQuickPick } from '../helpers'; import { openZeppelinHelper, showQuickPick } from '../helpers';
import { Output } from '../Output'; import { Output } from '../Output';
import { import { OpenZeppelinMigrationsService, OpenZeppelinService } from '../services';
IOZAsset, import { IOZAsset, IOZContractCategory, PromiseState } from '../services/openZeppelin/models';
IOZContractCategory,
OpenZeppelinMigrationsService,
OpenZeppelinService,
PromiseState,
} from '../services';
import { Telemetry } from '../TelemetryClient'; import { Telemetry } from '../TelemetryClient';
export namespace OpenZeppelinCommands { export namespace OpenZeppelinCommands {
export async function addCategory(): Promise<void> { export async function addCategory(): Promise<void> {
Telemetry.sendEvent('OpenZeppelinCommands.addCategory'); 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); const category = await selectCategory(categories);
Telemetry.sendEvent('OpenZeppelinCommands.addCategory.selected', { name: category.name }); 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( Output.outputLine(
Constants.outputChannel.azureBlockchain, Constants.outputChannel.azureBlockchain,
Constants.openZeppelin.categoryWillDownloaded(category.name), Constants.openZeppelin.categoryWillDownloaded(category.name),
); );
const assetsStatuses = OpenZeppelinService.getAssetsStatus(fullAssetWithDependencies); const assetsStatuses = await OpenZeppelinService.getAssetsStatus(fullAssetWithDependencies);
Output.outputLine( Output.outputLine(
Constants.outputChannel.azureBlockchain, Constants.outputChannel.azureBlockchain,
Constants.openZeppelin.fileNow(assetsStatuses.existing.length), Constants.openZeppelin.fileNow(assetsStatuses.existing.length),
); );
if (assetsStatuses.existing.length > 0) { const downloadedAssets
const answer = await window.showInformationMessage( = await downloadOZFiles(baseUrl, assetsStatuses.existing, assetsStatuses.missing, fullAssetWithDependencies);
Constants.openZeppelin.alreadyExisted(assetsStatuses.existing),
Constants.openZeppelin.replaceButtonTitle, await OpenZeppelinService.updateProjectJsonAsync(manifest.getVersion(), category, downloadedAssets);
Constants.openZeppelin.skipButtonTitle,
); 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'); 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({ return window.withProgress({
location: ProgressLocation.Notification, location: ProgressLocation.Notification,
title: Constants.openZeppelin.downloadingContractsFromOpenZeppelin, title: Constants.openZeppelin.downloadingContractsFromOpenZeppelin,
}, async () => downloadFileSet(assets, overwrite), }, async () => downloadFileSet(assets));
);
}
async function downloadFileSet(assets: IOZAsset[], overwrite: boolean): Promise<void> { async function downloadFileSet(_assets: IOZAsset[])
const results = await OpenZeppelinService.downloadFiles(assets, overwrite); : Promise<IOZAsset[]> {
const results = await OpenZeppelinService.downloadAssetsAsync(baseUri, _assets, overwrite);
const downloaded = results let downloaded = results
.filter((result) => result.state === PromiseState.fulfilled) .filter((result) => result.state === PromiseState.fulfilled)
.map((result) => result.asset); .map((result) => result.asset);
const rejected = results const rejected = results
.filter((result) => result.state === PromiseState.rejected) .filter((result) => result.state === PromiseState.rejected)
.map((result) => result.asset); .map((result) => result.asset);
Telemetry.sendEvent( Telemetry.sendEvent(
'OpenZeppelinCommands.downloadFileSet.result', 'OpenZeppelinCommands.downloadFileSet.result',
{ downloadedCount: downloaded.length.toString(), rejectedCount: rejected.length.toString() }, { 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,
); );
if (answer === Constants.openZeppelin.retryButtonTitle) {
Output.outputLine( if (rejected.length > 0) {
Constants.outputChannel.azureBlockchain, const answer = await window.showErrorMessage(
Constants.openZeppelin.retryDownloading, Constants.openZeppelin.wereNotDownloaded(rejected.length),
Constants.openZeppelin.retryButtonTitle,
Constants.openZeppelin.cancelButtonTitle,
); );
Telemetry.sendEvent('OpenZeppelinCommands.downloadFileSet.retry', { assetsCount: rejected.length.toString() }); if (answer === Constants.openZeppelin.retryButtonTitle) {
await downloadFileSet(rejected, overwrite); 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> { async function openDocumentationUrl(documentationUrl?: string): Promise<void> {
const documentationUrl = OpenZeppelinService.getCategoryApiDocumentationUrl(category);
if (!documentationUrl) { if (!documentationUrl) {
return; return;
} }

Просмотреть файл

@ -2,12 +2,13 @@
// Licensed under the MIT license. // Licensed under the MIT license.
import * as fs from 'fs-extra'; 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 { Constants, RequiredApps } from '../Constants';
import { import {
gitHelper, gitHelper,
outputCommandHelper, outputCommandHelper,
required, required,
showIgnorableNotification,
showInputBox, showInputBox,
showOpenFolderDialog, showOpenFolderDialog,
showQuickPick, showQuickPick,
@ -79,36 +80,38 @@ async function chooseNewProjectDir(): Promise<string> {
async function createNewEmptyProject(projectPath: string): Promise<void> { async function createNewEmptyProject(projectPath: string): Promise<void> {
Telemetry.sendEvent('ProjectCommands.createNewEmptyProject.baseProject'); Telemetry.sendEvent('ProjectCommands.createNewEmptyProject.baseProject');
return window.withProgress({
location: ProgressLocation.Window, return createProject(projectPath, Constants.defaultTruffleBox);
title: Constants.statusBarMessages.creatingProject,
}, async () => {
return createProject(projectPath, Constants.defaultTruffleBox);
});
} }
async function createProjectFromTruffleBox(projectPath: string): Promise<void> { async function createProjectFromTruffleBox(projectPath: string): Promise<void> {
Telemetry.sendEvent('ProjectCommands.createProjectFromTruffleBox.customProject'); Telemetry.sendEvent('ProjectCommands.createProjectFromTruffleBox.customProject');
const truffleBoxName = await getTruffleBoxName(); const truffleBoxName = await getTruffleBoxName();
await createProject(projectPath, truffleBoxName);
return createProject(projectPath, truffleBoxName);
} }
async function createProject(projectPath: string, truffleBoxName: string): Promise<void> { async function createProject(projectPath: string, truffleBoxName: string): Promise<void> {
try { await showIgnorableNotification(
Telemetry.sendEvent('ProjectCommands.createProject.unbox', { truffleBoxName }); Constants.statusBarMessages.creatingProject,
await outputCommandHelper.executeCommand(projectPath, 'npx', RequiredApps.truffle, 'unbox', truffleBoxName); async () => {
try {
Telemetry.sendEvent('ProjectCommands.createProject.unbox', { truffleBoxName });
await outputCommandHelper.executeCommand(projectPath, 'npx', RequiredApps.truffle, 'unbox', truffleBoxName);
TruffleConfiguration.checkTruffleConfigNaming(projectPath); TruffleConfiguration.checkTruffleConfigNaming(projectPath);
workspace.updateWorkspaceFolders( workspace.updateWorkspaceFolders(
0, 0,
workspace.workspaceFolders ? workspace.workspaceFolders.length : null, workspace.workspaceFolders ? workspace.workspaceFolders.length : null,
{ uri: Uri.file(projectPath) }); { uri: Uri.file(projectPath) });
} catch (error) { } catch (error) {
fs.emptyDirSync(projectPath); fs.emptyDirSync(projectPath);
Telemetry.sendException(new Error(Constants.errorMessageStrings.NewProjectCreationFailed)); Telemetry.sendException(new Error(Constants.errorMessageStrings.NewProjectCreationFailed));
throw new Error(`${Constants.errorMessageStrings.NewProjectCreationFailed} ${error.message}`); throw new Error(`${Constants.errorMessageStrings.NewProjectCreationFailed} ${error.message}`);
} }
},
);
} }
async function getTruffleBoxName(): Promise<string> { async function getTruffleBoxName(): Promise<string> {

Просмотреть файл

@ -6,24 +6,35 @@ import * as fs from 'fs-extra';
// @ts-ignore // @ts-ignore
import * as hdkey from 'hdkey'; import * as hdkey from 'hdkey';
import * as path from 'path'; import * as path from 'path';
import { ProgressLocation, QuickPickItem, Uri, window } from 'vscode'; import { QuickPickItem, Uri, window } from 'vscode';
import { Constants, RequiredApps } from '../Constants'; import { Constants, RequiredApps } from '../Constants';
import { import {
getWorkspaceRoot, getWorkspaceRoot,
openZeppelinHelper,
outputCommandHelper, outputCommandHelper,
required, required,
showConfirmPaidOperationDialog, showConfirmPaidOperationDialog,
showIgnorableNotification,
showQuickPick, showQuickPick,
TruffleConfig, TruffleConfig,
TruffleConfiguration, TruffleConfiguration,
vscodeEnvironment, vscodeEnvironment,
} from '../helpers'; } from '../helpers';
import { IDeployDestination, ItemType } from '../Models'; import { IDeployDestination, ItemType } from '../Models';
import { NetworkForContractItem } from '../Models/QuickPickItems/NetworkForContractItem';
import { LocalService } from '../Models/TreeItems'; import { LocalService } from '../Models/TreeItems';
import { Project } from '../Models/TreeItems'; import { Project } from '../Models/TreeItems';
import { Output } from '../Output'; import { Output } from '../Output';
import { ContractDB, GanacheService, MnemonicRepository, OpenZeppelinService, TreeManager } from '../services'; import {
import { OZContractValidated } from '../services/openZeppelin/OpenZeppelinService'; ContractDB,
ContractInstanceWithMetadata,
ContractService,
GanacheService,
MnemonicRepository,
OpenZeppelinService,
TreeManager,
} from '../services';
import { OZContractValidated } from '../services/openZeppelin/models';
import { Telemetry } from '../TelemetryClient'; import { Telemetry } from '../TelemetryClient';
import { ProjectView } from '../ViewItems'; import { ProjectView } from '../ViewItems';
import { ServiceCommands } from './ServiceCommands'; import { ServiceCommands } from './ServiceCommands';
@ -47,17 +58,18 @@ interface IExtendedQuickPickItem extends QuickPickItem {
export namespace TruffleCommands { export namespace TruffleCommands {
export async function buildContracts(): Promise<void> { export async function buildContracts(): Promise<void> {
Telemetry.sendEvent('TruffleCommands.buildContracts.commandStarted'); Telemetry.sendEvent('TruffleCommands.buildContracts.commandStarted');
await window.withProgress({ await showIgnorableNotification(
location: ProgressLocation.Window, Constants.statusBarMessages.buildingContracts,
title: Constants.statusBarMessages.buildingContracts, async () => {
}, async () => { if (!await required.checkAppsSilent(RequiredApps.truffle)) {
if (!await required.checkAppsSilent(RequiredApps.truffle)) { Telemetry.sendEvent('TruffleCommands.buildContracts.truffleInstallation');
Telemetry.sendEvent('TruffleCommands.buildContracts.truffleInstallation'); await required.installTruffle(required.Scope.locally);
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'); Telemetry.sendEvent('TruffleCommands.buildContracts.commandFinished');
} }
@ -89,8 +101,7 @@ export namespace TruffleCommands {
{ url: Telemetry.obfuscate(command.description || '') }, { url: Telemetry.obfuscate(command.description || '') },
); );
await validateOpenZeppelinContracts(); await checkOpenZeppelinIfUsed();
await command.cmd(); await command.cmd();
Telemetry.sendEvent('TruffleCommands.deployContracts.commandFinished'); Telemetry.sendEvent('TruffleCommands.deployContracts.commandFinished');
@ -114,9 +125,39 @@ export namespace TruffleCommands {
export async function writeDeployedBytecodeToBuffer(uri: Uri): Promise<void> { export async function writeDeployedBytecodeToBuffer(uri: Uri): Promise<void> {
Telemetry.sendEvent('TruffleCommands.writeBytecodeToBuffer.commandStarted'); 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'); 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[] { function removeDuplicateNetworks(deployDestinations: IDeployDestinationItem[]): IDeployDestinationItem[] {
return deployDestinations.filter((destination, index, destinations) => { return deployDestinations.filter((destination, index, destinations) => {
return destinations.findIndex((dest) => dest.label === destination.label) === index; return destinations.findIndex((dest) => dest.label === destination.label) === index;
@ -208,7 +260,7 @@ async function installRequiredDependencies(): Promise<void> {
} }
async function validateOpenZeppelinContracts(): Promise<void> { async function validateOpenZeppelinContracts(): Promise<void> {
const validatedContracts = await OpenZeppelinService.validateContracts(); const validatedContracts = await OpenZeppelinService.validateContractsAsync();
validatedContracts.forEach((ozContract: OZContractValidated) => { validatedContracts.forEach((ozContract: OZContractValidated) => {
if (ozContract.isExistedOnDisk) { if (ozContract.isExistedOnDisk) {
Output.outputLine('', ozContract.isHashValid Output.outputLine('', ozContract.isHashValid
@ -396,29 +448,29 @@ async function createNetwork(getTruffleNetwork: () => Promise<TruffleConfigurati
} }
async function deployToNetwork(networkName: string, truffleConfigPath: string): Promise<void> { async function deployToNetwork(networkName: string, truffleConfigPath: string): Promise<void> {
return window.withProgress({ await showIgnorableNotification(
location: ProgressLocation.Window, Constants.statusBarMessages.deployingContracts(networkName),
title: Constants.statusBarMessages.deployingContracts(networkName), async () => {
}, async () => { const workspaceRoot = path.dirname(truffleConfigPath);
const workspaceRoot = path.dirname(truffleConfigPath);
await fs.ensureDir(workspaceRoot); await fs.ensureDir(workspaceRoot);
try { try {
await installRequiredDependencies(); await installRequiredDependencies();
await outputCommandHelper.executeCommand( await outputCommandHelper.executeCommand(
workspaceRoot, workspaceRoot,
'npx', 'npx',
RequiredApps.truffle, 'migrate', '--reset', '--network', networkName, RequiredApps.truffle, 'migrate', '--reset', '--network', networkName,
); );
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deploySucceeded); Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deploySucceeded);
} catch (error) { } catch (error) {
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deployFailed); Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deployFailed);
throw error; throw error;
} }
await ContractDB.updateContracts(); await ContractDB.updateContracts();
}); },
);
} }
async function deployToLocalGanache(networkName: string, truffleConfigPath: string, port: number): Promise<void> { 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> { async function readCompiledContract(uri: Uri): Promise<any> {
if (path.extname(uri.fsPath) !== Constants.contractExtension.json) { ensureFileIsContractJson(uri.fsPath);
const error = new Error(Constants.errorMessageStrings.InvalidContract);
Telemetry.sendException(error);
throw error;
}
const data = fs.readFileSync(uri.fsPath, null); const data = fs.readFileSync(uri.fsPath, null);
return JSON.parse(data.toString()); 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 cp from 'child_process';
import * as os from 'os'; 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. // The difference is that all code which uses 'vscode' module is removed.
// TODO: think how to reuse code // TODO: think how to reuse code
interface IForkMessage {
command: string;
message?: string;
batch?: {
index: number;
done: boolean;
message: string;
};
}
export interface ICommandResult { export interface ICommandResult {
code: number; code: number;
cmdOutput: string; cmdOutput: string;
cmdOutputIncludingStderr: string; cmdOutputIncludingStderr: string;
messages?: Array<{[key: string]: any}>;
}
export interface ICommandExecute {
childProcess: cp.ChildProcess;
result: Promise<ICommandResult>;
} }
export async function executeCommand( export async function executeCommand(
@ -18,7 +37,7 @@ export async function executeCommand(
const result: ICommandResult = await tryExecuteCommand(workingDirectory, commands, ...args); const result: ICommandResult = await tryExecuteCommand(workingDirectory, commands, ...args);
if (result.code !== 0) { 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; 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 { import {
DebugAdapterDescriptor, DebugAdapterDescriptor,
DebugAdapterDescriptorFactory, DebugAdapterDescriptorFactory,
DebugAdapterExecutable, DebugAdapterExecutable,
DebugAdapterServer, DebugAdapterServer,
DebugSession, DebugSession,
ProviderResult, ProviderResult,
} from 'vscode'; } from 'vscode';
import * as Net from 'net'; import * as Net from 'net';
import { SolidityDebugSession } from '../debugSession'; import { SolidityDebugSession } from '../debugSession';
export default class TruffleDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory { export default class TruffleDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory {
private _server?: Net.Server; private _server?: Net.Server;
public createDebugAdapterDescriptor( public createDebugAdapterDescriptor(
_session: DebugSession, _session: DebugSession,
_executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor> { _executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor> {
if (!this._server) { if (!this._server) {
// start listening on a random port // start listening on a random port
this._server = Net.createServer((socket) => { this._server = Net.createServer((socket) => {
const debugSession = new SolidityDebugSession(); const debugSession = new SolidityDebugSession();
debugSession.setRunAsServer(true); debugSession.setRunAsServer(true);
debugSession.start(socket as NodeJS.ReadableStream, socket); debugSession.start(socket as NodeJS.ReadableStream, socket);
}).listen(0); }).listen(0);
}
// make VS Code connect to debug server
const address: any = this._server.address();
return new DebugAdapterServer(address.port);
} }
public dispose() { // make VS Code connect to debug server
if (this._server) { const address: any = this._server.address();
this._server.close(); 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 { import {
CancellationToken, CancellationToken,
DebugConfiguration, DebugConfiguration,
DebugConfigurationProvider, DebugConfigurationProvider,
ProviderResult, ProviderResult,
WorkspaceFolder, WorkspaceFolder,
} from 'vscode'; } from 'vscode';
export default class TruffleDebuggerConfigurationProvider implements DebugConfigurationProvider { export default class TruffleDebuggerConfigurationProvider implements DebugConfigurationProvider {
/** /**
* Massage a debug configuration just before a debug session is being launched, * Massage a debug configuration just before a debug session is being launched,
* e.g. add all missing attributes to the debug configuration. * e.g. add all missing attributes to the debug configuration.
*/ */
public resolveDebugConfiguration( public resolveDebugConfiguration(
_folder: WorkspaceFolder | undefined, _folder: WorkspaceFolder | undefined,
config: DebugConfiguration, config: DebugConfiguration,
_token?: CancellationToken): ProviderResult<DebugConfiguration> { _token?: CancellationToken): ProviderResult<DebugConfiguration> {
return config; 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, ExtensionContext } from 'vscode';
import { DEBUG_TYPE, EMBED_DEBUG_ADAPTER } from '../constants/debugAdapter'; import { DEBUG_TYPE, EMBED_DEBUG_ADAPTER } from '../constants/debugAdapter';
import DebugAdapterTrackerFactory from '../debugAdapterTracker/debugAdapterTrackerFactory'; import DebugAdapterTrackerFactory from '../debugAdapterTracker/debugAdapterTrackerFactory';
@ -5,18 +8,18 @@ import DebugAdapterDescriptorFactory from './debugAdapterDescriptorFactory';
import DebuggerConfigurationProvider from './debugConfigurationProvider'; import DebuggerConfigurationProvider from './debugConfigurationProvider';
export class DebuggerConfiguration { export class DebuggerConfiguration {
public static initialize(context: ExtensionContext) { public static initialize(context: ExtensionContext) {
const debugConfigProvider = new DebuggerConfigurationProvider(); const debugConfigProvider = new DebuggerConfigurationProvider();
context.subscriptions.push(debug.registerDebugConfigurationProvider(DEBUG_TYPE, debugConfigProvider)); context.subscriptions.push(debug.registerDebugConfigurationProvider(DEBUG_TYPE, debugConfigProvider));
if (EMBED_DEBUG_ADAPTER) { if (EMBED_DEBUG_ADAPTER) {
const factory = new DebugAdapterDescriptorFactory(); const factory = new DebugAdapterDescriptorFactory();
context.subscriptions.push(debug.registerDebugAdapterDescriptorFactory(DEBUG_TYPE, factory)); context.subscriptions.push(debug.registerDebugAdapterDescriptorFactory(DEBUG_TYPE, factory));
context.subscriptions.push(factory); context.subscriptions.push(factory);
}
const debugAdapterTrackerFactory = new DebugAdapterTrackerFactory();
const trackerFactory = debug.registerDebugAdapterTrackerFactory(DEBUG_TYPE, debugAdapterTrackerFactory);
context.subscriptions.push(trackerFactory);
} }
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 ESTree from 'estree';
import * as fs from 'fs-extra'; import * as fs from 'fs-extra';
import * as path from 'path'; import * as path from 'path';
import { tryExecuteCommandInFork } from './cmdCommandExecutor';
export namespace ConfigurationReader { export namespace ConfigurationReader {
const notAllowedSymbols = new RegExp( const notAllowedSymbols = new RegExp(
@ -203,11 +204,11 @@ export namespace ConfigurationReader {
} }
} }
public getConfiguration(): IConfiguration { public async getConfiguration(workingDirectory: string): Promise<IConfiguration> {
const moduleExports = getModuleExportsObjectExpression(this.ast); const truffleConfig = await getTruffleMetadata(workingDirectory);
if (moduleExports) { if (truffleConfig) {
return astToConfiguration(moduleExports); return jsonToConfiguration(truffleConfig);
} }
return getDefaultConfiguration(); 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 { function getDefaultConfiguration(): IConfiguration {
return { return {
contracts_build_directory: path.join('./', 'build', 'contracts'), contracts_build_directory: path.join('./', 'build', 'contracts'),
@ -463,35 +481,29 @@ export namespace ConfigurationReader {
}; };
} }
function astToConfiguration(node: ESTree.ObjectExpression): IConfiguration { function jsonToConfiguration(truffleConfig: {[key: string]: any}): IConfiguration {
const configuration = getDefaultConfiguration(); const { contracts_directory, contracts_build_directory, migrations_directory }
= getDefaultConfiguration();
const contractsDir = findProperty(node, 'contracts_directory'); truffleConfig.contracts_directory = truffleConfig.contracts_directory || contracts_directory;
if (contractsDir && contractsDir.value.type === 'Literal' && truffleConfig.contracts_build_directory = truffleConfig.contracts_build_directory || contracts_build_directory;
typeof contractsDir.value.value === 'string' && contractsDir.value.value) { truffleConfig.migrations_directory = truffleConfig.migrations_directory || migrations_directory;
configuration.contracts_directory = contractsDir.value.value;
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'); truffleConfig.networks = arrayNetwork;
if (contractsBuildDir && contractsBuildDir.value.type === 'Literal' &&
typeof contractsBuildDir.value.value === 'string' && contractsBuildDir.value.value) {
configuration.contracts_build_directory = contractsBuildDir.value.value;
}
const migrationsDir = findProperty(node, 'migrations_directory'); return truffleConfig as IConfiguration;
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;
} }
function astToNetworks(node: ESTree.ObjectExpression): INetwork[] { 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_EXTENSION = '.json';
export const CONTRACT_JSON_ENCODING = 'utf-8'; 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 = { export const EVENT_TYPES = {
breakpointValidated: 'breakpointValidated', breakpointValidated: 'breakpointValidated',
end: 'end', end: 'end',
launched: 'launched', launched: 'launched',
stopOnBreakpoint: 'stopOnBreakpoint', stopOnBreakpoint: 'stopOnBreakpoint',
stopOnEntry: 'stopOnEntry', stopOnEntry: 'stopOnEntry',
stopOnException: 'stopOnException', stopOnException: 'stopOnException',
stopOnStepIn: 'stopOnStepIn', stopOnStepIn: 'stopOnStepIn',
stopOnStepOut: 'stopOnStepOut', stopOnStepOut: 'stopOnStepOut',
stopOnStepOver: 'stopOnStepOver', stopOnStepOver: 'stopOnStepOver',
stopped: 'stopped', stopped: 'stopped',
}; };
export const EVENT_REASONS = { export const EVENT_REASONS = {
breakpoint: 'breakpoint', breakpoint: 'breakpoint',
changed: 'changed', changed: 'changed',
entry: 'entry', entry: 'entry',
exception: 'exception', exception: 'exception',
stepIn: 'stepin', stepIn: 'stepin',
stepOut: 'stepout', stepOut: 'stepout',
stepOver: 'step', stepOver: 'step',
}; };
// we don't support multiple threads, so we can use a hardcoded ID for the default thread // we don't support multiple threads, so we can use a hardcoded ID for the default thread
export const MAIN_THREAD = { export const MAIN_THREAD = {
id: 1, id: 1,
name: 'thread 1', name: 'thread 1',
}; };
export const EVALUATE_REQUEST_TYPES = { export const EVALUATE_REQUEST_TYPES = {
hover: 'hover', hover: 'hover',
watch: 'watch', watch: 'watch',
}; };
export const DEBUG_TYPE = 'truffle'; 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; 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_INSTRUCTIONS = 'requestInstructions';
export const GET_CURRENT_INSTRUCTION = 'requestCurrentInstruction'; 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_NUMBER_TO_SHOW = 5;
export const TRANSACTION_DEFAULT_METHOD_NAME = 'constructor'; export const TRANSACTION_DEFAULT_METHOD_NAME = 'constructor';
export const LAST_BLOCK_QUERY = 'latest'; 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_NAME = 'truffle-config.js';
export const TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE = 'development'; 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 = { const VARIABLE_REFERANCE = {
all: 1, all: 1,
dynamicVariables: 2, dynamicVariables: 2,
}; };
export const SCOPES = { export const SCOPES = {
all: { all: {
name: 'All', name: 'All',
ref: VARIABLE_REFERANCE.all, ref: VARIABLE_REFERANCE.all,
}, },
dynamicVariables: { dynamicVariables: {
ref: VARIABLE_REFERANCE.dynamicVariables, ref: VARIABLE_REFERANCE.dynamicVariables,
}, },
}; };
export const OBJECT_VARIABLE_DISPLAY_NAME = 'Object'; 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 fs from 'fs-extra';
import * as path from 'path'; import * as path from 'path';
import { CONTRACT_JSON_ENCODING } from '../constants/contractJson'; 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 { DebugNetwork } from '../debugNetwork';
import { sortFilePaths } from '../helpers'; import { sortFilePaths } from '../helpers';
import { IContractJsonModel } from '../models/IContractJsonModel'; 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 { DebugAdapterTracker, DebugSession, window } from 'vscode';
import InstructionView from '../instructionsView/instructionView'; import InstructionView from '../instructionsView/instructionView';
@ -6,50 +9,50 @@ import { GET_CURRENT_INSTRUCTION, GET_INSTRUCTIONS } from '../constants/debugSes
import { IInstruction } from '../models/IInstruction'; import { IInstruction } from '../models/IInstruction';
export default class SolidityDebugAdapterTracker implements DebugAdapterTracker { export default class SolidityDebugAdapterTracker implements DebugAdapterTracker {
private session: DebugSession; private session: DebugSession;
private instructionView: InstructionView; private instructionView: InstructionView;
constructor(session: DebugSession) { constructor(session: DebugSession) {
this.session = session; this.session = session;
this.instructionView = new InstructionView(); this.instructionView = new InstructionView();
} }
public onDidSendMessage(message: any): void { public onDidSendMessage(message: any): void {
if (message.success === false) { if (message.success === false) {
window.showErrorMessage('Error occured in debug mode: ' + message.body.error.format); window.showErrorMessage('Error occured in debug mode: ' + message.body.error.format);
return; 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;
}
} }
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() { private requestForInstructions() {
this.session.customRequest(GET_INSTRUCTIONS); this.session.customRequest(GET_INSTRUCTIONS);
} }
private requestForCurrentInstruction() { private requestForCurrentInstruction() {
this.session.customRequest(GET_CURRENT_INSTRUCTION); this.session.customRequest(GET_CURRENT_INSTRUCTION);
} }
private updateInstructionView(instructions: IInstruction[]) { private updateInstructionView(instructions: IInstruction[]) {
this.instructionView.update(instructions); this.instructionView.update(instructions);
} }
private revealInstruction(instruction: IInstruction) { private revealInstruction(instruction: IInstruction) {
this.instructionView.revealInstruction(instruction); this.instructionView.revealInstruction(instruction);
} }
} }

Просмотреть файл

@ -1,13 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { import {
DebugAdapterTracker, DebugAdapterTracker,
DebugAdapterTrackerFactory, DebugAdapterTrackerFactory,
DebugSession, DebugSession,
ProviderResult, ProviderResult,
} from 'vscode'; } from 'vscode';
import SolidityDebugAdapterTracker from './debugAdapterTracker'; import SolidityDebugAdapterTracker from './debugAdapterTracker';
export default class SolidityDebugAdapterTrackerFactory implements DebugAdapterTrackerFactory { export default class SolidityDebugAdapterTrackerFactory implements DebugAdapterTrackerFactory {
public createDebugAdapterTracker(session: DebugSession): ProviderResult<DebugAdapterTracker> { public createDebugAdapterTracker(session: DebugSession): ProviderResult<DebugAdapterTracker> {
return new SolidityDebugAdapterTracker(session); 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 * as path from 'path';
import { executeCommand } from './cmdCommandExecutor'; import { executeCommand } from './cmdCommandExecutor';
import { ConfigurationReader } from './configurationReader'; import { ConfigurationReader } from './configurationReader';
import { TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE, TRUFFLE_CONFIG_NAME } from './constants/truffleConfig'; import { TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE, TRUFFLE_CONFIG_NAME } from './constants/truffleConfig';
export class DebugNetwork { export class DebugNetwork {
public workingDirectory: string; public workingDirectory: string;
private _basedConfig: ConfigurationReader.TruffleConfig | undefined; private _basedConfig: ConfigurationReader.TruffleConfig | undefined;
private _truffleConfiguration: ConfigurationReader.IConfiguration | undefined; private _truffleConfiguration: ConfigurationReader.IConfiguration | undefined;
private _networkForDebug: ConfigurationReader.INetwork | undefined; private _networkForDebug: ConfigurationReader.INetwork | undefined;
constructor(truffleConfigDirectory: string) { constructor(truffleConfigDirectory: string) {
this.workingDirectory = truffleConfigDirectory; this.workingDirectory = truffleConfigDirectory;
} }
public async load(): Promise<void> { public async load(): Promise<void> {
this._basedConfig = this._basedConfig =
new ConfigurationReader.TruffleConfig(path.join(this.workingDirectory, TRUFFLE_CONFIG_NAME)); new ConfigurationReader.TruffleConfig(path.join(this.workingDirectory, TRUFFLE_CONFIG_NAME));
this._truffleConfiguration = this.loadConfiguration(); this._truffleConfiguration = await this.loadConfiguration();
this._networkForDebug = await this.loadNetworkForDebug(); this._networkForDebug = await this.loadNetworkForDebug();
} }
public getTruffleConfiguration() { public getTruffleConfiguration() {
return this._truffleConfiguration; return this._truffleConfiguration;
} }
public getNetwork() { public getNetwork() {
return this._networkForDebug; return this._networkForDebug;
} }
// Port and host are defined // Port and host are defined
public isLocalNetwork() { public isLocalNetwork() {
if (!this._networkForDebug || !this._networkForDebug.options) { if (!this._networkForDebug || !this._networkForDebug.options) {
throw new Error('Network is not defined. Try to call this.load()'); throw new Error('Network is not defined. Try to call this.load()');
}
const options = this._networkForDebug.options;
return !!(options.host && options.port);
} }
const options = this._networkForDebug.options;
return !!(options.host && options.port);
}
private loadConfiguration(): ConfigurationReader.IConfiguration { private async loadConfiguration(): Promise<ConfigurationReader.IConfiguration> {
const configuration = this._basedConfig!.getConfiguration(); const configuration = await this._basedConfig!.getConfiguration(this.workingDirectory);
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 loadNetworkForDebug(): Promise<ConfigurationReader.INetwork> { return {
const networks = this._basedConfig!.getNetworks(); contracts_build_directory: this.relativeToAbsolutePath(configuration.contracts_build_directory),
const networkForDebug = networks contracts_directory: this.relativeToAbsolutePath(configuration.contracts_directory),
.find((n) => n.name === TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE); migrations_directory: this.relativeToAbsolutePath(configuration.migrations_directory),
if (!this.isNetworkForDebugValid(networkForDebug)) { };
const provider = await this.getProviderByResolvingConfig(TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE); }
if (provider.url) {
networkForDebug!.options.provider = { private async loadNetworkForDebug(): Promise<ConfigurationReader.INetwork> {
url: provider.url, const networks = this._basedConfig!.getNetworks();
}; const networkForDebug = networks
} else { .find((n) => n.name === TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
throw new Error(`Truffle config is not properly defined. 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, Please create ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network,
set host+port, or hdwallet/http/websocket provider.`); set host+port, or hdwallet/http/websocket provider.`);
} }
}
return networkForDebug!;
} }
private isNetworkForDebugValid(networkForDebug: ConfigurationReader.INetwork | undefined): boolean { return networkForDebug!;
if (!networkForDebug || !networkForDebug.options) { }
throw new Error(`No ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network in the truffle config`);
}
if (networkForDebug.options.host && networkForDebug.options.port) { private isNetworkForDebugValid(networkForDebug: ConfigurationReader.INetwork | undefined): boolean {
return true; if (!networkForDebug || !networkForDebug.options) {
} throw new Error(`No ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network in the truffle config`);
// truffle-config helper can read only hdwallet provider
const isHdWalletProvider = !!networkForDebug.options.provider;
if (isHdWalletProvider) {
return true;
}
return false;
} }
private async getProviderByResolvingConfig(network: string) { if (networkForDebug.options.host && networkForDebug.options.port) {
// use truffle exec web3ProviderResolver.js to solve http- or websocket- web3 provider return true;
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);
} }
// 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 { IInstruction } from '../models/IInstruction';
import InstructionTreeNode from './instructionTreeNode'; import InstructionTreeNode from './instructionTreeNode';
export default class InstructionDataManager { export default class InstructionDataManager {
private instructionObject: any = {}; private instructionObject: any = {};
public load(instructions: IInstruction[]) { public load(instructions: IInstruction[]) {
this.instructionObject = this.mapInstructionsArrayToObject(instructions); 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[] { const item = this.getItemByPath(element.getPaths());
if (!element) { if (item === undefined) {
return Object.keys(this.instructionObject).map((k) => k); return [];
}
const item = this.getItemByPath(element.getPaths());
if (item === undefined) {
return [];
}
return Object.keys(item);
} }
return Object.keys(item);
}
public getItem(element: InstructionTreeNode): any { public getItem(element: InstructionTreeNode): any {
return this.getItemByPath(element.getPaths()); return this.getItemByPath(element.getPaths());
} }
public getItemParent(element: InstructionTreeNode): any { public getItemParent(element: InstructionTreeNode): any {
return this.getItemByPath(element.getParentPaths()); return this.getItemByPath(element.getParentPaths());
} }
// Map from array to object in order to used in view // 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:''}} // [{pc:1,op: ''},{pc:2,op:''}] ==> { 1:{pc:1,op:''}, 2:{pc:2,op:''}}
private mapInstructionsArrayToObject(steps: IInstruction[]): any { private mapInstructionsArrayToObject(steps: IInstruction[]): any {
const res: any = {}; const res: any = {};
steps.forEach((s) => { steps.forEach((s) => {
res[s.pc] = s; res[s.pc] = s;
}); });
return res; return res;
} }
private getItemByPath(paths: string[]): any { private getItemByPath(paths: string[]): any {
if (paths.length === 0) { if (paths.length === 0) {
return void 0; return void 0;
}
let item = this.instructionObject;
paths.forEach((key) => {
item = item[key];
});
return item;
} }
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 { Event, EventEmitter, ProviderResult, TreeDataProvider, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { IInstruction } from '../models/IInstruction'; import { IInstruction } from '../models/IInstruction';
import InstructionDataManager from './instructionDataManager'; import InstructionDataManager from './instructionDataManager';
import InstructionTreeNode from './instructionTreeNode'; import InstructionTreeNode from './instructionTreeNode';
export default class InstructionDataProvider implements TreeDataProvider<InstructionTreeNode> { export default class InstructionDataProvider implements TreeDataProvider<InstructionTreeNode> {
public _onDidChangeTreeData: EventEmitter<InstructionTreeNode> = new EventEmitter<InstructionTreeNode>(); public _onDidChangeTreeData: EventEmitter<InstructionTreeNode> = new EventEmitter<InstructionTreeNode>();
public readonly onDidChangeTreeData: Event<InstructionTreeNode> = this._onDidChangeTreeData.event; public readonly onDidChangeTreeData: Event<InstructionTreeNode> = this._onDidChangeTreeData.event;
private instructionDataManager: InstructionDataManager; private instructionDataManager: InstructionDataManager;
constructor(instructionDataManager: InstructionDataManager) { constructor(instructionDataManager: InstructionDataManager) {
this.instructionDataManager = instructionDataManager; this.instructionDataManager = instructionDataManager;
} }
public refresh(newInstructions: IInstruction[]) { public refresh(newInstructions: IInstruction[]) {
this.instructionDataManager.load(newInstructions); this.instructionDataManager.load(newInstructions);
this._onDidChangeTreeData.fire(); this._onDidChangeTreeData.fire();
} }
public getChildren(element?: InstructionTreeNode): ProviderResult<InstructionTreeNode[]> { public getChildren(element?: InstructionTreeNode): ProviderResult<InstructionTreeNode[]> {
const items = this.instructionDataManager.getChidren(element); const items = this.instructionDataManager.getChidren(element);
return items.map((e) => new InstructionTreeNode(e, element)); return items.map((e) => new InstructionTreeNode(e, element));
} }
public getTreeItem(element: InstructionTreeNode): TreeItem { public getTreeItem(element: InstructionTreeNode): TreeItem {
const item = this.instructionDataManager.getItem(element); const item = this.instructionDataManager.getItem(element);
const isSpecificObjectValueType = this.isSpecificObjectValueType(item); const isSpecificObjectValueType = this.isSpecificObjectValueType(item);
const collapsibleState = isSpecificObjectValueType const collapsibleState = isSpecificObjectValueType
? TreeItemCollapsibleState.Collapsed ? TreeItemCollapsibleState.Collapsed
: TreeItemCollapsibleState.None; : TreeItemCollapsibleState.None;
return { return {
collapsibleState, collapsibleState,
id: element.getId(), id: element.getId(),
label: this.generateTreeItemLabel(element.getKey(), item, isSpecificObjectValueType), label: this.generateTreeItemLabel(element.getKey(), item, isSpecificObjectValueType),
}; };
} }
public getParent(element: InstructionTreeNode): ProviderResult<InstructionTreeNode> { public getParent(element: InstructionTreeNode): ProviderResult<InstructionTreeNode> {
return element.getParent(); return element.getParent();
} }
private generateTreeItemLabel(treeItemKey: string, treeItemValue: any, isSpecificObjectValueType: boolean) { private generateTreeItemLabel(treeItemKey: string, treeItemValue: any, isSpecificObjectValueType: boolean) {
return isSpecificObjectValueType return isSpecificObjectValueType
? treeItemKey ? treeItemKey
: `${treeItemKey}: ${JSON.stringify(treeItemValue)}`; : `${treeItemKey}: ${JSON.stringify(treeItemValue)}`;
} }
// TODO: refactroign - same method in variablesHandler // TODO: refactroign - same method in variablesHandler
private isSpecificObjectValueType(item: any) { private isSpecificObjectValueType(item: any) {
return !Array.isArray(item) return !Array.isArray(item)
&& item !== null && item !== null
&& item !== undefined && item !== undefined
&& typeof(item) === 'object'; && typeof (item) === 'object';
} }
} }

Просмотреть файл

@ -1,45 +1,48 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { IInstruction } from '../models/IInstruction'; import { IInstruction } from '../models/IInstruction';
export default class InstructionTreeNode { export default class InstructionTreeNode {
private key: string; private key: string;
private path: string; private path: string;
private parent?: InstructionTreeNode; private parent?: InstructionTreeNode;
constructor(key?: string, parent?: InstructionTreeNode, instructionData?: IInstruction) { constructor(key?: string, parent?: InstructionTreeNode, instructionData?: IInstruction) {
if (!key && (!instructionData || (!instructionData.pc && instructionData.pc !== 0))) { if (!key && (!instructionData || (!instructionData.pc && instructionData.pc !== 0))) {
throw new Error('Incorrect input params'); 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);
} }
public getId(): string { const nodeKey = instructionData
return this.path; ? instructionData.pc.toString()
} : (key || '');
this.key = nodeKey;
this.parent = parent;
this.path = this.generatePath(nodeKey, parent);
}
public getKey(): string { public getId(): string {
return this.key; return this.path;
} }
public getParent(): InstructionTreeNode | undefined { public getKey(): string {
return this.parent; return this.key;
} }
public getParentPaths(): string[] { public getParent(): InstructionTreeNode | undefined {
return this.path.split(/\//).slice(1, this.path.length - 1); // not take first empty element and last return this.parent;
} }
public getPaths(): string[] { public getParentPaths(): string[] {
return this.path.split(/\//).slice(1); // not take first empty element return this.path.split(/\//).slice(1, this.path.length - 1); // not take first empty element and last
} }
private generatePath(key: string, parent?: InstructionTreeNode) { public getPaths(): string[] {
const parentPath = parent ? parent.path : ''; return this.path.split(/\//).slice(1); // not take first empty element
return `${parentPath}/${key}`; }
}
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 { TreeView, window } from 'vscode';
import { IInstruction } from '../models/IInstruction'; import { IInstruction } from '../models/IInstruction';
import InstructionDataManager from './instructionDataManager'; import InstructionDataManager from './instructionDataManager';
@ -7,23 +10,23 @@ import InstructionTreeNode from './instructionTreeNode';
const INSTRUCTION_VIEW_ID = 'InstructionView'; const INSTRUCTION_VIEW_ID = 'InstructionView';
export default class InstructionView { export default class InstructionView {
private view: TreeView<InstructionTreeNode>; private view: TreeView<InstructionTreeNode>;
private dataProvider: InstructionDataProvider; private dataProvider: InstructionDataProvider;
constructor() { constructor() {
const dataManager = new InstructionDataManager(); const dataManager = new InstructionDataManager();
this.dataProvider = new InstructionDataProvider(dataManager); this.dataProvider = new InstructionDataProvider(dataManager);
this.view = window.createTreeView(INSTRUCTION_VIEW_ID, this.view = window.createTreeView(INSTRUCTION_VIEW_ID,
{ treeDataProvider: this.dataProvider, showCollapseAll: true }); { treeDataProvider: this.dataProvider, showCollapseAll: true });
} }
public update(newInstructions: IInstruction[]) { public update(newInstructions: IInstruction[]) {
this.dataProvider.refresh(newInstructions); this.dataProvider.refresh(newInstructions);
} }
public revealInstruction(instruction: IInstruction) { public revealInstruction(instruction: IInstruction) {
if (this.view.visible) { if (this.view.visible) {
const treeNode = new InstructionTreeNode(undefined, undefined, instruction); const treeNode = new InstructionTreeNode(undefined, undefined, instruction);
this.view.reveal(treeNode, { focus: true, select: true, expand: true }); 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 { export interface ICallInfo {
column: number; column: number;
file: string; file: string;
line: number; line: number;
method: string; method: string;
} }

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше