This commit is contained in:
Cale Teeter 2020-01-09 20:03:34 -05:00
Родитель 46145a5fdd
Коммит e7a86bd639
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/debugger.js
!out/src/web3ProviderResolver.js
!out/src/checkTruffleConfigTemplate.js
src/**
test/**
.editorconfig

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

@ -2,7 +2,24 @@
All notable changes to the "azure blockchain" extension will be documented in this file.
## 0.1.13
### Enhancements
- Added progress notifications for long running tasks.
- Updated transaction bytecode copy option to support libraries and complex contracts.
- Added the ability to upgrade contracts deployed as part of OpenZeppelin.
- Added the ability for contract build redirects from configuration to be respected.
### Fixes
- Updated requirements for minimum VS Code version to 1.36.1. This was to resolve some issues specific to Mac OS.
- Updated notifications for code generation to be accurate for each type (logic app, flow app, function).
### Internal Improvements
- Test runner enhancements to fix some test issues (timing)
- Updated search tags for SEO
## 0.1.12
@ -20,7 +37,7 @@ All notable changes to the "azure blockchain" extension will be documented in th
- Bumped HD wallet provider to latest Truffle version
- Minimized output channel logs
- Fixed output channel issue which shows JavaScript object after contract migration
- Preview features added for token (TTI compliant) generation were added.
- Preview features added for token (TTI compliant) generation were added.
## 0.1.10
@ -55,14 +72,14 @@ All notable changes to the "azure blockchain" extension will be documented in th
## 0.1.5
- Backend test coverage
- Cleanup of packaging output, optimization
- Truffle installation fails on new installs fix
- Improved support for multiple ganache instances
- Preflight validation for ABS deployments
- Cleanup of code generation output
- Ganache commands cleanup
- Add command to export private key from mnemonic
- Backend test coverage
- Cleanup of packaging output, optimization
- Truffle installation fails on new installs fix
- Improved support for multiple ganache instances
- Preflight validation for ABS deployments
- Cleanup of code generation output
- Ganache commands cleanup
- Add command to export private key from mnemonic
- Better error handling ABS deployments
## 0.1.4
@ -83,7 +100,6 @@ All notable changes to the "azure blockchain" extension will be documented in th
- Updated menu options
## 0.1.0
## 0.1.0
- Initial release

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

@ -15,7 +15,7 @@ Azure Blockchain Development Kit simplifies how you create, connect to, build an
- Supported Operating Systems
- Windows 10
- Mac OSX
- VS Code 1.32.0 (or greater)
- VS Code 1.36.1 (or greater)
- Python 2.7.15
- Node 10.15.x
- Git 2.10.x
@ -30,9 +30,9 @@ The first thing to do is to create an Azure Blockchain Service in your subscript
2. Choose your subscription, resource group and region to deploy to.
4. Enter the name of your [Consortium](https://docs.microsoft.com/azure/blockchain/service/consortium)
3. Enter the name of your [Consortium](https://docs.microsoft.com/azure/blockchain/service/consortium)
5. Wait until your resource has been created in Azure.
4. Wait until your resource has been created in Azure.
`Note: Deploying the Azure Blockchain Service takes quite some time to complete. Please check the deployment status in the Azure portal.`
## Create a new Solidity Contract
@ -55,8 +55,7 @@ For developers who are not familiar with Truffle, or prefer to use the Command P
Once complete, your project directory should look like this:
![completed directory](https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/newProjectDir.png)
[![completed directory](https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/newProjectDirCloseup.png)](https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/newProjectDir.png#lightbox)
## Build your Solidity Contract

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

@ -11,45 +11,47 @@
"lint:fix": "npm run lint -- --fix"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-object-rest-spread": "^7.5.5",
"@babel/plugin-syntax-bigint": "^7.4.4",
"@babel/plugin-transform-runtime": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"@babel/runtime": "^7.5.5",
"babel-eslint": "^10.0.2",
"@babel/core": "^7.7.7",
"@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-proposal-object-rest-spread": "^7.7.7",
"@babel/plugin-syntax-bigint": "^7.7.4",
"@babel/plugin-transform-runtime": "^7.7.6",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@babel/runtime": "^7.7.7",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"cross-env": "^5.2.0",
"css-loader": "^3.1.0",
"eslint": "^6.1.0",
"eslint-config-airbnb": "^17.1.1",
"eslint-loader": "^2.2.1",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^22.14.0",
"cross-env": "^6.0.3",
"css-loader": "^3.4.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-loader": "^3.0.3",
"eslint-plugin-import": "^2.19.1",
"eslint-plugin-jest": "^23.2.0",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.14.3",
"file-loader": "^4.1.0",
"eslint-plugin-react": "^7.17.0",
"eslint-plugin-react-hooks": "^2.3.0",
"file-loader": "^5.0.2",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"less": "^3.9.0",
"less": "^3.10.3",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.8.0",
"mini-css-extract-plugin": "^0.9.0",
"prop-types": "^15.7.2",
"style-loader": "^0.23.1",
"url-loader": "^2.1.0",
"webpack": "^4.38.0",
"webpack-cli": "^3.3.6"
"string-replace-loader": "^2.2.0",
"style-loader": "^1.1.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10"
},
"dependencies": {
"@drizzle/react-components": "^1.5.1",
"@drizzle/react-plugin": "^1.5.1",
"@drizzle/store": "^1.5.1",
"@material-ui/core": "^4.2.1",
"@material-ui/icons": "^4.2.1",
"@truffle/hdwallet-provider": "^1.0.23",
"react": "^16.10.2",
"react-dom": "^16.10.2"
"@material-ui/core": "^4.8.2",
"@material-ui/icons": "^4.5.1",
"@truffle/hdwallet-provider": "^1.0.28",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}

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

@ -1,14 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import BooleanInput from './BooleanInput';
import TextInput from './TextInput';
const InputComponentMapping = {
address: TextInput,
string: TextInput,
uint: TextInput,
bool: BooleanInput,
};
export default InputComponentMapping;

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

@ -1,56 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import PropTypes from 'prop-types';
import React from 'react';
import { TextField } from '@material-ui/core';
class ContractProperty extends React.Component {
constructor(props) {
super(props);
this.state = {
property: {
name: '',
value: '',
},
};
}
componentDidMount() {
this.getPropertyInfo();
}
componentDidUpdate() {
this.getPropertyInfo();
}
getPropertyInfo = () => {
this.props.property.method().call().then(result => {
const property = Object.assign({ name: this.props.property.name, value: result });
if (property.name !== this.state.property.name
|| property.value !== this.state.property.value) {
this.setState({ property });
}
});
}
render() {
const { property } = this.state;
return <TextField
className='metadata text field'
disabled
fullWidth
id='contract-address'
label={property.name}
value={property.value}
/>;
}
}
export default ContractProperty;
ContractProperty.propTypes = {
property: PropTypes.object.isRequired,
};

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

@ -4,10 +4,36 @@
import App from './App';
import { contractEventNotifier } from 'middlewares';
import { DrizzleContext } from '@drizzle/react-plugin';
import { LocalStorage } from 'polyfills/localStorage';
import React from 'react';
import { render } from 'react-dom';
import { Drizzle, generateStore } from '@drizzle/store';
const storage = new LocalStorage();
window.ls = new Proxy(storage, {
set: (_, prop, value) => {
if (LocalStorage.prototype.hasOwnProperty(prop)) {
storage[prop] = value;
} else {
storage.setItem(prop, value);
}
return true;
},
get: (_, name) => {
if (LocalStorage.prototype.hasOwnProperty(name)) {
return storage[name];
}
if (storage.values.has(name)) {
return storage.getItem(name);
}
return undefined;
},
});
Drizzle.prototype.deleteAllContracts = function () {
Object.keys(this.contracts)
.forEach(contractName => this.deleteContract(contractName));

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

@ -1,57 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
const getCommandList = commands => commands
.trim()
.split(' ')
.map(command => command.trim());
const execute = (listeners, command, data) => {
if (listeners.has(command)) {
const handlers = listeners.get(command);
handlers.forEach(handler => handler(data));
}
};
const addToListeners = (listeners, commands, handler) => {
const commandsList = getCommandList(commands);
commandsList.forEach(command => {
if (!listeners.has(command)) {
listeners.set(command, []);
}
const handlers = listeners.get(command);
handlers.push(handler);
});
};
const removeFromListeners = (listeners, commands, handler) => {
const commandsList = getCommandList(commands);
commandsList.forEach(command => {
if (listeners.has(command)) {
if (!handler) {
listeners.delete(command);
return;
}
let handlers = listeners.get(command);
handlers = handlers.filter(element => element !== handler);
listeners.set(command, handlers);
}
});
};
const removeAllListers = (listeners, command) => listeners.delete(command);
export const Helpers = {
execute,
addToListeners,
removeFromListeners,
removeAllListers
};

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

@ -1,39 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Helpers } from './helpers';
// eslint-disable-next-line no-undef
const vscode = acquireVsCodeApi();
const listeners = new Map();
const onceListeners = new Map();
const on = (commands, handler) => Helpers.addToListeners(listeners, commands, handler);
const once = (commands, handler) => Helpers.addToListeners(onceListeners, commands, handler);
const off = (commands, handler) => {
Helpers.removeFromListeners(listeners, commands, handler);
Helpers.removeFromListeners(onceListeners, commands, handler);
};
const postMessage = (command, value) => vscode.postMessage({ command, value });
const messageReceived = (event) => {
const { command, value: data } = event.data;
Helpers.execute(listeners, command, data);
Helpers.execute(onceListeners, command, data);
Helpers.removeAllListers(onceListeners, command);
};
window.addEventListener('message', messageReceived, false);
export const IPCService = {
on,
once,
off,
postMessage
};

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

@ -37,6 +37,7 @@ module.exports = () => {
components: path.join(__dirname, './src/components'),
constants: path.join(__dirname, './src/constants'),
helpers: path.join(__dirname, './src/helpers'),
polyfills: path.join(__dirname, './src/polyfills'),
services: path.join(__dirname, './src/services'),
views: path.join(__dirname, './src/views'),
middlewares: path.join(__dirname, './src/middlewares'),
@ -69,6 +70,19 @@ module.exports = () => {
test: [/\.js$/, /\.jsx$/],
exclude: /node_modules/,
loader: 'eslint-loader'
},
{
test: /\.js$/,
loader: 'string-replace-loader',
options: {
search: 'localStorage',
replace: 'ls',
flags: 'g'
},
exclude: path.join(__dirname, 'src', 'index.js'),
include: [
path.resolve(__dirname, 'node_modules')
]
}
]
},

Двоичные данные
images/createConsortium.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 94 KiB

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

@ -5,7 +5,7 @@
"publisher": "AzBlockchain",
"preview": true,
"icon": "images/blockchain-service-logo.png",
"version": "0.1.12",
"version": "0.1.13",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum"
@ -16,12 +16,13 @@
"homepage": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum/blob/master/README.md",
"license": "MIT",
"engines": {
"vscode": "^1.32.0"
"vscode": "^1.36.1"
},
"keywords": [
"azure",
"blockchain",
"azure",
"ethereum",
"debuggers",
"snippet"
],
"categories": [
@ -59,6 +60,21 @@
"onDebug"
],
"contributes": {
"configuration": {
"title": "Azure Blockchain Development Kit for Ethereum",
"properties": {
"azureBlockchainService.ignoreLongRunningTaskNotification": {
"type": "boolean",
"default": false,
"description": "Disable notification on long running tasks."
},
"azureBlockchainService.openZeppelin.version": {
"type": "string",
"default": "2.4.0",
"scope": "The latest Open Zeppelin version"
}
}
},
"commands": [
{
"command": "azureBlockchainService.generateMicroservicesWorkflows",
@ -498,7 +514,7 @@
"@types/semver": "^6.0.0",
"@types/sinon": "^7.0.11",
"@types/uuid": "^3.4.4",
"@types/vscode": "^1.32.0",
"@types/vscode": "^1.36.1",
"copy-webpack-plugin": "^5.0.3",
"decache": "^4.5.1",
"glob": "^7.1.4",

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

@ -1,83 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#7FBA00" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
C19.11,0.138,18.823,0,18.519,0z"/>
<path opacity="0.15" d="M5,6.056C5,5.473,5.473,5,6.056,5h16.877c-0.037-0.098-0.086-0.191-0.152-0.274L19.3,0.375
C19.11,0.138,18.823,0,18.519,0H1C0.448,0,0,0.448,0,1v15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
c0.083,0.099,0.189,0.171,0.3,0.231V6.056z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<path fill="#68217A" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
C46.11,27.138,45.823,27,45.519,27z"/>
<path fill="#804998" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
C50,32.448,49.552,32,49,32z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
<path opacity="0.4" fill="#FFFFFF" d="M32,32.375c-0.096,0-0.192-0.036-0.266-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C32.192,32.339,32.096,32.375,32,32.375z"/>
<path fill="#DD5900" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
C46.11,0.138,45.823,0,45.519,0z"/>
<path opacity="0.2" fill="#FFFFFF" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6
C50,5.448,49.552,5,49,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
<path opacity="0.4" fill="#FFFFFF" d="M32,5.375c-0.096,0-0.192-0.037-0.266-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C32.192,5.338,32.096,5.375,32,5.375z"/>
<rect x="40" y="18" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
<g>
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
</g>
</g>
<path fill="#0072C6" d="M18.519,27H1c-0.552,0-1,0.448-1,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,49.64
C4.89,49.868,5.172,50,5.468,50H22c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L19.3,27.375
C19.11,27.138,18.823,27,18.519,27z"/>
<path fill="#3999C6" d="M22,32H6c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33C23,32.448,22.552,32,22,32
z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,50H6c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L9.5,50z"/>
<g>
<circle fill="#00188F" cx="14" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,37.1,14,37.1 M14,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,36.1,14,36.1L14,36.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
</g>
</g>
<path opacity="0.4" fill="#FFFFFF" d="M5,5.375c-0.096,0-0.192-0.037-0.265-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C5.192,5.338,5.096,5.375,5,5.375z"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
<path opacity="0.4" fill="#FFFFFF" d="M14,31c-1.103,0-2-0.897-2-2v-2h4v2C16,30.103,15.103,31,14,31z"/>
<path fill="#00188F" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,41c0,1.103-0.897,2-2,2h-2v-4h2C30.103,39,31,39.897,31,41z"/>
<path fill="#00188F" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
<path opacity="0.5" fill="#0072C6" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.5" fill="#0072C6" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
<path opacity="0.5" fill="#0072C6" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
<path opacity="0.5" fill="#0072C6" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
<rect x="32" y="40" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<rect x="13" y="32" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
<path opacity="0.4" fill="#FFFFFF" d="M5,32.375c-0.096,0-0.192-0.036-0.265-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C5.192,32.339,5.096,32.375,5,32.375z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 6.0 KiB

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

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#0072C6" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
C19.11,0.138,18.823,0,18.519,0z"/>
<path fill="#3999C6" d="M22,5H6C5.448,5,5,5.448,5,6v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C23,5.448,22.552,5,22,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<path fill="#0072C6" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
C46.11,27.138,45.823,27,45.519,27z"/>
<path fill="#3999C6" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
C50,32.448,49.552,32,49,32z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="27.5" x2="32" y2="32"/>
<path fill="#0072C6" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
C46.11,0.138,45.823,0,45.519,0z"/>
<path fill="#3999C6" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C50,5.448,49.552,5,49,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="0.5" x2="32" y2="5"/>
<line opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="41" y1="23" x2="41" y2="18"/>
<g>
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
</g>
</g>
<g>
<g>
<g>
<path fill="#00188F" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
</g>
</g>
</g>
<g opacity="0.5">
<path fill="#0072C6" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
</g>
<path opacity="0.2" fill="#FFFFFF" d="M7.141,45.315l-0.114,2.307l3.742-6.05c-0.732-0.45-1.338-1.118-1.691-1.974
c-0.885-2.152,0.142-4.607,2.298-5.491c1.299-0.532,2.702-0.362,3.811,0.321l3.741-6.049l0.065-1.3L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.231,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231L7.141,45.315z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="0.5" y1="0.5" x2="5" y2="5"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 5.7 KiB

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

@ -1,5 +0,0 @@
<svg width="32" height="36" viewBox="0 0 32 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 10L15 18.5V35.5L0 27V10Z" fill="white"/>
<path d="M32 10L17 18.5V35.5L32 27V10Z" fill="white"/>
<path d="M7.42857 4.95833L16 0L23.8571 4.25L31 8.5L16 17L1 8.5L7.42857 4.95833Z" fill="white"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 313 B

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

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#0072C6" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
C19.11,0.138,18.823,0,18.519,0z"/>
<path fill="#3999C6" d="M22,5H6C5.448,5,5,5.448,5,6v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C23,5.448,22.552,5,22,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<path fill="#0072C6" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
C46.11,27.138,45.823,27,45.519,27z"/>
<path fill="#3999C6" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
C50,32.448,49.552,32,49,32z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="27.5" x2="32" y2="32"/>
<path fill="#0072C6" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
C46.11,0.138,45.823,0,45.519,0z"/>
<path fill="#3999C6" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C50,5.448,49.552,5,49,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="0.5" x2="32" y2="5"/>
<line opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="41" y1="23" x2="41" y2="18"/>
<g>
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
</g>
</g>
<g>
<g>
<g>
<path fill="#00188F" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
</g>
</g>
</g>
<g opacity="0.5">
<path fill="#0072C6" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
</g>
<path opacity="0.2" fill="#FFFFFF" d="M7.141,45.315l-0.114,2.307l3.742-6.05c-0.732-0.45-1.338-1.118-1.691-1.974
c-0.885-2.152,0.142-4.607,2.298-5.491c1.299-0.532,2.702-0.362,3.811,0.321l3.741-6.049l0.065-1.3L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.231,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231L7.141,45.315z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="0.5" y1="0.5" x2="5" y2="5"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 5.7 KiB

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

@ -1,83 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#7FBA00" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
C19.11,0.138,18.823,0,18.519,0z"/>
<path opacity="0.15" d="M5,6.056C5,5.473,5.473,5,6.056,5h16.877c-0.037-0.098-0.086-0.191-0.152-0.274L19.3,0.375
C19.11,0.138,18.823,0,18.519,0H1C0.448,0,0,0.448,0,1v15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
c0.083,0.099,0.189,0.171,0.3,0.231V6.056z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<path fill="#68217A" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
C46.11,27.138,45.823,27,45.519,27z"/>
<path fill="#804998" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
C50,32.448,49.552,32,49,32z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
<path opacity="0.4" fill="#FFFFFF" d="M32,32.375c-0.096,0-0.192-0.036-0.266-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C32.192,32.339,32.096,32.375,32,32.375z"/>
<path fill="#DD5900" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
C46.11,0.138,45.823,0,45.519,0z"/>
<path opacity="0.2" fill="#FFFFFF" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6
C50,5.448,49.552,5,49,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
<path opacity="0.4" fill="#FFFFFF" d="M32,5.375c-0.096,0-0.192-0.037-0.266-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C32.192,5.338,32.096,5.375,32,5.375z"/>
<rect x="40" y="18" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
<g>
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
</g>
</g>
<path fill="#0072C6" d="M18.519,27H1c-0.552,0-1,0.448-1,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,49.64
C4.89,49.868,5.172,50,5.468,50H22c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L19.3,27.375
C19.11,27.138,18.823,27,18.519,27z"/>
<path fill="#3999C6" d="M22,32H6c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33C23,32.448,22.552,32,22,32
z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,50H6c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L9.5,50z"/>
<g>
<circle fill="#00188F" cx="14" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,37.1,14,37.1 M14,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,36.1,14,36.1L14,36.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
</g>
</g>
<path opacity="0.4" fill="#FFFFFF" d="M5,5.375c-0.096,0-0.192-0.037-0.265-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C5.192,5.338,5.096,5.375,5,5.375z"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
<path opacity="0.4" fill="#FFFFFF" d="M14,31c-1.103,0-2-0.897-2-2v-2h4v2C16,30.103,15.103,31,14,31z"/>
<path fill="#00188F" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,41c0,1.103-0.897,2-2,2h-2v-4h2C30.103,39,31,39.897,31,41z"/>
<path fill="#00188F" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
<path opacity="0.5" fill="#0072C6" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.5" fill="#0072C6" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
<path opacity="0.5" fill="#0072C6" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
<path opacity="0.5" fill="#0072C6" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
<rect x="32" y="40" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<rect x="13" y="32" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
<path opacity="0.4" fill="#FFFFFF" d="M5,32.375c-0.096,0-0.192-0.036-0.265-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C5.192,32.339,5.096,32.375,5,32.375z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 6.0 KiB

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

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#0072C6" d="M38.428,3H4.913C3.856,3,3,3.856,3,4.913v29.916c0,0.448,0.157,0.881,0.443,1.225l8.548,10.258
C12.355,46.748,12.893,47,13.461,47h31.626C46.144,47,47,46.144,47,45.087V13.236c0-0.434-0.148-0.856-0.419-1.195l-6.659-8.323
C39.559,3.264,39.01,3,38.428,3z"/>
<path fill="#3999C6" d="M45.111,13H14.889C13.846,13,13,13.846,13,14.889v30.222C13,46.154,13.846,47,14.889,47h30.222
C46.154,47,47,46.154,47,45.111V14.889C47,13.846,46.154,13,45.111,13z"/>
<path opacity="0.25" fill="#FFFFFF" d="M21.5,47h-6.611C13.846,47,13,46.154,13,45.111V14.889C13,13.846,13.846,13,14.889,13H40.2
L21.5,47z"/>
<g>
<circle fill="#00188F" cx="29.783" cy="29.783" r="6.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M29.783,22.883c3.804,0,6.9,3.096,6.9,6.9s-3.096,6.9-6.9,6.9s-6.9-3.096-6.9-6.9
S25.978,22.883,29.783,22.883 M29.783,21.383c-4.632,0-8.4,3.768-8.4,8.4s3.768,8.4,8.4,8.4s8.4-3.768,8.4-8.4
S34.414,21.383,29.783,21.383L29.783,21.383z"/>
</g>
</g>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="4.5" y1="4.5" x2="13" y2="13"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.5 KiB

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

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<polygon fill="#804998" points="45.946,26.164 44.054,23.836 29.698,35.5 23.488,20.332 21.089,19.709 4.089,32.709 5.911,35.091
21.43,23.224 27.712,38.568 29.911,39.192 29.907,39.116 29.946,39.164 "/>
<g>
<circle fill="#00188F" cx="5" cy="33.9" r="4.9"/>
</g>
<g>
<circle fill="#00188F" cx="22" cy="20.9" r="4.9"/>
</g>
<g>
<circle fill="#00188F" cx="29" cy="38" r="4.9"/>
</g>
<g>
<circle fill="#00188F" cx="45" cy="25" r="4.9"/>
</g>
<g opacity="0.5">
<circle fill="#0072C6" cx="5" cy="33.9" r="4.9"/>
</g>
<g opacity="0.5">
<circle fill="#0072C6" cx="22" cy="20.9" r="4.9"/>
</g>
<g opacity="0.5">
<circle fill="#0072C6" cx="29" cy="38" r="4.9"/>
</g>
<g opacity="0.5">
<circle fill="#0072C6" cx="45" cy="25" r="4.9"/>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.1 KiB

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

@ -1,83 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#7FBA00" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
C19.11,0.138,18.823,0,18.519,0z"/>
<path opacity="0.15" d="M5,6.056C5,5.473,5.473,5,6.056,5h16.877c-0.037-0.098-0.086-0.191-0.152-0.274L19.3,0.375
C19.11,0.138,18.823,0,18.519,0H1C0.448,0,0,0.448,0,1v15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
c0.083,0.099,0.189,0.171,0.3,0.231V6.056z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<path fill="#68217A" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
C46.11,27.138,45.823,27,45.519,27z"/>
<path fill="#804998" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
C50,32.448,49.552,32,49,32z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
<path opacity="0.4" fill="#FFFFFF" d="M32,32.375c-0.096,0-0.192-0.036-0.266-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C32.192,32.339,32.096,32.375,32,32.375z"/>
<path fill="#DD5900" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
C46.11,0.138,45.823,0,45.519,0z"/>
<path opacity="0.2" fill="#FFFFFF" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6
C50,5.448,49.552,5,49,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
<path opacity="0.4" fill="#FFFFFF" d="M32,5.375c-0.096,0-0.192-0.037-0.266-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C32.192,5.338,32.096,5.375,32,5.375z"/>
<rect x="40" y="18" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
<g>
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
</g>
</g>
<path fill="#0072C6" d="M18.519,27H1c-0.552,0-1,0.448-1,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,49.64
C4.89,49.868,5.172,50,5.468,50H22c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L19.3,27.375
C19.11,27.138,18.823,27,18.519,27z"/>
<path fill="#3999C6" d="M22,32H6c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33C23,32.448,22.552,32,22,32
z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,50H6c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L9.5,50z"/>
<g>
<circle fill="#00188F" cx="14" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,37.1,14,37.1 M14,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,36.1,14,36.1L14,36.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
</g>
</g>
<path opacity="0.4" fill="#FFFFFF" d="M5,5.375c-0.096,0-0.192-0.037-0.265-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C5.192,5.338,5.096,5.375,5,5.375z"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
<path opacity="0.4" fill="#FFFFFF" d="M14,31c-1.103,0-2-0.897-2-2v-2h4v2C16,30.103,15.103,31,14,31z"/>
<path fill="#00188F" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,41c0,1.103-0.897,2-2,2h-2v-4h2C30.103,39,31,39.897,31,41z"/>
<path fill="#00188F" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
<path opacity="0.5" fill="#0072C6" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.5" fill="#0072C6" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
<path opacity="0.5" fill="#0072C6" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
<path opacity="0.5" fill="#0072C6" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
<rect x="32" y="40" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<rect x="13" y="32" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
<path opacity="0.4" fill="#FFFFFF" d="M5,32.375c-0.096,0-0.192-0.036-0.265-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C5.192,32.339,5.096,32.375,5,32.375z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 6.0 KiB

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

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#0072C6" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
C19.11,0.138,18.823,0,18.519,0z"/>
<path fill="#3999C6" d="M22,5H6C5.448,5,5,5.448,5,6v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C23,5.448,22.552,5,22,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<path fill="#0072C6" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
C46.11,27.138,45.823,27,45.519,27z"/>
<path fill="#3999C6" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
C50,32.448,49.552,32,49,32z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="27.5" x2="32" y2="32"/>
<path fill="#0072C6" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
C46.11,0.138,45.823,0,45.519,0z"/>
<path fill="#3999C6" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C50,5.448,49.552,5,49,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="0.5" x2="32" y2="5"/>
<line opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="41" y1="23" x2="41" y2="18"/>
<g>
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
</g>
</g>
<g>
<g>
<g>
<path fill="#00188F" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
</g>
</g>
</g>
<g opacity="0.5">
<path fill="#0072C6" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
</g>
<path opacity="0.2" fill="#FFFFFF" d="M7.141,45.315l-0.114,2.307l3.742-6.05c-0.732-0.45-1.338-1.118-1.691-1.974
c-0.885-2.152,0.142-4.607,2.298-5.491c1.299-0.532,2.702-0.362,3.811,0.321l3.741-6.049l0.065-1.3L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.231,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231L7.141,45.315z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="0.5" y1="0.5" x2="5" y2="5"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 5.7 KiB

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

@ -1,5 +0,0 @@
<svg width="32" height="36" viewBox="0 0 32 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 10L15 18.5V35.5L0 27V10Z" fill="black"/>
<path d="M32 10L17 18.5V35.5L32 27V10Z" fill="black"/>
<path d="M7.42857 4.95833L16 0L23.8571 4.25L31 8.5L16 17L1 8.5L7.42857 4.95833Z" fill="black"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 313 B

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

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#0072C6" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
C19.11,0.138,18.823,0,18.519,0z"/>
<path fill="#3999C6" d="M22,5H6C5.448,5,5,5.448,5,6v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C23,5.448,22.552,5,22,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<path fill="#0072C6" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
C46.11,27.138,45.823,27,45.519,27z"/>
<path fill="#3999C6" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
C50,32.448,49.552,32,49,32z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="27.5" x2="32" y2="32"/>
<path fill="#0072C6" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
C46.11,0.138,45.823,0,45.519,0z"/>
<path fill="#3999C6" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6C50,5.448,49.552,5,49,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="27.5" y1="0.5" x2="32" y2="5"/>
<line opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="41" y1="23" x2="41" y2="18"/>
<g>
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
</g>
</g>
<g>
<g>
<g>
<path fill="#00188F" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
</g>
</g>
</g>
<g opacity="0.5">
<path fill="#0072C6" d="M24.956,34.536l-1.074-2.61l-0.424,0.013l-3.175,0.231l-1.469-1.485l0.179-3.605L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.232,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231l1.469,1.485L6.962,48.92L9.551,50l0.292-0.334l2.069-2.4
l2.091-0.001l2.447,2.69l2.615-1.072l-0.013-0.423l-0.232-3.169l1.488-1.466l3.612,0.179L25,41.421l-0.334-0.291l-2.404-2.065
l-0.001-2.087L24.956,34.536z M14.579,41.892c-2.156,0.884-4.615-0.142-5.501-2.294c-0.885-2.152,0.142-4.607,2.298-5.491
s4.615,0.142,5.501,2.294C17.763,38.554,16.735,41.009,14.579,41.892z"/>
</g>
<path opacity="0.2" fill="#FFFFFF" d="M7.141,45.315l-0.114,2.307l3.742-6.05c-0.732-0.45-1.338-1.118-1.691-1.974
c-0.885-2.152,0.142-4.607,2.298-5.491c1.299-0.532,2.702-0.362,3.811,0.321l3.741-6.049l0.065-1.3L16.405,26l-0.292,0.334
l-2.069,2.4l-2.091,0.001l-2.447-2.69l-2.615,1.072l0.013,0.423l0.231,3.169l-1.488,1.466l-3.566-0.197L1.002,34.56l0.334,0.291
l2.404,2.065l0.001,2.087L1,41.464l1.074,2.61l0.424-0.013l3.175-0.231L7.141,45.315z"/>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="0.5" stroke-linecap="round" stroke-miterlimit="10" x1="0.5" y1="0.5" x2="5" y2="5"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 5.7 KiB

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

@ -1,83 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#7FBA00" d="M18.519,0L1,0C0.448,0,0,0.448,0,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
C4.89,22.868,5.172,23,5.468,23H22c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L19.3,0.375
C19.11,0.138,18.823,0,18.519,0z"/>
<path opacity="0.15" d="M5,6.056C5,5.473,5.473,5,6.056,5h16.877c-0.037-0.098-0.086-0.191-0.152-0.274L19.3,0.375
C19.11,0.138,18.823,0,18.519,0H1C0.448,0,0,0.448,0,1v15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,22.64
c0.083,0.099,0.189,0.171,0.3,0.231V6.056z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,23H6c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L9.5,23z"/>
<rect x="40" y="23" fill="#00188F" width="2" height="14"/>
<rect x="18" y="13" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<path fill="#68217A" d="M45.519,27H28c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,49.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L46.3,27.375
C46.11,27.138,45.823,27,45.519,27z"/>
<path fill="#804998" d="M49,32H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33
C50,32.448,49.552,32,49,32z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,50H33c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L36.5,50z"/>
<path opacity="0.4" fill="#FFFFFF" d="M32,32.375c-0.096,0-0.192-0.036-0.266-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C32.192,32.339,32.096,32.375,32,32.375z"/>
<path fill="#DD5900" d="M45.519,0L28,0c-0.552,0-1,0.448-1,1v15.638c0,0.234,0.082,0.46,0.232,0.64L31.7,22.64
c0.19,0.228,0.471,0.36,0.768,0.36H49c0.552,0,1-0.448,1-1V5.351c0-0.227-0.077-0.447-0.219-0.625L46.3,0.375
C46.11,0.138,45.823,0,45.519,0z"/>
<path opacity="0.2" fill="#FFFFFF" d="M49,5H33c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V6
C50,5.448,49.552,5,49,5z"/>
<path opacity="0.25" fill="#FFFFFF" d="M36.5,23H33c-0.552,0-1-0.448-1-1V6c0-0.552,0.448-1,1-1h13.4L36.5,23z"/>
<path opacity="0.4" fill="#FFFFFF" d="M32,5.375c-0.096,0-0.192-0.037-0.266-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
c0.146-0.146,0.385-0.146,0.531,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C32.192,5.338,32.096,5.375,32,5.375z"/>
<rect x="40" y="18" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
<g>
<circle fill="#00188F" cx="41" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,10.1,41,10.1 M41,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,9.1,41,9.1L41,9.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="41" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M41,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S38.85,37.1,41,37.1 M41,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S43.702,36.1,41,36.1L41,36.1z"/>
</g>
</g>
<path fill="#0072C6" d="M18.519,27H1c-0.552,0-1,0.448-1,1l0,15.638c0,0.234,0.082,0.46,0.232,0.64L4.7,49.64
C4.89,49.868,5.172,50,5.468,50H22c0.552,0,1-0.448,1-1V32.351c0-0.227-0.077-0.447-0.219-0.625L19.3,27.375
C19.11,27.138,18.823,27,18.519,27z"/>
<path fill="#3999C6" d="M22,32H6c-0.552,0-1,0.448-1,1v16c0,0.552,0.448,1,1,1h16c0.552,0,1-0.448,1-1V33C23,32.448,22.552,32,22,32
z"/>
<path opacity="0.25" fill="#FFFFFF" d="M9.5,50H6c-0.552,0-1-0.448-1-1V33c0-0.552,0.448-1,1-1h13.4L9.5,50z"/>
<g>
<circle fill="#00188F" cx="14" cy="41" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,37.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,37.1,14,37.1 M14,36.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,36.1,14,36.1L14,36.1z"/>
</g>
</g>
<g>
<circle fill="#00188F" cx="14" cy="14" r="3.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M14,10.1c2.15,0,3.9,1.75,3.9,3.9s-1.75,3.9-3.9,3.9s-3.9-1.75-3.9-3.9S11.85,10.1,14,10.1 M14,9.1
c-2.702,0-4.9,2.198-4.9,4.9s2.198,4.9,4.9,4.9s4.9-2.198,4.9-4.9S16.702,9.1,14,9.1L14,9.1z"/>
</g>
</g>
<path opacity="0.4" fill="#FFFFFF" d="M5,5.375c-0.096,0-0.192-0.037-0.265-0.11l-4.5-4.5c-0.146-0.146-0.146-0.384,0-0.53
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.384,0,0.53C5.192,5.338,5.096,5.375,5,5.375z"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,14c0,1.103-0.897,2-2,2h-2v-4h2C30.103,12,31,12.897,31,14z"/>
<path fill="#00188F" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M41,31c-1.103,0-2-0.897-2-2v-2h4v2C43,30.103,42.103,31,41,31z"/>
<path fill="#00188F" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
<path opacity="0.4" fill="#FFFFFF" d="M14,31c-1.103,0-2-0.897-2-2v-2h4v2C16,30.103,15.103,31,14,31z"/>
<path fill="#00188F" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
<path opacity="0.4" fill="#FFFFFF" d="M31,41c0,1.103-0.897,2-2,2h-2v-4h2C30.103,39,31,39.897,31,41z"/>
<path fill="#00188F" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
<path opacity="0.5" fill="#0072C6" d="M29,13h-6v2h6c0.552,0,1-0.448,1-1C30,13.448,29.552,13,29,13z"/>
<path opacity="0.5" fill="#0072C6" d="M40,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H40z"/>
<path opacity="0.5" fill="#0072C6" d="M13,23v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6H13z"/>
<path opacity="0.5" fill="#0072C6" d="M23,42h6c0.552,0,1-0.448,1-1s-0.448-1-1-1h-6V42z"/>
<rect x="32" y="40" opacity="0.6" fill="#FFFFFF" width="5" height="2"/>
<rect x="13" y="32" opacity="0.6" fill="#FFFFFF" width="2" height="5"/>
<path opacity="0.4" fill="#FFFFFF" d="M5,32.375c-0.096,0-0.192-0.036-0.265-0.109l-4.5-4.5c-0.146-0.146-0.146-0.385,0-0.531
s0.384-0.146,0.53,0l4.5,4.5c0.146,0.146,0.146,0.385,0,0.531C5.192,32.339,5.096,32.375,5,32.375z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 6.0 KiB

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

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<path fill="#0072C6" d="M38.428,3H4.913C3.856,3,3,3.856,3,4.913v29.916c0,0.448,0.157,0.881,0.443,1.225l8.548,10.258
C12.355,46.748,12.893,47,13.461,47h31.626C46.144,47,47,46.144,47,45.087V13.236c0-0.434-0.148-0.856-0.419-1.195l-6.659-8.323
C39.559,3.264,39.01,3,38.428,3z"/>
<path fill="#3999C6" d="M45.111,13H14.889C13.846,13,13,13.846,13,14.889v30.222C13,46.154,13.846,47,14.889,47h30.222
C46.154,47,47,46.154,47,45.111V14.889C47,13.846,46.154,13,45.111,13z"/>
<path opacity="0.25" fill="#FFFFFF" d="M21.5,47h-6.611C13.846,47,13,46.154,13,45.111V14.889C13,13.846,13.846,13,14.889,13H40.2
L21.5,47z"/>
<g>
<circle fill="#00188F" cx="29.783" cy="29.783" r="6.9"/>
<g opacity="0.8">
<path fill="#FFFFFF" d="M29.783,22.883c3.804,0,6.9,3.096,6.9,6.9s-3.096,6.9-6.9,6.9s-6.9-3.096-6.9-6.9
S25.978,22.883,29.783,22.883 M29.783,21.383c-4.632,0-8.4,3.768-8.4,8.4s3.768,8.4,8.4,8.4s8.4-3.768,8.4-8.4
S34.414,21.383,29.783,21.383L29.783,21.383z"/>
</g>
</g>
<line opacity="0.4" fill="none" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round" stroke-miterlimit="10" x1="4.5" y1="4.5" x2="13" y2="13"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.5 KiB

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

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<polygon fill="#804998" points="45.946,26.164 44.054,23.836 29.698,35.5 23.488,20.332 21.089,19.709 4.089,32.709 5.911,35.091
21.43,23.224 27.712,38.568 29.911,39.192 29.907,39.116 29.946,39.164 "/>
<g>
<circle fill="#00188F" cx="5" cy="33.9" r="4.9"/>
</g>
<g>
<circle fill="#00188F" cx="22" cy="20.9" r="4.9"/>
</g>
<g>
<circle fill="#00188F" cx="29" cy="38" r="4.9"/>
</g>
<g>
<circle fill="#00188F" cx="45" cy="25" r="4.9"/>
</g>
<g opacity="0.5">
<circle fill="#0072C6" cx="5" cy="33.9" r="4.9"/>
</g>
<g opacity="0.5">
<circle fill="#0072C6" cx="22" cy="20.9" r="4.9"/>
</g>
<g opacity="0.5">
<circle fill="#0072C6" cx="29" cy="38" r="4.9"/>
</g>
<g opacity="0.5">
<circle fill="#0072C6" cx="45" cy="25" r="4.9"/>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.1 KiB

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

@ -1,260 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ProgressLocation, QuickPickItem, window } from 'vscode';
import { AzureBlockchainServiceClient, IAzureMemberDto, ICreateQuorumMember, ISkuDto } from './ARMBlockchain';
import { Constants } from './Constants';
import { showInputBox, showQuickPick } from './helpers';
import {
AzureConsortium,
LocationItem,
Member,
ResourceGroupItem,
SkuItem,
SubscriptionItem,
TransactionNode,
} from './Models';
import { ConsortiumItem } from './Models/ConsortiumItem';
import { ResourceExplorerAndGenerator } from './ResourceExplorerAndGenerator';
import { Telemetry } from './TelemetryClient';
import { AzureBlockchainServiceValidator } from './validators/AzureBlockchainServiceValidator';
export class ConsortiumResourceExplorer extends ResourceExplorerAndGenerator {
public async selectOrCreateConsortium(childrenFilters?: string[]): Promise<AzureConsortium> {
await this.waitForLogin();
const subscriptionItem = await this.getOrSelectSubscriptionItem();
const resourceGroupItem = await this.getOrCreateResourceGroupItem(subscriptionItem);
return this.getOrCreateConsortiumItem(subscriptionItem, resourceGroupItem, childrenFilters);
}
public async getAccessKeys(consortium: AzureConsortium): Promise<string[]> {
await this.waitForLogin();
await this._accountApi.waitForFilters();
const subscriptionId = consortium.getSubscriptionId();
const resourceGroup = consortium.getResourceGroup();
const subscription = this._accountApi.filters
.find((filter) => filter.subscription.subscriptionId === subscriptionId);
if (!subscription) {
const error = new Error(Constants.errorMessageStrings.NoSubscriptionFoundClick);
Telemetry.sendException(error);
throw error;
}
const azureClient = await this.getAzureClient(
new SubscriptionItem(consortium.label, subscriptionId, subscription.session),
new ResourceGroupItem(resourceGroup),
);
const accessKeys = await azureClient.memberResource.getMemberAccessKeys(consortium.getMemberName());
return accessKeys.keys.map((key) => key.value);
}
private async getAzureClient(subscriptionItem: SubscriptionItem, resourceGroupItem: ResourceGroupItem)
: Promise<AzureBlockchainServiceClient> {
return new AzureBlockchainServiceClient(
subscriptionItem.session.credentials,
subscriptionItem.subscriptionId,
resourceGroupItem.label,
resourceGroupItem.description,
Constants.azureResourceExplorer.requestBaseUri,
Constants.azureResourceExplorer.requestApiVersion,
{
acceptLanguage: Constants.azureResourceExplorer.requestAcceptLanguage,
filters: [],
generateClientRequestId: true,
longRunningOperationRetryTimeout: 30,
noRetryPolicy: false,
requestOptions: {
customHeaders: {},
},
rpRegistrationRetryTimeout: 30,
},
);
}
private async getOrCreateConsortiumItem(
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
excludedItems?: string[],
): Promise<AzureConsortium> {
const pick = await showQuickPick(
this.getConsortiumItems(subscriptionItem, resourceGroupItem, excludedItems),
{ placeHolder: Constants.placeholders.selectConsortium, ignoreFocusOut: true });
if (pick instanceof ConsortiumItem) {
Telemetry.sendEvent('ConsortiumResourceExplorer.getOrCreateConsortiumItem.consortiumItemIsSelected');
return this.getAzureConsortium(pick, subscriptionItem, resourceGroupItem);
} else {
Telemetry.sendEvent('ConsortiumResourceExplorer.getOrCreateConsortiumItem.createConsortiumItemIsSelected');
return this.createAzureConsortium(subscriptionItem, resourceGroupItem);
}
}
private async getConsortiumItems(
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
excludedItems?: string[],
): Promise<QuickPickItem[]> {
const items: QuickPickItem[] = [];
const createConsortiumItem: QuickPickItem = { label: '$(plus) Create Consortium' };
const consortiumItems = await this.loadConsortiumItems(subscriptionItem, resourceGroupItem, excludedItems);
items.push(createConsortiumItem, ...consortiumItems);
return items;
}
private async loadConsortiumItems(
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
excludedItems: string[] = [],
): Promise<ConsortiumItem[]> {
const azureClient = await this.getAzureClient(subscriptionItem, resourceGroupItem);
const members: IAzureMemberDto[] = await azureClient.memberResource.getListMember();
return members
.map((member) => new ConsortiumItem(
member.properties.consortium,
subscriptionItem.subscriptionId,
resourceGroupItem.label,
member.name,
member.properties.dns,
))
.filter((item) => !excludedItems.includes(item.label))
.sort((a, b) => a.label.localeCompare(b.label));
}
private async getAzureConsortium(
consortiumItems: ConsortiumItem,
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
): Promise<AzureConsortium> {
const azureClient = await this.getAzureClient(subscriptionItem, resourceGroupItem);
const transactionNodes = await azureClient
.transactionNodeResource
.getListTransactionNode(consortiumItems.memberName);
const memberItem = new Member(consortiumItems.memberName);
const azureConsortium = new AzureConsortium(
consortiumItems.consortiumName,
consortiumItems.subscriptionId,
consortiumItems.resourcesGroup,
consortiumItems.memberName,
consortiumItems.url,
);
await azureConsortium.setChildren([
memberItem,
...transactionNodes.map((transactionNode) => {
return new TransactionNode(transactionNode.name, transactionNode.properties.dns);
}),
]);
return azureConsortium;
}
private async getSkus(
client: AzureBlockchainServiceClient,
location: LocationItem)
: Promise<SkuItem[]> {
const skus: ISkuDto[] = await client.skuResource.getListSkus();
const skuItems: SkuItem[] = [];
for (const sku of skus) {
if (sku.locations.find((element) => element.toLowerCase() === location.description.toLowerCase())) {
skuItems.push(new SkuItem(sku.tier, sku.name));
}
}
return skuItems;
}
private async createAzureConsortium(subscriptionItem: SubscriptionItem, resourceGroupItem: ResourceGroupItem)
: Promise<AzureConsortium> {
const azureClient = await this.getAzureClient(subscriptionItem, resourceGroupItem);
const { consortiumResource, memberResource } = azureClient;
const consortiumName = await showInputBox({
ignoreFocusOut: true,
prompt: Constants.paletteABSLabels.enterConsortiumName,
validateInput: async (name) => {
return await window.withProgress({
location: ProgressLocation.Notification,
title: Constants.informationMessage.consortiumNameValidating,
}, async () => {
return await AzureBlockchainServiceValidator.validateConsortiumName(name, consortiumResource);
});
},
});
const memberName = await showInputBox({
ignoreFocusOut: true,
prompt: Constants.paletteABSLabels.enterMemberName,
validateInput: async (name) => {
return await window.withProgress({
location: ProgressLocation.Notification,
title: Constants.informationMessage.memberNameValidating,
},
async () => await AzureBlockchainServiceValidator.validateMemberName(name, memberResource));
},
});
const protocol = await showQuickPick(
[{ label: 'Quorum' }],
{
ignoreFocusOut: true,
placeHolder: Constants.paletteABSLabels.selectConsortiumProtocol,
},
);
const memberPassword = await showInputBox({
ignoreFocusOut: true,
password: true,
prompt: Constants.paletteABSLabels.enterMemberPassword,
validateInput: AzureBlockchainServiceValidator.validateAccessPassword,
});
const consortiumPassword = await showInputBox({
ignoreFocusOut: true,
password: true,
prompt: Constants.paletteABSLabels.enterConsortiumManagementPassword,
validateInput: AzureBlockchainServiceValidator.validateAccessPassword,
});
const region = await showQuickPick(
this.getLocationItems(subscriptionItem),
{ placeHolder: Constants.paletteABSLabels.selectConsortiumRegion, ignoreFocusOut: true },
);
const sku = await showQuickPick(
this.getSkus(azureClient, region),
{ placeHolder: Constants.paletteABSLabels.selectConsortiumSku, ignoreFocusOut: true },
);
const bodyParams: ICreateQuorumMember = {
consortiumManagementAccountPassword: memberPassword,
consortiumName,
consortiumPassword,
protocol: protocol.label,
region: region.description,
sku: {
name: sku.description,
tier: sku.label,
},
};
return window.withProgress({
location: ProgressLocation.Window,
title: Constants.statusBarMessages.creatingConsortium,
}, async () => {
await azureClient.consortiumResource.createConsortium(memberName, bodyParams);
return new AzureConsortium(consortiumName, subscriptionItem.subscriptionId, resourceGroupItem.label, memberName);
});
}
}

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

@ -4,7 +4,7 @@
import * as os from 'os';
import * as path from 'path';
import { ExtensionContext, extensions } from 'vscode';
import { IOZAsset } from './services';
import { IOZAsset } from './services/openZeppelin/models';
const extensionId = 'AzBlockchain.azure-blockchain';
const packageJSON = extensions.getExtension(extensionId)!.packageJSON;
@ -19,10 +19,15 @@ export enum RequiredApps {
hdwalletProvider = 'truffle-hdwallet-provider',
}
export enum NotificationOptions {
error = 'error',
info = 'info',
warning = 'warning',
}
export class Constants {
public static extensionContext: ExtensionContext;
public static temporaryDirectory = '';
public static extensionName = packageJSON.name;
public static extensionVersion = packageJSON.version;
public static extensionKey = packageJSON.aiKey;
@ -44,6 +49,12 @@ export class Constants {
hdwalletProvider: 'HDWalletProvider',
};
public static truffleConfigDefaultDirectory = {
contracts_build_directory: path.join('./', 'build', 'contracts'),
contracts_directory: path.join('./', 'contracts'),
migrations_directory: path.join('./', 'migrations'),
};
public static defaultTruffleBox = 'Azure-Samples/Blockchain-Ethereum-Template';
public static defaultDebounceTimeout = 300;
@ -201,9 +212,11 @@ export class Constants {
},
hasDigits: /(?=.*\d)/g,
infuraProjectname: /^([a-zA-Z]|\d|\s|[-_:]){3,}$/g,
isJsonFile: new RegExp(Constants.contractExtension.json + '$'),
isLowerCase: /^[a-z0-9_\-!@$^&()+=?\/<>|[\]{}:.\\~ #`*"'%;,]+$/g,
isUrl: /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=]+$/igm,
lowerCaseLetter: /(?=.*[a-z]).*/g,
moduleExportsTemplate: /{(.*)}$/g,
// tslint:disable-next-line: max-line-length
port: /^([1-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/,
specialChars: {
@ -371,8 +384,10 @@ export class Constants {
};
public static executeCommandMessage = {
failedToRunCommand: Constants.getMessageFailedCommand,
failedToRunCommand: (command: string) => `Failed to run command - ${command}. More details in output`,
failedToRunScript: (scriptPath: string) => `Failed to run script - ${scriptPath}. More details in output`,
finishRunningCommand: 'Finished running command',
forkingModule: 'Forking script',
runningCommand: 'Running command',
};
@ -395,9 +410,11 @@ export class Constants {
deployingContracts: (destination: string) => {
return `Deploying contracts to '${destination}'`;
},
generatingLogicApp: (appName: string) => `Generating ${appName}!`,
};
public static rpcMethods = {
getCode: 'eth_getCode',
netListening: 'net_listening',
netVersion: 'net_version',
};
@ -430,12 +447,13 @@ export class Constants {
BuildContractsDirIsNotExist: Constants.getMessageContractsBuildDirectoryIsNotExist,
CompiledContractIsMissing: 'Compiled contract is missing for solidity file.',
DirectoryIsNotEmpty: 'Directory is not empty. Open another one?',
ErrorWhileExecutingCommand: 'Error while executing command: ',
FetchingDeployedBytecodeIsFailed: 'An error occurred while fetching bytecode from network',
GetMessageChildAlreadyConnected: Constants.getMessageChildAlreadyConnected,
GitIsNotInstalled: 'Git is not installed',
InfuraUnauthorized: 'Unauthorized: please sign in with Infura account.',
InvalidContract: 'This file is not a valid contract.',
InvalidMnemonic: 'Invalid mnemonic',
InvalidServiceType: 'Invalid service type.',
LoadServiceTreeFailed: 'Load service tree has failed.',
MnemonicFileHaveNoText: 'Mnemonic file have no text',
NetworkAlreadyExist: Constants.getMessageNetworkAlreadyExist,
@ -448,6 +466,7 @@ export class Constants {
PleaseRenameOldStyleTruffleConfig: 'Please rename file "truffle.js" to "truffle-config.js"',
RequiredAppsAreNotInstalled: 'To run command you should install required apps',
ThereAreNoMnemonics: 'There are no mnemonics',
TruffleConfigHasIncorrectFormat: '"truffle-config.js" has incorrect format',
TruffleConfigIsNotExist: 'Truffle configuration file not found',
VariableShouldBeDefined: Constants.getMessageVariableShouldBeDefined,
WaitForLogin: 'You should sign-in on Azure Portal',
@ -465,7 +484,7 @@ export class Constants {
deployFailed: 'Deploy failed',
deploySucceeded: 'Deploy succeeded',
detailsButton: 'Details',
generatedLogicApp: 'Generated the logic app!',
generatedLogicApp: (appName: string) => `Generated the ${appName}!`,
infuraAccountSuccessfullyCreated: 'Your Infura account successfully created. Please check you email for complete registration',
infuraSignInPrompt: 'Not signed in to Infura account, sign in first.',
installButton: 'Install',
@ -479,6 +498,7 @@ export class Constants {
rpcEndpointCopiedToClipboard: 'RPCEndpointAddress copied to clipboard',
seeDetailsRequirementsPage: 'Please see details on the Requirements Page',
signInButton: 'Sign In',
transactionBytecodeWasCopiedToClipboard: 'Transaction Bytecode was copied to clipboard',
};
public static infuraCredentials = {
@ -520,15 +540,10 @@ export class Constants {
Service: 'Service',
};
public static logicApp = {
AzureFunction: 'Azure Function',
FlowApp: 'Flow App',
LogicApp: 'Logic App',
output: {
AzureFunction: 'generatedAzureFunction',
FlowApp: 'generatedFlowApp',
LogicApp: 'generatedLogicApp',
},
public static azureApps = {
AzureFunction: { label: 'Azure Function', serviceType: 2, outputDir: 'generatedAzureFunction' },
FlowApp: { label: 'Flow App', serviceType: 0, outputDir: 'generatedFlowApp' },
LogicApp: { label: 'Logic App', serviceType: 1, outputDir: 'generatedLogicApp'},
};
public static azureResourceExplorer = {
@ -541,12 +556,19 @@ export class Constants {
resourceType: 'blockchainMembers',
};
public static firstOZVersion = '2.3.0';
public static allOpenZeppelinVersions = ['2.3.0', '2.4.0'];
public static ozVersionUserSettingsKey = 'azureBlockchainService.openZeppelin.version';
public static openZeppelin = {
cancelButtonTitle: 'Cancel',
contractsUpgradeIsFailed: 'Upgrade of OpenZeppelin contracts has failed',
descriptionDownloadingFailed: 'Description downloading failed',
downloadingContractsFromOpenZeppelin: 'Downloading contracts from OpenZeppelin',
exploreDownloadedContractsInfo: 'Explore more information about the contracts downloaded',
invalidVersionException: 'Invalid version. All OpenZeppelin work will be stopped',
moreDetailsButtonTitle: 'More details',
newVersionAvailable: 'There is a new version of your OpenZeppelin contracts available. Would you like to download the latest version?',
overwriteExistedContracts: 'Overwrite existed contracts',
projectFileName: 'project.json',
replaceButtonTitle: 'Replace',
@ -554,6 +576,7 @@ export class Constants {
retryDownloading: 'Retry downloading',
selectCategoryForDownloading: 'Select category for downloading',
skipButtonTitle: 'Skip files',
upgradeOpenZeppelin: 'Upgrading OpenZeppelin',
hashCalculationFailed(errorMessage: string): string {
return `Error while calculating file hash. Message: ${errorMessage}`;
},
@ -583,6 +606,10 @@ export class Constants {
fileNow(count: number): string {
return `${count} file(s) on OpenZeppelin library now`;
},
invalidVersionDialog(version: string, location: string, lastVersion: string) {
return `There is invalid OpenZeppelin version (${version}) in ${location}. ` +
`Do you want to use the latest one (${lastVersion})?`;
},
};
public static initialize(context: ExtensionContext) {
@ -690,10 +717,6 @@ export class Constants {
return `Length must be between ${min} and ${max} characters`;
}
private static getMessageFailedCommand(command: string): string {
return `Failed to run command - ${command}. More details in output`;
}
private static getMessageInputHasUnresolvedSymbols(unresolvedSymbols: string): string {
return `Input value must not have '${unresolvedSymbols}'.`;
}

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

@ -1,100 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ChildProcess, spawn } from 'child_process';
import { OutputChannel, window } from 'vscode';
import { Constants, RequiredApps } from '../Constants';
import { shell } from '../helpers';
import { Telemetry } from '../TelemetryClient';
import { UrlValidator } from '../validators/UrlValidator';
import { isGanacheServer, waitGanacheStarted } from './GanacheServiceClient';
export namespace GanacheService {
export interface IGanacheProcess {
process: ChildProcess;
output: OutputChannel;
}
export const ganacheProcesses: { [port: string]: IGanacheProcess } = {};
export async function startGanacheServer(port: number | string)
: Promise<IGanacheProcess | null> {
Telemetry.sendEvent('GanacheService.startGanacheServer');
if (UrlValidator.validatePort(port)) {
Telemetry.sendException(new Error(Constants.ganacheCommandStrings.invalidGanachePort));
throw new Error(`${Constants.ganacheCommandStrings.invalidGanachePort}: ${port}.`);
}
if (!isNaN(await shell.findPid(port))) {
Telemetry.sendEvent('GanacheService.startGanacheServer.portIsFree', { port: port.toString() });
if (await isGanacheServer(port)) {
Telemetry.sendEvent('GanacheService.startGanacheServer.isGanacheServer', { port: port.toString() });
return null;
} else {
const error = new Error(Constants.ganacheCommandStrings.cannotStartServer);
Telemetry.sendException(error);
throw error;
}
}
const process = spawn('npx', [RequiredApps.ganache, `-p ${port}`], { shell: true });
const output = window.createOutputChannel(`${Constants.outputChannel.ganacheCommands}:${port}`);
output.show();
process.stdout.on('data', (data: string | Buffer) => {
output.appendLine(data.toString());
});
process.stderr.on('data', (data: string | Buffer) => {
output.appendLine(data.toString());
});
process.on('close', () => {
delete ganacheProcesses[port];
output.dispose();
});
try {
await waitGanacheStarted(port, Constants.ganacheRetryAttempts);
} catch (error) {
Telemetry.sendException(error);
process.removeAllListeners();
output.dispose();
await shell.killPort(port);
throw error;
}
Telemetry.sendEvent('GanacheServiceClient.waitGanacheStarted.serverStarted');
const ganacheProcess = { process, output };
ganacheProcesses[port] = ganacheProcess;
return ganacheProcess;
}
export async function stopGanacheServer(port: number | string): Promise<void> {
await shell.killPort(port);
const ganacheProcess = ganacheProcesses[port];
if (ganacheProcess) {
ganacheProcess.process.removeAllListeners();
ganacheProcess.output.dispose();
delete ganacheProcesses[port];
}
}
export async function dispose(): Promise<void[]> {
const shouldBeFree: Array<Promise<void>> = [];
Object.keys(ganacheProcesses).forEach((port) => {
delete ganacheProcesses[port];
shouldBeFree.push(shell.killPort(port));
});
return Promise.all(shouldBeFree);
}
export function getPortFromUrl(url: string): string {
const result = url.match(/(:\d{2,4})/);
return result ? result[0].slice(1) : Constants.defaultLocalhostPort.toString();
}
}

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

@ -1,35 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Constants } from '../Constants';
import { HttpService } from '../services';
import { Telemetry } from '../TelemetryClient';
export async function isGanacheServer(port: number | string): Promise<boolean> {
try {
const response = await HttpService.sendRPCRequest(
`http://${Constants.localhost}:${port}`,
Constants.rpcMethods.netListening);
return response && !!response.result || false;
} catch (error) {
Telemetry.sendException(error);
return false;
}
}
export async function waitGanacheStarted(port: number | string, maxRetries: number = 1): Promise<void> {
const retry = async (retries: number) => {
if (retries < maxRetries) {
if (await isGanacheServer(port)) {
return;
}
await new Promise((resolve) => setTimeout(resolve, Constants.ganacheRetryTimeout));
await retry(retries + 1);
} else {
const error = new Error(Constants.ganacheCommandStrings.cannotStartServer);
Telemetry.sendException(error);
throw error;
}
};
await retry(0);
}

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

@ -5,7 +5,7 @@ import * as fs from 'fs-extra';
import * as path from 'path';
import { Uri, window } from 'vscode';
import { Constants } from '../Constants';
import { getWorkspaceRoot, TruffleConfiguration } from '../helpers';
import { getWorkspaceRoot, showIgnorableNotification, TruffleConfiguration } from '../helpers';
import { showInputBox, showQuickPick } from '../helpers/userInteraction';
import { ResourceGroupItem, SubscriptionItem } from '../Models/QuickPickItems';
import { Output } from '../Output';
@ -23,48 +23,60 @@ interface ILogicAppData {
subscriptionId: string;
topicName?: string;
workflowType: string;
label: string;
}
interface IAzureAppsItem {
label: string;
serviceType: number;
outputDir: string;
}
export class LogicAppGenerator {
public async generateMicroservicesWorkflows(filePath?: Uri): Promise<void> {
Telemetry.sendEvent('LogicAppGenerator.microservicesWorkflows');
this.generateWorkflows(Constants.microservicesWorkflows.Service, filePath);
await this.generateWorkflows(Constants.microservicesWorkflows.Service, filePath);
}
public async generateDataPublishingWorkflows(filePath?: Uri): Promise<void> {
Telemetry.sendEvent('LogicAppGenerator.dataPublishingWorkflows');
this.generateWorkflows(Constants.microservicesWorkflows.Data, filePath);
await this.generateWorkflows(Constants.microservicesWorkflows.Data, filePath);
}
public async generateEventPublishingWorkflows(filePath?: Uri): Promise<void> {
Telemetry.sendEvent('LogicAppGenerator.eventPublishingWorkflows');
this.generateWorkflows(Constants.microservicesWorkflows.Messaging, filePath);
await this.generateWorkflows(Constants.microservicesWorkflows.Messaging, filePath);
}
public async generateReportPublishingWorkflows(filePath?: Uri): Promise<void> {
Telemetry.sendEvent('LogicAppGenerator.reportPublishingWorkflows');
this.generateWorkflows(Constants.microservicesWorkflows.Reporting, filePath);
await this.generateWorkflows(Constants.microservicesWorkflows.Reporting, filePath);
}
private async generateWorkflows(workflowType: string, filePath?: Uri): Promise<void> {
const filePaths = await this.getContractsPath(filePath);
const logicAppData = await this.getLogicAppData(workflowType);
for (const file of filePaths) {
const contract = await fs.readJson(file, { encoding: 'utf8' });
const generatedFiles: any[] = this.getGenerator(contract, logicAppData).GenerateAll();
for (const generatedFile of generatedFiles) {
await this.writeFile(generatedFile);
}
}
await showIgnorableNotification(
Constants.statusBarMessages.generatingLogicApp(logicAppData.label),
async () => {
for (const file of filePaths) {
const contract = await fs.readJson(file, { encoding: 'utf8' });
const generatedFiles: any[] = this.getGenerator(contract, logicAppData).GenerateAll();
for (const generatedFile of generatedFiles) {
await this.writeFile(generatedFile);
}
}
window.showInformationMessage(Constants.informationMessage.generatedLogicApp);
Telemetry.sendEvent('LogicAppGenerator.generateWorkflows.commandFinished');
window.showInformationMessage(Constants.informationMessage.generatedLogicApp(logicAppData.label));
Telemetry.sendEvent('LogicAppGenerator.generateWorkflows.commandFinished');
},
);
}
private async getContractsPath(filePath?: Uri): Promise<string[]> {
const truffleConfigPath = TruffleConfiguration.getTruffleConfigUri();
const truffleConfig = new TruffleConfiguration.TruffleConfig(truffleConfigPath);
const configuration = truffleConfig.getConfiguration();
const configuration = await truffleConfig.getConfiguration();
const buildDir = path.join(getWorkspaceRoot()!, configuration.contracts_build_directory);
const files: string[] = [];
@ -102,15 +114,15 @@ export class LogicAppGenerator {
}
private async getLogicAppData(workflowType: string): Promise<ILogicAppData> {
const serviceType = await this.getServiceType(workflowType);
const outputDir = await this.getOutputDir(serviceType);
const azureAppItem: IAzureAppsItem = await this.getAzureAppItem(workflowType);
const contractAddress = await showInputBox({ ignoreFocusOut: true, value: 'contract address' });
const [subscriptionItem, resourceGroupItem] = await this.selectSubscriptionAndResourceGroup();
const logicAppData: ILogicAppData = {
contractAddress,
outputDir,
label: azureAppItem.label,
outputDir: path.join(getWorkspaceRoot()!, azureAppItem.outputDir),
resourceGroup: resourceGroupItem.description,
serviceType,
serviceType: azureAppItem.serviceType,
subscriptionId: subscriptionItem.subscriptionId,
workflowType,
};
@ -157,34 +169,14 @@ export class LogicAppGenerator {
return [subscriptionItem, resourceGroupItem];
}
private async getServiceType(workflowType: string): Promise<number> {
const items = [
{ label: Constants.logicApp.LogicApp, serviceType: 1 },
{ label: Constants.logicApp.FlowApp, serviceType: 0 },
];
private async getAzureAppItem(workflowType: string): Promise<IAzureAppsItem> {
const items = [Constants.azureApps.LogicApp, Constants.azureApps.FlowApp ];
if (workflowType === Constants.microservicesWorkflows.Service) {
items.push({ label: Constants.logicApp.AzureFunction, serviceType: 2 });
items.push(Constants.azureApps.AzureFunction);
}
const item = await showQuickPick(items, { ignoreFocusOut: true });
return item.serviceType;
}
private getOutputDir(serviceType: int): string {
switch (serviceType) {
case 0:
return path.join(getWorkspaceRoot()!, Constants.logicApp.output.FlowApp);
case 1:
return path.join(getWorkspaceRoot()!, Constants.logicApp.output.LogicApp);
case 2:
return path.join(getWorkspaceRoot()!, Constants.logicApp.output.AzureFunction);
default: {
const error = new Error(Constants.errorMessageStrings.InvalidServiceType);
Telemetry.sendException(error);
throw error;
}
}
return await showQuickPick(items, { ignoreFocusOut: true });
}
private async getMessagingType(): Promise<number> {

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

@ -1,36 +0,0 @@
import * as fs from 'fs';
import { Memento } from 'vscode';
import { Constants } from '../Constants';
export class MnemonicRepository {
public static initialize(globalState: Memento): void {
MnemonicRepository.globalState = globalState;
}
public static getMnemonic(filePath: string): string {
return fs.readFileSync(filePath).toString().trim();
}
public static getAllMnemonicPaths(): string[] {
return MnemonicRepository.globalState.get(Constants.mnemonicConstants.mnemonicStorage) as string[] || [];
}
public static getExistedMnemonicPaths(): string[] {
return MnemonicRepository.getAllMnemonicPaths().filter((path) => fs.existsSync(path));
}
public static saveMnemonicPath(filePath: string): void {
const storage = MnemonicRepository.globalState.get(Constants.mnemonicConstants.mnemonicStorage) as string[] || [];
storage.push(filePath);
MnemonicRepository.globalState.update(Constants.mnemonicConstants.mnemonicStorage, storage);
}
public static MaskMnemonic(mnemonic: string) {
return mnemonic
? `${mnemonic.slice(0, 3)} ... ${mnemonic.slice(-3)}`
: Constants.placeholders.emptyLineText;
}
private static globalState: Memento;
}

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

@ -1,78 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ConsortiumResourceExplorer } from '../ConsortiumResourceExplorer';
import { Constants } from '../Constants';
import { TruffleConfiguration } from '../helpers';
import { ItemType } from './ItemType';
import { ProtectedConsortium } from './ProtectedConsortium';
export class AzureConsortium extends ProtectedConsortium {
private readonly subscriptionId: string;
private readonly resourcesGroup: string;
private readonly memberName: string;
constructor(
consortiumName: string,
subscriptionId: string,
resourcesGroup: string,
memberName: string,
url?: string,
) {
super(ItemType.AZURE_CONSORTIUM, consortiumName);
this.subscriptionId = subscriptionId;
this.resourcesGroup = resourcesGroup;
this.memberName = memberName;
if (url) {
this.addUrl(url);
}
}
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
const network = await super.getTruffleNetwork();
network.options.gasPrice = 0;
network.options.gas = 0;
return network;
}
public getSubscriptionId(): string {
return this.subscriptionId;
}
public getResourceGroup(): string {
return this.resourcesGroup;
}
public getMemberName(): string {
return this.memberName;
}
public async getRPCAddress(): Promise<string> {
const url = this.getUrls()[0];
if (!url) {
return '';
}
if (!url.port) {
url.port = `${Constants.defaultAzureBSPort}`;
}
const consortiumResourceExplorer = new ConsortiumResourceExplorer();
const keys = await consortiumResourceExplorer.getAccessKeys(this);
return keys ? `${url.origin}/${keys[0]}` : url.origin;
}
public toJSON(): { [p: string]: any } {
const obj = super.toJSON();
obj.subscriptionId = this.subscriptionId;
obj.resourcesGroup = this.resourcesGroup;
obj.memberName = this.memberName;
return obj;
}
}

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

@ -1,17 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ExtensionItem } from './ExtensionItem';
import { ItemType } from './ItemType';
export class Command extends ExtensionItem {
constructor(label: string, commandName: string, args?: any[]) {
super(ItemType.COMMAND, `-> ${label}`);
this.command = {
arguments: args,
command: commandName,
title: `-> ${label}`,
};
}
}

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

@ -1,88 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { URL } from 'url';
import { Constants } from '../Constants';
import { TruffleConfiguration } from '../helpers';
import { ExtensionItem } from './ExtensionItem';
import { ItemType } from './ItemType';
const protocolRegExp = new RegExp('^(' +
Constants.networkProtocols.http + '|' +
Constants.networkProtocols.https + '|' +
Constants.networkProtocols.ftp + '|' +
Constants.networkProtocols.file +
').*', 'i');
export abstract class Consortium extends ExtensionItem {
private readonly urls: URL[];
private consortiumId: number;
protected constructor(itemType: ItemType, consortiumName: string, description?: string) {
super(itemType, consortiumName, description);
this.contextValue = Constants.contextValue.consortium;
this.iconPath = Constants.icons.consortium;
this.urls = [];
this.consortiumId = + Date.now();
}
public addUrl(url: URL | string) {
if (typeof url === 'string') {
if (!url.match(protocolRegExp)) {
url = `${this.defaultProtocol()}${url}`;
}
url = new URL(url);
}
this.urls.push(url);
}
public addUrls(urls: URL[] | string[]) {
urls.forEach((url: URL | string) => this.addUrl(url));
}
public getUrls(): URL[] {
return this.urls;
}
public toJSON(): { [key: string]: any } {
const obj = super.toJSON();
obj.urls = this.urls.map((url) => url.toString());
obj.consortiumId = this.consortiumId;
return obj;
}
public async getRPCAddress(): Promise<string> {
if (this.urls.length === 0) {
return '';
}
const url = this.urls[0];
return url.pathname === '/' ? url.origin : `${url.origin}/${url.pathname}`;
}
public getConsortiumId(): number {
return this.consortiumId;
}
public setConsortiumId(id: number): void {
this.consortiumId = id;
}
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
return {
name: this.label,
options: {
consortium_id: this.getConsortiumId(),
network_id: '*',
},
};
}
protected defaultProtocol(): string {
return Constants.networkProtocols.https;
}
}

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

@ -1,30 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { QuickPickItem } from 'vscode';
export class ConsortiumItem implements QuickPickItem {
public readonly consortiumName: string;
public readonly memberName: string;
public readonly resourcesGroup: string;
public readonly subscriptionId: string;
public readonly url?: string;
public readonly label: string;
constructor(
consortiumName: string,
subscriptionId: string,
resourcesGroup: string,
memberName: string,
url?: string,
) {
this.subscriptionId = subscriptionId;
this.resourcesGroup = resourcesGroup;
this.memberName = memberName;
this.url = url;
this.consortiumName = consortiumName;
this.label = consortiumName;
}
}

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

@ -1,95 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { commands, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { Constants } from '../Constants';
import { Telemetry } from '../TelemetryClient';
import { IExtensionItem } from './IExtensionItem';
import { ItemType } from './ItemType';
import Timeout = NodeJS.Timeout;
export abstract class ExtensionItem extends TreeItem implements IExtensionItem {
protected static timeoutID: NodeJS.Timeout | undefined;
protected children: IExtensionItem[];
protected parent: IExtensionItem | null;
protected constructor(
public readonly itemType: ItemType,
public readonly label: string,
public readonly description?: string,
) {
super(label);
this.children = [];
this.parent = null;
}
public getParent(): IExtensionItem | null {
return this.parent;
}
public getChildren(): IExtensionItem[] {
return this.children;
}
public addParent(parent: IExtensionItem): void {
this.parent = parent;
}
public addChild(child: IExtensionItem): void {
if (this.children.some((_child) => _child.label === child.label)) {
Telemetry.sendException(new Error(Constants.errorMessageStrings.GetMessageChildAlreadyConnected(
Telemetry.obfuscate(child.label || ''),
)));
throw new Error(Constants.errorMessageStrings.GetMessageChildAlreadyConnected(child.label || ''));
}
child.addParent(this);
this.children.push(child);
this.collapse();
return this.refreshTree();
}
public removeChild(child: IExtensionItem): void {
this.children = this.children.filter((_child) => _child !== child);
this.collapse();
return this.refreshTree();
}
public setChildren(children: IExtensionItem[]): void {
this.children = children;
this.children.forEach((child) => child.addParent(this));
this.collapse();
return this.refreshTree();
}
public toJSON(): { [key: string]: any } {
return {
children: this.children,
description: this.description,
itemType: this.itemType,
label: this.label,
};
}
private collapse() {
if (this.children.length > 0) {
Telemetry.sendEvent('ExtensionItem.collapse.childrenLengthGreaterThanZero');
this.collapsibleState = TreeItemCollapsibleState.Collapsed;
}
}
private refreshTree(): void {
clearTimeout(ExtensionItem.timeoutID as Timeout);
ExtensionItem.timeoutID = setTimeout(async () => {
try {
await commands.executeCommand('azureBlockchainService.refresh');
} catch (error) {
Telemetry.sendException(error);
}
}, 300);
}
}

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

@ -1,17 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TreeItem } from 'vscode';
import { ItemType } from './ItemType';
export interface IExtensionItem extends TreeItem {
itemType: ItemType;
getParent(): IExtensionItem | null;
getChildren(): IExtensionItem[];
addParent(parent: IExtensionItem): void;
addChild(child: IExtensionItem): void;
removeChild(child: IExtensionItem): void;
setChildren(children: IExtensionItem[]): void;
toJSON(): { [key: string]: any };
}

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

@ -1,11 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ExtensionItem } from './ExtensionItem';
import { ItemType } from './ItemType';
export class Info extends ExtensionItem {
constructor(label: string, description?: string) {
super(ItemType.INFO, label, description);
}
}

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

@ -1,32 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { AzureConsortium } from '../AzureConsortium';
import { ConsortiumItemCreator } from './ConsortiumItemCreator';
export class AzureConsortiumItemCreator extends ConsortiumItemCreator {
protected getRequiredFields(): Array<{ fieldName: string, type: string }> {
const requiredFields = super.getRequiredFields();
requiredFields.push(...[
{ fieldName: 'subscriptionId', type: 'string' },
{ fieldName: 'resourcesGroup', type: 'string' },
{ fieldName: 'memberName', type: 'string' },
]);
return requiredFields;
}
protected getAdditionalConstructorArguments(obj: { [key: string]: any }): any[] {
const { memberName, resourcesGroup, subscriptionId } = obj;
return [
subscriptionId,
resourcesGroup,
memberName,
];
}
protected createConsortium(consortiumName: string, subscriptionId: string, resourcesGroup: string, memberName: string)
: AzureConsortium {
return new AzureConsortium(consortiumName, subscriptionId, resourcesGroup, memberName);
}
}

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

@ -1,32 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Consortium } from '../Consortium';
import { ItemCreator } from './ItemCreator';
export abstract class ConsortiumItemCreator extends ItemCreator {
protected createFromObject(obj: { [key: string]: any }): Consortium {
const { label, consortiumId, urls } = obj;
const args = this.getAdditionalConstructorArguments(obj);
const consortium = this.createConsortium(label, ...args);
consortium.addUrls(urls);
consortium.setConsortiumId(consortiumId);
return consortium;
}
protected getRequiredFields(): Array<{ fieldName: string, type: string }> {
const requiredFields = super.getRequiredFields();
requiredFields.push(...[
{ fieldName: 'urls', type: 'array' },
{ fieldName: 'consortiumId', type: 'number' },
]);
return requiredFields;
}
protected abstract getAdditionalConstructorArguments(obj: { [key: string]: any }): any[];
protected abstract createConsortium(consortiumName: string, ...args: any[]): Consortium;
}

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

@ -1,13 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Info } from '../Info';
import { ItemCreator } from './ItemCreator';
export class InfoItemCreator extends ItemCreator {
protected createFromObject(obj: { [key: string]: any }): Info {
const { label, description } = obj;
return new Info(label, description);
}
}

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

@ -1,15 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { LocalNetworkConsortium } from '../LocalNetworkConsortium';
import { ConsortiumItemCreator } from './ConsortiumItemCreator';
export class LocalNetworkConsortiumItemCreator extends ConsortiumItemCreator {
protected getAdditionalConstructorArguments(): any[] {
return [];
}
protected createConsortium(consortiumName: string): LocalNetworkConsortium {
return new LocalNetworkConsortium(consortiumName);
}
}

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

@ -1,15 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { MainNetworkConsortium } from '../MainNetworkConsortium';
import { ConsortiumItemCreator } from './ConsortiumItemCreator';
export class MainNetworkConsortiumItemCreator extends ConsortiumItemCreator {
protected getAdditionalConstructorArguments(): any[] {
return [];
}
protected createConsortium(consortiumName: string): MainNetworkConsortium {
return new MainNetworkConsortium(consortiumName);
}
}

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

@ -1,13 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Network } from '../Network';
import { ItemCreator } from './ItemCreator';
export class NetworkItemCreator extends ItemCreator {
protected createFromObject(obj: { [key: string]: any }): Network {
const { label, itemType } = obj;
return new Network(label, itemType);
}
}

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

@ -1,15 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TestNetworkConsortium } from '../TestNetworkConsortium';
import { ConsortiumItemCreator } from './ConsortiumItemCreator';
export class TestNetworkConsortiumItemCreator extends ConsortiumItemCreator {
protected getAdditionalConstructorArguments(): any[] {
return [];
}
protected createConsortium(consortiumName: string): TestNetworkConsortium {
return new TestNetworkConsortium(consortiumName);
}
}

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

@ -1,19 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TransactionNode } from '../TransactionNode';
import { ItemCreator } from './ItemCreator';
export class TransactionNodeItemCreator extends ItemCreator {
protected createFromObject(obj: { [key: string]: any }): TransactionNode {
const { label, dns } = obj;
return new TransactionNode(label, dns);
}
protected getRequiredFields(): Array<{ fieldName: string, type: string }> {
const requiredFields = super.getRequiredFields();
return requiredFields.concat({ fieldName: 'dns', type: 'string' });
}
}

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

@ -1,39 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Constants } from '../Constants';
import { TruffleConfiguration } from '../helpers';
import { Consortium } from './Consortium';
import { ItemType } from './ItemType';
export class LocalNetworkConsortium extends Consortium {
constructor(consortiumName: string, url?: string) {
super(ItemType.LOCAL_CONSORTIUM, consortiumName);
if (url) {
this.addUrl(url);
}
this.contextValue = Constants.contextValue.localConsortium;
}
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
const network = await super.getTruffleNetwork();
const url = this.getUrls()[0];
network.options.host = url.hostname || Constants.localhost;
network.options.port = parseInt(url.port, 10) || Constants.defaultLocalhostPort;
return network;
}
public async getPort(): Promise<number | undefined> {
const network = await this.getTruffleNetwork();
return network.options.port;
}
protected defaultProtocol(): string {
return Constants.networkProtocols.http;
}
}

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

@ -1,14 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { QuickPickItem } from 'vscode';
export class LocationItem implements QuickPickItem {
public readonly label: string;
public readonly description: string;
constructor(label?: string, description?: string) {
this.label = label || '';
this.description = description || '';
}
}

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

@ -1,24 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TruffleConfiguration } from '../helpers';
import { ItemType } from './ItemType';
import { NetworkConsortium } from './NetworkConsortium';
export class MainNetworkConsortium extends NetworkConsortium {
constructor(consortiumName: string, url?: string) {
super(ItemType.ETHEREUM_MAIN_CONSORTIUM, consortiumName);
if (url) {
this.addUrl(url);
}
}
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
const network = await super.getTruffleNetwork();
network.options.network_id = 1;
return network;
}
}

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

@ -1,19 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Constants } from '../Constants';
import { ExtensionItem } from './ExtensionItem';
import { ItemType } from './ItemType';
export class Member extends ExtensionItem {
constructor(memberName: string) {
super(ItemType.MEMBER, memberName);
this.contextValue = Constants.contextValue.member;
this.iconPath = Constants.icons.member;
}
public toJSON(): { [p: string]: any } {
return super.toJSON();
}
}

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

@ -1,19 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Constants } from '../Constants';
import { ExtensionItem } from './ExtensionItem';
import { ItemType } from './ItemType';
export class Network extends ExtensionItem {
constructor(
networkName: string,
itemType: ItemType.AZURE_BLOCKCHAIN | ItemType.LOCAL_NETWORK |
ItemType.ETHEREUM_TEST_NETWORK | ItemType.ETHEREUM_MAIN_NETWORK,
) {
super(itemType, networkName);
this.contextValue = Constants.contextValue.blockchainService;
this.iconPath = Constants.icons.blockchainService;
}
}

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

@ -1,61 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Constants } from '../Constants';
import { showInputBox, TruffleConfiguration } from '../helpers';
import { ItemType } from './ItemType';
import { ProtectedConsortium } from './ProtectedConsortium';
export abstract class NetworkConsortium extends ProtectedConsortium {
protected constructor(itemType: ItemType, consortiumName: string, description?: string) {
super(itemType, consortiumName, description);
}
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
const network = await super.getTruffleNetwork();
network.options.gasPrice = await this.getGasPrice();
network.options.gas = await this.getGasLimit();
return network;
}
protected async getGasPrice(): Promise<number> {
const value = await showInputBox({
ignoreFocusOut: true,
prompt: Constants.paletteABSLabels.valueOrDefault(
Constants.propertyLabels.gasPrice,
Constants.defaultContractSettings.gasPrice),
validateInput: this.validation,
});
if (!value) {
return Constants.defaultContractSettings.gasPrice;
} else {
return Number(value);
}
}
protected async getGasLimit(): Promise<number> {
const value = await showInputBox({
ignoreFocusOut: true,
prompt: Constants.paletteABSLabels.valueOrDefault(
Constants.propertyLabels.gasLimit,
Constants.defaultContractSettings.gasLimit),
validateInput: this.validation,
});
if (!value) {
return Constants.defaultContractSettings.gasLimit;
} else {
return Number.parseInt(value, 0);
}
}
private validation(value: string): string | undefined {
return value && !value.match(new RegExp(/^\d+$/g)) ?
Constants.validationMessages.valueShouldBeNumberOrEmpty :
undefined;
}
}

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

@ -1,82 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Constants } from '../Constants';
import { saveTextInFile, showInputBox, showQuickPick, TruffleConfiguration } from '../helpers';
import { MnemonicRepository } from '../MnemonicService/MnemonicRepository';
import { Consortium } from './Consortium';
import { ItemType } from './ItemType';
export abstract class ProtectedConsortium extends Consortium {
protected constructor(itemType: ItemType, consortiumName: string, description?: string) {
super(itemType, consortiumName, description);
}
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
const truffleConfigPath = TruffleConfiguration.getTruffleConfigUri();
const config = new TruffleConfiguration.TruffleConfig(truffleConfigPath);
const network = await super.getTruffleNetwork();
const targetURL = await this.getRPCAddress();
const mnemonic = await this.getMnemonic();
await config.importPackage('fs', 'fs');
network.options.provider = {
mnemonic: mnemonic.path,
url: `${targetURL}`,
};
return network;
}
private async getMnemonic(): Promise<{mnemonic: string, path: string}> {
const mnemonicOptions = [
{
cmd: async () => {
const mnemonic = await TruffleConfiguration.generateMnemonic();
const path = await this.saveMnemonicFile(mnemonic);
return {mnemonic, path};
},
label: Constants.placeholders.generateMnemonic,
},
{
cmd: async () => {
const mnemonic = await showInputBox({
ignoreFocusOut: true,
placeHolder: Constants.placeholders.pasteMnemonic,
});
const path = await this.saveMnemonicFile(mnemonic);
return {mnemonic, path};
},
label: Constants.placeholders.pasteMnemonic,
},
];
const savedMnemonics = MnemonicRepository.getExistedMnemonicPaths()
.map((path) => {
const mnemonic = MnemonicRepository.getMnemonic(path);
const label = MnemonicRepository.MaskMnemonic(mnemonic);
return {
cmd: async () => ({mnemonic, path}),
detail: path,
label,
};
});
mnemonicOptions.push(...savedMnemonics);
return await (await showQuickPick(
mnemonicOptions,
{ placeHolder: Constants.placeholders.setupMnemonic, ignoreFocusOut: true })).cmd();
}
private async saveMnemonicFile(mnemonic: string): Promise<string> {
const path = await saveTextInFile(
mnemonic,
'',
{ Files: [Constants.mnemonicConstants.fileExt]});
MnemonicRepository.saveMnemonicPath(path);
return path;
}
}

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

@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { QuickPickItem } from 'vscode';
export class NetworkForContractItem implements QuickPickItem {
public readonly label: string;
public readonly host: string;
public readonly contractAddress: string;
constructor(label: string, host: string, contractAddress: string) {
this.label = label;
this.host = host;
this.contractAddress = contractAddress;
}
}

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

@ -1,14 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { QuickPickItem } from 'vscode';
export class ResourceGroupItem implements QuickPickItem {
public readonly label: string;
public readonly description: string;
constructor(label?: string, location?: string) {
this.label = label || '';
this.description = location || '';
}
}

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

@ -1,14 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { QuickPickItem } from 'vscode';
export class SkuItem implements QuickPickItem {
public readonly label: string;
public readonly description: string;
constructor(tier: string, name: string) {
this.label = tier;
this.description = name;
}
}

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

@ -1,19 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { QuickPickItem } from 'vscode';
import { AzureSession } from '../azure-account.api';
export class SubscriptionItem implements QuickPickItem {
public readonly label: string;
public readonly description: string;
public readonly session: AzureSession;
public readonly subscriptionId: string;
constructor(label: string, subscriptionId: string, session: AzureSession) {
this.label = label;
this.description = subscriptionId;
this.subscriptionId = subscriptionId;
this.session = session;
}
}

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

@ -1,45 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TruffleConfiguration } from '../helpers';
import { ItemType } from './ItemType';
import { NetworkConsortium } from './NetworkConsortium';
export class TestNetworkConsortium extends NetworkConsortium {
constructor(consortiumName: string, url?: string) {
super(ItemType.ETHEREUM_TEST_CONSORTIUM, consortiumName);
if (url) {
this.addUrl(url);
}
}
public async getTruffleNetwork(): Promise<TruffleConfiguration.INetwork> {
const network = await super.getTruffleNetwork();
const targetURL = network.options.provider!.url;
network.options.network_id = this.getNetworkId(targetURL!);
return network;
}
/**
* https://ethereum.stackexchange.com/questions/17051/how-to-select-a-network-id-or-is-there-a-list-of-network-ids
*/
private getNetworkId(host: string): number | string {
host = host.toLowerCase();
if (host.includes('ropsten')) {
return 3;
} else if (host.includes('rinkeby')) {
return 4;
} else if (host.includes('kovan')) {
return 42;
} else if (host.includes('goerli')) {
return 5;
} else if (host.includes('kotti')) {
return 6;
}
return '*';
}
}

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

@ -1,25 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Constants } from '../Constants';
import { ExtensionItem } from './ExtensionItem';
import { ItemType } from './ItemType';
export class TransactionNode extends ExtensionItem {
private readonly dns: string;
constructor(transactionNodeName: string, dns: string) {
super(ItemType.TRANSACTION_NODE, transactionNodeName);
this.contextValue = Constants.contextValue.transactionNode;
this.iconPath = Constants.icons.transactionNode;
this.dns = dns;
}
public toJSON(): { [p: string]: any } {
const obj = super.toJSON();
obj.dns = this.dns;
return obj;
}
}

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

@ -1,194 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ResourceManagementClient, SubscriptionClient } from 'azure-arm-resource';
import { commands, extensions, ProgressLocation, QuickPickItem, window } from 'vscode';
import { AzureAccount } from './azure-account.api';
import { Constants } from './Constants';
import { showInputBox, showQuickPick } from './helpers';
import { LocationItem, ResourceGroupItem, SubscriptionItem } from './Models';
import { Telemetry } from './TelemetryClient';
import { AzureBlockchainServiceValidator } from './validators/AzureBlockchainServiceValidator';
interface ICachedLocationItems {
locationItems: LocationItem[];
providerLocationItems: LocationItem[];
}
export class ResourceExplorerAndGenerator {
private static cache: { [subscriptionId: string]: ICachedLocationItems } = {};
protected readonly _accountApi: AzureAccount;
constructor() {
this._accountApi = extensions.getExtension<AzureAccount>('ms-vscode.azure-account')!.exports;
}
protected async getOrSelectSubscriptionItem(): Promise<SubscriptionItem> {
return showQuickPick(
await this.getSubscriptionItems(),
{ placeHolder: Constants.placeholders.selectSubscription, ignoreFocusOut: true },
);
}
protected async getOrCreateResourceGroupItem(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem> {
const pick = await showQuickPick(
this.getResourceGroupItems(subscriptionItem),
{ placeHolder: Constants.placeholders.selectResourceGroup, ignoreFocusOut: true },
);
if (pick instanceof ResourceGroupItem) {
Telemetry.sendEvent('ResourceExplorerAndGenerator.getOrCreateResourceGroupItem.itemIsResourceGroupItem');
return pick;
} else {
Telemetry.sendEvent('ResourceExplorerAndGenerator.getOrCreateResourceGroupItem.createResourceGroupItemSelected');
return this.createResourceGroup(subscriptionItem);
}
}
protected async getLocationItems(subscriptionItem: SubscriptionItem): Promise<LocationItem[]> {
const cachedLocationItems = await this.getCachedLocationItems(subscriptionItem);
const locationItems = cachedLocationItems.locationItems;
const providerLocationItems = cachedLocationItems.providerLocationItems;
return providerLocationItems.length !== 0 ? providerLocationItems : locationItems;
}
protected async waitForLogin(): Promise<boolean> {
let result = await this._accountApi.waitForLogin();
if (!result) {
await commands.executeCommand('azure-account.askForLogin');
result = await this._accountApi.waitForLogin();
if (!result) {
const error = new Error(Constants.errorMessageStrings.WaitForLogin);
Telemetry.sendException(error);
throw error;
}
}
return true;
}
private async getSubscriptionItems(): Promise<SubscriptionItem[]> {
await this._accountApi.waitForFilters();
const subscriptionItems = this._accountApi.filters
.map((filter) => new SubscriptionItem(
filter.subscription.displayName || '',
filter.subscription.subscriptionId || '',
filter.session,
));
if (subscriptionItems.length === 0) {
const error = new Error(Constants.errorMessageStrings.NoSubscriptionFoundClick);
Telemetry.sendException(error);
throw error;
}
return subscriptionItems;
}
private async getResourceGroupItems(subscriptionItem: SubscriptionItem): Promise<QuickPickItem[]> {
const createGroupItem: QuickPickItem = { label: '$(plus) Create Resource Group' };
const items: QuickPickItem[] = [];
const resourceManagementClient = await this.getResourceClient(subscriptionItem);
const resourceGroups = await resourceManagementClient.resourceGroups.list();
const cachedLocationItems = await this.getCachedLocationItems(subscriptionItem);
const locationItems = cachedLocationItems.locationItems;
const resourceItems = resourceGroups.map((resourceGroup) => {
const location = locationItems.find((locationItem) => locationItem.description === resourceGroup.location);
return new ResourceGroupItem(
resourceGroup.name,
location ? location.description : resourceGroup.location,
);
});
items.push(createGroupItem);
items.push(...resourceItems);
return items;
}
private async getSubscriptionClient(subscriptionItem: SubscriptionItem)
: Promise<SubscriptionClient.SubscriptionClient> {
return new SubscriptionClient.SubscriptionClient(
subscriptionItem.session.credentials,
subscriptionItem.session.environment.resourceManagerEndpointUrl,
);
}
private async getResourceClient(subscriptionItem: SubscriptionItem)
: Promise<ResourceManagementClient.ResourceManagementClient> {
return new ResourceManagementClient.ResourceManagementClient(
subscriptionItem.session.credentials,
subscriptionItem.subscriptionId,
subscriptionItem.session.environment.resourceManagerEndpointUrl,
);
}
private async createResourceGroup(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem> {
const { resourceGroups } = await this.getResourceClient(subscriptionItem);
const resourceGroupName = await showInputBox({
ignoreFocusOut: true,
placeHolder: Constants.placeholders.resourceGroupName,
prompt: Constants.paletteABSLabels.provideResourceGroupName,
validateInput: (name) => AzureBlockchainServiceValidator.validateResourceGroupName(name, resourceGroups),
});
const locationItem = await showQuickPick(
this.getLocationItems(subscriptionItem),
{ placeHolder: Constants.placeholders.selectRgLocation, ignoreFocusOut: true },
);
return window.withProgress({
location: ProgressLocation.Notification,
title: `Creating resource group '${resourceGroupName}'`,
}, async () => {
if (subscriptionItem.subscriptionId === undefined) {
const error = new Error(Constants.errorMessageStrings.NoSubscriptionFound);
Telemetry.sendException(error);
throw error;
} else {
Telemetry.sendEvent('ResourceExplorerAndGenerator.createResourceGroup.withProgress.subscriptionIdIsDefined');
const resourceManagementClient = await this.getResourceClient(subscriptionItem);
const resourceGroup = await resourceManagementClient.resourceGroups.createOrUpdate(
resourceGroupName,
{ location: locationItem.description },
);
return new ResourceGroupItem(resourceGroup.name, resourceGroup.location);
}
});
}
private async getCachedLocationItems(subscriptionItem: SubscriptionItem): Promise<ICachedLocationItems> {
const cache = ResourceExplorerAndGenerator.cache;
if (cache[subscriptionItem.subscriptionId]) {
return cache[subscriptionItem.subscriptionId];
}
const subscriptionClient = await this.getSubscriptionClient(subscriptionItem);
const resourceManagementClient = await this.getResourceClient(subscriptionItem);
const locations = await subscriptionClient.subscriptions.listLocations(subscriptionItem.subscriptionId);
const blockchain = await resourceManagementClient.providers.get(Constants.azureResourceExplorer.providerName);
const locationItems = locations.map((location) => new LocationItem(location.displayName, location.name));
const providerLocationItems: LocationItem[] = [];
const blockchainMember = blockchain.resourceTypes && blockchain.resourceTypes.find((resourceType) => {
return resourceType.resourceType === Constants.azureResourceExplorer.resourceType;
});
if (blockchainMember && blockchainMember.locations) {
providerLocationItems.push(...locationItems
.filter((item) => blockchainMember.locations!.includes(item.label))
.sort((a, b) => a.label.localeCompare(b.label)));
}
const cachedLocationItems = {
locationItems,
providerLocationItems,
};
cache[subscriptionItem.subscriptionId] = cachedLocationItems;
return cachedLocationItems;
}
}

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

@ -1,11 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Command } from '../Models';
import { ExtensionView } from './ExtensionView';
export class CommandView extends ExtensionView<Command> {
constructor(commandItem: Command) {
super(commandItem);
}
}

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

@ -1,15 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Consortium } from '../Models';
import { ExtensionView } from './ExtensionView';
export class ConsortiumView extends ExtensionView<Consortium> {
constructor(consortiumItem: Consortium) {
super(consortiumItem);
}
public async getRPCAddress(): Promise<string> {
return this.extensionItem.getRPCAddress();
}
}

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

@ -1,11 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Info } from '../Models';
import { ExtensionView } from './ExtensionView';
export class InfoView extends ExtensionView<Info> {
constructor(infoItem: Info) {
super(infoItem);
}
}

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

@ -1,11 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Network } from '../Models';
import { ExtensionView } from './ExtensionView';
export class NetworkView extends ExtensionView<Network> {
constructor(networkItem: Network) {
super(networkItem);
}
}

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

@ -1,11 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TransactionNode } from '../Models';
import { ExtensionView } from './ExtensionView';
export class TransactionNodeView extends ExtensionView<TransactionNode> {
constructor(transactionNodeItem: TransactionNode) {
super(transactionNodeItem);
}
}

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

@ -1,12 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Command } from '../../Models';
import { CommandView } from '../CommandView';
import { ViewCreator } from './ViewCreator';
export class CommandViewCreator extends ViewCreator {
public create(commandItem: Command): CommandView {
return new CommandView(commandItem);
}
}

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

@ -1,12 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Consortium } from '../../Models';
import { ConsortiumView } from '../ConsortiumView';
import { ViewCreator } from './ViewCreator';
export class ConsortiumViewCreator extends ViewCreator {
public create(consortiumItem: Consortium): ConsortiumView {
return new ConsortiumView(consortiumItem);
}
}

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

@ -1,12 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Info } from '../../Models';
import { InfoView } from '../InfoView';
import { ViewCreator } from './ViewCreator';
export class InfoViewCreator extends ViewCreator {
public create(infoItem: Info): InfoView {
return new InfoView(infoItem);
}
}

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

@ -1,12 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Network } from '../../Models';
import { NetworkView } from '../NetworkView';
import { ViewCreator } from './ViewCreator';
export class NetworkViewCreator extends ViewCreator {
public create(networkItem: Network): NetworkView {
return new NetworkView(networkItem);
}
}

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

@ -1,12 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TransactionNode } from '../../Models';
import { TransactionNodeView } from '../TransactionNodeView';
import { ViewCreator } from './ViewCreator';
export class TransactionNodeViewCreator extends ViewCreator {
public create(transactionNodeItem: TransactionNode): TransactionNodeView {
return new TransactionNodeView(transactionNodeItem);
}
}

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

@ -1,228 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ConsortiumResourceExplorer } from '../ConsortiumResourceExplorer';
import { Constants } from '../Constants';
import { GanacheService } from '../GanacheService/GanacheService';
import { showInputBox, showQuickPick } from '../helpers';
import { findPid } from '../helpers/shell';
import {
AzureConsortium,
Consortium,
ItemType,
LocalNetworkConsortium,
MainNetworkConsortium,
Network,
TestNetworkConsortium,
} from '../Models';
import { Telemetry } from '../TelemetryClient';
import { ConsortiumTreeManager } from '../treeService/ConsortiumTreeManager';
import { UrlValidator } from '../validators/UrlValidator';
import { ConsortiumView } from '../ViewItems';
interface IConsortiumDestination {
cmd: (network?: Network) => Promise<Consortium>;
itemType: ItemType;
label: string;
}
export namespace ConsortiumCommands {
export async function createConsortium(consortiumTreeManager: ConsortiumTreeManager): Promise<Consortium> {
Telemetry.sendEvent('ConsortiumCommands.createConsortium.commandStarted');
const createConsortiumDestination: IConsortiumDestination[] = [
{
cmd: selectOrCreateConsortium,
itemType: ItemType.AZURE_BLOCKCHAIN,
label: Constants.uiCommandStrings.CreateConsortiumAzureBlockchainService,
},
];
const consortium = await execute(createConsortiumDestination, consortiumTreeManager, false);
Telemetry.sendEvent('ConsortiumCommands.createConsortium.commandFinished');
return consortium;
}
export async function connectConsortium(consortiumTreeManager: ConsortiumTreeManager): Promise<Consortium> {
Telemetry.sendEvent('ConsortiumCommands.connectConsortium.commandStarted');
const connectConsortiumDestination: IConsortiumDestination[] = [
{
cmd: connectLocalNetwork,
itemType: ItemType.LOCAL_NETWORK,
label: Constants.uiCommandStrings.ConnectConsortiumLocalGanache,
},
{
cmd: selectOrCreateConsortium,
itemType: ItemType.AZURE_BLOCKCHAIN,
label: Constants.uiCommandStrings.ConnectConsortiumAzureBlockchainService,
},
{
cmd: connectToEthereumTestnet,
itemType: ItemType.ETHEREUM_TEST_NETWORK,
label: Constants.uiCommandStrings.ConnectConsortiumTestEthereum,
},
{
cmd: connectToPublicNetwork,
itemType: ItemType.ETHEREUM_MAIN_NETWORK,
label: Constants.uiCommandStrings.ConnectConsortiumPublicEthereum,
},
];
const consortium = await execute(connectConsortiumDestination, consortiumTreeManager);
Telemetry.sendEvent('ConsortiumCommands.connectConsortium.commandFinished');
return consortium;
}
export async function disconnectConsortium(consortiumTreeManager: ConsortiumTreeManager, viewItem: ConsortiumView)
: Promise<void> {
Telemetry.sendEvent('ConsortiumCommands.disconnectConsortium.commandStarted');
if (viewItem.extensionItem instanceof LocalNetworkConsortium) {
Telemetry.sendEvent('ConsortiumCommands.disconnectConsortium.localNetworkConsortiumSelected');
const port = await viewItem.extensionItem.getPort();
if (port) {
Telemetry.sendEvent('ConsortiumCommands.disconnectConsortium.portDefined');
await GanacheService.stopGanacheServer(port);
}
}
const consortiumView = await consortiumTreeManager.removeItem(viewItem.extensionItem);
Telemetry.sendEvent('ConsortiumCommands.disconnectConsortium.commandFinished');
return consortiumView;
}
}
async function execute(
consortiumDestination: IConsortiumDestination[],
consortiumTreeManager: ConsortiumTreeManager,
addChild: boolean = true,
): Promise<Consortium> {
const destination = await selectDestination(consortiumDestination);
const networkItem = await getNetwork(consortiumTreeManager, destination.itemType);
const consortiumItem = await destination.cmd(networkItem);
if (addChild) {
Telemetry.sendEvent('ConsortiumCommands.execute.addChild');
await networkItem.addChild(consortiumItem);
}
Telemetry.sendEvent(
'ConsortiumCommands.execute.newConsortiumItem',
{
ruri: Telemetry.obfuscate((consortiumItem.resourceUri || '').toString()),
type: Telemetry.obfuscate(consortiumItem.itemType.toString()),
urls: Telemetry.obfuscate(JSON.stringify(consortiumItem.getUrls())),
});
return consortiumItem;
}
function getConnectedAbsConsortia(networkItem: Network): string[] {
return networkItem
.getChildren()
.filter((e) => e.label)
.map((e) => e.label) as string[];
}
async function selectDestination(consortiumDestination: IConsortiumDestination[]): Promise<IConsortiumDestination> {
return showQuickPick(
consortiumDestination,
{
ignoreFocusOut: true,
placeHolder: Constants.placeholders.selectDestination,
},
);
}
async function getNetwork(consortiumTreeManager: ConsortiumTreeManager, itemType: ItemType): Promise<Network> {
const networkItem = consortiumTreeManager.getItem(itemType) as Network;
if (networkItem === undefined) {
const error = new Error(Constants.errorMessageStrings.ActionAborted);
Telemetry.sendException(error);
throw error;
}
return networkItem;
}
async function selectOrCreateConsortium(network?: Network): Promise<AzureConsortium> {
const excludedItems = network ? getConnectedAbsConsortia(network) : [];
const azureResourceExplorer = new ConsortiumResourceExplorer();
return azureResourceExplorer.selectOrCreateConsortium(excludedItems);
}
async function connectLocalNetwork(network?: Network): Promise<LocalNetworkConsortium> {
const ports = await getExistingLocalPorts(network);
const port = await showInputBox({
ignoreFocusOut: true,
prompt: Constants.paletteABSLabels.enterLocalNetworkLocation,
validateInput: async (value: string) => {
const validationError = UrlValidator.validatePort(value);
if (validationError) {
return validationError;
}
if (ports.some((existPort) => existPort === value)) {
return Constants.validationMessages.networkAlreadyExists;
}
if (!isNaN(await findPid(value))) {
return Constants.validationMessages.portAlreadyInUse;
}
return null;
},
});
await GanacheService.startGanacheServer(port);
const label = `${Constants.localhostName}:${port}`;
const url = `${Constants.networkProtocols.http}${Constants.localhost}:${port}`;
return new LocalNetworkConsortium(label, url);
}
async function connectToEthereumTestnet(): Promise<TestNetworkConsortium> {
const consortiumName = await getConsortiumName();
const url = await getConsortiumUrl();
return new TestNetworkConsortium(consortiumName, url);
}
async function connectToPublicNetwork(): Promise<MainNetworkConsortium> {
const consortiumName = await getConsortiumName();
const url = await getConsortiumUrl();
return new MainNetworkConsortium(consortiumName, url);
}
async function getConsortiumName() {
return showInputBox({
ignoreFocusOut: true,
prompt: Constants.paletteABSLabels.enterConsortiumName,
validateInput: (value: string) => {
if (!value) {
return Constants.validationMessages.valueCannotBeEmpty;
}
return;
},
});
}
async function getConsortiumUrl() {
return showInputBox({
ignoreFocusOut: true,
prompt: Constants.paletteABSLabels.enterNetworkLocation,
validateInput: (value: string) => {
return UrlValidator.validateHostUrl(value);
},
});
}
async function getExistingLocalPorts(network?: Network): Promise<string[]> {
const localNetworks = network ? await network.getChildren() : [];
return await Promise.all((localNetworks as LocalNetworkConsortium[])
.map(async (item) => `${await item.getPort()}`));
}

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

@ -4,102 +4,126 @@
import open = require('open');
import { ProgressLocation, window } from 'vscode';
import { Constants } from '../Constants';
import { showQuickPick } from '../helpers';
import { openZeppelinHelper, showQuickPick } from '../helpers';
import { Output } from '../Output';
import {
IOZAsset,
IOZContractCategory,
OpenZeppelinMigrationsService,
OpenZeppelinService,
PromiseState,
} from '../services';
import { OpenZeppelinMigrationsService, OpenZeppelinService } from '../services';
import { IOZAsset, IOZContractCategory, PromiseState } from '../services/openZeppelin/models';
import { Telemetry } from '../TelemetryClient';
export namespace OpenZeppelinCommands {
export async function addCategory(): Promise<void> {
Telemetry.sendEvent('OpenZeppelinCommands.addCategory');
const categories = OpenZeppelinService.getCategories();
const currentOZVersion = await openZeppelinHelper.tryGetCurrentOpenZeppelinVersionAsync();
const manifest = await openZeppelinHelper.createManifestAsync(currentOZVersion);
const categories = await manifest.getCategories();
const category = await selectCategory(categories);
Telemetry.sendEvent('OpenZeppelinCommands.addCategory.selected', { name: category.name });
const fullAssetWithDependencies = OpenZeppelinService.collectAssetsWithDependencies(category.assets);
const baseUrl = manifest.getBaseUrlToContractsSource();
const fullAssetWithDependencies = manifest.collectAssetsWithDependencies(category.assets);
Output.outputLine(
Constants.outputChannel.azureBlockchain,
Constants.openZeppelin.categoryWillDownloaded(category.name),
);
const assetsStatuses = OpenZeppelinService.getAssetsStatus(fullAssetWithDependencies);
const assetsStatuses = await OpenZeppelinService.getAssetsStatus(fullAssetWithDependencies);
Output.outputLine(
Constants.outputChannel.azureBlockchain,
Constants.openZeppelin.fileNow(assetsStatuses.existing.length),
);
if (assetsStatuses.existing.length > 0) {
const answer = await window.showInformationMessage(
Constants.openZeppelin.alreadyExisted(assetsStatuses.existing),
Constants.openZeppelin.replaceButtonTitle,
Constants.openZeppelin.skipButtonTitle,
);
const downloadedAssets
= await downloadOZFiles(baseUrl, assetsStatuses.existing, assetsStatuses.missing, fullAssetWithDependencies);
await OpenZeppelinService.updateProjectJsonAsync(manifest.getVersion(), category, downloadedAssets);
openDocumentationUrl(manifest.getCategoryApiDocumentationUrl(category));
Telemetry.sendEvent('OpenZeppelinCommands.addCategory.overwriteExistedDialog', { name: answer || '' });
if (answer === Constants.openZeppelin.replaceButtonTitle) {
Output.outputLine(
Constants.outputChannel.azureBlockchain,
Constants.openZeppelin.overwriteExistedContracts,
);
await downloadFileSetWithProgress(fullAssetWithDependencies, true);
} else {
await downloadFileSetWithProgress(assetsStatuses.missing, false);
}
} else {
await downloadFileSetWithProgress(fullAssetWithDependencies, false);
}
openDocumentationUrl(category);
Telemetry.sendEvent('OpenZeppelinCommands.addCategory.generateMigrations');
await OpenZeppelinMigrationsService.generateMigrations(await OpenZeppelinService.getAllDownloadedAssets());
await OpenZeppelinMigrationsService.generateMigrations(await OpenZeppelinService.getAllDownloadedAssetsAsync());
}
}
async function downloadFileSetWithProgress(assets: IOZAsset[], overwrite: boolean = false): Promise<void> {
async function downloadOZFiles(
baseUrl: string,
existing: IOZAsset[],
missing: IOZAsset[],
fullAssetWithDependencies: IOZAsset[])
: Promise<IOZAsset[]> {
let downloadedAssets: IOZAsset[];
if (existing.length > 0) {
const answer = await window.showInformationMessage(
Constants.openZeppelin.alreadyExisted(existing),
Constants.openZeppelin.replaceButtonTitle,
Constants.openZeppelin.skipButtonTitle,
);
Telemetry.sendEvent('OpenZeppelinCommands.downloadOZFiles.overwriteExistedDialog', { name: answer || '' });
if (answer === Constants.openZeppelin.replaceButtonTitle) {
Output.outputLine(
Constants.outputChannel.azureBlockchain,
Constants.openZeppelin.overwriteExistedContracts,
);
downloadedAssets = await downloadFileSetWithProgress(baseUrl, fullAssetWithDependencies, true);
} else {
downloadedAssets = await downloadFileSetWithProgress(baseUrl, missing, false);
}
} else {
downloadedAssets = await downloadFileSetWithProgress(baseUrl, fullAssetWithDependencies, false);
}
if (downloadedAssets.length) {
window.showInformationMessage(Constants.openZeppelin.wereDownloaded(downloadedAssets.length));
}
return downloadedAssets;
}
async function downloadFileSetWithProgress(
baseUri: string,
assets: IOZAsset[],
overwrite: boolean = false)
: Promise<IOZAsset[]> {
return window.withProgress({
location: ProgressLocation.Notification,
title: Constants.openZeppelin.downloadingContractsFromOpenZeppelin,
}, async () => downloadFileSet(assets, overwrite),
);
}
}, async () => downloadFileSet(assets));
async function downloadFileSet(assets: IOZAsset[], overwrite: boolean): Promise<void> {
const results = await OpenZeppelinService.downloadFiles(assets, overwrite);
async function downloadFileSet(_assets: IOZAsset[])
: Promise<IOZAsset[]> {
const results = await OpenZeppelinService.downloadAssetsAsync(baseUri, _assets, overwrite);
const downloaded = results
.filter((result) => result.state === PromiseState.fulfilled)
.map((result) => result.asset);
let downloaded = results
.filter((result) => result.state === PromiseState.fulfilled)
.map((result) => result.asset);
const rejected = results
.filter((result) => result.state === PromiseState.rejected)
.map((result) => result.asset);
Telemetry.sendEvent(
'OpenZeppelinCommands.downloadFileSet.result',
{ downloadedCount: downloaded.length.toString(), rejectedCount: rejected.length.toString() },
);
if (downloaded.length > 0) {
await OpenZeppelinService.addAssetsToProjectJson(downloaded);
window.showInformationMessage(Constants.openZeppelin.wereDownloaded(downloaded.length));
}
if (rejected.length > 0) {
const answer = await window.showErrorMessage(
Constants.openZeppelin.wereNotDownloaded(rejected.length),
Constants.openZeppelin.retryButtonTitle,
Constants.openZeppelin.cancelButtonTitle,
const rejected = results
.filter((result) => result.state === PromiseState.rejected)
.map((result) => result.asset);
Telemetry.sendEvent(
'OpenZeppelinCommands.downloadFileSet.result',
{ downloadedCount: downloaded.length.toString(), rejectedCount: rejected.length.toString() },
);
if (answer === Constants.openZeppelin.retryButtonTitle) {
Output.outputLine(
Constants.outputChannel.azureBlockchain,
Constants.openZeppelin.retryDownloading,
if (rejected.length > 0) {
const answer = await window.showErrorMessage(
Constants.openZeppelin.wereNotDownloaded(rejected.length),
Constants.openZeppelin.retryButtonTitle,
Constants.openZeppelin.cancelButtonTitle,
);
Telemetry.sendEvent('OpenZeppelinCommands.downloadFileSet.retry', { assetsCount: rejected.length.toString() });
await downloadFileSet(rejected, overwrite);
if (answer === Constants.openZeppelin.retryButtonTitle) {
Output.outputLine(
Constants.outputChannel.azureBlockchain,
Constants.openZeppelin.retryDownloading,
);
Telemetry.sendEvent('OpenZeppelinCommands.downloadFileSet.retry', { assetsCount: rejected.length.toString() });
downloaded = downloaded.concat(await downloadFileSet(rejected));
}
}
return downloaded;
}
}
@ -118,8 +142,7 @@ async function selectCategory(categories: IOZContractCategory[]): Promise<IOZCon
);
}
async function openDocumentationUrl(category: IOZContractCategory): Promise<void> {
const documentationUrl = OpenZeppelinService.getCategoryApiDocumentationUrl(category);
async function openDocumentationUrl(documentationUrl?: string): Promise<void> {
if (!documentationUrl) {
return;
}

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

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

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

@ -6,24 +6,35 @@ import * as fs from 'fs-extra';
// @ts-ignore
import * as hdkey from 'hdkey';
import * as path from 'path';
import { ProgressLocation, QuickPickItem, Uri, window } from 'vscode';
import { QuickPickItem, Uri, window } from 'vscode';
import { Constants, RequiredApps } from '../Constants';
import {
getWorkspaceRoot,
openZeppelinHelper,
outputCommandHelper,
required,
showConfirmPaidOperationDialog,
showIgnorableNotification,
showQuickPick,
TruffleConfig,
TruffleConfiguration,
vscodeEnvironment,
} from '../helpers';
import { IDeployDestination, ItemType } from '../Models';
import { NetworkForContractItem } from '../Models/QuickPickItems/NetworkForContractItem';
import { LocalService } from '../Models/TreeItems';
import { Project } from '../Models/TreeItems';
import { Output } from '../Output';
import { ContractDB, GanacheService, MnemonicRepository, OpenZeppelinService, TreeManager } from '../services';
import { OZContractValidated } from '../services/openZeppelin/OpenZeppelinService';
import {
ContractDB,
ContractInstanceWithMetadata,
ContractService,
GanacheService,
MnemonicRepository,
OpenZeppelinService,
TreeManager,
} from '../services';
import { OZContractValidated } from '../services/openZeppelin/models';
import { Telemetry } from '../TelemetryClient';
import { ProjectView } from '../ViewItems';
import { ServiceCommands } from './ServiceCommands';
@ -47,17 +58,18 @@ interface IExtendedQuickPickItem extends QuickPickItem {
export namespace TruffleCommands {
export async function buildContracts(): Promise<void> {
Telemetry.sendEvent('TruffleCommands.buildContracts.commandStarted');
await window.withProgress({
location: ProgressLocation.Window,
title: Constants.statusBarMessages.buildingContracts,
}, async () => {
if (!await required.checkAppsSilent(RequiredApps.truffle)) {
Telemetry.sendEvent('TruffleCommands.buildContracts.truffleInstallation');
await required.installTruffle(required.Scope.locally);
}
await showIgnorableNotification(
Constants.statusBarMessages.buildingContracts,
async () => {
if (!await required.checkAppsSilent(RequiredApps.truffle)) {
Telemetry.sendEvent('TruffleCommands.buildContracts.truffleInstallation');
await required.installTruffle(required.Scope.locally);
}
await outputCommandHelper.executeCommand(getWorkspaceRoot(), 'npx', RequiredApps.truffle, 'compile');
},
);
await outputCommandHelper.executeCommand(getWorkspaceRoot(), 'npx', RequiredApps.truffle, 'compile');
});
Telemetry.sendEvent('TruffleCommands.buildContracts.commandFinished');
}
@ -89,8 +101,7 @@ export namespace TruffleCommands {
{ url: Telemetry.obfuscate(command.description || '') },
);
await validateOpenZeppelinContracts();
await checkOpenZeppelinIfUsed();
await command.cmd();
Telemetry.sendEvent('TruffleCommands.deployContracts.commandFinished');
@ -114,9 +125,39 @@ export namespace TruffleCommands {
export async function writeDeployedBytecodeToBuffer(uri: Uri): Promise<void> {
Telemetry.sendEvent('TruffleCommands.writeBytecodeToBuffer.commandStarted');
const contract = await readCompiledContract(uri);
await vscodeEnvironment.writeToClipboard(contract[Constants.contractProperties.deployedBytecode]);
ensureFileIsContractJson(uri.fsPath);
const contractInstances = await ContractDB.getContractInstances(
path.basename(uri.fsPath, Constants.contractExtension.json)) as ContractInstanceWithMetadata[];
const contractInstancesWithNetworkInfo = contractInstances.filter((contractIns) => {
return contractIns.network.name !== undefined && !!contractIns.provider && !!contractIns.address;
});
if (!contractInstancesWithNetworkInfo.length) {
window.showInformationMessage(Constants.informationMessage.contractNotDeployed);
return;
}
const networkQuickPickItems = contractInstancesWithNetworkInfo.map((contractIns) =>
new NetworkForContractItem(contractIns.network.name!, contractIns.provider!.host, contractIns.address!));
const networkItem = await showQuickPick(
networkQuickPickItems,
{ placeHolder: 'Select a network', ignoreFocusOut: true },
);
try {
const deployedBytecode =
await ContractService.getDeployedBytecodeByAddress(networkItem.host, networkItem.contractAddress);
window.showInformationMessage(Constants.informationMessage.transactionBytecodeWasCopiedToClipboard);
await vscodeEnvironment.writeToClipboard(deployedBytecode);
} catch (ex) {
Telemetry.sendException(ex);
window.showErrorMessage(Constants.errorMessageStrings.FetchingDeployedBytecodeIsFailed);
}
Telemetry.sendEvent('TruffleCommands.writeBytecodeToBuffer.commandFinished');
}
@ -179,6 +220,17 @@ export namespace TruffleCommands {
}
}
async function checkOpenZeppelinIfUsed(): Promise<void> {
if (OpenZeppelinService.projectJsonExists()) {
if (await openZeppelinHelper.shouldUpgradeOpenZeppelinAsync()) {
await openZeppelinHelper.upgradeOpenZeppelinContractsAsync();
await openZeppelinHelper.upgradeOpenZeppelinUserSettingsAsync();
}
await validateOpenZeppelinContracts();
}
}
function removeDuplicateNetworks(deployDestinations: IDeployDestinationItem[]): IDeployDestinationItem[] {
return deployDestinations.filter((destination, index, destinations) => {
return destinations.findIndex((dest) => dest.label === destination.label) === index;
@ -208,7 +260,7 @@ async function installRequiredDependencies(): Promise<void> {
}
async function validateOpenZeppelinContracts(): Promise<void> {
const validatedContracts = await OpenZeppelinService.validateContracts();
const validatedContracts = await OpenZeppelinService.validateContractsAsync();
validatedContracts.forEach((ozContract: OZContractValidated) => {
if (ozContract.isExistedOnDisk) {
Output.outputLine('', ozContract.isHashValid
@ -396,29 +448,29 @@ async function createNetwork(getTruffleNetwork: () => Promise<TruffleConfigurati
}
async function deployToNetwork(networkName: string, truffleConfigPath: string): Promise<void> {
return window.withProgress({
location: ProgressLocation.Window,
title: Constants.statusBarMessages.deployingContracts(networkName),
}, async () => {
const workspaceRoot = path.dirname(truffleConfigPath);
await showIgnorableNotification(
Constants.statusBarMessages.deployingContracts(networkName),
async () => {
const workspaceRoot = path.dirname(truffleConfigPath);
await fs.ensureDir(workspaceRoot);
await fs.ensureDir(workspaceRoot);
try {
await installRequiredDependencies();
await outputCommandHelper.executeCommand(
workspaceRoot,
'npx',
RequiredApps.truffle, 'migrate', '--reset', '--network', networkName,
);
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deploySucceeded);
} catch (error) {
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deployFailed);
throw error;
}
try {
await installRequiredDependencies();
await outputCommandHelper.executeCommand(
workspaceRoot,
'npx',
RequiredApps.truffle, 'migrate', '--reset', '--network', networkName,
);
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deploySucceeded);
} catch (error) {
Output.outputLine(Constants.outputChannel.azureBlockchain, Constants.informationMessage.deployFailed);
throw error;
}
await ContractDB.updateContracts();
});
await ContractDB.updateContracts();
},
);
}
async function deployToLocalGanache(networkName: string, truffleConfigPath: string, port: number): Promise<void> {
@ -433,13 +485,16 @@ async function deployToMainNetwork(networkName: string, truffleConfigPath: strin
}
async function readCompiledContract(uri: Uri): Promise<any> {
if (path.extname(uri.fsPath) !== Constants.contractExtension.json) {
const error = new Error(Constants.errorMessageStrings.InvalidContract);
Telemetry.sendException(error);
throw error;
}
ensureFileIsContractJson(uri.fsPath);
const data = fs.readFileSync(uri.fsPath, null);
return JSON.parse(data.toString());
}
function ensureFileIsContractJson(filePath: string) {
if (path.extname(filePath) !== Constants.contractExtension.json) {
const error = new Error(Constants.errorMessageStrings.InvalidContract);
Telemetry.sendException(error);
throw error;
}
}

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

@ -1,13 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as cp from 'child_process';
import * as os from 'os';
// The same implementation as in helpers/truffleConfig.ts
// The same implementation as in helpers/command.ts
// The difference is that all code which uses 'vscode' module is removed.
// TODO: think how to reuse code
interface IForkMessage {
command: string;
message?: string;
batch?: {
index: number;
done: boolean;
message: string;
};
}
export interface ICommandResult {
code: number;
cmdOutput: string;
cmdOutputIncludingStderr: string;
code: number;
cmdOutput: string;
cmdOutputIncludingStderr: string;
messages?: Array<{[key: string]: any}>;
}
export interface ICommandExecute {
childProcess: cp.ChildProcess;
result: Promise<ICommandResult>;
}
export async function executeCommand(
@ -18,7 +37,7 @@ export async function executeCommand(
const result: ICommandResult = await tryExecuteCommand(workingDirectory, commands, ...args);
if (result.code !== 0) {
throw new Error('Error while executin command: ' + commands.concat(' ', ...args.join(' ')));
throw new Error('Error while execution command: ' + commands.concat(' ', ...args.join(' ')));
}
return result.cmdOutput;
@ -54,3 +73,77 @@ async function tryExecuteCommand(workingDirectory: string | undefined, commands:
});
});
}
export async function executeCommandInFork(workingDirectory: string | undefined, modulePath: string, ...args: string[])
: Promise<string> {
const result: ICommandResult = await tryExecuteCommandInFork(workingDirectory, modulePath, ...args);
if (result.code !== 0) {
throw new Error(`Failed to run script - ${modulePath}. More details in output`);
}
return result.cmdOutput;
}
export function forkProcess(workingDirectory: string | undefined, modulePath: string, args: string[]): cp.ChildProcess {
const options: cp.ForkOptions = { cwd: workingDirectory || os.tmpdir(), silent: true };
return cp.fork(modulePath, args, options);
}
export async function tryExecuteCommandInFork(
workingDirectory: string | undefined,
modulePath: string,
...args: string[]
): Promise<ICommandResult> {
const { result } = tryExecuteCommandInForkAsync(workingDirectory, modulePath, ...args);
return result;
}
export function tryExecuteCommandInForkAsync(
workingDirectory: string | undefined,
modulePath: string,
...args: string[]
): ICommandExecute {
let cmdOutput: string = '';
let cmdOutputIncludingStderr: string = '';
const messages: Array<string | object> = [];
const batches: {[key: string]: string[]} = {};
const childProcess = forkProcess(workingDirectory, modulePath, args);
const result = new Promise((resolve: (res: any) => void, reject: (error: Error) => void): void => {
childProcess.stdout.on('data', (data: string | Buffer) => {
data = data.toString();
cmdOutput = cmdOutput.concat(data);
cmdOutputIncludingStderr = cmdOutputIncludingStderr.concat(data);
});
childProcess.stderr.on('data', (data: string | Buffer) => {
data = data.toString();
cmdOutputIncludingStderr = cmdOutputIncludingStderr.concat(data);
});
childProcess.on('message', (message: IForkMessage) => {
if (message.batch) {
batches[message.command] = batches[message.command] || [];
batches[message.command][message.batch.index] = message.batch.message;
if (message.batch.done) {
messages.push({command: message.command, message: batches[message.command].join('')});
}
} else {
messages.push(message);
}
const data = JSON.stringify(message);
cmdOutput = cmdOutput.concat(data);
cmdOutputIncludingStderr = cmdOutputIncludingStderr.concat(data);
});
childProcess.on('error', reject);
childProcess.on('exit', (code: number) => {
resolve({ cmdOutput, cmdOutputIncludingStderr, code, messages });
});
});
return { childProcess, result };
}

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

@ -1,39 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import {
DebugAdapterDescriptor,
DebugAdapterDescriptorFactory,
DebugAdapterExecutable,
DebugAdapterServer,
DebugSession,
ProviderResult,
DebugAdapterDescriptor,
DebugAdapterDescriptorFactory,
DebugAdapterExecutable,
DebugAdapterServer,
DebugSession,
ProviderResult,
} from 'vscode';
import * as Net from 'net';
import { SolidityDebugSession } from '../debugSession';
export default class TruffleDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory {
private _server?: Net.Server;
private _server?: Net.Server;
public createDebugAdapterDescriptor(
_session: DebugSession,
_executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor> {
public createDebugAdapterDescriptor(
_session: DebugSession,
_executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor> {
if (!this._server) {
// start listening on a random port
this._server = Net.createServer((socket) => {
const debugSession = new SolidityDebugSession();
debugSession.setRunAsServer(true);
debugSession.start(socket as NodeJS.ReadableStream, socket);
}).listen(0);
}
// make VS Code connect to debug server
const address: any = this._server.address();
return new DebugAdapterServer(address.port);
if (!this._server) {
// start listening on a random port
this._server = Net.createServer((socket) => {
const debugSession = new SolidityDebugSession();
debugSession.setRunAsServer(true);
debugSession.start(socket as NodeJS.ReadableStream, socket);
}).listen(0);
}
public dispose() {
if (this._server) {
this._server.close();
}
// make VS Code connect to debug server
const address: any = this._server.address();
return new DebugAdapterServer(address.port);
}
public dispose() {
if (this._server) {
this._server.close();
}
}
}

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

@ -1,20 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import {
CancellationToken,
DebugConfiguration,
DebugConfigurationProvider,
ProviderResult,
WorkspaceFolder,
CancellationToken,
DebugConfiguration,
DebugConfigurationProvider,
ProviderResult,
WorkspaceFolder,
} from 'vscode';
export default class TruffleDebuggerConfigurationProvider implements DebugConfigurationProvider {
/**
* Massage a debug configuration just before a debug session is being launched,
* e.g. add all missing attributes to the debug configuration.
*/
public resolveDebugConfiguration(
_folder: WorkspaceFolder | undefined,
config: DebugConfiguration,
_token?: CancellationToken): ProviderResult<DebugConfiguration> {
return config;
}
/**
* Massage a debug configuration just before a debug session is being launched,
* e.g. add all missing attributes to the debug configuration.
*/
public resolveDebugConfiguration(
_folder: WorkspaceFolder | undefined,
config: DebugConfiguration,
_token?: CancellationToken): ProviderResult<DebugConfiguration> {
return config;
}
}

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

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { debug, ExtensionContext } from 'vscode';
import { DEBUG_TYPE, EMBED_DEBUG_ADAPTER } from '../constants/debugAdapter';
import DebugAdapterTrackerFactory from '../debugAdapterTracker/debugAdapterTrackerFactory';
@ -5,18 +8,18 @@ import DebugAdapterDescriptorFactory from './debugAdapterDescriptorFactory';
import DebuggerConfigurationProvider from './debugConfigurationProvider';
export class DebuggerConfiguration {
public static initialize(context: ExtensionContext) {
const debugConfigProvider = new DebuggerConfigurationProvider();
context.subscriptions.push(debug.registerDebugConfigurationProvider(DEBUG_TYPE, debugConfigProvider));
public static initialize(context: ExtensionContext) {
const debugConfigProvider = new DebuggerConfigurationProvider();
context.subscriptions.push(debug.registerDebugConfigurationProvider(DEBUG_TYPE, debugConfigProvider));
if (EMBED_DEBUG_ADAPTER) {
const factory = new DebugAdapterDescriptorFactory();
context.subscriptions.push(debug.registerDebugAdapterDescriptorFactory(DEBUG_TYPE, factory));
context.subscriptions.push(factory);
}
const debugAdapterTrackerFactory = new DebugAdapterTrackerFactory();
const trackerFactory = debug.registerDebugAdapterTrackerFactory(DEBUG_TYPE, debugAdapterTrackerFactory);
context.subscriptions.push(trackerFactory);
if (EMBED_DEBUG_ADAPTER) {
const factory = new DebugAdapterDescriptorFactory();
context.subscriptions.push(debug.registerDebugAdapterDescriptorFactory(DEBUG_TYPE, factory));
context.subscriptions.push(factory);
}
const debugAdapterTrackerFactory = new DebugAdapterTrackerFactory();
const trackerFactory = debug.registerDebugAdapterTrackerFactory(DEBUG_TYPE, debugAdapterTrackerFactory);
context.subscriptions.push(trackerFactory);
}
}

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

@ -13,6 +13,7 @@ import * as crypto from 'crypto';
import * as ESTree from 'estree';
import * as fs from 'fs-extra';
import * as path from 'path';
import { tryExecuteCommandInFork } from './cmdCommandExecutor';
export namespace ConfigurationReader {
const notAllowedSymbols = new RegExp(
@ -203,11 +204,11 @@ export namespace ConfigurationReader {
}
}
public getConfiguration(): IConfiguration {
const moduleExports = getModuleExportsObjectExpression(this.ast);
public async getConfiguration(workingDirectory: string): Promise<IConfiguration> {
const truffleConfig = await getTruffleMetadata(workingDirectory);
if (moduleExports) {
return astToConfiguration(moduleExports);
if (truffleConfig) {
return jsonToConfiguration(truffleConfig);
}
return getDefaultConfiguration();
@ -245,6 +246,23 @@ export namespace ConfigurationReader {
}
}
async function getTruffleMetadata(workingDirectory: string): Promise<IConfiguration> {
const truffleConfigTemplatePath = typeof(IS_BUNDLE_TIME) === 'undefined' || IS_BUNDLE_TIME === false
? path.join(__dirname, '..', 'helpers', 'checkTruffleConfigTemplate.js')
: path.join(__dirname, 'checkTruffleConfigTemplate.js');
const truffleConfigPath =
path.relative(path.dirname(truffleConfigTemplatePath), path.join(workingDirectory, 'truffle-config.js'));
const result = await tryExecuteCommandInFork(workingDirectory, truffleConfigTemplatePath, truffleConfigPath);
const truffleConfigObject = result.messages!.find((message) => message.command === 'truffleConfig');
if (!truffleConfigObject || !truffleConfigObject.message) {
throw new Error('"truffle-config.js" has incorrect format');
}
return JSON.parse(truffleConfigObject.message);
}
function getDefaultConfiguration(): IConfiguration {
return {
contracts_build_directory: path.join('./', 'build', 'contracts'),
@ -463,35 +481,29 @@ export namespace ConfigurationReader {
};
}
function astToConfiguration(node: ESTree.ObjectExpression): IConfiguration {
const configuration = getDefaultConfiguration();
function jsonToConfiguration(truffleConfig: {[key: string]: any}): IConfiguration {
const { contracts_directory, contracts_build_directory, migrations_directory }
= getDefaultConfiguration();
const contractsDir = findProperty(node, 'contracts_directory');
if (contractsDir && contractsDir.value.type === 'Literal' &&
typeof contractsDir.value.value === 'string' && contractsDir.value.value) {
configuration.contracts_directory = contractsDir.value.value;
truffleConfig.contracts_directory = truffleConfig.contracts_directory || contracts_directory;
truffleConfig.contracts_build_directory = truffleConfig.contracts_build_directory || contracts_build_directory;
truffleConfig.migrations_directory = truffleConfig.migrations_directory || migrations_directory;
const arrayNetwork: INetwork[] = [];
if (truffleConfig.networks) {
// Networks are not used yet in the code
Object.entries(truffleConfig.networks).forEach(([key, value]) => {
arrayNetwork.push({
name: key,
options: value as INetworkOption,
});
});
}
const contractsBuildDir = findProperty(node, 'contracts_build_directory');
if (contractsBuildDir && contractsBuildDir.value.type === 'Literal' &&
typeof contractsBuildDir.value.value === 'string' && contractsBuildDir.value.value) {
configuration.contracts_build_directory = contractsBuildDir.value.value;
}
truffleConfig.networks = arrayNetwork;
const migrationsDir = findProperty(node, 'migrations_directory');
if (migrationsDir && migrationsDir.value.type === 'Literal' &&
typeof migrationsDir.value.value === 'string' && migrationsDir.value.value) {
configuration.migrations_directory = migrationsDir.value.value;
}
const networks = findProperty(node, 'networks');
if (networks && networks.value.type === 'ObjectExpression') {
configuration.networks = astToNetworks(networks.value);
}
// TODO: compilers
return configuration;
return truffleConfig as IConfiguration;
}
function astToNetworks(node: ESTree.ObjectExpression): INetwork[] {

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

@ -1,2 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
export const CONTRACT_JSON_EXTENSION = '.json';
export const CONTRACT_JSON_ENCODING = 'utf-8';

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

@ -1,39 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
export const EVENT_TYPES = {
breakpointValidated: 'breakpointValidated',
end: 'end',
launched: 'launched',
stopOnBreakpoint: 'stopOnBreakpoint',
stopOnEntry: 'stopOnEntry',
stopOnException: 'stopOnException',
stopOnStepIn: 'stopOnStepIn',
stopOnStepOut: 'stopOnStepOut',
stopOnStepOver: 'stopOnStepOver',
stopped: 'stopped',
breakpointValidated: 'breakpointValidated',
end: 'end',
launched: 'launched',
stopOnBreakpoint: 'stopOnBreakpoint',
stopOnEntry: 'stopOnEntry',
stopOnException: 'stopOnException',
stopOnStepIn: 'stopOnStepIn',
stopOnStepOut: 'stopOnStepOut',
stopOnStepOver: 'stopOnStepOver',
stopped: 'stopped',
};
export const EVENT_REASONS = {
breakpoint: 'breakpoint',
changed: 'changed',
entry: 'entry',
exception: 'exception',
stepIn: 'stepin',
stepOut: 'stepout',
stepOver: 'step',
breakpoint: 'breakpoint',
changed: 'changed',
entry: 'entry',
exception: 'exception',
stepIn: 'stepin',
stepOut: 'stepout',
stepOver: 'step',
};
// we don't support multiple threads, so we can use a hardcoded ID for the default thread
export const MAIN_THREAD = {
id: 1,
name: 'thread 1',
id: 1,
name: 'thread 1',
};
export const EVALUATE_REQUEST_TYPES = {
hover: 'hover',
watch: 'watch',
hover: 'hover',
watch: 'watch',
};
export const DEBUG_TYPE = 'truffle';
export const EMBED_DEBUG_ADAPTER = !!(typeof(IS_BUNDLE_TIME) === 'undefined');
export const EMBED_DEBUG_ADAPTER = typeof (IS_BUNDLE_TIME) === 'undefined' || IS_BUNDLE_TIME === false;
export const ERROR_MESSAGE_ID = 1;

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

@ -1,2 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
export const GET_INSTRUCTIONS = 'requestInstructions';
export const GET_CURRENT_INSTRUCTION = 'requestCurrentInstruction';

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

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
export const TRANSACTION_NUMBER_TO_SHOW = 5;
export const TRANSACTION_DEFAULT_METHOD_NAME = 'constructor';
export const LAST_BLOCK_QUERY = 'latest';

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

@ -1,2 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
export const TRUFFLE_CONFIG_NAME = 'truffle-config.js';
export const TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE = 'development';

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

@ -1,16 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
const VARIABLE_REFERANCE = {
all: 1,
dynamicVariables: 2,
all: 1,
dynamicVariables: 2,
};
export const SCOPES = {
all: {
name: 'All',
ref: VARIABLE_REFERANCE.all,
},
dynamicVariables: {
ref: VARIABLE_REFERANCE.dynamicVariables,
},
all: {
name: 'All',
ref: VARIABLE_REFERANCE.all,
},
dynamicVariables: {
ref: VARIABLE_REFERANCE.dynamicVariables,
},
};
export const OBJECT_VARIABLE_DISPLAY_NAME = 'Object';

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

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as fs from 'fs-extra';
import * as path from 'path';
import { CONTRACT_JSON_ENCODING } from '../constants/contractJson';

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

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { DebugNetwork } from '../debugNetwork';
import { sortFilePaths } from '../helpers';
import { IContractJsonModel } from '../models/IContractJsonModel';

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

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { DebugAdapterTracker, DebugSession, window } from 'vscode';
import InstructionView from '../instructionsView/instructionView';
@ -6,50 +9,50 @@ import { GET_CURRENT_INSTRUCTION, GET_INSTRUCTIONS } from '../constants/debugSes
import { IInstruction } from '../models/IInstruction';
export default class SolidityDebugAdapterTracker implements DebugAdapterTracker {
private session: DebugSession;
private instructionView: InstructionView;
private session: DebugSession;
private instructionView: InstructionView;
constructor(session: DebugSession) {
this.session = session;
this.instructionView = new InstructionView();
}
constructor(session: DebugSession) {
this.session = session;
this.instructionView = new InstructionView();
}
public onDidSendMessage(message: any): void {
if (message.success === false) {
window.showErrorMessage('Error occured in debug mode: ' + message.body.error.format);
return;
}
switch (message.event) {
case EVENT_TYPES.launched: // init instructions after launch
this.requestForInstructions();
return;
case EVENT_TYPES.stopped: // get current instruction on every stop event
this.requestForCurrentInstruction();
return;
}
switch (message.command) {
case GET_INSTRUCTIONS:
this.updateInstructionView(message.body.instructions);
return;
case GET_CURRENT_INSTRUCTION:
this.revealInstruction(message.body.currentInstruction);
return;
}
public onDidSendMessage(message: any): void {
if (message.success === false) {
window.showErrorMessage('Error occured in debug mode: ' + message.body.error.format);
return;
}
switch (message.event) {
case EVENT_TYPES.launched: // init instructions after launch
this.requestForInstructions();
return;
case EVENT_TYPES.stopped: // get current instruction on every stop event
this.requestForCurrentInstruction();
return;
}
switch (message.command) {
case GET_INSTRUCTIONS:
this.updateInstructionView(message.body.instructions);
return;
case GET_CURRENT_INSTRUCTION:
this.revealInstruction(message.body.currentInstruction);
return;
}
}
private requestForInstructions() {
this.session.customRequest(GET_INSTRUCTIONS);
}
private requestForInstructions() {
this.session.customRequest(GET_INSTRUCTIONS);
}
private requestForCurrentInstruction() {
this.session.customRequest(GET_CURRENT_INSTRUCTION);
}
private requestForCurrentInstruction() {
this.session.customRequest(GET_CURRENT_INSTRUCTION);
}
private updateInstructionView(instructions: IInstruction[]) {
this.instructionView.update(instructions);
}
private updateInstructionView(instructions: IInstruction[]) {
this.instructionView.update(instructions);
}
private revealInstruction(instruction: IInstruction) {
this.instructionView.revealInstruction(instruction);
}
private revealInstruction(instruction: IInstruction) {
this.instructionView.revealInstruction(instruction);
}
}

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

@ -1,13 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import {
DebugAdapterTracker,
DebugAdapterTrackerFactory,
DebugSession,
ProviderResult,
DebugAdapterTracker,
DebugAdapterTrackerFactory,
DebugSession,
ProviderResult,
} from 'vscode';
import SolidityDebugAdapterTracker from './debugAdapterTracker';
export default class SolidityDebugAdapterTrackerFactory implements DebugAdapterTrackerFactory {
public createDebugAdapterTracker(session: DebugSession): ProviderResult<DebugAdapterTracker> {
return new SolidityDebugAdapterTracker(session);
}
public createDebugAdapterTracker(session: DebugSession): ProviderResult<DebugAdapterTracker> {
return new SolidityDebugAdapterTracker(session);
}
}

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

@ -1,95 +1,105 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as path from 'path';
import { executeCommand } from './cmdCommandExecutor';
import { ConfigurationReader } from './configurationReader';
import { TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE, TRUFFLE_CONFIG_NAME } from './constants/truffleConfig';
export class DebugNetwork {
public workingDirectory: string;
private _basedConfig: ConfigurationReader.TruffleConfig | undefined;
private _truffleConfiguration: ConfigurationReader.IConfiguration | undefined;
private _networkForDebug: ConfigurationReader.INetwork | undefined;
constructor(truffleConfigDirectory: string) {
this.workingDirectory = truffleConfigDirectory;
}
public workingDirectory: string;
private _basedConfig: ConfigurationReader.TruffleConfig | undefined;
private _truffleConfiguration: ConfigurationReader.IConfiguration | undefined;
private _networkForDebug: ConfigurationReader.INetwork | undefined;
constructor(truffleConfigDirectory: string) {
this.workingDirectory = truffleConfigDirectory;
}
public async load(): Promise<void> {
this._basedConfig =
new ConfigurationReader.TruffleConfig(path.join(this.workingDirectory, TRUFFLE_CONFIG_NAME));
this._truffleConfiguration = this.loadConfiguration();
this._networkForDebug = await this.loadNetworkForDebug();
}
public async load(): Promise<void> {
this._basedConfig =
new ConfigurationReader.TruffleConfig(path.join(this.workingDirectory, TRUFFLE_CONFIG_NAME));
this._truffleConfiguration = await this.loadConfiguration();
this._networkForDebug = await this.loadNetworkForDebug();
}
public getTruffleConfiguration() {
return this._truffleConfiguration;
}
public getTruffleConfiguration() {
return this._truffleConfiguration;
}
public getNetwork() {
return this._networkForDebug;
}
public getNetwork() {
return this._networkForDebug;
}
// Port and host are defined
public isLocalNetwork() {
if (!this._networkForDebug || !this._networkForDebug.options) {
throw new Error('Network is not defined. Try to call this.load()');
}
const options = this._networkForDebug.options;
return !!(options.host && options.port);
// Port and host are defined
public isLocalNetwork() {
if (!this._networkForDebug || !this._networkForDebug.options) {
throw new Error('Network is not defined. Try to call this.load()');
}
const options = this._networkForDebug.options;
return !!(options.host && options.port);
}
private loadConfiguration(): ConfigurationReader.IConfiguration {
const configuration = this._basedConfig!.getConfiguration();
configuration.contracts_build_directory =
path.join(this.workingDirectory, configuration.contracts_build_directory);
configuration.contracts_directory =
path.join(this.workingDirectory, configuration.contracts_directory);
configuration.migrations_directory =
path.join(this.workingDirectory, configuration.migrations_directory);
return configuration;
}
private async loadConfiguration(): Promise<ConfigurationReader.IConfiguration> {
const configuration = await this._basedConfig!.getConfiguration(this.workingDirectory);
private async loadNetworkForDebug(): Promise<ConfigurationReader.INetwork> {
const networks = this._basedConfig!.getNetworks();
const networkForDebug = networks
.find((n) => n.name === TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
if (!this.isNetworkForDebugValid(networkForDebug)) {
const provider = await this.getProviderByResolvingConfig(TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
if (provider.url) {
networkForDebug!.options.provider = {
url: provider.url,
};
} else {
throw new Error(`Truffle config is not properly defined.
return {
contracts_build_directory: this.relativeToAbsolutePath(configuration.contracts_build_directory),
contracts_directory: this.relativeToAbsolutePath(configuration.contracts_directory),
migrations_directory: this.relativeToAbsolutePath(configuration.migrations_directory),
};
}
private async loadNetworkForDebug(): Promise<ConfigurationReader.INetwork> {
const networks = this._basedConfig!.getNetworks();
const networkForDebug = networks
.find((n) => n.name === TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
if (!this.isNetworkForDebugValid(networkForDebug)) {
const provider = await this.getProviderByResolvingConfig(TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE);
if (provider.url) {
networkForDebug!.options.provider = {
url: provider.url,
};
} else {
throw new Error(`Truffle config is not properly defined.
Please create ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network,
set host+port, or hdwallet/http/websocket provider.`);
}
}
return networkForDebug!;
}
}
private isNetworkForDebugValid(networkForDebug: ConfigurationReader.INetwork | undefined): boolean {
if (!networkForDebug || !networkForDebug.options) {
throw new Error(`No ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network in the truffle config`);
}
return networkForDebug!;
}
if (networkForDebug.options.host && networkForDebug.options.port) {
return true;
}
// truffle-config helper can read only hdwallet provider
const isHdWalletProvider = !!networkForDebug.options.provider;
if (isHdWalletProvider) {
return true;
}
return false;
private isNetworkForDebugValid(networkForDebug: ConfigurationReader.INetwork | undefined): boolean {
if (!networkForDebug || !networkForDebug.options) {
throw new Error(`No ${TRUFFLE_CONFIG_DEBUG_NETWORK_TYPE} network in the truffle config`);
}
private async getProviderByResolvingConfig(network: string) {
// use truffle exec web3ProviderResolver.js to solve http- or websocket- web3 provider
const truffleConfigReaderPath = path.join(__dirname, 'web3ProviderResolver.js');
const args = [ 'truffle', 'exec', truffleConfigReaderPath, '--network', network ];
const result = await executeCommand(this.workingDirectory, 'npx', ...args);
const providerJson = result.split('provider%=')[1];
return JSON.parse(providerJson);
if (networkForDebug.options.host && networkForDebug.options.port) {
return true;
}
// truffle-config helper can read only hdwallet provider
const isHdWalletProvider = !!networkForDebug.options.provider;
if (isHdWalletProvider) {
return true;
}
return false;
}
private async getProviderByResolvingConfig(network: string) {
// use truffle exec web3ProviderResolver.js to solve http- or websocket- web3 provider
const truffleConfigReaderPath = path.join(__dirname, 'web3ProviderResolver.js');
const args = ['truffle', 'exec', truffleConfigReaderPath, '--network', network];
const result = await executeCommand(this.workingDirectory, 'npx', ...args);
const providerJson = result.split('provider%=')[1];
return JSON.parse(providerJson);
}
private relativeToAbsolutePath(directory: string) {
if (directory && path.isAbsolute(directory)) {
return directory;
}
return path.join(this.workingDirectory, directory);
}
}

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

@ -1,52 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { IInstruction } from '../models/IInstruction';
import InstructionTreeNode from './instructionTreeNode';
export default class InstructionDataManager {
private instructionObject: any = {};
private instructionObject: any = {};
public load(instructions: IInstruction[]) {
this.instructionObject = this.mapInstructionsArrayToObject(instructions);
public load(instructions: IInstruction[]) {
this.instructionObject = this.mapInstructionsArrayToObject(instructions);
}
public getChidren(element?: InstructionTreeNode): string[] {
if (!element) {
return Object.keys(this.instructionObject).map((k) => k);
}
public getChidren(element?: InstructionTreeNode): string[] {
if (!element) {
return Object.keys(this.instructionObject).map((k) => k);
}
const item = this.getItemByPath(element.getPaths());
if (item === undefined) {
return [];
}
return Object.keys(item);
const item = this.getItemByPath(element.getPaths());
if (item === undefined) {
return [];
}
return Object.keys(item);
}
public getItem(element: InstructionTreeNode): any {
return this.getItemByPath(element.getPaths());
}
public getItemParent(element: InstructionTreeNode): any {
return this.getItemByPath(element.getParentPaths());
}
// Map from array to object in order to used in view
// [{pc:1,op: ''},{pc:2,op:''}] ==> { 1:{pc:1,op:''}, 2:{pc:2,op:''}}
private mapInstructionsArrayToObject(steps: IInstruction[]): any {
const res: any = {};
steps.forEach((s) => {
res[s.pc] = s;
});
return res;
}
private getItemByPath(paths: string[]): any {
if (paths.length === 0) {
return void 0;
}
let item = this.instructionObject;
paths.forEach((key) => {
item = item[key];
});
return item;
public getItem(element: InstructionTreeNode): any {
return this.getItemByPath(element.getPaths());
}
public getItemParent(element: InstructionTreeNode): any {
return this.getItemByPath(element.getParentPaths());
}
// Map from array to object in order to used in view
// [{pc:1,op: ''},{pc:2,op:''}] ==> { 1:{pc:1,op:''}, 2:{pc:2,op:''}}
private mapInstructionsArrayToObject(steps: IInstruction[]): any {
const res: any = {};
steps.forEach((s) => {
res[s.pc] = s;
});
return res;
}
private getItemByPath(paths: string[]): any {
if (paths.length === 0) {
return void 0;
}
let item = this.instructionObject;
paths.forEach((key) => {
item = item[key];
});
return item;
}
}

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

@ -1,57 +1,60 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { Event, EventEmitter, ProviderResult, TreeDataProvider, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { IInstruction } from '../models/IInstruction';
import InstructionDataManager from './instructionDataManager';
import InstructionTreeNode from './instructionTreeNode';
export default class InstructionDataProvider implements TreeDataProvider<InstructionTreeNode> {
public _onDidChangeTreeData: EventEmitter<InstructionTreeNode> = new EventEmitter<InstructionTreeNode>();
public readonly onDidChangeTreeData: Event<InstructionTreeNode> = this._onDidChangeTreeData.event;
public _onDidChangeTreeData: EventEmitter<InstructionTreeNode> = new EventEmitter<InstructionTreeNode>();
public readonly onDidChangeTreeData: Event<InstructionTreeNode> = this._onDidChangeTreeData.event;
private instructionDataManager: InstructionDataManager;
private instructionDataManager: InstructionDataManager;
constructor(instructionDataManager: InstructionDataManager) {
this.instructionDataManager = instructionDataManager;
}
constructor(instructionDataManager: InstructionDataManager) {
this.instructionDataManager = instructionDataManager;
}
public refresh(newInstructions: IInstruction[]) {
this.instructionDataManager.load(newInstructions);
this._onDidChangeTreeData.fire();
}
public refresh(newInstructions: IInstruction[]) {
this.instructionDataManager.load(newInstructions);
this._onDidChangeTreeData.fire();
}
public getChildren(element?: InstructionTreeNode): ProviderResult<InstructionTreeNode[]> {
const items = this.instructionDataManager.getChidren(element);
return items.map((e) => new InstructionTreeNode(e, element));
}
public getChildren(element?: InstructionTreeNode): ProviderResult<InstructionTreeNode[]> {
const items = this.instructionDataManager.getChidren(element);
return items.map((e) => new InstructionTreeNode(e, element));
}
public getTreeItem(element: InstructionTreeNode): TreeItem {
const item = this.instructionDataManager.getItem(element);
const isSpecificObjectValueType = this.isSpecificObjectValueType(item);
const collapsibleState = isSpecificObjectValueType
? TreeItemCollapsibleState.Collapsed
: TreeItemCollapsibleState.None;
public getTreeItem(element: InstructionTreeNode): TreeItem {
const item = this.instructionDataManager.getItem(element);
const isSpecificObjectValueType = this.isSpecificObjectValueType(item);
const collapsibleState = isSpecificObjectValueType
? TreeItemCollapsibleState.Collapsed
: TreeItemCollapsibleState.None;
return {
collapsibleState,
id: element.getId(),
label: this.generateTreeItemLabel(element.getKey(), item, isSpecificObjectValueType),
};
}
return {
collapsibleState,
id: element.getId(),
label: this.generateTreeItemLabel(element.getKey(), item, isSpecificObjectValueType),
};
}
public getParent(element: InstructionTreeNode): ProviderResult<InstructionTreeNode> {
return element.getParent();
}
public getParent(element: InstructionTreeNode): ProviderResult<InstructionTreeNode> {
return element.getParent();
}
private generateTreeItemLabel(treeItemKey: string, treeItemValue: any, isSpecificObjectValueType: boolean) {
return isSpecificObjectValueType
? treeItemKey
: `${treeItemKey}: ${JSON.stringify(treeItemValue)}`;
}
private generateTreeItemLabel(treeItemKey: string, treeItemValue: any, isSpecificObjectValueType: boolean) {
return isSpecificObjectValueType
? treeItemKey
: `${treeItemKey}: ${JSON.stringify(treeItemValue)}`;
}
// TODO: refactroign - same method in variablesHandler
private isSpecificObjectValueType(item: any) {
return !Array.isArray(item)
&& item !== null
&& item !== undefined
&& typeof(item) === 'object';
}
// TODO: refactroign - same method in variablesHandler
private isSpecificObjectValueType(item: any) {
return !Array.isArray(item)
&& item !== null
&& item !== undefined
&& typeof (item) === 'object';
}
}

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

@ -1,45 +1,48 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { IInstruction } from '../models/IInstruction';
export default class InstructionTreeNode {
private key: string;
private path: string;
private parent?: InstructionTreeNode;
private key: string;
private path: string;
private parent?: InstructionTreeNode;
constructor(key?: string, parent?: InstructionTreeNode, instructionData?: IInstruction) {
if (!key && (!instructionData || (!instructionData.pc && instructionData.pc !== 0))) {
throw new Error('Incorrect input params');
}
const nodeKey = instructionData
? instructionData.pc.toString()
: (key || '');
this.key = nodeKey;
this.parent = parent;
this.path = this.generatePath(nodeKey, parent);
constructor(key?: string, parent?: InstructionTreeNode, instructionData?: IInstruction) {
if (!key && (!instructionData || (!instructionData.pc && instructionData.pc !== 0))) {
throw new Error('Incorrect input params');
}
public getId(): string {
return this.path;
}
const nodeKey = instructionData
? instructionData.pc.toString()
: (key || '');
this.key = nodeKey;
this.parent = parent;
this.path = this.generatePath(nodeKey, parent);
}
public getKey(): string {
return this.key;
}
public getId(): string {
return this.path;
}
public getParent(): InstructionTreeNode | undefined {
return this.parent;
}
public getKey(): string {
return this.key;
}
public getParentPaths(): string[] {
return this.path.split(/\//).slice(1, this.path.length - 1); // not take first empty element and last
}
public getParent(): InstructionTreeNode | undefined {
return this.parent;
}
public getPaths(): string[] {
return this.path.split(/\//).slice(1); // not take first empty element
}
public getParentPaths(): string[] {
return this.path.split(/\//).slice(1, this.path.length - 1); // not take first empty element and last
}
private generatePath(key: string, parent?: InstructionTreeNode) {
const parentPath = parent ? parent.path : '';
return `${parentPath}/${key}`;
}
public getPaths(): string[] {
return this.path.split(/\//).slice(1); // not take first empty element
}
private generatePath(key: string, parent?: InstructionTreeNode) {
const parentPath = parent ? parent.path : '';
return `${parentPath}/${key}`;
}
}

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

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { TreeView, window } from 'vscode';
import { IInstruction } from '../models/IInstruction';
import InstructionDataManager from './instructionDataManager';
@ -7,23 +10,23 @@ import InstructionTreeNode from './instructionTreeNode';
const INSTRUCTION_VIEW_ID = 'InstructionView';
export default class InstructionView {
private view: TreeView<InstructionTreeNode>;
private dataProvider: InstructionDataProvider;
constructor() {
const dataManager = new InstructionDataManager();
this.dataProvider = new InstructionDataProvider(dataManager);
this.view = window.createTreeView(INSTRUCTION_VIEW_ID,
{ treeDataProvider: this.dataProvider, showCollapseAll: true });
}
private view: TreeView<InstructionTreeNode>;
private dataProvider: InstructionDataProvider;
constructor() {
const dataManager = new InstructionDataManager();
this.dataProvider = new InstructionDataProvider(dataManager);
this.view = window.createTreeView(INSTRUCTION_VIEW_ID,
{ treeDataProvider: this.dataProvider, showCollapseAll: true });
}
public update(newInstructions: IInstruction[]) {
this.dataProvider.refresh(newInstructions);
}
public update(newInstructions: IInstruction[]) {
this.dataProvider.refresh(newInstructions);
}
public revealInstruction(instruction: IInstruction) {
if (this.view.visible) {
const treeNode = new InstructionTreeNode(undefined, undefined, instruction);
this.view.reveal(treeNode, { focus: true, select: true, expand: true });
}
public revealInstruction(instruction: IInstruction) {
if (this.view.visible) {
const treeNode = new InstructionTreeNode(undefined, undefined, instruction);
this.view.reveal(treeNode, { focus: true, select: true, expand: true });
}
}
}

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

@ -1,6 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
export interface ICallInfo {
column: number;
file: string;
line: number;
method: string;
column: number;
file: string;
line: number;
method: string;
}

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