This commit is contained in:
Chris Segura 2019-05-15 08:20:11 -07:00
Родитель 1e51606a2f
Коммит ed54becea2
24 изменённых файлов: 545 добавлений и 699 удалений

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

@ -13,3 +13,4 @@ max_line_length = 120
[*.html]
indent_size = 4
tab_width = 4
max_line_length = off

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

@ -2,15 +2,23 @@
All notable changes to the "azureblockchain" extension will be documented in this file.
## 0.1.0
- Initial release
## 0.1.1
## 0.1.3
- Updated menu options
- various bug fixes
- moved logic app/function/flow generators out of Truffle build directory into their own directory
- refactoring of Welcome/Requirements pages
## 0.1.2
- doc and bug fixes for contract code generation
## 0.1.1
- Updated menu options
## 0.1.0
- Initial release

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

@ -5,7 +5,7 @@
"publisher": "AzBlockchain",
"preview": true,
"icon": "images/blockchain-service-logo.png",
"version": "0.1.2",
"version": "0.1.3",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum"
@ -51,7 +51,6 @@
"onCommand:azureBlockchainService.connectConsortium",
"onCommand:drizzle.generateSmartContractUI",
"onCommand:azureBlockchainService.copyRPCEndpointAddress",
"onCommand:azureBlockchainService.copyAccessKey",
"onCommand:azureBlockchainService.createConsortium",
"onCommand:azureBlockchainService.disconnectConsortium"
],
@ -166,11 +165,6 @@
"title": "Copy RPC Endpoint Address",
"category": "Azure Blockchain"
},
{
"command": "azureBlockchainService.copyAccessKey",
"title": "Copy Access Key",
"category": "Azure Blockchain"
},
{
"command": "azureBlockchainService.createConsortium",
"title": "Create Azure Blockchain Service",
@ -178,7 +172,7 @@
},
{
"command": "azureBlockchainService.disconnectConsortium",
"title": "Disconnect Consortium",
"title": "Disconnect",
"category": "Azure Blockchain"
},
{
@ -238,10 +232,6 @@
"when": "false",
"command": "azureBlockchainService.copyRPCEndpointAddress"
},
{
"when": "false",
"command": "azureBlockchainService.copyAccessKey"
},
{
"when": "false",
"command": "azureBlockchainService.disconnectConsortium"
@ -308,11 +298,6 @@
"when": "view == AzureBlockchain && viewItem == consortium",
"group": "azureBlockchain-0@0"
},
{
"command": "azureBlockchainService.copyAccessKey",
"when": "view == AzureBlockchain && viewItem == consortium",
"group": "azureBlockchain-0@1"
},
{
"command": "azureBlockchainService.startGanacheServer",
"when": "view == AzureBlockchain && viewItem == localconsortium && azureBlockchainService:isGanacheRunning == false",
@ -326,7 +311,7 @@
{
"command": "azureBlockchainService.disconnectConsortium",
"when": "view == AzureBlockchain && viewItem == consortium",
"group": "azureBlockchain-1@1"
"group": "azureBlockchain-0@1"
},
{
"command": "azureBlockchainService.copyRPCEndpointAddress",
@ -336,7 +321,7 @@
{
"command": "azureBlockchainService.disconnectConsortium",
"when": "view == AzureBlockchain && viewItem == localconsortium",
"group": "azureBlockchain-1@1"
"group": "azureBlockchain-0@1"
}
],
"explorer/context": [

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

@ -6,152 +6,157 @@
</head>
<body class="vscode-dark">
<header>
<div id="title-area">
<h1>Azure Blockchain Development Kit</h1>
<p>Interact with your private, public, and local ledgers. Develop smart contracts, test and integrate with business back ends with Logic Apps and Flow.</p>
</div>
</header>
<div id="content">
<div id="main-content">
<div>
<div id="quickstarts">
<h2>Quick Starts</h2>
<div class="quick-starts-blocks">
<div>
<h3>Create a New Azure Blockchain Service</h3>
<p class="description">Click below button to create an Azure Blockchain Service</p>
<a href="command:azureBlockchainService.createConsortium">Create Azure Blockchain Service</a>
</div>
</div>
<div class="quick-starts-blocks">
<div>
<h3>Connect to an Existing Consortium</h3>
<p class="description">Click below button to connect to an Azure, public or local consortium.</p>
<a href="command:azureBlockchainService.connectConsortium">Connect to Consortium</a>
</div>
</div>
</div>
<div id="tutorial">
<h2>Say Hello to Azure Blockchain in 1 Minute</h2>
<header>
<div id="title-area">
<h1>Azure Blockchain Development Kit</h1>
<p>Interact with your private, public, and local ledgers. Develop smart contracts, test and integrate with business back ends with Logic Apps and Flow.</p>
</div>
</header>
<div id="content">
<div id="main-content">
<div>
<div id="quickstarts">
<h2>Quick Starts</h2>
<div class="quick-starts-blocks">
<div>
<div class="interactive">
<div>
<div class="arrow"></div>
<h3>Create a New Azure Blockchain Service</h3>
</div>
<div class="detail">
To create a new Azure Blockchain Service if you don't have one.
<ol>
<li>
<div>From the Command Palette, or Azure Blockchain tab, click on "Create Azure Blockchain Service</div>
<img src="https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/createService.gif">
</li>
</ol>
If you have an existing Azure Blockchain Service, you may connect to it.
<ol>
<li>
<div>From the Command Palette, or Azure Blockchain tab, click on "Connect to Consortium" and select Azure Blockchain Service</div>
<img src="https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/connectService.gif">
</li>
</ol>
</div>
</div>
<div class="interactive">
<div>
<div class="arrow"></div>
<h3>Create a Smart Contract and Project Folder</h3>
</div>
<div class="detail">
To create a basic smart contract folder structure and contract.
<ol>
<li>
<div>From the Command Palette click on "New Solidity Project"</div>
<img src="https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/createNewProject.gif">
</li>
</ol>
</div>
</div>
<div class="interactive">
<div>
<div class="arrow"></div>
<h3>Interact with your Smart Contract</h3>
</div>
<div class="detail">
To interact with your contract
<ol>
<li>
<div>Coming soon!</div>
<img>
</li>
</ol>
</div>
</div>
<h3>Create a New Azure Blockchain Service</h3>
<p class="description">Click below button to create an Azure Blockchain Service</p>
<a href="command:azureBlockchainService.createConsortium">Create Azure Blockchain Service</a>
</div>
<h2>Learn more about our partners</h2>
<div class="partners">
<a href="https://www.ethereum.org/">
<div class="specific-partner">
<div><img class="small-image-logo" src="{{root}}/images/EthereumLogo.png"></div>
<div>Ethereum Foundation</div>
</div>
</a>
<a href="https://solidity.readthedocs.io/en/v0.5.5/">
<div class="specific-partner">
<div><img class="small-image-logo" src="{{root}}/images/SolidityLogo.png"></div>
<div>Solidity plugin</div>
</div>
</a>
<a href="https://truffleframework.com/docs/truffle/reference/truffle-commands">
<div class="specific-partner">
<div><img class="small-image-logo" src="{{root}}/images/TruffleLogo.png"></div>
<div>Truffle Suite</div>
</div>
</a>
</div>
<div class="quick-starts-blocks">
<div>
<h3>Connect to an Existing Consortium</h3>
<p class="description">Click below button to connect to an Azure, public or local consortium.</p>
<a href="command:azureBlockchainService.connectConsortium">Connect to Consortium</a>
</div>
</div>
</div>
<footer>
<div id="tutorial">
<h2>Say Hello to Azure Blockchain in 1 Minute</h2>
<div>
Having trouble with the extension? -
<a href="https://aka.ms/vscodebcextensionwiki">Browse the documentation</a> -
<a href="https://aka.ms/vscodevcextensiongitissues">Report an issue</a>
<div class="interactive">
<div>
<div class="arrow"></div>
<h3>Create a New Azure Blockchain Service</h3>
</div>
<div class="detail">
To create a new Azure Blockchain Service if you don't have one.
<ol>
<li>
<div>From the Command Palette, or Azure Blockchain tab, click on "Create Azure Blockchain Service"</div>
<img src="https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/createService.gif">
</li>
</ol>
If you have an existing Azure Blockchain Service, you may connect to it.
<ol>
<li>
<div>From the Command Palette, or Azure Blockchain tab, click on "Connect to Consortium" and select Azure Blockchain Service</div>
<img src="https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/connectService.gif">
</li>
</ol>
</div>
</div>
<div class="interactive">
<div>
<div class="arrow"></div>
<h3>Create a Smart Contract and Project Folder</h3>
</div>
<div class="detail">
To create a basic smart contract folder structure and contract.
<ol>
<li>
<div>From the Command Palette click on "New Solidity Project"</div>
<img src="https://raw.githubusercontent.com/Microsoft/vscode-azure-blockchain-ethereum/master/images/createNewProject.gif">
</li>
</ol>
</div>
</div>
<div class="interactive">
<div>
<div class="arrow"></div>
<h3>Interact with your Smart Contract</h3>
</div>
<div class="detail">
To interact with your contract
<ol>
<li>
<div>Coming soon!</div>
</li>
</ol>
</div>
</div>
</div>
</footer>
<h2>Learn more about our partners</h2>
<div class="partners">
<a href="https://www.ethereum.org/">
<div class="specific-partner">
<div><img class="small-image-logo" src="{{root}}/images/EthereumLogo.png"></div>
<div>Ethereum Foundation</div>
</div>
</a>
<a href="https://solidity.readthedocs.io/en/v0.5.5/">
<div class="specific-partner">
<div><img class="small-image-logo" src="{{root}}/images/SolidityLogo.png"></div>
<div>Solidity plugin</div>
</div>
</a>
<a href="https://truffleframework.com/docs/truffle/reference/truffle-commands">
<div class="specific-partner">
<div><img class="small-image-logo" src="{{root}}/images/TruffleLogo.png"></div>
<div>Truffle Suite</div>
</div>
</a>
</div>
</div>
</div>
<div id="sidebar">
<p class="showOnStartup">
<input type="checkbox" id="showOnStartup" class="checkbox" checked="checked">
<label class="caption" for="showOnStartup">Show this page on startup</label>
</p>
<footer>
<div>
<h3>Quick Links</h3>
<div>
<a href="https://aka.ms/vscodebcextension">Marketplace </a>
</div>
<div>
<a href="https://aka.ms/vscodebcextensiongitrepo">Repository</a>
</div>
<div>
<a href="https://aka.ms/vscodevcextensiongitissues">Issues</a>
</div>
<div>
<a href="https://aka.ms/vscodebcextensionchangelog">Changelog</a>
</div>
Having trouble with the extension? -
<a href="https://aka.ms/vscodebcextensionwiki">Browse the documentation</a> -
<a href="https://aka.ms/vscodevcextensiongitissues">Report an issue</a>
</div>
<div id="resources">
<h3>Resources</h3>
<div>
<a href="https://aka.ms/vscodebcextensionch9">Channel 9 video: Walkthrough of Azure Blockchain Development Kit Extension</a>
</div>
<div>
<a href="https://aka.ms/vscodebcextensionwiki">Azure Blockchain Development Kit User Guide</a>
</div>
<div>
<a href="https://docs.microsoft.com/azure/blockchain/service">Azure Blockchain Service Documentation</a>
</div>
</footer>
</div>
<div id="sidebar">
<div>
<h3>Quick Links</h3>
<div>
<a href="https://aka.ms/vscodebcextension">Marketplace </a>
</div>
<div>
<a href="https://aka.ms/vscodebcextensiongitrepo">Repository</a>
</div>
<div>
<a href="https://aka.ms/vscodevcextensiongitissues">Issues</a>
</div>
<div>
<a href="https://aka.ms/vscodebcextensionchangelog">Changelog</a>
</div>
</div>
<div id="resources">
<h3>Resources</h3>
<div>
<a href="https://aka.ms/vscodebcextensionch9">Channel 9 video: Walkthrough of Azure Blockchain Development Kit Extension</a>
</div>
<div>
<a href="https://aka.ms/vscodebcextensionwiki">Azure Blockchain Development Kit User Guide</a>
</div>
<div>
<a href="https://docs.microsoft.com/azure/blockchain/service">Azure Blockchain Service Documentation</a>
</div>
</div>
</div>
<a href="#" id="back-to-top">&uarr;</a>
<script type="text/javascript" src="{{root}}/resources/welcome/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="{{root}}/resources/welcome/main.js"></script>
</div>
<a href="#" id="back-to-top">&uarr;</a>
<script type="text/javascript" src="{{root}}/resources/welcome/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="{{root}}/resources/welcome/main.js"></script>
</body>
</html>

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

@ -74,13 +74,12 @@ header p {
display: flex;
flex-direction: row;
align-content: stretch;
min-width: 620px;
min-width: 660px;
}
#main-content {
max-width: 740px;
/* float: left; */
padding-right: 40px;
margin-right: 40px;
min-width: 400px;
}
@ -243,9 +242,12 @@ header p {
width: 40px;
}
.showOnStartup {
margin: 40px 0;
}
footer {
padding-top: 60px;
padding-bottom: 40px;
margin: 40px 0;
text-align: center
}
@ -260,7 +262,6 @@ footer {
align-items: stretch;
align-content: center;
min-width: 400px;
max-width: 600px;
}
.required-app {
@ -269,13 +270,18 @@ footer {
text-align: center;
align-items: center;
align-content: space-between;
flex: 0 1 185px;
flex: 1;
margin-top: 25px;
}
.required-app:not(:last-child) {
margin-right: 25px;
}
.required-app img {
flex: 1;
width: 60px;
max-width: 60px;
max-height: 60px;
}
.required-app div {
@ -347,11 +353,14 @@ footer {
align-items: stretch;
align-content: center;
min-width: 400px;
max-width: 600px;
}
.partners > a {
flex: 0 1 185px;
flex: 1;
}
.partners > a:not(:last-child) {
margin-right: 15px;
}
.specific-partner {
@ -363,6 +372,10 @@ footer {
flex: 1;
}
.specific-partner > div:last-child {
height: 30px;
}
.specific-partner > div {
text-align: center;
}

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

@ -36,14 +36,18 @@ function main() {
});
$(document).ready(() => {
vscode.postMessage({ command: 'documentready'});
vscode.postMessage({ command: 'documentReady'});
});
$('#showOnStartup').change(function() {
vscode.postMessage({ command: 'toggleShowPage', value: this.checked});
});
window.addEventListener('message', (event) => {
const message = event.data; // The JSON data our extension sent
if (message.versions) {
const versions = message.versions;
if (message.command === 'versions') {
const versions = message.value;
if (Array.isArray(versions)) {
versions.forEach((version) => {
const element = $(`#${version.app}`);
@ -53,5 +57,8 @@ function main() {
});
}
}
if (message.command === 'showOnStartup') {
$('#showOnStartup').attr('checked', !!message.value);
}
});
}

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

@ -1,60 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="{{root}}/resources/welcome/main.css">
</head>
<body class ="vscode-dark">
<div id="content">
<div id="main-content">
<div class="required-block">
<div>
<h2>Required apps</h2>
<br>This extension requires your development machine have the following tools already installed. These cannot be installed directly by the extension.
If you do not have these tools already installed, the links below will take you to the download page.
<ul>
<li>Node JS</li>
<li>Git</li>
<li>Python</li>
</ul>
<p><a href="https://aka.ms/vscodebcextensionwiki">Click here</a> to learn more about this extension, and view the users guide </p>
<div class="required">
<div id="node" class="required-app disabled">
<img src="{{root}}/images/NodeLogo.png">
<div class="description">Required version: <span class="version">10.15.0</span></div>
<a class="spinner" href="https://nodejs.org"><span>Install Node.js</span></a>
</div>
<div id="git" class="required-app disabled">
<img src="{{root}}/images/GitLogo.png">
<div class="description">Required version: <span class="version">2.10.0</span> or higher</div>
<a class="spinner" href="https://git-scm.com/downloads"><span>Install Git</span></a>
</div>
<div id="python" class="required-app disabled">
<img src="{{root}}/images/PythonLogo.png">
<div class="description">Required version: <span class="version">2.7.15</span></div>
<a class="spinner" href="https://www.python.org/downloads/release/python-2715/"><span>Install Python</span></a>
</div>
<p>At this time, while the extension is still in public-preview, you will also need to install the Truffle Suite of developer tools. Click the links below to install the Truffle tools directly from this extension</p>
<div id="npm" class="required-app disabled">
<img src="{{root}}/images/NpmLogo.png">
<div class="description">Required version: <span class="version">6.4.1</span></div>
<a class="spinner action" href="command:azureBlockchainService.required.installNpm"><span>Install NPM</span></a>
</div>
<div id="truffle" class="required-app disabled">
<img src="{{root}}/images/TruffleLogo.svg">
<div class="description">Required version: <span class="version">5.0.0</span></div>
<a class="spinner action" href="command:azureBlockchainService.required.installTruffle"><span>Install Truffle Suite</span></a>
</div>
<div id="ganache" class="required-app disabled">
<img src="{{root}}/images/GanacheLogo.png">
<div class="description">Required version: <span class="version">6.0.0</span></div>
<a class="spinner action" href="command:azureBlockchainService.required.installGanache"><span>Install Ganache CLI</span></a>
</div>
<head>
<link rel="stylesheet" href="{{root}}/resources/welcome/main.css">
</head>
<body class="vscode-dark">
<div id="content">
<div id="main-content">
<div class="required-block">
<div>
<h2>Required apps</h2>
<br>
This extension requires your development machine have the following tools already installed. These cannot be installed directly by the extension.
If you do not have these tools already installed, the links below will take you to the download page
<ul>
<li>Node JS</li>
<li>Git</li>
<li>Python</li>
</ul>
<p>
<a href="https://aka.ms/vscodebcextensionwiki">Click here</a> to learn more about this extension, and view the users guide
</p>
<div class="required">
<div id="node" class="required-app disabled">
<img src="{{root}}/images/NodeLogo.png">
<div class="description">Required version: <span class="version">10.15.0</span></div>
<a class="spinner" href="https://nodejs.org"><span>Install Node.js</span></a>
</div>
<div id="git" class="required-app disabled">
<img src="{{root}}/images/GitLogo.png">
<div class="description">Required version: <span class="version">2.10.0</span></div>
<a class="spinner" href="https://git-scm.com/downloads"><span>Install Git</span></a>
</div>
<div id="python" class="required-app disabled">
<img src="{{root}}/images/PythonLogo.png">
<div class="description">Required version: <span class="version">2.7.15</span></div>
<a class="spinner" href="https://www.python.org/downloads/release/python-2715/"><span>Install Python</span></a>
</div>
</div>
<p>
At this time, while the extension is still in public-preview, you will also need to install the Truffle Suite of developer tools.
Click the links below to install the Truffle tools directly from this extension
</p>
<div class="required">
<div id="npm" class="required-app disabled">
<img src="{{root}}/images/NpmLogo.png">
<div class="description">Required version: <span class="version">6.4.1</span></div>
<a class="spinner action" href="command:azureBlockchainService.required.installNpm"><span>Install NPM</span></a>
</div>
<div id="truffle" class="required-app disabled">
<img src="{{root}}/images/TruffleLogo.svg">
<div class="description">Required version: <span class="version">5.0.0</span></div>
<a class="spinner action" href="command:azureBlockchainService.required.installTruffle"><span>Install Truffle Suite</span></a>
</div>
<div id="ganache" class="required-app disabled">
<img src="{{root}}/images/GanacheLogo.png">
<div class="description">Required version: <span class="version">6.0.0</span></div>
<a class="spinner action" href="command:azureBlockchainService.required.installGanache"><span>Install Ganache CLI</span></a>
</div>
</div>
</div>
</div>
<p class="showOnStartup">
<input type="checkbox" id="showOnStartup" class="checkbox" checked="checked">
<label class="caption" for="showOnStartup">Show this page on startup</label>
</p>
</div>
<script type="text/javascript" src="{{root}}/resources/welcome/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="{{root}}/resources/welcome/main.js"></script>
</div>
<script type="text/javascript" src="{{root}}/resources/welcome/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="{{root}}/resources/welcome/main.js"></script>
</body>
</html>
</html>

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

@ -53,7 +53,7 @@ export class AzureBlockchainServiceClient extends AzureServiceClient {
Output.outputLine(Constants.outputChannel.azureBlockchainServiceClient, err.message);
}
env.openExternal(Uri.parse(`${Constants.azurePortalBasUri}/resource/${urlDetailsOfConsortium}`));
env.openExternal(Uri.parse(`${Constants.azureResourceExplorer.portalBasUri}/resource/${urlDetailsOfConsortium}`));
});
}
@ -98,7 +98,7 @@ export class AzureBlockchainServiceClient extends AzureServiceClient {
callback: (error: Error | null, result?: any) => void,
): Promise<void> {
// @ts-ignore
return await this.pipeline(httpRequest, (err: ServiceError, response: IncomingMessage, responseBody: string) => {
return this.pipeline(httpRequest, (err: ServiceError, response: IncomingMessage, responseBody: string) => {
if (err) {
window.showErrorMessage(err.message);
return callback(err);

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

@ -11,11 +11,6 @@ export namespace AzureBlockchain {
await AzureBlockchain.addDataInClipboard(Constants.rpcEndpointAddress, rpcEndpointAddress);
}
export async function copyAccessKey(consortiumNode: ConsortiumView): Promise<void> {
const accessKey = await consortiumNode.getAccessKey();
await AzureBlockchain.addDataInClipboard(Constants.accessKey, accessKey);
}
export async function addDataInClipboard(typeOfData: string, data?: string | null) {
if (data) {
await env.clipboard.writeText(data);

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

@ -1,37 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ResourceManagementClient, SubscriptionClient, SubscriptionModels } from 'azure-arm-resource';
import { commands, extensions, ProgressLocation, QuickPickItem, window } from 'vscode';
import { ProgressLocation, QuickPickItem, window } from 'vscode';
import { AzureBlockchainServiceClient, IAzureMemberDto, ICreateQuorumMember } from './ARMBlockchain';
import { AzureAccount } from './azure-account.api';
import { Constants } from './Constants';
import { showInputBox, showQuickPick } from './helpers';
import { AzureConsortium, LocationItem, Member, ResourceGroupItem, SubscriptionItem, TransactionNode } from './Models';
import { getAzureRegions } from './Regions';
import { AzureConsortium, Member, ResourceGroupItem, SubscriptionItem, TransactionNode } from './Models';
import { ConsortiumItem } from './Models/ConsortiumItem';
import { ResourceExplorerAndGenerator } from './ResourceExplorerAndGenerator';
import { WestlakeInputValidator } from './validators/WestlakeInputValidator';
export class ConsortiumResourceExplorer {
private readonly _accountApi: AzureAccount;
constructor() {
this._accountApi = extensions.getExtension<AzureAccount>('ms-vscode.azure-account')!.exports;
}
public async selectConsortium(childrenFilters?: string[]): Promise<AzureConsortium> {
export class ConsortiumResourceExplorer extends ResourceExplorerAndGenerator {
public async selectOrCreateConsortium(childrenFilters?: string[]): Promise<AzureConsortium> {
await this.waitForLogin();
const subscriptionItem = await this.getOrSelectSubscriptionItem();
const resourceGroupItem = await this.getOrSelectResourceGroup(subscriptionItem);
return await this.getOrSelectConsortiumItem(subscriptionItem, resourceGroupItem, childrenFilters);
}
const resourceGroupItem = await this.getOrCreateResourceGroupItem(subscriptionItem);
public async createConsortium(): Promise<AzureConsortium> {
await this.waitForLogin();
const subscriptionItem = await this.getOrSelectSubscriptionItem();
const resourceGroupItem = await this.getOrCreateResourceGroup(subscriptionItem);
return await this.createConsortiumItem(subscriptionItem, resourceGroupItem);
return this.getOrCreateConsortiumItem(subscriptionItem, resourceGroupItem, childrenFilters);
}
public async getAccessKeys(consortium: AzureConsortium): Promise<string[]> {
@ -64,10 +50,10 @@ export class ConsortiumResourceExplorer {
subscriptionItem.session.credentials,
subscriptionItem.subscriptionId,
resourceGroupItem.label,
Constants.requestBaseUri,
Constants.requestApiVersion,
Constants.azureResourceExplorer.requestBaseUri,
Constants.azureResourceExplorer.requestApiVersion,
{
acceptLanguage: Constants.requestAcceptLanguage,
acceptLanguage: Constants.azureResourceExplorer.requestAcceptLanguage,
filters: [],
generateClientRequestId: true,
longRunningOperationRetryTimeout: 30,
@ -80,175 +66,82 @@ export class ConsortiumResourceExplorer {
);
}
private async getResourceClient(subscriptionItem: SubscriptionItem)
: Promise<ResourceManagementClient.ResourceManagementClient> {
return new ResourceManagementClient.ResourceManagementClient(
subscriptionItem.session.credentials,
subscriptionItem.subscriptionId,
subscriptionItem.session.environment.resourceManagerEndpointUrl,
);
}
private async getOrSelectSubscriptionItem(): Promise<SubscriptionItem> {
return showQuickPick(
await this.loadSubscriptionItems(),
{ placeHolder: Constants.placeholders.selectSubscription, ignoreFocusOut: true },
);
}
private async loadSubscriptionItems(): 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) {
throw new Error(Constants.errorMessageStrings.NoSubscriptionFoundClick);
}
return subscriptionItems;
}
private async getOrSelectResourceGroup(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem> {
return showQuickPick(
this.getResourceGroupItems(subscriptionItem),
{ placeHolder: Constants.placeholders.selectResourceGroup, ignoreFocusOut: true },
);
}
private async getOrCreateResourceGroup(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem> {
const createGroupItem: QuickPickItem = {
label: '$(plus) Create Resource Group',
};
const items: QuickPickItem[] = [];
items.push(createGroupItem);
items.push(...await this.getResourceGroupItems(subscriptionItem));
private async getOrCreateConsortiumItem(
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
excludedItems?: string[],
): Promise<AzureConsortium> {
const pick = await showQuickPick(
items,
{ placeHolder: Constants.placeholders.selectResourceGroup, ignoreFocusOut: true },
);
if (pick instanceof (ResourceGroupItem)) {
return pick;
} else {
return this.createResourceGroup(subscriptionItem);
}
}
private async createResourceGroup(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem> {
const resourceGroupName = await showInputBox({
ignoreFocusOut: true,
placeHolder: 'Resource Group Name',
prompt: 'Provide a resource group name',
validateInput: WestlakeInputValidator.validateNames,
});
const locationItem = await showQuickPick(
this.getLocationItems(subscriptionItem),
{ placeHolder: 'Select a location to create your Resource Group in...', ignoreFocusOut: true },
);
return window.withProgress({
location: ProgressLocation.Notification,
title: `Creating resource group '${resourceGroupName}'`,
}, async () => {
if (subscriptionItem.subscriptionId === undefined) {
throw new Error(Constants.errorMessageStrings.NoSubscriptionFound);
} else {
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 getResourceGroupItems(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem[]> {
const resourceManagementClient = await this.getResourceClient(subscriptionItem);
const resourceGroups = await resourceManagementClient.resourceGroups.list();
return resourceGroups.map((resourceGroup) => new ResourceGroupItem(resourceGroup.name, resourceGroup.location));
}
private async getLocationItems(subscriptionItem: SubscriptionItem): Promise<LocationItem[]> {
const subscriptionClient = new SubscriptionClient.SubscriptionClient(
subscriptionItem.session.credentials,
subscriptionItem.session.environment.resourceManagerEndpointUrl,
);
const locations = await subscriptionClient.subscriptions.listLocations(subscriptionItem.subscriptionId);
return locations.map((location: SubscriptionModels.Location) => new LocationItem(location));
}
private async getOrSelectConsortiumItem(
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
childrenFilters?: string[])
: Promise<AzureConsortium> {
const consortiumItems = this.getNewConsortiumItems(subscriptionItem, resourceGroupItem, childrenFilters);
return showQuickPick(consortiumItems,
this.getConsortiumItems(subscriptionItem, resourceGroupItem, excludedItems),
{ placeHolder: Constants.placeholders.selectConsortium, ignoreFocusOut: true });
if (pick instanceof ConsortiumItem) {
return this.getAzureConsortium(pick, subscriptionItem, resourceGroupItem);
} else {
return this.createAzureConsortium(subscriptionItem, resourceGroupItem);
}
}
private async getNewConsortiumItems(
private async getConsortiumItems(
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
childrenFilters?: string[])
: Promise<AzureConsortium[]> {
const consortiumItems = await this.loadConsortiumItems(subscriptionItem, resourceGroupItem);
excludedItems?: string[],
): Promise<QuickPickItem[]> {
const items: QuickPickItem[] = [];
const createConsortiumItem: QuickPickItem = { label: '$(plus) Create Consortium' };
const consortiumItems = await this.loadConsortiumItems(subscriptionItem, resourceGroupItem, excludedItems);
if (childrenFilters) {
return consortiumItems.filter((item) => !childrenFilters.includes(item.label));
}
items.push(createConsortiumItem, ...consortiumItems);
return consortiumItems;
return items;
}
private async loadConsortiumItems(subscriptionItem: SubscriptionItem, resourceGroupItem: ResourceGroupItem)
: Promise<AzureConsortium[]> {
private async loadConsortiumItems(
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
excludedItems: string[] = [],
): Promise<ConsortiumItem[]> {
const client = await this.getClient(subscriptionItem, resourceGroupItem);
const members: IAzureMemberDto[] = await client.memberResource.getListMember();
if (!members.length) {
throw new Error(`No members found in resource group ${resourceGroupItem.label}.`);
}
const consortiumItems = members
.map((member) => new AzureConsortium(
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));
for (const consortium of consortiumItems) {
const filterMembers = members.filter((x: IAzureMemberDto) => x.properties.consortium === consortium.label);
for (const member of filterMembers) {
const transactionNodes = await client.transactionNodeResource.getListTransactionNode(member.name);
const memberItem = new Member(member.name);
await consortium.setChildren([
memberItem,
...transactionNodes.map((transactionNode) => {
return new TransactionNode(transactionNode.name, transactionNode.properties.dns);
}),
]);
}
}
return consortiumItems;
}
private async createConsortiumItem(subscriptionItem: SubscriptionItem, resourceGroupItem: ResourceGroupItem)
private async getAzureConsortium(
consortiumItems: ConsortiumItem,
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
): Promise<AzureConsortium> {
const client = await this.getClient(subscriptionItem, resourceGroupItem);
const transactionNodes = await client.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 createAzureConsortium(subscriptionItem: SubscriptionItem, resourceGroupItem: ResourceGroupItem)
: Promise<AzureConsortium> {
const client = await this.getClient(subscriptionItem, resourceGroupItem);
@ -265,7 +158,7 @@ export class ConsortiumResourceExplorer {
});
const protocol = await showQuickPick(
[{label: 'Quorum'}],
[{ label: 'Quorum' }],
{
ignoreFocusOut: true,
placeHolder: Constants.paletteWestlakeLabels.selectConsortiumProtocol,
@ -287,7 +180,7 @@ export class ConsortiumResourceExplorer {
});
const region = await showQuickPick(
getAzureRegions(),
this.getLocationItems(subscriptionItem),
{ placeHolder: Constants.paletteWestlakeLabels.selectConsortiumRegion, ignoreFocusOut: true },
);
@ -296,24 +189,16 @@ export class ConsortiumResourceExplorer {
consortiumName,
consortiumPassword,
protocol: protocol.label,
region: region.key,
region: region.description,
};
await client.consortiumResource.createConsortium(memberName, bodyParams);
return window.withProgress({
location: ProgressLocation.Window,
title: Constants.statusBarMessages.creatingConsortium,
}, async () => {
await client.consortiumResource.createConsortium(memberName, bodyParams);
return new AzureConsortium(consortiumName, subscriptionItem.subscriptionId, resourceGroupItem.label, memberName);
}
private 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) {
throw new Error(Constants.errorMessageStrings.WaitForLogin);
}
}
return true;
return new AzureConsortium(consortiumName, subscriptionItem.subscriptionId, resourceGroupItem.label, memberName);
});
}
}

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

@ -8,6 +8,9 @@ import { ExtensionContext } from 'vscode';
export class Constants {
public static extensionContext: ExtensionContext;
public static temporaryDirectory = '';
public static logicAppOutputDir = 'generatedLogicApp';
public static flowAppOutputDir = 'generatedFlowApp';
public static azureFunctionOutputDir = 'generatedAzureFunction';
public static extensionId = '';
public static extensionVersion = '';
@ -23,7 +26,8 @@ export class Constants {
telemetryClient: 'Telemetry Client',
};
public static isWelcomePageShown = 'isWelcomePageShown';
public static showOnStartupWelcomePage = 'showOnStartupWelcomePage';
public static showOnStartupRequirementsPage = 'showOnStartupRequirementsPage';
public static defaultTruffleBox = 'Azure-Samples/Blockchain-Ethereum-Template';
public static tempPath = 'tempPath';
@ -45,6 +49,11 @@ export class Constants {
truffle: '5.0.0',
};
public static webViewPages = {
requirements: 'Azure Blockchain Development Kit - Preview',
welcome: 'Welcome to Azure Blockchain',
};
public static contractExtension = {
json: '.json',
sol: '.sol',
@ -82,8 +91,6 @@ export class Constants {
gasPrice: 100000000000,
};
public static telemetry = 'Telemetry';
public static networkName = {
azure: 'Azure Blockchain Service',
local: 'Local Network',
@ -110,6 +117,7 @@ export class Constants {
enterTruffleBoxName: 'Enter pre-built Truffle project',
enterWestlakeUrl: 'Enter Westlake url',
enterYourGanacheUrl: 'Enter your Ganache url',
provideResourceGroupName: 'Provide a resource group name',
selectConsortiumProtocol: 'Select protocol',
selectConsortiumRegion: 'Select region',
selectResourceGroup: 'Select resource group',
@ -138,11 +146,13 @@ export class Constants {
deployedUrlStructure: 'host:port',
generateMnemonic: 'Generate mnemonic',
pasteMnemonic: 'Paste mnemonic',
resourceGroupName: 'Resource Group Name',
selectConsortium: 'Select consortium',
selectDeployDestination: 'Select deploy destination',
selectLedgerEventsDestination: 'Select ledger events destination',
selectNewProjectPath: 'Select new project path',
selectResourceGroup: 'Select a resource group to select or create your consortium in...',
selectResourceGroup: 'Select a resource group',
selectRgLocation: 'Select a location to create your Resource Group in...',
selectSubscription: 'Select subscription',
selectTypeOfMnemonic: 'Select type of mnemonic',
selectTypeOfSolidityProject: 'Select type of solidity project',
@ -170,22 +180,6 @@ export class Constants {
runningCommand: 'Running command',
};
public static mnemonicMessages = {
invalidStorageTypeSelected: 'Invalid storage type selected',
whereStored: 'Where are your mnemonics stored?',
};
public static mnemonicTypeQuickPick = {
text: {
local: 'In local file',
truffle: 'In truffle-config',
},
types: {
local: 'local',
truffle: 'truffle',
},
};
public static typeOfSolidityProject = {
action: {
emptyProject: 'createEmptyProject',
@ -210,10 +204,15 @@ export class Constants {
},
};
public static requestApiVersion = '2018-06-01-preview';
public static requestAcceptLanguage = 'en-US';
public static requestBaseUri = 'https://management.azure.com';
public static azurePortalBasUri = 'https://portal.azure.com/#@microsoft.onmicrosoft.com';
public static statusBarMessages = {
buildingContracts: 'Building contracts',
checkingRequirementDependencies: 'Checking requirement dependencies version',
creatingConsortium: 'Creating new consortium',
creatingProject: 'Creating new project',
deployingContracts: (destination: string) => {
return `Deploying contracts to '${destination}'`;
},
};
public static welcomePagePath = '';
public static requirementsPagePath = '';
@ -221,11 +220,6 @@ export class Constants {
public static dataCopied = ' copied to clipboard';
public static rpcEndpointAddress = 'RPCEndpointAddress';
public static accessKey = 'AccessKey';
public static folderStrings = {
folderNotSelected: 'Folder not selected',
};
public static ganacheCommandStrings = {
serverAlreadyRunning: 'Ganache server already running',
@ -249,6 +243,7 @@ export class Constants {
public static errorMessageStrings = {
ActionAborted: 'Action aborted',
GitIsNotInstalled: 'Git is not installed',
NewProjectCreationFailed: 'Command createProject has failed.',
NoSubscriptionFound: 'No subscription found.',
NoSubscriptionFoundClick: 'No subscription found, click an Azure account ' +
'at the bottom left corner and choose Select All',
@ -263,10 +258,32 @@ export class Constants {
newProjectCreationFinished: 'New project was created successfully',
newProjectCreationStarted: 'New project creation is started',
seeDetailsRequirementsPage: 'Please see details on the Requirements Page',
seeDetailsWelcomePage: 'Please see details on Welcome Page',
};
public static microservicesWorkflows = {
Data: 'Data',
Messaging: 'Messaging',
Reporting: 'Reporting',
Service: 'Service',
};
public static logicApp = {
AzureFunction: 'Azure Function',
FlowApp: 'Flow App',
LogicApp: 'Logic App',
};
public static gitCommand = 'git';
public static truffleCommand = 'truffle';
public static azureResourceExplorer = {
portalBasUri: 'https://portal.azure.com/#@microsoft.onmicrosoft.com',
providerName: 'Microsoft.Blockchain',
requestAcceptLanguage: 'en-US',
requestApiVersion: '2018-06-01-preview',
requestBaseUri: 'https://management.azure.com',
resourceType: 'blockchainMembers',
};
public static initialize(context: ExtensionContext) {
this.extensionContext = context;

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

@ -1,30 +1,30 @@
import './Nethereum.Generators.DuoCode';
function buildConstructor(item: any): Nethereum.Generators.Model.ConstructorABI {
var constructorItem = new Nethereum.Generators.Model.ConstructorABI();
const constructorItem = new Nethereum.Generators.Model.ConstructorABI();
constructorItem.set_InputParameters(buildFunctionParameters(item.inputs));
return constructorItem;
}
function buildFunction(item: any): Nethereum.Generators.Model.FunctionABI {
var functionItem = new Nethereum.Generators.Model.FunctionABI(item.name, item.constant, false);
const functionItem = new Nethereum.Generators.Model.FunctionABI(item.name, item.constant, false);
functionItem.set_InputParameters(buildFunctionParameters(item.inputs));
functionItem.set_OutputParameters(buildFunctionParameters(item.outputs));
return functionItem;
}
function buildEvent(item: any): Nethereum.Generators.Model.EventABI {
var eventItem = new Nethereum.Generators.Model.EventABI (item.name);
const eventItem = new Nethereum.Generators.Model.EventABI (item.name);
eventItem.set_InputParameters(buildEventParameters(item.inputs));
return eventItem;
}
function buildFunctionParameters(items: any): Nethereum.Generators.Model.ParameterABI[] {
var parameterOrder = 0;
var parameters = [];
for (var i = 0, len = items.length; i < len; i++) {
let parameterOrder = 0;
const parameters = [];
for (let i = 0, len = items.length; i < len; i++) {
parameterOrder = parameterOrder + 1;
var parameter = new Nethereum.Generators.Model.ParameterABI
const parameter = new Nethereum.Generators.Model.ParameterABI
.ctor$1(items[i].type, items[i].name, parameterOrder);
parameters.push(parameter);
}
@ -32,11 +32,11 @@ function buildFunctionParameters(items: any): Nethereum.Generators.Model.Paramet
}
function buildEventParameters(items: any): Nethereum.Generators.Model.ParameterABI[] {
var parameterOrder = 0;
var parameters = [];
for (var i = 0, len = items.length; i < len; i++) {
let parameterOrder = 0;
const parameters = [];
for (let i = 0, len = items.length; i < len; i++) {
parameterOrder = parameterOrder + 1;
var parameter = new Nethereum.Generators.Model.ParameterABI
const parameter = new Nethereum.Generators.Model.ParameterABI
.ctor$1(items[i].type, items[i].name, parameterOrder);
parameter.set_Indexed(items[i].indexed);
parameters.push(parameter);
@ -46,25 +46,25 @@ function buildEventParameters(items: any): Nethereum.Generators.Model.ParameterA
export function buildContract(abiStr: string): Nethereum.Generators.Model.ContractABI {
const abi = JSON.parse(abiStr);
let functions = [];
let events = [];
const functions = [];
const events = [];
let constructor = new Nethereum.Generators.Model.ConstructorABI();
for (var i = 0, len = abi.length; i < len; i++) {
if (abi[i].type === "function") {
for (let i = 0, len = abi.length; i < len; i++) {
if (abi[i].type === 'function') {
functions.push(buildFunction(abi[i]));
}
if (abi[i].type === "event") {
if (abi[i].type === 'event') {
events.push(buildEvent(abi[i]));
}
if (abi[i].type === "constructor") {
if (abi[i].type === 'constructor') {
constructor = buildConstructor(abi[i]);
}
}
let contract = new Nethereum.Generators.Model.ContractABI();
const contract = new Nethereum.Generators.Model.ContractABI();
contract.set_Constructor(constructor);
contract.set_Functions(functions);
contract.set_Events(events);

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

@ -1,61 +1,43 @@
import { ResourceManagementClient, ResourceModels } from 'azure-arm-resource';
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { mkdirp, readdir, readJson, writeFile } from 'fs-extra';
import * as path from 'path';
import { commands, extensions, QuickPickItem, Uri, window } from 'vscode';
import { AzureAccount } from '../azure-account.api';
import { QuickPickItem, Uri, window } from 'vscode';
import { Constants } from '../Constants';
import { getWorkspaceRoot } from '../helpers';
import { showInputBox, showQuickPick } from '../helpers/userInteraction';
import { ResourceGroupItem, SubscriptionItem } from '../Models';
import { Output } from '../Output';
import { ResourceExplorerAndGenerator } from '../ResourceExplorerAndGenerator';
import { buildContract } from './AbiDeserialiser';
import './Nethereum.Generators.DuoCode';
export class LogicAppGenerator {
private readonly _accountApi: AzureAccount;
constructor() {
this._accountApi = extensions.getExtension<AzureAccount>('ms-vscode.azure-account')!.exports;
}
export class LogicAppGenerator extends ResourceExplorerAndGenerator {
public async generateMicroservicesWorkflows(filePath: Uri | undefined): Promise<void> {
return this.generateWorkflows('Service', filePath);
return this.generateWorkflows(Constants.microservicesWorkflows.Service, filePath);
}
public async generateDataPublishingWorkflows(filePath: Uri | undefined): Promise<void> {
return this.generateWorkflows('Data', filePath);
return this.generateWorkflows(Constants.microservicesWorkflows.Data, filePath);
}
public async generateEventPublishingWorkflows(filePath: Uri | undefined): Promise<void> {
return this.generateWorkflows('Messaging', filePath);
return this.generateWorkflows(Constants.microservicesWorkflows.Messaging, filePath);
}
public async generateReportPublishingWorkflows(filePath: Uri | undefined): Promise<void> {
return this.generateWorkflows('Reporting', filePath);
return this.generateWorkflows(Constants.microservicesWorkflows.Reporting, filePath);
}
private async generateWorkflows(workflowType: string, filePath: Uri | undefined): Promise<void> {
const workspaceDir: Uri = Uri.parse(getWorkspaceRoot());
const dirPath: string = workspaceDir.fsPath + '/build/contracts/';
const dirPath: string = path.join(getWorkspaceRoot(), 'build/contracts');
if (filePath) {
const fileName = path.basename(filePath.fsPath);
const contractName = fileName.Remove(fileName.length - 4);
const compiledContractPath = dirPath + contractName + '.json';
let picks: QuickPickItem[];
if (workflowType === 'Service') {
picks = [
{ label: 'Logic App' },
{ label: 'Flow App' },
{ label: 'Azure Function' },
];
} else {
picks = [
{ label: 'Logic App' },
{ label: 'Flow App' },
];
}
const compiledContractPath = path.join(dirPath, `${contractName}.json`);
const picks = this.getLogicAppItems(workflowType);
const serviceTypeSelection: string = (await showQuickPick(picks, { })).label;
const serviceType: int = this.getServiceTypeFromString(serviceTypeSelection);
const contractAddress: string = await showInputBox({ value: 'contract address' });
@ -64,7 +46,6 @@ export class LogicAppGenerator {
async (err2: Error, contents: any) => await this.handleContractJsonFile(
err2,
contents,
dirPath,
contractAddress,
subscriptionItem,
resourceGroupItem,
@ -83,20 +64,7 @@ export class LogicAppGenerator {
return;
}
let picks: QuickPickItem[];
if (workflowType === 'Service') {
picks = [
{ label: 'Logic App' },
{ label: 'Flow App' },
{ label: 'Azure Function' },
];
} else {
picks = [
{ label: 'Logic App' },
{ label: 'Flow App' },
];
}
const picks = this.getLogicAppItems(workflowType);
const serviceTypeSelection: string = (await showQuickPick(picks, { })).label;
const serviceType: int = this.getServiceTypeFromString(serviceTypeSelection);
const contractAddress: string = await showInputBox({ value: 'contract address' });
@ -106,7 +74,6 @@ export class LogicAppGenerator {
async (err2: Error, contents: any) => await this.handleContractJsonFile(
err2,
contents,
dirPath,
contractAddress,
subscriptionItem,
resourceGroupItem,
@ -118,12 +85,27 @@ export class LogicAppGenerator {
window.showInformationMessage('Generated the logic app!');
}
private getLogicAppItems(workflowType: string): QuickPickItem[] {
if (workflowType === Constants.microservicesWorkflows.Service) {
return [
{ label: Constants.logicApp.LogicApp },
{ label: Constants.logicApp.FlowApp },
{ label: Constants.logicApp.AzureFunction },
];
} else {
return [
{ label: Constants.logicApp.LogicApp },
{ label: Constants.logicApp.FlowApp },
];
}
}
private getServiceTypeFromString(serviceTypeSelection: string): int {
if (serviceTypeSelection === 'Logic App') {
if (serviceTypeSelection === Constants.logicApp.LogicApp) {
return 1;
} else if (serviceTypeSelection === 'Flow App') {
} else if (serviceTypeSelection === Constants.logicApp.FlowApp) {
return 0;
} else if (serviceTypeSelection === 'Azure Function') {
} else if (serviceTypeSelection === Constants.logicApp.AzureFunction) {
return 2;
} else {
throw new Error('Service type string not valid');
@ -133,7 +115,6 @@ export class LogicAppGenerator {
private async handleContractJsonFile(
err: Error,
contents: any,
dirPath: string,
contractAddress: string,
subscriptionItem: SubscriptionItem,
resourceGroupItem: ResourceGroupItem,
@ -144,7 +125,7 @@ export class LogicAppGenerator {
return;
}
await this.createLogicAppFromAbi(contents,
dirPath,
this.getOutputDir(serviceType),
contractAddress,
subscriptionItem,
resourceGroupItem.description,
@ -162,13 +143,13 @@ export class LogicAppGenerator {
serviceType: int) {
let generator;
if (workflowType === 'Service') {
if (workflowType === Constants.microservicesWorkflows.Service) {
generator = new Nethereum.Generators.ServiceWorkflow.ServiceWorkflowProjectGenerator(
buildContract(JSON.stringify(contract.abi)),
contract.contractName,
contract.bytecode,
contract.contractName,
contract.contractName + '.Service',
contract.contractName + `.${workflowType}`,
dirPath,
'/',
serviceType,
@ -179,13 +160,13 @@ export class LogicAppGenerator {
location,
'',
);
} else if (workflowType === 'Data') {
} else if (workflowType === Constants.microservicesWorkflows.Data) {
generator = new Nethereum.Generators.DataWorkflow.DataWorkflowProjectGenerator(
buildContract(JSON.stringify(contract.abi)),
contract.contractName,
contract.bytecode,
contract.contractName,
contract.contractName + '.Data',
contract.contractName + `.${workflowType}`,
dirPath,
'/',
serviceType,
@ -195,7 +176,7 @@ export class LogicAppGenerator {
location,
JSON.stringify(contract.abi),
);
} else if (workflowType === 'Messaging') {
} else if (workflowType === Constants.microservicesWorkflows.Messaging) {
const topicName: string = await showInputBox({ value: 'topic name' });
const picks: QuickPickItem[] = [
{ label: 'Service Bus' },
@ -208,7 +189,7 @@ export class LogicAppGenerator {
contract.contractName,
contract.bytecode,
contract.contractName,
contract.contractName + '.Messaging',
contract.contractName + `.${workflowType}`,
dirPath,
'/',
serviceType,
@ -220,13 +201,13 @@ export class LogicAppGenerator {
topicName,
this.getMessagingType(messagingType),
);
} else if (workflowType === 'Reporting') {
} else if (workflowType === Constants.microservicesWorkflows.Reporting) {
generator = new Nethereum.Generators.ReportingWorkflow.ReportingWorkflowProjectGenerator(
buildContract(JSON.stringify(contract.abi)),
contract.contractName,
contract.bytecode,
contract.contractName,
contract.contractName + '.Reporting',
contract.contractName + `.${workflowType}`,
dirPath,
'/',
serviceType,
@ -268,65 +249,25 @@ export class LogicAppGenerator {
});
}
private getOutputDir(serviceType: int): string {
switch (serviceType) {
case 0:
return path.join(getWorkspaceRoot(), Constants.flowAppOutputDir);
case 1:
return path.join(getWorkspaceRoot(), Constants.logicAppOutputDir);
case 2:
return path.join(getWorkspaceRoot(), Constants.azureFunctionOutputDir);
default:
throw new Error('Invalid service type.');
}
}
private async selectSubscriptionAndResourceGroup(): Promise<[SubscriptionItem, ResourceGroupItem]> {
await this.waitForLogin();
const subscriptionItem = await this.getOrSelectSubscriptionItem();
const resourceGroupItem = await this.getOrCreateResourceGroup(subscriptionItem);
const resourceGroupItem = await this.getOrCreateResourceGroupItem(subscriptionItem);
return [subscriptionItem, resourceGroupItem];
}
private async getOrSelectSubscriptionItem(): Promise<SubscriptionItem> {
return await showQuickPick(
await this.loadSubscriptionItems(),
{ placeHolder: Constants.placeholders.selectSubscription, ignoreFocusOut: true },
);
}
private async loadSubscriptionItems(): Promise<SubscriptionItem[]> {
await this._accountApi.waitForFilters();
const subscriptionItems = this._accountApi.filters
.map((filter: any) => new SubscriptionItem(filter.subscription.displayName,
filter.subscription.subscriptionId, filter.session));
if (subscriptionItems.length === 0) {
throw new Error('No subscription found, click an Azure account at the \
bottom left corner and choose Select All.');
}
return subscriptionItems;
}
private async getOrCreateResourceGroup(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem> {
return await showQuickPick(
this.getResourceGroupItems(subscriptionItem),
{ placeHolder: Constants.placeholders.selectResourceGroup, ignoreFocusOut: true },
);
}
private async getResourceGroupItems(subscriptionItem: SubscriptionItem): Promise<ResourceGroupItem[]> {
// @ts-ignore
const resourceManagementClient = new ResourceManagementClient(
subscriptionItem.session.credentials,
subscriptionItem.subscriptionId,
subscriptionItem.session.environment.resourceManagerEndpointUrl,
);
const resourceGroups = await resourceManagementClient.resourceGroups.list();
return resourceGroups.map((resourceGroup: ResourceModels.ResourceGroup) =>
new ResourceGroupItem(resourceGroup.name, resourceGroup.location));
}
private 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) {
throw new Error(Constants.errorMessageStrings.WaitForLogin);
}
}
return true;
}
}

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

@ -61,13 +61,9 @@ export class AzureConsortium extends ProtectedConsortium {
url.port = `${Constants.defaultAzureBSPort}`;
}
return url.origin;
}
public async getAccessKey(): Promise<string> {
const consortiumResourceExplorer = new ConsortiumResourceExplorer();
const keys = await consortiumResourceExplorer.getAccessKeys(this);
return keys ? keys[0] : '';
return keys ? `${url.origin}/${keys[0]}` : url.origin;
}
public toJSON(): { [p: string]: any } {

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

@ -56,16 +56,12 @@ export abstract class Consortium extends ExtensionItem {
}
public async getRPCAddress(): Promise<string> {
return this.urls.length === 0 ? '' : this.urls[0].origin;
}
public async getAccessKey(): Promise<string> {
if (this.urls.length === 0) {
return '';
}
const url = this.urls[0];
return url.pathname === '/' ? '' : url.pathname || '';
return url.pathname === '/' ? url.origin : `${url.origin}/${url.pathname}`;
}
public getConsortiumId(): number {

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

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

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

@ -20,13 +20,12 @@ export abstract class ProtectedConsortium extends Consortium {
const network = await super.getTruffleNetwork();
const targetURL = await this.getRPCAddress();
const accessKey = await this.getAccessKey();
const mnemonic = await this.getMnemonic();
await config.importFs();
network.options.provider = {
mnemonic: mnemonic.path,
url: `${targetURL}/${accessKey}`,
url: `${targetURL}`,
};
return network;

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

@ -12,8 +12,4 @@ export class ConsortiumView extends ExtensionView<Consortium> {
public async getRPCAddress(): Promise<string> {
return this.extensionItem.getRPCAddress();
}
public async getAccessKey(): Promise<string> {
return this.extensionItem.getAccessKey();
}
}

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

@ -1,10 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { GanacheCommands } from '../commands/GanacheCommands';
import { ConsortiumResourceExplorer } from '../ConsortiumResourceExplorer';
import { Constants } from '../Constants';
import { showInputBox, showQuickPick } from '../helpers';
import {
AzureConsortium,
Consortium,
ItemType,
LocalNetworkConsortium,
@ -15,26 +16,29 @@ import {
import { ConsortiumTreeManager } from '../treeService/ConsortiumTreeManager';
import { UrlValidator } from '../validators/UrlValidator';
import { ConsortiumView } from '../ViewItems';
import { WestlakeCommands } from './WestlakeCommands';
import { GanacheCommands } from './GanacheCommands';
interface IConsortiumDestination {
cmd: (childrenFilters?: string[]) => Promise<Consortium>;
cmd: (excludedItems?: string[]) => Promise<Consortium>;
itemType: ItemType;
label: string;
}
export namespace ConsortiumCommands {
export async function createConsortium(): Promise<Consortium> {
export async function createConsortium(consortiumTreeManager: ConsortiumTreeManager): Promise<Consortium> {
const createConsortiumDestination: IConsortiumDestination[] = [
{
cmd: WestlakeCommands.createWestlakeConsortium,
cmd: selectOrCreateConsortium,
itemType: ItemType.AZURE_BLOCKCHAIN,
label: Constants.uiCommandStrings.CreateConsortiumAzureBlockchainService,
},
];
const destination = await selectDestination(createConsortiumDestination);
return await destination.cmd();
const networkItem = await getNetwork(consortiumTreeManager, destination.itemType);
const childrenFilters = await getChildrenFilters(networkItem);
return destination.cmd(childrenFilters);
}
export async function connectConsortium(consortiumTreeManager: ConsortiumTreeManager): Promise<Consortium> {
@ -45,7 +49,7 @@ export namespace ConsortiumCommands {
label: Constants.uiCommandStrings.ConnectConsortiumLocalGanache,
},
{
cmd: WestlakeCommands.selectWestlakeConsortium,
cmd: selectOrCreateConsortium,
itemType: ItemType.AZURE_BLOCKCHAIN,
label: Constants.uiCommandStrings.ConnectConsortiumAzureBlockchainService,
},
@ -67,7 +71,7 @@ export namespace ConsortiumCommands {
export async function disconnectConsortium(consortiumTreeManager: ConsortiumTreeManager, viewItem: ConsortiumView)
: Promise<void> {
if (viewItem.extensionItem instanceof LocalNetworkConsortium) {
GanacheCommands.stopGanacheServer();
await GanacheCommands.stopGanacheServer();
}
return consortiumTreeManager.removeItem(viewItem.extensionItem);
}
@ -114,6 +118,11 @@ async function getNetwork(consortiumTreeManager: ConsortiumTreeManager, itemType
return networkItem;
}
async function selectOrCreateConsortium(excludedItems?: string[]): Promise<AzureConsortium> {
const azureResourceExplorer = new ConsortiumResourceExplorer();
return azureResourceExplorer.selectOrCreateConsortium(excludedItems);
}
async function connectLocalNetwork(): Promise<LocalNetworkConsortium> {
await GanacheCommands.startGanacheServer();

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

@ -2,7 +2,7 @@
// Licensed under the MIT license.
import * as fs from 'fs-extra';
import { Uri, window, workspace } from 'vscode';
import { ProgressLocation, Uri, window, workspace } from 'vscode';
import { Constants } from '../Constants';
import {
createTemporaryDir,
@ -50,7 +50,12 @@ export namespace ProjectCommands {
}
async function createNewEmptyProject(projectPath: string): Promise<void> {
await createProject(projectPath, Constants.defaultTruffleBox);
return window.withProgress({
location: ProgressLocation.Window,
title: Constants.statusBarMessages.creatingProject,
}, async () => {
return createProject(projectPath, Constants.defaultTruffleBox);
});
}
async function createProjectFromTruffleBox(projectPath: string): Promise<void> {
@ -65,9 +70,8 @@ async function createProject(projectPath: string, truffleBoxName: string): Promi
const path = (arrayFiles.length) ? createTemporaryDir(projectPath) : projectPath;
try {
window.showInformationMessage(Constants.informationMessage.newProjectCreationStarted);
Output.show();
await outputCommandHelper.executeCommand(path, 'npx', 'truffle', 'unbox', truffleBoxName);
await outputCommandHelper.executeCommand(path, 'npx', Constants.truffleCommand, 'unbox', truffleBoxName);
if (arrayFiles.length) {
fs.moveSync(path, projectPath);
}
@ -75,10 +79,9 @@ async function createProject(projectPath: string, truffleBoxName: string): Promi
0,
workspace.workspaceFolders ? workspace.workspaceFolders.length : null,
{uri: Uri.file(projectPath)});
window.showInformationMessage(Constants.informationMessage.newProjectCreationFinished);
} catch (error) {
// TODO: cleanup files after failed truffle unbox
throw Error(error);
arrayFiles.length ? fs.removeSync(path) : fs.emptyDirSync(path);
throw Error([Constants.errorMessageStrings.NewProjectCreationFailed, error.message].join(' '));
}
}

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

@ -4,7 +4,7 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import { format } from 'url';
import { env, Uri } from 'vscode';
import { env, ProgressLocation, Uri, window } from 'vscode';
import { Constants } from '../Constants';
import {
getWorkspaceRoot,
@ -35,16 +35,21 @@ const localGanacheRegexp = new RegExp(`127\.0\.0\.1\:${Constants.defaultLocalhos
export namespace TruffleCommands {
export async function buildContracts(): Promise<void> {
if (!await required.checkRequiredApps()) {
return;
}
await window.withProgress({
location: ProgressLocation.Window,
title: Constants.statusBarMessages.buildingContracts,
}, async () => {
if (!await required.checkRequiredApps()) {
return;
}
try {
Output.show();
await outputCommandHelper.executeCommand(getWorkspaceRoot(), 'npx', 'truffle', 'compile');
} catch (error) {
throw Error(error);
}
try {
Output.show();
await outputCommandHelper.executeCommand(getWorkspaceRoot(), 'npx', 'truffle', 'compile');
} catch (error) {
throw Error(error);
}
});
}
export async function deployContracts(consortiumTreeManager: ConsortiumTreeManager): Promise<void> {
@ -197,7 +202,8 @@ async function execute(deployDestination: IDeployDestination[]): Promise<void> {
async function createNewDeploymentNetwork(consortiumTreeManager: ConsortiumTreeManager, truffleConfigPath: string)
: Promise<void> {
const consortium = await ConsortiumCommands.connectConsortium(consortiumTreeManager);
return createNetwork(consortium, truffleConfigPath);
await createNetwork(consortium, truffleConfigPath);
}
async function createNetwork(consortium: Consortium, truffleConfigPath: string): Promise<void> {
@ -206,29 +212,28 @@ async function createNetwork(consortium: Consortium, truffleConfigPath: string):
await truffleConfig.setNetworks(network);
await deployToNetwork(network.name, truffleConfigPath);
if (network.options.provider) {
network.options.provider.mnemonic = undefined;
}
return await truffleConfig.setNetworks(network);
}
async function createMainNetwork(consortium: Consortium, truffleConfigPath: string): Promise<void> {
await showConfirmPaidOperationDialog();
return await createNetwork(consortium, truffleConfigPath);
await createNetwork(consortium, truffleConfigPath);
}
async function deployToNetwork(networkName: string, truffleConfigPath: string): Promise<void> {
const workspaceRoot = path.dirname(truffleConfigPath);
return window.withProgress({
location: ProgressLocation.Window,
title: Constants.statusBarMessages.deployingContracts(networkName),
}, async () => {
const workspaceRoot = path.dirname(truffleConfigPath);
await fs.ensureDir(workspaceRoot);
await outputCommandHelper.executeCommand(
workspaceRoot,
'npx',
'truffle', 'migrate', '--reset', '--network', networkName,
);
await fs.ensureDir(workspaceRoot);
await outputCommandHelper.executeCommand(
workspaceRoot,
'npx',
'truffle', 'migrate', '--reset', '--network', networkName,
);
});
}
async function createLocalGanacheNetwork(consortium: Consortium, truffleConfigPath: string): Promise<void> {

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

@ -2,23 +2,10 @@
// Licensed under the MIT license.
import { Uri, window } from 'vscode';
import { ConsortiumResourceExplorer } from '../ConsortiumResourceExplorer';
import { Constants } from '../Constants';
import { AzureConsortium } from '../Models';
import { TruffleCommands } from './TruffleCommands';
export namespace WestlakeCommands {
export async function createWestlakeConsortium(): Promise<AzureConsortium> {
const azureResourceExplorer = new ConsortiumResourceExplorer();
return azureResourceExplorer.createConsortium();
}
export async function selectWestlakeConsortium(childrenFilters?: string[]): Promise<AzureConsortium> {
const azureResourceExplorer = new ConsortiumResourceExplorer();
return azureResourceExplorer.selectConsortium(childrenFilters);
}
export async function showLedgerEventsDialog(uri: Uri): Promise<void> {
const ledgerEventsDestination = [
{
@ -44,7 +31,7 @@ export namespace WestlakeCommands {
throw new Error('Action aborted');
}
return await target.cmd(uri);
return target.cmd(uri);
}
}

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

@ -15,12 +15,11 @@ import { CommandContext, isWorkspaceOpen, required, setCommandContext } from './
import { MnemonicRepository } from './MnemonicService/MnemonicRepository';
import { CancellationEvent } from './Models';
import { Output } from './Output';
import { RequirementsPage } from './RequirementsPage';
import { RequirementsPage, WelcomePage } from './pages';
import { TelemetryClient } from './TelemetryClient';
import { ConsortiumTree } from './treeService/ConsortiumTree';
import { ConsortiumTreeManager } from './treeService/ConsortiumTreeManager';
import { ConsortiumView } from './ViewItems';
import { WelcomePage } from './WelcomePage';
export async function activate(context: ExtensionContext) {
Constants.initialize(context);
@ -35,27 +34,24 @@ export async function activate(context: ExtensionContext) {
const consortiumTreeManager = new ConsortiumTreeManager(context);
const consortiumTree = new ConsortiumTree(consortiumTreeManager);
welcomePage.checkAndShow();
await welcomePage.checkAndShow();
window.registerTreeDataProvider('AzureBlockchain', consortiumTree);
//#region azureBlockchain extension commands
const refresh = commands.registerCommand('azureBlockchainService.refresh', (element) => {
consortiumTree.refresh(element);
});
const showWelcomePage = commands.registerCommand('azureBlockchainService.showWelcomePage', () => {
welcomePage.show();
const showWelcomePage = commands.registerCommand('azureBlockchainService.showWelcomePage', async () => {
return welcomePage.show();
});
const showRequirementsPage = commands.registerCommand('azureBlockchainService.showRequirementsPage', () => {
requirementsPage.show();
const showRequirementsPage = commands.registerCommand('azureBlockchainService.showRequirementsPage',
async (checkShowOnStartup: boolean) => {
return checkShowOnStartup ? requirementsPage.checkAndShow() : requirementsPage.show();
});
const copyRPCEndpointAddress = commands.registerCommand('azureBlockchainService.copyRPCEndpointAddress',
async (viewItem: ConsortiumView) => {
await tryExecute(() => AzureBlockchain.copyRPCEndpointAddress(viewItem));
});
const copyAccessKey = commands.registerCommand('azureBlockchainService.copyAccessKey',
async (viewItem: ConsortiumView) => {
await tryExecute(() => AzureBlockchain.copyAccessKey(viewItem));
});
const installNpm = commands.registerCommand('azureBlockchainService.required.installNpm', async () => {
await tryExecute(() => required.installNpm());
});
@ -102,7 +98,7 @@ export async function activate(context: ExtensionContext) {
//#region commands with dialog
const createConsortium = commands.registerCommand('azureBlockchainService.createConsortium', async () => {
await tryExecute(() => ConsortiumCommands.createConsortium());
await tryExecute(() => ConsortiumCommands.createConsortium(consortiumTreeManager));
});
const connectConsortium = commands.registerCommand('azureBlockchainService.connectConsortium', async () => {
await tryExecute(() => ConsortiumCommands.connectConsortium(consortiumTreeManager));
@ -175,7 +171,6 @@ export async function activate(context: ExtensionContext) {
context.subscriptions.push(copyByteCode);
context.subscriptions.push(copyABI);
context.subscriptions.push(copyRPCEndpointAddress);
context.subscriptions.push(copyAccessKey);
context.subscriptions.push(startGanacheServer);
context.subscriptions.push(stopGanacheServer);
context.subscriptions.push(generateMicroservicesWorkflows);

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

@ -4,9 +4,6 @@ import { Constants } from '../Constants';
import { Output } from '../Output';
import { executeCommand, tryExecuteCommand } from './command';
import { CommandContext, setCommandContext } from './commandContext';
import Timeout = NodeJS.Timeout;
let timeoutID: NodeJS.Timeout;
export namespace required {
export interface IRequiredVersion {
@ -18,7 +15,6 @@ export namespace required {
const currentState: {[key: string]: IRequiredVersion} = {};
const requiredApps = [ 'node', 'npm', 'git' ];
// const auxiliaryApps = [ 'python', 'truffle', 'ganache' ];
export function isValid(version: string, minVersion: string, maxVersion?: string): boolean {
return !!semver.valid(version) &&
@ -27,37 +23,47 @@ export namespace required {
}
/**
* Function check all apps:
* Node.js, npm, git, truffle, ganache, python
* Function check all apps: Node.js, npm, git, truffle, ganache, python
* Show Requirements Page with checking showOnStartup flag
*/
export async function checkAllApps(): Promise<boolean> {
const versions = await getAllVersions();
const invalid = versions.some((version) => !version.isValid);
if (invalid) {
showRequiredAppsMessage();
return false;
const message = Constants.informationMessage.invalidRequiredVersion;
const details = Constants.informationMessage.seeDetailsRequirementsPage;
window
.showErrorMessage(`${message}. ${details}`, Constants.informationMessage.detailsButton)
.then((answer) => {
if (answer) {
commands.executeCommand('azureBlockchainService.showRequirementsPage');
}
});
commands.executeCommand('azureBlockchainService.showRequirementsPage', true);
}
return true;
return !invalid;
}
/**
* Function check only required apps:
* Node.js, npm, git
* Function check only required apps: Node.js, npm, git
* Show Requirements Page
*/
export async function checkRequiredApps(message?: string): Promise<boolean> {
export async function checkRequiredApps(): Promise<boolean> {
const versions = await getAllVersions();
const invalid = versions
.filter((version) => requiredApps.includes(version.app))
.some((version) => !version.isValid);
if (invalid) {
showRequiredAppsMessage(message || Constants.errorMessageStrings.RequiredAppsAreNotInstalled);
return false;
const message = Constants.errorMessageStrings.RequiredAppsAreNotInstalled;
const details = Constants.informationMessage.seeDetailsRequirementsPage;
window.showErrorMessage(`${message}. ${details}`);
commands.executeCommand('azureBlockchainService.showRequirementsPage');
}
return true;
return !invalid;
}
export async function getAllVersions(): Promise<IRequiredVersion[]> {
@ -79,21 +85,6 @@ export namespace required {
return Object.values(currentState);
}
export function showRequiredAppsMessage(message?: string): void {
commands.executeCommand('azureBlockchainService.showRequirementsPage');
clearTimeout(timeoutID as Timeout);
timeoutID = setTimeout(async () => {
try {
message = message || Constants.informationMessage.invalidRequiredVersion;
window.showErrorMessage(`${message} ${Constants.informationMessage.seeDetailsRequirementsPage}`);
} catch (e) {
// ignore
}
}, 500);
}
export async function getNodeVersion(): Promise<string> {
return getVersion('node', '--version', /v(\d+.\d+.\d+)/);
}