Updates for release v1.3.0
This commit is contained in:
Родитель
a1ed777db3
Коммит
430b073c9d
|
@ -51,6 +51,21 @@
|
|||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/out/src/debugger.js",
|
||||
"args": [ "--server=4711" ]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug Ui tests",
|
||||
"program": "${workspaceFolder}/ui-test/node_modules/vscode-extension-tester/out/cli.js",
|
||||
"args": [
|
||||
"run-tests",
|
||||
"ui-test/out/*.test.js",
|
||||
"-s",
|
||||
"ui-test/test-resources"
|
||||
],
|
||||
"sourceMaps": true,
|
||||
"outFiles": ["${workspaceFolder}/ui-test/out/*/*.js"],
|
||||
"preLaunchTask": "Prepare resources for ui-tests"
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
|
|
|
@ -68,6 +68,18 @@
|
|||
"Build Drizzle UI",
|
||||
"Build extension"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Prepare resources for ui-tests",
|
||||
"type": "npm",
|
||||
"script": "prepare-ui-test",
|
||||
"path": "ui-test/",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"group": "test"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ out/**
|
|||
!out/src/checkTruffleConfigTemplate.js
|
||||
src/**
|
||||
test/**
|
||||
ui-test/**
|
||||
.editorconfig
|
||||
.gitignore
|
||||
.npmignore
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
.idea/**
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
coverage/**
|
||||
drizzleUI/**
|
||||
node_modules/**
|
||||
out/**
|
||||
!out/src/mscorlib.js
|
||||
!out/src/Nethereum.Generators.DuoCode.js
|
||||
!out/src/extension.js
|
||||
!out/src/debugger.js
|
||||
!out/src/web3ProviderResolver.js
|
||||
!out/src/checkTruffleConfigTemplate.js
|
||||
src/**
|
||||
test/**
|
||||
.editorconfig
|
||||
.gitignore
|
||||
.npmignore
|
||||
**/tsconfig.json
|
||||
**/tslint.json
|
||||
**/*.map
|
||||
**/*.ts
|
||||
**/webpack.config.js
|
||||
**/coverconfig.json
|
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -2,6 +2,24 @@
|
|||
|
||||
All notable changes to the "azure blockchain" extension will be documented in this file.
|
||||
|
||||
## 1.3.0
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Add version 2.5 of OpenZeppelin contracts to the extension
|
||||
- Added new code generator for logic apps
|
||||
- Added new code generator for flow apps
|
||||
- Adding initial code for decoupling frameworks from UI to support partner extensions better
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fixed loader error for typescript in webpack (packaging error)
|
||||
- Fixed some unit test issues
|
||||
|
||||
### Internal Improvements
|
||||
|
||||
- Improving package locks for specific core packages to help with stability
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Enhancements
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
# Change Log
|
||||
|
||||
All notable changes to the "azure blockchain" extension will be documented in this file.
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Add the ability to create new Blockchain Applications for Blockchain Data Manager
|
||||
- Remove token menu and UI from extension
|
||||
- Add changelog popup on extension upgrade
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix issue with broken code generation when using custom build directories
|
||||
- Fix issue with OpenZeppelin contracts not showing as valid contracts for Blockchain Data Manager applications
|
||||
|
||||
### Internal Improvements
|
||||
|
||||
- Updates to telemetry for ABS deployments
|
||||
|
||||
## 1.1.0
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Implement BDM core operations
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fixed error when adding Mocks category from OpenZeppelin
|
||||
- Removed unnecessary notifications when deploying to removed networks
|
||||
|
||||
### Internal Improvements
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Added UI to handle required parameters for OpenZeppelin contract deployment.
|
||||
- Added Blockchain Data Manager to the core view for connecting to existing instances.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Cleanup of obfuscation for build directory path.
|
||||
- Merge of public PR for url checker to include basic auth.
|
||||
|
||||
### Internal Improvements
|
||||
|
||||
- Refactoring custom build directory code.
|
||||
|
||||
## 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
|
||||
|
||||
- Deployments from external truffle boxes can now deploy to Azure Blockchain Service
|
||||
- Additional context menu for deployed contract bytecode (transaction bytecode)
|
||||
- Fix on Mocks category for OpenZeppelin to remove the dead link for not existent docs
|
||||
- Better handling of OpenZeppelin when multiple categories are downloaded.
|
||||
- Fix misspelling of OpenZeppelin on the welcome page.
|
||||
|
||||
## 0.1.11
|
||||
|
||||
- Fixed issue with Logic App generation JSON schema
|
||||
- Added Contract UI support for contracts deployed on Azure Blockchain Service
|
||||
- Updated deprecated Truffle NPM packages
|
||||
- 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.
|
||||
|
||||
## 0.1.10
|
||||
|
||||
- Fixed Drizzle error handling issues
|
||||
- Updated Azure Blockchain Service logos in tree view
|
||||
- Updated Azure Blockchain Development Kit logo
|
||||
- Fixed unit tests for debugger, OpenZeppelin and Truffle commands
|
||||
- Improved sign-in support for Infura projects
|
||||
|
||||
## 0.1.9
|
||||
|
||||
- Added support for Infura project integration and account management
|
||||
|
||||
## 0.1.8
|
||||
|
||||
- Added support for Open Zeppelin contract/library download and deployment
|
||||
- Contract UI/Interaction functionality updates
|
||||
- Implement support for array types as function parameters
|
||||
- Support Enum types
|
||||
- Bug fixes
|
||||
- Ganache not properly shutting down on VS Code exit
|
||||
- Closing open items raised in the extension VS Code public GitHub repo
|
||||
|
||||
## 0.1.7
|
||||
|
||||
- Added contract UI/interaction feature
|
||||
- Added Solidity debugging feature
|
||||
|
||||
## 0.1.6
|
||||
|
||||
- Added telemetry reporting capabilities
|
||||
|
||||
## 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
|
||||
- Better error handling ABS deployments
|
||||
|
||||
## 0.1.4
|
||||
|
||||
- bug fixes
|
||||
|
||||
## 0.1.3
|
||||
|
||||
- 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
|
48
package.json
48
package.json
|
@ -5,7 +5,7 @@
|
|||
"publisher": "AzBlockchain",
|
||||
"preview": false,
|
||||
"icon": "images/blockchain-service-logo.png",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum"
|
||||
|
@ -41,8 +41,8 @@
|
|||
"onCommand:contract.copyABI",
|
||||
"onCommand:truffle.createLocalUI",
|
||||
"onCommand:truffle.newSolidityProject",
|
||||
"onCommand:truffle.buildContracts",
|
||||
"onCommand:truffle.deployContracts",
|
||||
"onCommand:azureBlockchainService.buildContracts",
|
||||
"onCommand:azureBlockchainService.deployContracts",
|
||||
"onCommand:azureBlockchainService.generateReportPublishingWorkflows",
|
||||
"onCommand:azureBlockchainService.generateMicroservicesWorkflows",
|
||||
"onCommand:azureBlockchainService.generateEventPublishingWorkflows",
|
||||
|
@ -72,12 +72,21 @@
|
|||
},
|
||||
"azureBlockchainService.openZeppelin.version": {
|
||||
"type": "string",
|
||||
"default": "2.4.0",
|
||||
"default": "2.5.0",
|
||||
"scope": "The latest Open Zeppelin version"
|
||||
},
|
||||
"azureBlockchainService.storageAccount.name": {
|
||||
"type": "string",
|
||||
"scope": "Storage Account name"
|
||||
},
|
||||
"azureBlockchainService.coreSDK": {
|
||||
"type": "string",
|
||||
"scope": "Core SDK for extensions backend",
|
||||
"default": "Truffle",
|
||||
"enum": [
|
||||
"Truffle",
|
||||
"OpenZeppelin"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -137,12 +146,12 @@
|
|||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "truffle.buildContracts",
|
||||
"command": "azureBlockchainService.buildContracts",
|
||||
"title": "Build Contracts",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "truffle.deployContracts",
|
||||
"command": "azureBlockchainService.deployContracts",
|
||||
"title": "Deploy Contracts",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
|
@ -278,11 +287,11 @@
|
|||
},
|
||||
{
|
||||
"when": "azureBlockchainService:isWorkspaceOpen",
|
||||
"command": "truffle.buildContracts"
|
||||
"command": "azureBlockchainService.buildContracts"
|
||||
},
|
||||
{
|
||||
"when": "azureBlockchainService:isWorkspaceOpen",
|
||||
"command": "truffle.deployContracts"
|
||||
"command": "azureBlockchainService.deployContracts"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
|
@ -380,7 +389,7 @@
|
|||
"explorer/context": [
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "truffle.buildContracts",
|
||||
"command": "azureBlockchainService.buildContracts",
|
||||
"group": "8_buildContractGroup"
|
||||
},
|
||||
{
|
||||
|
@ -390,12 +399,12 @@
|
|||
},
|
||||
{
|
||||
"when": "resourceLangId == json",
|
||||
"command": "truffle.deployContracts",
|
||||
"command": "azureBlockchainService.deployContracts",
|
||||
"group": "8_buildContractGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "truffle.deployContracts",
|
||||
"command": "azureBlockchainService.deployContracts",
|
||||
"group": "8_buildContractGroup"
|
||||
},
|
||||
{
|
||||
|
@ -559,7 +568,7 @@
|
|||
"@types/sinon": "^7.0.11",
|
||||
"@types/uuid": "^3.4.4",
|
||||
"@types/vscode": "^1.36.1",
|
||||
"copy-webpack-plugin": "^5.0.3",
|
||||
"copy-webpack-plugin": "5.1.1",
|
||||
"decache": "^4.5.1",
|
||||
"glob": "^7.1.4",
|
||||
"husky": "^2.4.0",
|
||||
|
@ -570,15 +579,15 @@
|
|||
"rewire": "^4.0.1",
|
||||
"sinon": "^7.3.2",
|
||||
"truffle": "^5.0.14",
|
||||
"ts-loader": "6.2.1",
|
||||
"ts-loader": "7.0.2",
|
||||
"tslint": "^5.18.0",
|
||||
"tslint-microsoft-contrib": "^6.2.0",
|
||||
"typescript": "^3.3.1",
|
||||
"typescript": "3.8.3",
|
||||
"vscode-debugadapter": "^1.33.0",
|
||||
"vscode-debugprotocol": "^1.33.0",
|
||||
"vscode-test": "^1.2.0",
|
||||
"webpack": "^4.35.3",
|
||||
"webpack-cli": "^3.3.6"
|
||||
"webpack": "4.43.0",
|
||||
"webpack-cli": "3.3.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@truffle/debug-utils": "1.0.19",
|
||||
|
@ -600,8 +609,9 @@
|
|||
"request-promise": "^4.2.4",
|
||||
"semver": "^6.0.0",
|
||||
"uuid": "^3.3.2",
|
||||
"vscode-azureextensionui": "^0.25.1",
|
||||
"vscode-extension-telemetry": "^0.1.1"
|
||||
"vscode-azureextensionui": "^0.29.12",
|
||||
"vscode-extension-telemetry": "^0.1.1",
|
||||
"solidity-parser-antlr": "^0.4.11"
|
||||
},
|
||||
"extensionDependencies": [
|
||||
"JuanBlanco.solidity",
|
||||
|
@ -618,4 +628,4 @@
|
|||
"git add"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,621 @@
|
|||
{
|
||||
"name": "azure-blockchain",
|
||||
"displayName": "Azure Blockchain Development Kit for Ethereum",
|
||||
"description": "Develop, deploy debug and manage your Azure Blockchain Service solution",
|
||||
"publisher": "AzBlockchain",
|
||||
"preview": false,
|
||||
"icon": "images/blockchain-service-logo.png",
|
||||
"version": "1.2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Microsoft/vscode-azure-blockchain-ethereum/blob/master/README.md",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"vscode": "^1.36.1"
|
||||
},
|
||||
"keywords": [
|
||||
"blockchain",
|
||||
"azure",
|
||||
"ethereum",
|
||||
"debuggers",
|
||||
"snippet"
|
||||
],
|
||||
"categories": [
|
||||
"Azure",
|
||||
"Extension Packs",
|
||||
"Programming Languages"
|
||||
],
|
||||
"aiKey": "INSERTAIKEY",
|
||||
"main": "./out/src/extension.js",
|
||||
"activationEvents": [
|
||||
"onView:AzureBlockchain",
|
||||
"onCommand:azureBlockchainService.showWelcomePage",
|
||||
"onCommand:azureBlockchainService.refresh",
|
||||
"onCommand:contract.copyByteCode",
|
||||
"onCommand:contract.copyDeployedByteCode",
|
||||
"onCommand:contract.copyABI",
|
||||
"onCommand:truffle.createLocalUI",
|
||||
"onCommand:truffle.newSolidityProject",
|
||||
"onCommand:truffle.buildContracts",
|
||||
"onCommand:truffle.deployContracts",
|
||||
"onCommand:azureBlockchainService.generateReportPublishingWorkflows",
|
||||
"onCommand:azureBlockchainService.generateMicroservicesWorkflows",
|
||||
"onCommand:azureBlockchainService.generateEventPublishingWorkflows",
|
||||
"onCommand:azureBlockchainService.generateDataPublishingWorkflows",
|
||||
"onCommand:azureBlockchainService.connectProject",
|
||||
"onCommand:azureBlockchainService.showSmartContractPage",
|
||||
"onCommand:azureBlockchainService.copyRPCEndpointAddress",
|
||||
"onCommand:azureBlockchainService.createProject",
|
||||
"onCommand:azureBlockchainService.disconnectProject",
|
||||
"onCommand:extension.truffle.debugTransaction",
|
||||
"onCommand:openZeppelin.addCategory",
|
||||
"onCommand:azureBlockchainService.signInToInfuraAccount",
|
||||
"onCommand:azureBlockchainService.signOutOfInfuraAccount",
|
||||
"onCommand:azureBlockchainService.openAtAzurePortal",
|
||||
"onCommand:azureBlockchainService.createNewBDMApplication",
|
||||
"onCommand:azureBlockchainService.deleteBDMApplication",
|
||||
"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"
|
||||
},
|
||||
"azureBlockchainService.storageAccount.name": {
|
||||
"type": "string",
|
||||
"scope": "Storage Account name"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "azureBlockchainService.generateMicroservicesWorkflows",
|
||||
"title": "Generate Microservices for Smart Contracts",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.generateDataPublishingWorkflows",
|
||||
"title": "Generate Data Publishing Workflows for Smart Contracts",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.generateReportPublishingWorkflows",
|
||||
"title": "Generate Report Publishing Workflows for Smart Contracts",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.generateEventPublishingWorkflows",
|
||||
"title": "Generate Event Publishing Workflows for Smart Contracts",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.showWelcomePage",
|
||||
"title": "Show Welcome Page",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.refresh",
|
||||
"title": "Refresh",
|
||||
"category": "Azure Blockchain",
|
||||
"icon": {
|
||||
"light": "resources/light/refresh.svg",
|
||||
"dark": "resources/dark/refresh.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "contract.copyByteCode",
|
||||
"title": "Copy Constructor Bytecode",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "contract.copyDeployedByteCode",
|
||||
"title": "Copy Transaction Bytecode",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "contract.copyABI",
|
||||
"title": "Copy Contract ABI",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "truffle.newSolidityProject",
|
||||
"title": "New Solidity Project",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "truffle.buildContracts",
|
||||
"title": "Build Contracts",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "truffle.deployContracts",
|
||||
"title": "Deploy Contracts",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.connectProject",
|
||||
"title": "Connect to network",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.showSmartContractPage",
|
||||
"title": "Show Smart Contract Interaction Page",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.copyRPCEndpointAddress",
|
||||
"title": "Copy RPC Endpoint Address",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.createProject",
|
||||
"title": "Create a new network",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.disconnectProject",
|
||||
"title": "Disconnect",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.startGanacheServer",
|
||||
"title": "Start Ganache Server",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.stopGanacheServer",
|
||||
"title": "Stop Ganache Server",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.signInToInfuraAccount",
|
||||
"title": "Sign in to Infura account",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.signOutOfInfuraAccount",
|
||||
"title": "Sign out of Infura account",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.getPrivateKey",
|
||||
"title": "Retrieve private key",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "extension.truffle.debugTransaction",
|
||||
"title": "Debug Transaction",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "openZeppelin.addCategory",
|
||||
"title": "Add contracts from OpenZeppelin",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.openAtAzurePortal",
|
||||
"title": "Open at Azure Portal",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.createNewBDMApplication",
|
||||
"title": "Create Blockchain Application",
|
||||
"category": "Azure Blockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.deleteBDMApplication",
|
||||
"title": "Delete Blockchain Application",
|
||||
"category": "Azure Blockchain"
|
||||
}
|
||||
],
|
||||
"breakpoints": [
|
||||
{
|
||||
"language": "solidity"
|
||||
},
|
||||
{
|
||||
"language": "sol"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"commandPalette": [
|
||||
{
|
||||
"when": "false",
|
||||
"command": "azureBlockchainService.showSmartContractPage"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "azureBlockchainService.refresh"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "azureBlockchainService.copyRPCEndpointAddress"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "azureBlockchainService.disconnectProject"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.generateMicroservicesWorkflows"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.generateDataPublishingWorkflows"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.generateEventPublishingWorkflows"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.generateReportPublishingWorkflows"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "contract.copyByteCode"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "contract.copyDeployedByteCode"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "contract.copyABI"
|
||||
},
|
||||
{
|
||||
"when": "azureBlockchainService:isWorkspaceOpen",
|
||||
"command": "truffle.buildContracts"
|
||||
},
|
||||
{
|
||||
"when": "azureBlockchainService:isWorkspaceOpen",
|
||||
"command": "truffle.deployContracts"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "openZeppelin.addCategory"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "azureBlockchainService.openAtAzurePortal"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "azureBlockchainService.deleteBDMApplication"
|
||||
},
|
||||
{
|
||||
"when": "false",
|
||||
"command": "azureBlockchainService.createNewBDMApplication"
|
||||
}
|
||||
],
|
||||
"view/title": [
|
||||
{
|
||||
"command": "azureBlockchainService.showWelcomePage",
|
||||
"when": "view == AzureBlockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.createProject",
|
||||
"when": "view == AzureBlockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.connectProject",
|
||||
"when": "view == AzureBlockchain"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.refresh",
|
||||
"when": "view == AzureBlockchain",
|
||||
"group": "navigation"
|
||||
}
|
||||
],
|
||||
"view/item/context": [
|
||||
{
|
||||
"command": "azureBlockchainService.disconnectProject",
|
||||
"when": "view == AzureBlockchain && viewItem == project",
|
||||
"group": "azureBlockchain-0@0"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.startGanacheServer",
|
||||
"when": "view == AzureBlockchain && viewItem == localproject",
|
||||
"group": "azureBlockchain-1@0"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.stopGanacheServer",
|
||||
"when": "view == AzureBlockchain && viewItem == localproject",
|
||||
"group": "azureBlockchain-1@1"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.disconnectProject",
|
||||
"when": "view == AzureBlockchain && viewItem == localproject",
|
||||
"group": "azureBlockchain-0@0"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.disconnectProject",
|
||||
"when": "view == AzureBlockchain && viewItem == bdmproject",
|
||||
"group": "azureBlockchain-0@0"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.copyRPCEndpointAddress",
|
||||
"when": "view == AzureBlockchain && viewItem == network",
|
||||
"group": "azureBlockchain-0@0"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.copyRPCEndpointAddress",
|
||||
"when": "view == AzureBlockchain && viewItem == localnetwork",
|
||||
"group": "azureBlockchain-0@0"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.openAtAzurePortal",
|
||||
"when": "view == AzureBlockchain && viewItem == input",
|
||||
"group": "azureBlockchain-0@0"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.openAtAzurePortal",
|
||||
"when": "view == AzureBlockchain && viewItem == output",
|
||||
"group": "azureBlockchain-0@0"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.createNewBDMApplication",
|
||||
"when": "view == AzureBlockchain && viewItem == bdmproject",
|
||||
"group": "azureBlockchain-1@1"
|
||||
},
|
||||
{
|
||||
"command": "azureBlockchainService.deleteBDMApplication",
|
||||
"when": "view == AzureBlockchain && viewItem == bdmApplication",
|
||||
"group": "azureBlockchain-0@0"
|
||||
}
|
||||
],
|
||||
"explorer/context": [
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "truffle.buildContracts",
|
||||
"group": "8_buildContractGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.showSmartContractPage",
|
||||
"group": "8_buildContractGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == json",
|
||||
"command": "truffle.deployContracts",
|
||||
"group": "8_buildContractGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "truffle.deployContracts",
|
||||
"group": "8_buildContractGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == json",
|
||||
"command": "contract.copyByteCode",
|
||||
"group": "9_copyFromContractGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == json",
|
||||
"command": "contract.copyDeployedByteCode",
|
||||
"group": "9_copyFromContractGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == json",
|
||||
"command": "contract.copyABI",
|
||||
"group": "9_copyFromContractGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.generateMicroservicesWorkflows",
|
||||
"group": "9_generationGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.generateDataPublishingWorkflows",
|
||||
"group": "9_generationGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.generateEventPublishingWorkflows",
|
||||
"group": "9_generationGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "azureBlockchainService.generateReportPublishingWorkflows",
|
||||
"group": "9_generationGroup"
|
||||
},
|
||||
{
|
||||
"when": "resourceLangId == solidity",
|
||||
"command": "openZeppelin.addCategory",
|
||||
"group": "8_buildContractGroup"
|
||||
}
|
||||
]
|
||||
},
|
||||
"views": {
|
||||
"explorer": [
|
||||
{
|
||||
"id": "AzureBlockchain",
|
||||
"name": "Azure Blockchain"
|
||||
}
|
||||
],
|
||||
"debug": [
|
||||
{
|
||||
"id": "InstructionView",
|
||||
"name": "Instructions"
|
||||
}
|
||||
]
|
||||
},
|
||||
"debuggers": [
|
||||
{
|
||||
"type": "truffle",
|
||||
"label": "Truffle Debugger",
|
||||
"program": "./out/src/debugger.js",
|
||||
"runtime": "node",
|
||||
"configurationAttributes": {
|
||||
"launch": {
|
||||
"required": [],
|
||||
"properties": {
|
||||
"stopOnEntry": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically stop after launch.",
|
||||
"default": true
|
||||
},
|
||||
"trace": {
|
||||
"type": "boolean",
|
||||
"description": "Enable logging of the Debug Adapter Protocol.",
|
||||
"default": true
|
||||
},
|
||||
"txHash": {
|
||||
"type": "string",
|
||||
"description": "Transaction hash to debug",
|
||||
"default": "0x"
|
||||
},
|
||||
"files": {
|
||||
"type": "string[]",
|
||||
"description": "Array of file paths of solidity files to debug",
|
||||
"default": []
|
||||
},
|
||||
"workingDirectory": {
|
||||
"type": "string",
|
||||
"description": "Directory of truffle box",
|
||||
"default": "${workspaceFolder}"
|
||||
},
|
||||
"providerUrl": {
|
||||
"type": "string",
|
||||
"description": "URL of provider",
|
||||
"default": "http://127.0.0.1:8545"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialConfigurations": [
|
||||
{
|
||||
"type": "truffle",
|
||||
"request": "launch",
|
||||
"name": "Debug Transaction with Truffle",
|
||||
"stopOnEntry": false,
|
||||
"txHash": "0x",
|
||||
"files": [],
|
||||
"workingDirectory": "${workspaceFolder}",
|
||||
"providerUrl": "http://127.0.0.1:8545"
|
||||
}
|
||||
],
|
||||
"configurationSnippets": [
|
||||
{
|
||||
"label": "Truffle Debugger: Launch",
|
||||
"description": "Runs the Truffle debugger (truffle) and attaches to a TestRPC instance",
|
||||
"body": {
|
||||
"type": "truffle",
|
||||
"request": "launch",
|
||||
"name": "Debug Transaction with Truffle",
|
||||
"stopOnEntry": false,
|
||||
"txHash": "0x",
|
||||
"files": [],
|
||||
"workingDirectory": "^\"\\${workspaceFolder}/",
|
||||
"providerUrl": "http://127.0.0.1:8545"
|
||||
}
|
||||
}
|
||||
],
|
||||
"variables": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"package": "npx vsce package",
|
||||
"publish": "npx vsce publish",
|
||||
"vscode:prepublish": "npm i && npm run webpack:prod && cd ./drizzleUI && npm i && npm run build:ext",
|
||||
"compile": "npm run clean && tsc -p ./",
|
||||
"webpack:prod": "webpack --mode production",
|
||||
"watch": "tsc -watch -p ./",
|
||||
"tslint": "tslint -t verbose src/**/*.ts test/**/*.ts",
|
||||
"tslint:fix": "npm run tslint -- --fix",
|
||||
"version": "tsc -v",
|
||||
"test": "npm run compile && node ./out/test/runTest",
|
||||
"clean": "npx rimraf -- ./out/*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/astring": "^1.3.0",
|
||||
"@types/estree": "^0.0.39",
|
||||
"@types/download": "^6.2.4",
|
||||
"@types/fs-extra": "^7.0.0",
|
||||
"@types/glob": "^7.1.1",
|
||||
"@types/hdkey": "^0.7.0",
|
||||
"@types/istanbul": "^0.4.30",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^10.12.21",
|
||||
"@types/request": "^2.48.1",
|
||||
"@types/request-promise": "^4.1.44",
|
||||
"@types/rewire": "^2.5.28",
|
||||
"@types/semver": "^6.0.0",
|
||||
"@types/sinon": "^7.0.11",
|
||||
"@types/uuid": "^3.4.4",
|
||||
"@types/vscode": "^1.36.1",
|
||||
"copy-webpack-plugin": "^5.0.3",
|
||||
"decache": "^4.5.1",
|
||||
"glob": "^7.1.4",
|
||||
"husky": "^2.4.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"lint-staged": "^8.2.0",
|
||||
"mocha": "^6.2.0",
|
||||
"remap-istanbul": "^0.13.0",
|
||||
"rewire": "^4.0.1",
|
||||
"sinon": "^7.3.2",
|
||||
"truffle": "^5.0.14",
|
||||
"ts-loader": "6.2.1",
|
||||
"tslint": "^5.18.0",
|
||||
"tslint-microsoft-contrib": "^6.2.0",
|
||||
"typescript": "^3.3.1",
|
||||
"vscode-debugadapter": "^1.33.0",
|
||||
"vscode-debugprotocol": "^1.33.0",
|
||||
"vscode-test": "^1.2.0",
|
||||
"webpack": "^4.35.3",
|
||||
"webpack-cli": "^3.3.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@truffle/debug-utils": "1.0.19",
|
||||
"@truffle/debugger": "5.0.35",
|
||||
"@truffle/provider": "0.2.1",
|
||||
"abi-decoder": "^2.0.1",
|
||||
"acorn": "^6.1.1",
|
||||
"acorn-walk": "^6.1.1",
|
||||
"astring": "^1.4.0",
|
||||
"azure-arm-resource": "^7.3.0",
|
||||
"bip39": "^3.0.1",
|
||||
"download": "^7.1.0",
|
||||
"fs-extra": "^7.0.1",
|
||||
"hdkey": "^1.1.1",
|
||||
"ms-rest": "^2.5.0",
|
||||
"ms-rest-azure": "^2.6.0",
|
||||
"open": "^6.4.0",
|
||||
"request": "^2.88.0",
|
||||
"request-promise": "^4.2.4",
|
||||
"semver": "^6.0.0",
|
||||
"uuid": "^3.3.2",
|
||||
"vscode-azureextensionui": "^0.25.1",
|
||||
"vscode-extension-telemetry": "^0.1.1"
|
||||
},
|
||||
"extensionDependencies": [
|
||||
"JuanBlanco.solidity",
|
||||
"ms-vscode.azure-account"
|
||||
],
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged && npm run compile"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.ts": [
|
||||
"npx tslint -t verbose",
|
||||
"git add"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -134,6 +134,7 @@ export class Constants {
|
|||
azureBlockchainExtensionVersion: 'azureBlockchainExtensionVersion',
|
||||
infuraCredentialsCacheKey: 'InfuraCache',
|
||||
infuraExcludedProjectsListKey: 'InfuraExcludedProjects',
|
||||
isNotifiedAboutOZSdk: 'isNotifiedAboutOZSdk',
|
||||
mnemonicStorageKey: 'mnemonicStorage',
|
||||
serviceResourceKey: 'treeContent',
|
||||
};
|
||||
|
@ -200,6 +201,11 @@ export class Constants {
|
|||
yes: 'Yes',
|
||||
};
|
||||
|
||||
public static installationDialogResult = {
|
||||
cancel: 'Cancel',
|
||||
install: 'Install',
|
||||
};
|
||||
|
||||
public static mnemonicConstants = {
|
||||
fileExt: 'env',
|
||||
};
|
||||
|
@ -578,6 +584,8 @@ export class Constants {
|
|||
ContractNotDeployed: 'Contracts are not deployed. Please deploy first.',
|
||||
DirectoryIsNotEmpty: 'Directory is not empty. Open another one?',
|
||||
ErrorWhileExecutingCommand: 'Error while executing command: ',
|
||||
ExtensionNotInstalled: (extensionName: string) =>
|
||||
`Please install ${extensionName} extension or change user settings to use another extension`,
|
||||
FetchingDeployedBytecodeIsFailed: 'An error occurred while fetching bytecode from network',
|
||||
GetMessageChildAlreadyConnected: Constants.getMessageChildAlreadyConnected,
|
||||
GitIsNotInstalled: 'Git is not installed',
|
||||
|
@ -594,7 +602,7 @@ export class Constants {
|
|||
NoContractBody: 'No contract body in AST',
|
||||
NoSubscriptionFound: 'No subscription found.',
|
||||
NoSubscriptionFoundClick: 'No subscription found, click an Azure account ' +
|
||||
'at the bottom left corner and choose Select All',
|
||||
'at the bottom left corner and choose Select All',
|
||||
PleaseRenameOldStyleTruffleConfig: 'Please rename file "truffle.js" to "truffle-config.js"',
|
||||
RequiredAppsAreNotInstalled: 'To run command you should install required apps',
|
||||
SolidityContractsNotFound: 'Solidity contracts were not found',
|
||||
|
@ -631,6 +639,7 @@ export class Constants {
|
|||
memberNameValidating: 'Member name validating...',
|
||||
networkIsNotReady: Constants.getNetworkIsNotReadyMessage,
|
||||
openButton: 'Open',
|
||||
ozFrameworkIsAvailableNow: 'You can now use OpenZeppelin framework as well as Truffle',
|
||||
privateKeyWasCopiedToClipboard: 'Private key was copied to clipboard',
|
||||
provisioningResource: (name: string) => `${name} is provisioning. The provisioning status can be viewed in the Azure portal. ` +
|
||||
'You may return and complete this process once the provisioning is complete.',
|
||||
|
@ -640,6 +649,8 @@ export class Constants {
|
|||
signInButton: 'Sign In',
|
||||
transactionBytecodeWasCopiedToClipboard: 'Transaction Bytecode was copied to clipboard',
|
||||
transactionNodeNameValidating: 'Transaction Node name validating...',
|
||||
unsupportedVersionOfExternalExtension: (name: string, currentVersion: string, supportedVersion: string) =>
|
||||
`You try to use "${name}" extension of version ${currentVersion}, but current supported vesrion is ${supportedVersion}.`,
|
||||
};
|
||||
|
||||
public static infuraCredentials = {
|
||||
|
@ -731,9 +742,10 @@ export class Constants {
|
|||
};
|
||||
|
||||
public static firstOZVersion = '2.3.0';
|
||||
public static allOpenZeppelinVersions = ['2.3.0', '2.4.0'];
|
||||
public static allOpenZeppelinVersions = ['2.3.0', '2.4.0', '2.5.0'];
|
||||
|
||||
public static userSettings = {
|
||||
coreSdkSettingsKey: 'azureBlockchainService.coreSDK',
|
||||
ozVersionUserSettingsKey: 'azureBlockchainService.openZeppelin.version',
|
||||
storageAccountUserSettingsKey: 'azureBlockchainService.storageAccount.name',
|
||||
};
|
||||
|
@ -743,6 +755,11 @@ export class Constants {
|
|||
queryTargetTypes: ['ContractProperties', 'ContractEvents'],
|
||||
};
|
||||
|
||||
public static coreSdk = {
|
||||
openZeppelin: 'OpenZeppelin',
|
||||
truffle: 'Truffle',
|
||||
};
|
||||
|
||||
public static openZeppelin = {
|
||||
cancelButtonTitle: 'Cancel',
|
||||
contractsUpgradeIsFailed: 'Upgrade of OpenZeppelin contracts has failed',
|
||||
|
@ -800,6 +817,18 @@ export class Constants {
|
|||
},
|
||||
};
|
||||
|
||||
// TODO: add real extensions information when they will be released
|
||||
public static externalExtensions: Record<string, any> = {
|
||||
OpenZeppelin: {
|
||||
commands: {
|
||||
buildContracts: 'oz.build.command',
|
||||
deployContracts: 'oz.deploy.command',
|
||||
},
|
||||
name: 'openZeppelin.extension.name',
|
||||
supportedVersion: '1.0.0',
|
||||
},
|
||||
};
|
||||
|
||||
public static initialize(context: ExtensionContext) {
|
||||
this.extensionContext = context;
|
||||
this.temporaryDirectory = context.storagePath ? context.storagePath : os.tmpdir();
|
||||
|
|
|
@ -0,0 +1,974 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { ExtensionContext, extensions } from 'vscode';
|
||||
import { IOZAsset } from './services/openZeppelin/models';
|
||||
|
||||
const extensionId = 'AzBlockchain.azure-blockchain';
|
||||
const packageJSON = extensions.getExtension(extensionId)!.packageJSON;
|
||||
|
||||
export enum RequiredApps {
|
||||
node = 'node',
|
||||
npm = 'npm',
|
||||
git = 'git',
|
||||
python = 'python',
|
||||
truffle = 'truffle',
|
||||
ganache = 'ganache-cli',
|
||||
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;
|
||||
|
||||
public static outputChannel = {
|
||||
azureBlockchain: 'Azure Blockchain',
|
||||
azureBlockchainServiceClient: 'Azure Blockchain Service Client',
|
||||
executeCommand: 'Execute command',
|
||||
ganacheCommands: 'Ganache Server',
|
||||
logicAppGenerator: 'Logic App Generator',
|
||||
requirements: 'Requirements',
|
||||
telemetryClient: 'Telemetry Client',
|
||||
treeManager: 'Service Tree Manager',
|
||||
};
|
||||
|
||||
public static truffleConfigRequireNames = {
|
||||
fs: 'fs',
|
||||
fsPackageName: 'fs',
|
||||
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;
|
||||
public static defaultInputNameInBdm = 'transaction-node';
|
||||
public static containerAzureBlockchainExtension = 'container-azureblockchainextension';
|
||||
|
||||
public static infuraHost = 'infura.io';
|
||||
public static localhost = '127.0.0.1';
|
||||
public static localhostName = 'development';
|
||||
public static defaultLocalhostPort = 8545;
|
||||
public static defaultABSPort = 3200;
|
||||
public static defaultABSHost = 'blockchain.azure.com';
|
||||
|
||||
public static ganacheRetryTimeout = 2000; // milliseconds
|
||||
public static ganacheRetryAttempts = 5;
|
||||
|
||||
public static azureBlockchainResourceName = {
|
||||
eventGrid: 'Event Grid',
|
||||
transactionNode: 'Transaction Node',
|
||||
};
|
||||
|
||||
public static lengthParam = {
|
||||
azureBlockchainResourceName: {
|
||||
max: 20,
|
||||
min: 2,
|
||||
},
|
||||
bdmName: {
|
||||
max: 20,
|
||||
min: 1,
|
||||
},
|
||||
eventGridName: {
|
||||
max: 50,
|
||||
min: 3,
|
||||
},
|
||||
password: {
|
||||
max: 72,
|
||||
min: 12,
|
||||
},
|
||||
resourceGroup: {
|
||||
max: 90,
|
||||
min: 1,
|
||||
},
|
||||
};
|
||||
|
||||
public static requiredVersions: { [key: string]: string | { min: string, max: string } } = {
|
||||
[RequiredApps.ganache]: {
|
||||
max: '7.0.0',
|
||||
min: '6.0.0',
|
||||
},
|
||||
[RequiredApps.git]: '2.10.0',
|
||||
[RequiredApps.hdwalletProvider]: {
|
||||
max: '2.0.0',
|
||||
min: '1.0.17',
|
||||
},
|
||||
[RequiredApps.node]: '10.15.0',
|
||||
[RequiredApps.npm]: '6.4.1',
|
||||
[RequiredApps.python]: {
|
||||
max: '3.0.0',
|
||||
min: '2.7.15',
|
||||
},
|
||||
[RequiredApps.truffle]: {
|
||||
max: '6.0.0',
|
||||
min: '5.0.0',
|
||||
},
|
||||
};
|
||||
|
||||
public static telemetryEvents = {
|
||||
extensionActivated: 'Extension.Activated',
|
||||
failedToCheckRequiredApps: 'Requirements.FailedToCheckRequiredApps',
|
||||
webPages: {
|
||||
action: 'WebPages.action',
|
||||
disposeWebPage: 'WebPages.DisposeWebPage',
|
||||
showWebPage: 'WebPages.ShowWebPage',
|
||||
},
|
||||
};
|
||||
|
||||
public static globalStateKeys = {
|
||||
azureBlockchainExtensionVersion: 'azureBlockchainExtensionVersion',
|
||||
infuraCredentialsCacheKey: 'InfuraCache',
|
||||
infuraExcludedProjectsListKey: 'InfuraExcludedProjects',
|
||||
mnemonicStorageKey: 'mnemonicStorage',
|
||||
serviceResourceKey: 'treeContent',
|
||||
};
|
||||
|
||||
public static infuraFileResponse = {
|
||||
css: '',
|
||||
path: '',
|
||||
};
|
||||
|
||||
public static webViewPages = {
|
||||
changelog: {
|
||||
changelogPath: '',
|
||||
path: '',
|
||||
showOnStartup: 'showOnStartupChangelog',
|
||||
title: 'Azure Blockchain Development Kit for Ethereum Changelog',
|
||||
viewType: 'changelog',
|
||||
},
|
||||
contractUI: {
|
||||
path: '',
|
||||
showOnStartup: 'showOnStartupContractUI',
|
||||
title: 'Smart Contract UI',
|
||||
viewType: 'contractUIPage',
|
||||
},
|
||||
requirements: {
|
||||
path: '',
|
||||
showOnStartup: 'showOnStartupRequirementsPage',
|
||||
title: 'Azure Blockchain Development Kit - Preview',
|
||||
viewType: 'requirementsPage',
|
||||
},
|
||||
welcome: {
|
||||
path: '',
|
||||
showOnStartup: 'showOnStartupWelcomePage',
|
||||
title: 'Welcome to Azure Blockchain',
|
||||
viewType: 'welcomePage',
|
||||
},
|
||||
};
|
||||
|
||||
public static contractExtension = {
|
||||
json: '.json',
|
||||
sol: '.sol',
|
||||
txt: '.txt',
|
||||
};
|
||||
|
||||
public static networkProtocols = {
|
||||
file: 'file://',
|
||||
ftp: 'ftp://',
|
||||
http: 'http://',
|
||||
https: 'https://',
|
||||
};
|
||||
|
||||
public static contractProperties = {
|
||||
abi: 'abi',
|
||||
bytecode: 'bytecode',
|
||||
deployedBytecode: 'deployedBytecode',
|
||||
};
|
||||
|
||||
public static propertyLabels = {
|
||||
gasLimit: 'gas limit',
|
||||
gasPrice: 'gas price',
|
||||
};
|
||||
|
||||
public static confirmationDialogResult = {
|
||||
no: 'No',
|
||||
yes: 'Yes',
|
||||
};
|
||||
|
||||
public static mnemonicConstants = {
|
||||
fileExt: 'env',
|
||||
};
|
||||
|
||||
public static defaultContractSettings = {
|
||||
gasLimit: 4712388,
|
||||
gasPrice: 100000000000,
|
||||
};
|
||||
|
||||
public static paletteLabels = {
|
||||
enterApplicationName: 'Enter application name',
|
||||
enterBlockchainDataManagerName: 'Enter blockchain data manager name',
|
||||
enterConnectionName: 'Enter connection name',
|
||||
enterConsortiumManagementPassword: 'Enter consortium management password',
|
||||
enterConsortiumName: 'Enter consortium name',
|
||||
enterEventGridName: 'Enter event grid name',
|
||||
enterInfuraProjectName: 'Enter project name',
|
||||
enterLocalProjectName: 'Enter local project name',
|
||||
enterLocalProjectPort: 'Enter local port number',
|
||||
enterMemberName: 'Enter member name',
|
||||
enterMemberPassword: 'Enter member password',
|
||||
enterTransactionNodeName: 'Enter transaction node name',
|
||||
enterTransactionNodePassword: 'Enter transaction node password',
|
||||
enterTruffleBoxName: 'Enter pre-built Truffle project',
|
||||
enterUserEmail: 'Enter user email address',
|
||||
enterUserName: 'Enter user name',
|
||||
enterUserPassword: 'Enter user password',
|
||||
provideResourceGroupName: 'Provide a resource group name',
|
||||
selectConsortiumProtocol: 'Select protocol',
|
||||
selectConsortiumRegion: 'Select region',
|
||||
selectConsortiumSku: 'Select SKU',
|
||||
selectResourceGroup: 'Select resource group',
|
||||
valueOrDefault: Constants.getMessageValueOrDefault,
|
||||
};
|
||||
|
||||
public static treeItemData = {
|
||||
group: {
|
||||
azure: {
|
||||
member: {
|
||||
contextValue: 'member',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
},
|
||||
bdm: {
|
||||
input: {
|
||||
contextValue: 'inputGroup',
|
||||
iconPath: { dark: '', light: '' },
|
||||
label: 'Inputs',
|
||||
},
|
||||
output: {
|
||||
contextValue: 'outputGroup',
|
||||
iconPath: { dark: '', light: '' },
|
||||
label: 'Outputs',
|
||||
},
|
||||
},
|
||||
},
|
||||
network: {
|
||||
azure: {
|
||||
contextValue: 'network',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
bdm: {
|
||||
application: {
|
||||
contextValue: 'bdmApplication',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
input: {
|
||||
contextValue: 'input',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
output: {
|
||||
contextValue: 'output',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
},
|
||||
default: {
|
||||
contextValue: 'network',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
infura: {
|
||||
contextValue: 'network',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
local: {
|
||||
contextValue: 'localnetwork',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
},
|
||||
project: {
|
||||
azure: {
|
||||
contextValue: 'project',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
bdm: {
|
||||
contextValue: 'bdmproject',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
default: {
|
||||
contextValue: 'project',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
infura: {
|
||||
contextValue: 'project',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
local: {
|
||||
contextValue: 'localproject',
|
||||
iconPath: { dark: '', light: '' },
|
||||
},
|
||||
},
|
||||
service: {
|
||||
azure: {
|
||||
contextValue: 'service',
|
||||
iconPath: { dark: '', light: '' },
|
||||
label: 'Azure Blockchain Service',
|
||||
prefix: 'abs',
|
||||
},
|
||||
bdm: {
|
||||
contextValue: 'service',
|
||||
iconPath: { dark: '', light: '' },
|
||||
label: 'Blockchain Data Manager',
|
||||
prefix: 'bdm',
|
||||
},
|
||||
default: {
|
||||
contextValue: 'service',
|
||||
iconPath: { dark: '', light: '' },
|
||||
label: 'Default Service',
|
||||
},
|
||||
infura: {
|
||||
contextValue: 'service',
|
||||
iconPath: { dark: '', light: '' },
|
||||
label: 'Infura Service',
|
||||
prefix: 'inf',
|
||||
},
|
||||
local: {
|
||||
contextValue: 'service',
|
||||
iconPath: { dark: '', light: '' },
|
||||
label: 'Local Service',
|
||||
prefix: 'loc',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
public static validationRegexps = {
|
||||
array: /^\[.*\]$/g,
|
||||
forbiddenChars: {
|
||||
dotAtTheEnd: /^(?=.*[.]$).*$/g,
|
||||
networkName: /[^0-9a-z]/g,
|
||||
outboundConnectionName: /^(\d|[a-z])+$/g,
|
||||
password: /[#`*"'\-%;,]/g,
|
||||
resourceGroupName: /[#`*"'%;,!@$^&+=?\/<>|[\]{}:\\~]/g,
|
||||
},
|
||||
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,
|
||||
onlyNumber: /^(-\d+|\d+)$/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: {
|
||||
azureBlockchainResourceName: /^(?=^[a-z])[a-z0-9]+$/g,
|
||||
bdmName:
|
||||
new RegExp(`^([a-z0-9]){${Constants.lengthParam.bdmName.min},${Constants.lengthParam.bdmName.max}}$`, 'g'),
|
||||
eventGridName: new RegExp(`^([a-zA-Z0-9\-]){${Constants.lengthParam.eventGridName.min},${Constants.lengthParam.eventGridName.max}}$`, 'g'),
|
||||
password: /[!@$^&()+=?\/<>|[\]{}_:.\\~]/g,
|
||||
resourceGroupName: /[-\w.()]/g,
|
||||
transactionNodeName:
|
||||
new RegExp(`^(?=^[a-z])[a-z0-9]{${Constants.lengthParam.azureBlockchainResourceName.min},${Constants.lengthParam.azureBlockchainResourceName.max}}$`, 'g'),
|
||||
},
|
||||
types: {
|
||||
simpleArray: /\w+\[\]/g,
|
||||
simpleMapping: /^\[.+\]$/g,
|
||||
solidityAddress: /^(0x)[a-zA-Z0-9]{40}$/g,
|
||||
solidityInt: /^int\d+$/g,
|
||||
solidityInteger: /u*int\d*/g,
|
||||
solidityUint: /^uint\d+$/g,
|
||||
},
|
||||
upperCaseLetter: /(?=.*[A-Z]).*/g,
|
||||
};
|
||||
|
||||
public static responseReason = {
|
||||
alreadyExists: 'AlreadyExists',
|
||||
};
|
||||
|
||||
public static validationMessages = {
|
||||
arrayElementsShouldBeValid: (elementsType: string) => {
|
||||
return `Array elements should have valid value of type ${elementsType}`;
|
||||
},
|
||||
bdmApplicationNameExist: 'Blockchain Data Manager Application name already exists.',
|
||||
bdmNameAlreadyExists: 'Blockchain Data Manager name already exists.',
|
||||
eventGridAlreadyExists: 'Event Grid name already exists.',
|
||||
forbiddenChars: {
|
||||
dotAtTheEnd: "Input value must not have '.' at the end.",
|
||||
networkName: 'Invalid name. Name can contain only lowercase letters and numbers.',
|
||||
outboundConnectionName: 'Outbound connection must contain only lowercase letters and numbers.',
|
||||
password: "'#', '`', '*', '\"', ''', '-', '%', ',', ';'",
|
||||
// tslint:disable-next-line: max-line-length
|
||||
resourceGroupName: "'#', '`', '*', '\"', ''', '\%', ';', ',', '!', '@', '$', '^', '&', '+', '=', '?', '\/', '<', '>', '|', '[', '\]', '{', '}', ':', '\\', '~'",
|
||||
},
|
||||
forbiddenSymbols: 'Provided name has forbidden symbols.',
|
||||
infuraProjectInvalidName: 'Project name must be at least 3 characters and should have alphanumeric, space, and the symbols "-", "_", ":".',
|
||||
invalidAzureName: 'Invalid name. Name can contain only lowercase letters and numbers. ' +
|
||||
`The first character must be a letter. Length must be between ${Constants.lengthParam.azureBlockchainResourceName.min} ` +
|
||||
`and ${Constants.lengthParam.azureBlockchainResourceName.max} characters.`,
|
||||
invalidBDMApplicationName: 'The Blockchain Data Manager Application name is invalid. Name can contain only lowercase letters and numbers. Length must ' +
|
||||
`be between ${Constants.lengthParam.bdmName.min} and ${Constants.lengthParam.bdmName.max} characters.`,
|
||||
invalidBlockchainDataManagerName:
|
||||
'The Blockchain Data Manager name is invalid. Name can contain only lowercase letters and numbers. Length must ' +
|
||||
`be between ${Constants.lengthParam.bdmName.min} and ${Constants.lengthParam.bdmName.max} characters.`,
|
||||
invalidConfirmationResult: '\'yes\' or \'no\'',
|
||||
invalidEventGridName: 'The Event Grid name is invalid. Name can contain only letters, numbers and dashes. ' +
|
||||
`Length must be between ${Constants.lengthParam.eventGridName.min} and ${Constants.lengthParam.eventGridName.max} characters.`,
|
||||
invalidHostAddress: 'Invalid host address',
|
||||
invalidPort: 'Invalid port.',
|
||||
invalidResourceGroupName: 'Resource group names only allow alphanumeric characters, periods,' +
|
||||
'underscores, hyphens and parenthesis and cannot end in a period. ' +
|
||||
`Length must be between ${Constants.lengthParam.resourceGroup.min} and ${Constants.lengthParam.resourceGroup.max} characters.`,
|
||||
lengthRange: Constants.getMessageLengthRange,
|
||||
nameAlreadyInUse: 'This name is already in use. Choose another one.',
|
||||
noDigits: 'Password should have at least one digit.',
|
||||
noLowerCaseLetter: 'Password should have at least one lowercase letter from a to z.',
|
||||
noSpecialChars: 'Password must have 1 special character.',
|
||||
noUpperCaseLetter: 'Password should have at least one uppercase letter from A to Z.',
|
||||
onlyLowerCaseAllowed: 'Only lower case allowed.',
|
||||
onlyNumberAllowed: 'Value after \':\' should be a number.',
|
||||
openZeppelinFilesAreInvalid: Constants.getMessageOpenZeppelinFilesAreInvalid,
|
||||
portAlreadyInUse: 'This port is already in use. Choose another one.',
|
||||
portNotInUseGanache: 'No local service running on port. Please start service or select another port.',
|
||||
projectAlreadyExists: 'Network already exists.',
|
||||
projectAlreadyExistsOnInfura: 'Project already exist with the same name on Infura.',
|
||||
projectIdAlreadyExists: 'Network with project ID already exists.',
|
||||
resourceGroupAlreadyExists: Constants.getMessageResourceGroupAlreadyExist,
|
||||
transactionNodeNameAlreadyExists: 'Transaction Node name already exists.',
|
||||
unresolvedSymbols: Constants.getMessageInputHasUnresolvedSymbols,
|
||||
valueCanSafelyStoreUpToBits: (pow: string) => {
|
||||
return `Value can only safely store up to ${pow} bits`;
|
||||
},
|
||||
valueCannotBeEmpty: 'Value cannot be empty.',
|
||||
valueShouldBeArray: 'Value should be the array and enclosed in \[ \]',
|
||||
valueShouldBeBool: 'Value should be true or false.',
|
||||
valueShouldBeNumber: 'Value should be a number.',
|
||||
valueShouldBeNumberOrEmpty: 'Value should be a number or empty.',
|
||||
valueShouldBePositiveAndCanSafelyStoreUpToBits: (pow: string) => {
|
||||
return `Value should be positive and can only safely store up to ${pow} bits`;
|
||||
},
|
||||
valueShouldBeSolidityAddress: 'Value should be the correct solidity address.',
|
||||
};
|
||||
|
||||
public static placeholders = {
|
||||
confirmDialog: 'Are your sure?',
|
||||
confirmPaidOperation: 'This operation will cost Ether, type \'yes\' to continue',
|
||||
emptyLineText: '<empty line>',
|
||||
generateMnemonic: 'Generate mnemonic',
|
||||
pasteMnemonic: 'Paste mnemonic',
|
||||
resourceGroupName: 'Resource Group Name',
|
||||
selectBlockchainDataManagerInstance: 'Select Blockchain Data Manager instance',
|
||||
selectConsortium: 'Select consortium',
|
||||
selectContract: 'Select contract',
|
||||
selectDeployDestination: 'Select deploy destination',
|
||||
selectDestination: 'Select destination',
|
||||
selectEventGrid: 'Select event grid',
|
||||
selectGanacheServer: 'Select Ganache server',
|
||||
selectInfuraProject: 'Select Infura project',
|
||||
selectInfuraProjectAvailability: 'Select Infura project availability',
|
||||
selectMember: 'Select member',
|
||||
selectMnemonicExtractKey: 'Select mnemonic to extract key',
|
||||
selectMnemonicStorage: 'Select mnemonic storage',
|
||||
selectNetwork: 'Select network',
|
||||
selectNewProjectPath: 'Select new project path',
|
||||
selectProjects: 'Select Projects',
|
||||
selectResourceGroup: 'Select a resource group',
|
||||
selectRgLocation: 'Select a location to create your Resource Group in...',
|
||||
selectSubscription: 'Select subscription',
|
||||
selectTransactionNode: 'Select transaction node',
|
||||
selectTypeOfSolidityProject: 'Select type of solidity project',
|
||||
setupMnemonic: 'Setup mnemonic',
|
||||
};
|
||||
|
||||
// More information see here
|
||||
// https://ethereum.stackexchange.com/questions/17051/how-to-select-a-network-id-or-is-there-a-list-of-network-ids
|
||||
public static infuraEndpointsIds: { [key: string]: number } = {
|
||||
goerli: 5,
|
||||
kovan: 42,
|
||||
mainnet: 1,
|
||||
rinkeby: 4,
|
||||
ropsten: 3,
|
||||
};
|
||||
|
||||
public static projectAvailability = {
|
||||
private: 'Private',
|
||||
public: 'Public',
|
||||
};
|
||||
|
||||
public static consortiumMemberStatuses = {
|
||||
ready: 'Ready',
|
||||
};
|
||||
|
||||
public static executeCommandMessage = {
|
||||
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',
|
||||
};
|
||||
|
||||
public static typeOfSolidityProject = {
|
||||
action: {
|
||||
emptyProject: 'createEmptyProject',
|
||||
projectFromTruffleBox: 'createProjectFromTruffleBox',
|
||||
},
|
||||
text: {
|
||||
emptyProject: 'Create basic project',
|
||||
projectFromTruffleBox: 'Create Project from Truffle box',
|
||||
},
|
||||
};
|
||||
|
||||
public static statusBarMessages = {
|
||||
buildingContracts: 'Building contracts',
|
||||
checkingRequirementDependencies: 'Checking requirement dependencies version',
|
||||
createBDMApplication: 'Creating BDM app',
|
||||
createBlobs: 'Creating blobs',
|
||||
createContainer: 'Creating container',
|
||||
createStorageAccount: 'Creating storage account',
|
||||
creatingBlockchainDataManager: 'Creating new Blockchain Data Manager',
|
||||
creatingConsortium: 'Creating new consortium',
|
||||
creatingEventGrid: 'Creating new event grid',
|
||||
creatingProject: 'Creating new project',
|
||||
deleteBlobs: 'Deleting blobs',
|
||||
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',
|
||||
};
|
||||
|
||||
public static ganacheCommandStrings = {
|
||||
cannotStartServer: 'Cannot start ganache server',
|
||||
ganachePortIsBusy: 'Cannot start ganache server, port is busy',
|
||||
invalidGanachePort: 'Cannot start Ganache server. Invalid port',
|
||||
serverAlreadyRunning: 'Ganache server already running',
|
||||
serverCanNotRunWithoutGanache: 'To start a local server, installed ganache-cli is required',
|
||||
serverCanNotStop: 'Ganache stop server was failed because is not ganache application',
|
||||
serverNoGanacheAvailable: 'No Ganache network settings available',
|
||||
serverNoGanacheInstance: 'No Ganache instance running',
|
||||
serverSuccessfullyStarted: 'Ganache server successfully started',
|
||||
serverSuccessfullyStopped: 'Ganache server successfully stopped',
|
||||
};
|
||||
|
||||
public static uiCommandStrings = {
|
||||
createBlockchainDataManagerProject: '$(plus) Create Blockchain Data Manager Project',
|
||||
createConsortium: '$(plus) Create Consortium',
|
||||
createEventGrid: '$(plus) Create Event Grid',
|
||||
createInfuraProject: '$(plus) Create Infura Project',
|
||||
createProject: '$(plus) Create a new network',
|
||||
createTransactionNode: '$(plus) Create Transaction Node',
|
||||
deployToConsortium: 'Deploy to consortium',
|
||||
};
|
||||
|
||||
public static errorMessageStrings = {
|
||||
// TODO names to lower case
|
||||
ActionAborted: 'Action aborted',
|
||||
AstIsEmpty: 'enums could not be extracted, current AST is empty',
|
||||
BlockchainItemIsUnavailable: Constants.getNetworkIsNotAvailableMessage,
|
||||
BuildContractsBeforeGenerating: 'Please build contracts before generating',
|
||||
BuildContractsDirDoesNotExist: Constants.getMessageContractsBuildDirectoryDoesNotExist,
|
||||
BuildContractsDirIsEmpty: Constants.getMessageContractsBuildDirectoryIsEmpty,
|
||||
CompiledContractIsMissing: 'Compiled contract is missing for solidity file.',
|
||||
ContractNotDeployed: 'Contracts are not deployed. Please deploy first.',
|
||||
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',
|
||||
IncorrectInputUrl: 'Incorrect input url',
|
||||
InfuraUnauthorized: 'Unauthorized: please sign in with Infura account.',
|
||||
InvalidContract: 'This file is not a valid contract.',
|
||||
InvalidMnemonic: 'Invalid mnemonic',
|
||||
LoadServiceTreeFailed: 'Load service tree has failed.',
|
||||
MnemonicFileHaveNoText: 'Mnemonic file have no text',
|
||||
NetworkAlreadyExist: Constants.getMessageNetworkAlreadyExist,
|
||||
NetworkIsNotAvailable: 'The network the contract is deployed to is not available. Please deploy again.',
|
||||
NetworkNotFound: Constants.getMessageNetworkNotFound,
|
||||
NewProjectCreationFailed: 'Command createProject has failed.',
|
||||
NoContractBody: 'No contract body in AST',
|
||||
NoSubscriptionFound: 'No subscription found.',
|
||||
NoSubscriptionFoundClick: 'No subscription found, click an Azure account ' +
|
||||
'at the bottom left corner and choose Select All',
|
||||
PleaseRenameOldStyleTruffleConfig: 'Please rename file "truffle.js" to "truffle-config.js"',
|
||||
RequiredAppsAreNotInstalled: 'To run command you should install required apps',
|
||||
SolidityContractsNotFound: 'Solidity contracts were not found',
|
||||
SubscriptionNotFound: 'Can not find available subscription.',
|
||||
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',
|
||||
WorkflowTypeDoesNotMatch: 'workflowType does not match any available workflows',
|
||||
WorkspaceShouldBeOpened: 'Workspace should be opened',
|
||||
};
|
||||
|
||||
public static informationMessage = {
|
||||
bdm: {
|
||||
bdmApplicationNotReady: 'Creations of BDM application and dependent resources were started. You can view the status in the status bar below. ' +
|
||||
'Please do not close vscode until it is ready. Once ready it will be added to the tree.',
|
||||
contractMustBeDeployedForBDMApplication: 'The contract must be compiled and deployed before a BDM application can be created.',
|
||||
},
|
||||
cancelButton: 'Cancel',
|
||||
compileAndDeployButton: 'Compile and deploy',
|
||||
consortiumDoesNotHaveMemberWithUrl: 'Consortium does not have member with url',
|
||||
consortiumNameValidating: 'Consortium name validating...',
|
||||
contractNotDeployed: 'Contract not deployed yet.',
|
||||
deployButton: 'Deploy',
|
||||
deployFailed: 'Deploy failed',
|
||||
deploySucceeded: 'Deploy succeeded',
|
||||
detailsButton: 'Details',
|
||||
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',
|
||||
invalidRequiredVersion: 'Required app is not installed or has an old version.',
|
||||
memberNameValidating: 'Member name validating...',
|
||||
networkIsNotReady: Constants.getNetworkIsNotReadyMessage,
|
||||
openButton: 'Open',
|
||||
privateKeyWasCopiedToClipboard: 'Private key was copied to clipboard',
|
||||
provisioningResource: (name: string) => `${name} is provisioning. The provisioning status can be viewed in the Azure portal. ` +
|
||||
'You may return and complete this process once the provisioning is complete.',
|
||||
requiresDependency: 'This project deployment requires the truffle-hdwallet-provider.',
|
||||
rpcEndpointCopiedToClipboard: 'RPCEndpointAddress copied to clipboard',
|
||||
seeDetailsRequirementsPage: 'Please see details on the Requirements Page',
|
||||
signInButton: 'Sign In',
|
||||
transactionBytecodeWasCopiedToClipboard: 'Transaction Bytecode was copied to clipboard',
|
||||
transactionNodeNameValidating: 'Transaction Node name validating...',
|
||||
};
|
||||
|
||||
public static infuraCredentials = {
|
||||
clientId: 'vs-code',
|
||||
clientSecret: 'pRo64S3izL72crOsuZ9PatRad0og5dlB',
|
||||
scopes: {
|
||||
offline: 'offline',
|
||||
projectRead: 'projects.read',
|
||||
projectWrite: 'projects.write',
|
||||
userRead: 'user.read',
|
||||
},
|
||||
};
|
||||
|
||||
public static infuraAuthUrls = {
|
||||
authURL: 'oauth2/auth',
|
||||
baseURL: 'https://oauth.infura.io/',
|
||||
callbackURL: 'http://127.0.0.1:9010/callback',
|
||||
revoke: 'oauth2/revoke',
|
||||
tokenURL: 'oauth2/token',
|
||||
};
|
||||
|
||||
public static infuraAPIUrls = {
|
||||
projects: 'eth/projects',
|
||||
rootURL: 'https://system.infura.io/',
|
||||
userMe: 'user/me',
|
||||
};
|
||||
|
||||
public static infuraSigningIn = 'Signing in';
|
||||
|
||||
public static infuraRequestGrantType = {
|
||||
authorizationCode: 'authorization_code',
|
||||
refreshToken: 'refresh_token',
|
||||
};
|
||||
|
||||
public static microservicesWorkflows = {
|
||||
Data: 'Data',
|
||||
Messaging: 'Messaging',
|
||||
Reporting: 'Reporting',
|
||||
Service: 'Service',
|
||||
};
|
||||
|
||||
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 azureApiVersions = {
|
||||
preview20180601: '2018-06-01-preview',
|
||||
preview20190601: '2019-06-01-preview',
|
||||
preview20200101: '2020-01-01-preview',
|
||||
20190601: '2019-06-01',
|
||||
};
|
||||
|
||||
public static provisioningState = {
|
||||
creating: 'Creating',
|
||||
failed: 'Failed',
|
||||
resolvingDns: 'ResolvingDns',
|
||||
stopped: 'Stopped',
|
||||
succeeded: 'Succeeded',
|
||||
updating: 'Updating',
|
||||
};
|
||||
|
||||
public static availableBlockchainDataManagerLocations = ['eastus', 'westeurope'];
|
||||
|
||||
public static azureProviders = {
|
||||
blockchain: 'Microsoft.Blockchain',
|
||||
eventGrid: 'Microsoft.EventGrid',
|
||||
storage: 'Microsoft.Storage',
|
||||
};
|
||||
|
||||
public static azureResourceExplorer = {
|
||||
contentType: 'application/json',
|
||||
portalBasUri: 'https://ms.portal.azure.com/#@microsoft.onmicrosoft.com',
|
||||
portalBladeUri: 'https://ms.portal.azure.com/#blade/ManagedLedgerExtension/TransactionNodeMenuBlade',
|
||||
providerName: 'Microsoft.Blockchain',
|
||||
requestAcceptLanguage: 'en-US',
|
||||
requestBaseUri: 'https://management.azure.com',
|
||||
resourceType: 'blockchainMembers',
|
||||
xMsBlockBlobType: 'BlockBlob',
|
||||
};
|
||||
|
||||
public static solidityTypes = {
|
||||
address: 'address',
|
||||
bool: 'bool',
|
||||
int: 'int',
|
||||
string: 'string',
|
||||
uint: 'uint',
|
||||
};
|
||||
|
||||
public static firstOZVersion = '2.3.0';
|
||||
public static allOpenZeppelinVersions = ['2.3.0', '2.4.0'];
|
||||
|
||||
public static userSettings = {
|
||||
ozVersionUserSettingsKey: 'azureBlockchainService.openZeppelin.version',
|
||||
storageAccountUserSettingsKey: 'azureBlockchainService.storageAccount.name',
|
||||
};
|
||||
|
||||
public static bdmApplicationRequestParameters = {
|
||||
artifactType: 'EthereumSmartContract',
|
||||
queryTargetTypes: ['ContractProperties', 'ContractEvents'],
|
||||
};
|
||||
|
||||
public static openZeppelin = {
|
||||
cancelButtonTitle: 'Cancel',
|
||||
contractsUpgradeIsFailed: 'Upgrade of OpenZeppelin contracts has failed',
|
||||
contactParameterInformation(contractName: string, parameterName: string, parameterType: string) {
|
||||
return `Contract: ${contractName}. Parameter: ${parameterName}: ${parameterType}`;
|
||||
},
|
||||
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',
|
||||
retryButtonTitle: 'Retry',
|
||||
retryDownloading: 'Retry downloading',
|
||||
saveSpecifiedParameters: 'Not all contract parameters were defined. Do you want to save the progress?',
|
||||
selectCategoryForDownloading: 'Select category for downloading',
|
||||
skipButtonTitle: 'Skip files',
|
||||
specifyContractParameters: 'Some contracts have parameters required for deploy. Do you want to specify them?',
|
||||
upgradeOpenZeppelin: 'Upgrading OpenZeppelin',
|
||||
hashCalculationFailed(errorMessage: string): string {
|
||||
return `Error while calculating file hash. Message: ${errorMessage}`;
|
||||
},
|
||||
wereNotDownloaded(count: number): string {
|
||||
return `OpenZeppelin: Some files (${count}) were not downloaded`;
|
||||
},
|
||||
wereDownloaded(count: number): string {
|
||||
return `OpenZeppelin: (${count}) files were stored`;
|
||||
},
|
||||
alreadyExisted(existing: IOZAsset[]): string {
|
||||
return `OpenZeppelin: (${existing.length}) files already exist on disk: `
|
||||
+ existing.slice(0, 3).map((contract) => contract.name).join(' ')
|
||||
+ (existing.length > 3 ? '...' : '');
|
||||
},
|
||||
invalidHashMessage(contractPath: string): string {
|
||||
return `${contractPath} - invalid hash`;
|
||||
},
|
||||
validHashMessage(contractPath: string): string {
|
||||
return `${contractPath} - valid hash`;
|
||||
},
|
||||
contractNotExistedOnDisk(contractPath: string): string {
|
||||
return `${contractPath} - not existed on disk`;
|
||||
},
|
||||
categoryWillDownloaded(categoryName: string): string {
|
||||
return `OpenZeppelin category will be downloaded: ${categoryName}`;
|
||||
},
|
||||
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) {
|
||||
this.extensionContext = context;
|
||||
this.temporaryDirectory = context.storagePath ? context.storagePath : os.tmpdir();
|
||||
this.webViewPages.contractUI.path = context.asAbsolutePath(path.join('resources', 'drizzle', 'index.html'));
|
||||
this.webViewPages.welcome.path = context.asAbsolutePath(path.join('resources', 'welcome', 'index.html'));
|
||||
this.webViewPages.requirements.path = context.asAbsolutePath(path.join('resources', 'welcome', 'prereqs.html'));
|
||||
this.webViewPages.changelog.path = context.asAbsolutePath(
|
||||
path.join('resources', 'welcome', 'changelog.html'));
|
||||
this.webViewPages.changelog.changelogPath = context.asAbsolutePath(path.join('CHANGELOG.md'));
|
||||
this.infuraFileResponse.path = context.asAbsolutePath(path.join('resources', 'codeFlowResult', 'index.html'));
|
||||
this.infuraFileResponse.css = context.asAbsolutePath(path.join('resources', 'codeFlowResult', 'main.css'));
|
||||
|
||||
this.treeItemData.group.azure.member.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'ABS-member.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'ABS-member.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.group.bdm.input.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'BlockchainDataManagerGroupInput.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'BlockchainDataManagerGroupInput.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.group.bdm.output.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'BlockchainDataManagerGroupOutput.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'BlockchainDataManagerGroupOutput.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.network.default.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'EthereumNetwork.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'EthereumNetwork.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.network.azure.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'ABNetwork.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'ABNetwork.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.network.bdm.application.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'BlockchainDataManagerApplication.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'BlockchainDataManagerApplication.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.network.bdm.input.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'ABNetwork.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'ABNetwork.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.network.bdm.output.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'BlockchainDataManagerOutput.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'BlockchainDataManagerOutput.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.network.infura.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'EthereumNetwork.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'EthereumNetwork.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.network.local.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'LocalNetwork.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'LocalNetwork.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.project.azure.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'ABS-consortium.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'ABS-consortium.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.project.bdm.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'BlockchainDataManager-service_and_project.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'BlockchainDataManager-service_and_project.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.project.infura.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'InfuraProject.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'InfuraProject.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.project.local.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'LocalProject.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'LocalProject.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.service.azure.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'ABS-service.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'ABS-service.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.service.bdm.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'BlockchainDataManager-service_and_project.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'BlockchainDataManager-service_and_project.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.service.infura.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'InfuraService.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'InfuraService.svg')),
|
||||
};
|
||||
|
||||
this.treeItemData.service.local.iconPath = {
|
||||
dark: context.asAbsolutePath(path.join('resources/dark', 'LocalService.svg')),
|
||||
light: context.asAbsolutePath(path.join('resources/light', 'LocalService.svg')),
|
||||
};
|
||||
}
|
||||
|
||||
public static getTransactionNodeName(memberName: string, transactionNodeName: string): string {
|
||||
return memberName === transactionNodeName ? Constants.defaultInputNameInBdm : transactionNodeName;
|
||||
}
|
||||
|
||||
private static getMessageChildAlreadyConnected(consortium: string): string {
|
||||
return `Connection to '${consortium}' already exists`;
|
||||
}
|
||||
|
||||
private static getMessageValueOrDefault(valueName: string, defaultValue: any): string {
|
||||
return `Enter ${valueName}. Default value is `
|
||||
+ `${defaultValue}. `
|
||||
+ 'Press Enter for default.';
|
||||
}
|
||||
|
||||
private static getMessageResourceGroupAlreadyExist(resourceGroupName: string): string {
|
||||
return `A resource group with the same name: ${resourceGroupName} already exists. Please select other name`;
|
||||
}
|
||||
|
||||
private static getMessageContractsBuildDirectoryIsEmpty(buildDirPath: string): string {
|
||||
return `Contracts build directory "${buildDirPath}" is empty.`;
|
||||
}
|
||||
|
||||
private static getMessageContractsBuildDirectoryDoesNotExist(buildDirPath: string): string {
|
||||
return `Contracts build directory "${buildDirPath}" does not exist.`;
|
||||
}
|
||||
|
||||
private static getMessageNetworkAlreadyExist(networkName: string): string {
|
||||
return `Network with name "${networkName}" already existed in truffle-config.js`;
|
||||
}
|
||||
|
||||
private static getMessageNetworkNotFound(networkName: string): string {
|
||||
return `Network with name "${networkName}" not found in truffle-config.js`;
|
||||
}
|
||||
|
||||
private static getMessageVariableShouldBeDefined(variable: string): string {
|
||||
return `${variable} should be defined`;
|
||||
}
|
||||
|
||||
private static getMessageLengthRange(min: number, max: number): string {
|
||||
return `Length must be between ${min} and ${max} characters`;
|
||||
}
|
||||
|
||||
private static getMessageInputHasUnresolvedSymbols(unresolvedSymbols: string): string {
|
||||
return `Input value must not have '${unresolvedSymbols}'.`;
|
||||
}
|
||||
|
||||
private static getMessageOpenZeppelinFilesAreInvalid(invalidFilePaths: string[]): string {
|
||||
return `OpenZeppelin files have been modified or removed:
|
||||
${invalidFilePaths.join('; ')}. Please revert changes or download them again.`;
|
||||
}
|
||||
|
||||
private static getNetworkIsNotReadyMessage(itemType: string) {
|
||||
switch (itemType) {
|
||||
case 'AzureBlockchainNetworkNode':
|
||||
return 'Azure Blockchain Service item is not ready yet. Please wait.';
|
||||
default:
|
||||
return 'Blockchain item is not ready yet. Please wait.';
|
||||
}
|
||||
}
|
||||
|
||||
private static getNetworkIsNotAvailableMessage(itemType: string) {
|
||||
switch (itemType) {
|
||||
case 'AzureBlockchainNetworkNode':
|
||||
return 'Azure Blockchain Service item is unavailable.';
|
||||
default:
|
||||
return 'Blockchain item is unavailable.';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getActionResponseTemplate() {
|
||||
const runAfter: { [key: string]: any; } = {};
|
||||
|
||||
return {
|
||||
inputs: {
|
||||
body: '',
|
||||
statusCode: 200,
|
||||
},
|
||||
kind: 'Http',
|
||||
runAfter,
|
||||
type: 'Response',
|
||||
};
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getCaseTemplate() {
|
||||
return {
|
||||
actions: {},
|
||||
case: '',
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getDefinitionTemplate() {
|
||||
const properties: { [key: string]: any; } = {};
|
||||
|
||||
return {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
$schema: 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#',
|
||||
actions: {},
|
||||
contentVersion: '1.0.0.0',
|
||||
outputs: {},
|
||||
parameters: {
|
||||
$connections: {
|
||||
defaultValue: {},
|
||||
type: 'Object',
|
||||
},
|
||||
},
|
||||
triggers: {
|
||||
manual: {
|
||||
inputs: {
|
||||
schema: {
|
||||
properties,
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
kind: 'Http',
|
||||
type: 'Request',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getActionFlowAppTemplate() {
|
||||
return {
|
||||
inputs: {
|
||||
host: {
|
||||
apiId: '',
|
||||
connectionName: '',
|
||||
operationId: '',
|
||||
},
|
||||
parameters: {
|
||||
abi: {},
|
||||
contractAddress: '',
|
||||
functionName: '',
|
||||
} as { [key: string]: any },
|
||||
},
|
||||
runAfter: {},
|
||||
type: 'OpenApiConnection',
|
||||
};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getClientDataTemplate() {
|
||||
const connectionReferences: { [key: string]: any; } = {};
|
||||
|
||||
return {
|
||||
properties: {
|
||||
apiId: '/providers/Microsoft.PowerApps/apis/shared_logicflows',
|
||||
connectionReferences,
|
||||
definition: {},
|
||||
displayName: '',
|
||||
},
|
||||
schemaVersion: '1.0.0.0',
|
||||
};
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getConnectionReferenceTemplate() {
|
||||
return {
|
||||
connectionName: 'shared-blockchaineth-00000000-0000-0000-0000-000000000000',
|
||||
id: '',
|
||||
source: 'Embedded',
|
||||
tier: 'NotSpecified',
|
||||
};
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getFlowAppTemplate() {
|
||||
return {
|
||||
category: 5,
|
||||
clientdata: '',
|
||||
description: '',
|
||||
name: '',
|
||||
primaryentity: 'none',
|
||||
statecode: 0,
|
||||
type: 1,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getActionLogicAppTemplate() {
|
||||
return {
|
||||
inputs: {
|
||||
body: {},
|
||||
host: {
|
||||
connection: {
|
||||
name: '',
|
||||
},
|
||||
},
|
||||
method: 'post',
|
||||
path: '',
|
||||
queries: {
|
||||
abi: '',
|
||||
contractAddress: '',
|
||||
},
|
||||
},
|
||||
runAfter: {},
|
||||
type: 'ApiConnection',
|
||||
};
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getConnectionValueTemplate() {
|
||||
return {
|
||||
connectionId: '',
|
||||
connectionName: '',
|
||||
id: '',
|
||||
};
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getLogicAppTemplate() {
|
||||
const value: { [key: string]: any; } = {};
|
||||
|
||||
return {
|
||||
definition: {},
|
||||
parameters: {
|
||||
$connections: {
|
||||
value,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export function getSwitchTemplate() {
|
||||
const cases: { [key: string]: any; } = {};
|
||||
|
||||
return {
|
||||
Switch: {
|
||||
cases,
|
||||
default: {
|
||||
actions: {
|
||||
DefaultResponse: {
|
||||
inputs: {
|
||||
body: 'Method or state variable not found.',
|
||||
statusCode: 404,
|
||||
},
|
||||
kind: 'Http',
|
||||
runAfter: {},
|
||||
type: 'Response',
|
||||
},
|
||||
},
|
||||
},
|
||||
expression: '',
|
||||
runAfter: {},
|
||||
type: 'Switch',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { getActionResponseTemplate } from './ActionResponse';
|
||||
import { getCaseTemplate } from './Case';
|
||||
import { getDefinitionTemplate } from './Definition';
|
||||
import { getActionFlowAppTemplate } from './FlowApp/ActionFlowApp';
|
||||
import { getClientDataTemplate } from './FlowApp/ClientData';
|
||||
import { getConnectionReferenceTemplate } from './FlowApp/ConnectionReferences';
|
||||
import { getFlowAppTemplate } from './FlowApp/FlowApp';
|
||||
import { getActionLogicAppTemplate } from './LogicApp/ActionLogicApp';
|
||||
import { getConnectionValueTemplate } from './LogicApp/ConnectionValue';
|
||||
import { getLogicAppTemplate } from './LogicApp/LogicApp';
|
||||
import { getSwitchTemplate } from './Switch';
|
||||
|
||||
export {
|
||||
getActionResponseTemplate,
|
||||
getCaseTemplate,
|
||||
getDefinitionTemplate,
|
||||
getActionFlowAppTemplate,
|
||||
getClientDataTemplate,
|
||||
getConnectionReferenceTemplate,
|
||||
getFlowAppTemplate,
|
||||
getActionLogicAppTemplate,
|
||||
getConnectionValueTemplate,
|
||||
getLogicAppTemplate,
|
||||
getSwitchTemplate,
|
||||
};
|
|
@ -0,0 +1,161 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
getActionFlowAppTemplate,
|
||||
getActionLogicAppTemplate,
|
||||
getActionResponseTemplate,
|
||||
getCaseTemplate,
|
||||
getClientDataTemplate,
|
||||
getConnectionReferenceTemplate,
|
||||
getConnectionValueTemplate,
|
||||
getDefinitionTemplate,
|
||||
getFlowAppTemplate,
|
||||
getLogicAppTemplate,
|
||||
getSwitchTemplate,
|
||||
} from './ApplicationDto';
|
||||
import { parseSolidityContract } from './ContractParser';
|
||||
|
||||
const propertyFunctionName = 'methodOrState';
|
||||
const propertyInputParameters = 'inputParameters';
|
||||
const propertyBlockchainethereum = 'blockchainethereum';
|
||||
|
||||
export function generateLogicAppForMicroservice(
|
||||
abi: string,
|
||||
contractAddress: string,
|
||||
subscriptionId: string,
|
||||
location: string,
|
||||
solFilePath: string,
|
||||
) {
|
||||
const { variables, functionsDefinitions } = parseSolidityContract(solFilePath);
|
||||
|
||||
const logicApp = getLogicAppTemplate();
|
||||
const definition = getDefinitionTemplate();
|
||||
const switchBlock = getSwitchTemplate();
|
||||
|
||||
for (const item of [...variables, ...functionsDefinitions]) {
|
||||
const actions: { [key: string]: any } = {};
|
||||
const action = getActionLogicAppTemplate();
|
||||
const bodyParameters: { [key: string]: any } = {};
|
||||
|
||||
if (item.type === 'FunctionDefinition') {
|
||||
for (const parameter of item.parameters) {
|
||||
bodyParameters[parameter.name] = `@triggerBody()?['${propertyInputParameters}']?['${parameter.name}']`;
|
||||
}
|
||||
|
||||
action.inputs.path = `/contract/functions/@{encodeURIComponent(encodeURIComponent('${item.name}'))}/execute`;
|
||||
} else {
|
||||
action.inputs.path = `/contract/functions/@{encodeURIComponent(encodeURIComponent('${item.name}'))}/query`;
|
||||
}
|
||||
|
||||
action.inputs.body = bodyParameters;
|
||||
action.inputs.queries.abi = abi;
|
||||
action.inputs.queries.contractAddress = contractAddress;
|
||||
action.inputs.host.connection.name = `@parameters('$connections')['${propertyBlockchainethereum}']['connectionId']`;
|
||||
|
||||
const actionResponse = getActionResponseTemplate();
|
||||
actionResponse.inputs.body = `@body('${item.name}')`;
|
||||
actionResponse.runAfter[item.name!] = [ 'Succeeded' ];
|
||||
|
||||
actions[item.name!] = action;
|
||||
actions[`${item.name}Response`] = actionResponse;
|
||||
|
||||
const caseBlock = getCaseTemplate();
|
||||
caseBlock.case = item.name!;
|
||||
caseBlock.actions = actions;
|
||||
|
||||
switchBlock.Switch.cases[`Case_${item.name}`] = caseBlock;
|
||||
}
|
||||
|
||||
switchBlock.Switch.expression = `@triggerBody()?['${propertyFunctionName}']`;
|
||||
|
||||
definition.actions = switchBlock;
|
||||
definition.triggers.manual.inputs.schema.properties[propertyInputParameters] = { type: 'object' };
|
||||
definition.triggers.manual.inputs.schema.properties[propertyFunctionName] = { type: 'string' };
|
||||
|
||||
logicApp.definition = definition;
|
||||
|
||||
logicApp.parameters.$connections.value[propertyBlockchainethereum] = getConnectionValueTemplate();
|
||||
logicApp.parameters.$connections.value[propertyBlockchainethereum].connectionId
|
||||
= `/subscriptions/${subscriptionId}/resourceGroups/`;
|
||||
logicApp.parameters.$connections.value[propertyBlockchainethereum].id
|
||||
= `/subscriptions/${subscriptionId}/providers/Microsoft.Web/locations/${location}/managedApis/blockchainethereum`;
|
||||
|
||||
return logicApp;
|
||||
}
|
||||
|
||||
export function generateFlowAppForMicroservice(
|
||||
name: string,
|
||||
abi: string,
|
||||
contractAddress: string,
|
||||
solFilePath: string,
|
||||
) {
|
||||
const { variables, functionsDefinitions } = parseSolidityContract(solFilePath);
|
||||
|
||||
const flowApp = getFlowAppTemplate();
|
||||
const definition = getDefinitionTemplate();
|
||||
const switchBlock = getSwitchTemplate();
|
||||
const connectionReferenceName = `shared_${propertyBlockchainethereum}`;
|
||||
|
||||
for (const item of [...variables, ...functionsDefinitions]) {
|
||||
const actions: { [key: string]: any } = {};
|
||||
const bodyParameters: { [key: string]: any } = {};
|
||||
const action = getActionFlowAppTemplate();
|
||||
const actionResponseData = getActionResponseTemplate();
|
||||
|
||||
if (item.type === 'FunctionDefinition') {
|
||||
for (const parameter of item.parameters) {
|
||||
bodyParameters[parameter.name] = `@triggerBody()?['${propertyInputParameters}']?['${parameter.name}']`;
|
||||
action.inputs.parameters[`parameters/${parameter.name}`] = `${propertyInputParameters}.${parameter.name}`;
|
||||
}
|
||||
|
||||
if (item.stateMutability === 'view' || item.stateMutability === 'pure') {
|
||||
action.inputs.host.operationId = item.parameters.length ? 'ExecuteSmartContractFunction' : 'GetSmartContractProperties';
|
||||
} else {
|
||||
action.inputs.host.operationId = 'ExecuteContractFunction';
|
||||
}
|
||||
|
||||
actionResponseData.inputs.body = item.returnParameters
|
||||
? `@outputs('${item.name}')?['body/Function Output']`
|
||||
: `@body('${item.name}')`;
|
||||
} else {
|
||||
action.inputs.host.operationId = 'GetSmartContractProperties';
|
||||
actionResponseData.inputs.body = `@outputs('${item.name}')?['body/${item.name}']`;
|
||||
}
|
||||
|
||||
action.inputs.host.connectionName = connectionReferenceName;
|
||||
action.inputs.host.apiId = `/providers/Microsoft.PowerApps/apis/${connectionReferenceName}`;
|
||||
|
||||
action.inputs.parameters.contractAddress = contractAddress;
|
||||
action.inputs.parameters.functionName = item.name!;
|
||||
action.inputs.parameters.abi = abi;
|
||||
|
||||
actionResponseData.runAfter[item.name!] = [ 'Succeeded' ];
|
||||
|
||||
actions[item.name!] = action;
|
||||
actions[`${item.name}Response`] = actionResponseData;
|
||||
|
||||
const caseBlock = getCaseTemplate();
|
||||
caseBlock.case = item.name!;
|
||||
caseBlock.actions = actions;
|
||||
|
||||
switchBlock.Switch.cases[`Case_${item.name}`] = caseBlock;
|
||||
}
|
||||
|
||||
switchBlock.Switch.expression = `@triggerBody()?['${propertyFunctionName}']`;
|
||||
|
||||
definition.actions = switchBlock;
|
||||
definition.triggers.manual.inputs.schema.properties[propertyInputParameters] = { type: 'object' };
|
||||
definition.triggers.manual.inputs.schema.properties[propertyFunctionName] = { type: 'string' };
|
||||
|
||||
const clientData = getClientDataTemplate();
|
||||
clientData.properties.definition = definition;
|
||||
clientData.properties.displayName = name;
|
||||
clientData.properties.connectionReferences[connectionReferenceName] = getConnectionReferenceTemplate();
|
||||
clientData.properties.connectionReferences[connectionReferenceName].id = `/providers/Microsoft.PowerApps/apis/${connectionReferenceName}`;
|
||||
|
||||
flowApp.clientdata = JSON.stringify(clientData);
|
||||
flowApp.name = name;
|
||||
|
||||
return flowApp;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as fs from 'fs-extra';
|
||||
import {
|
||||
FunctionDefinition,
|
||||
parse,
|
||||
SourceUnit,
|
||||
StateVariableDeclaration,
|
||||
VariableDeclaration,
|
||||
visit,
|
||||
} from 'solidity-parser-antlr';
|
||||
|
||||
export function parseSolidityContract(solFilePath: string)
|
||||
: { variables: VariableDeclaration[], functionsDefinitions: FunctionDefinition[] } {
|
||||
const ast = parseFileToAstNode(solFilePath);
|
||||
const functionArray: FunctionDefinition[] = [];
|
||||
const stateVariableArray: VariableDeclaration[] = [];
|
||||
|
||||
visit(ast, {
|
||||
StateVariableDeclaration(node: StateVariableDeclaration) {
|
||||
for (const variable of node.variables) {
|
||||
if (variable.visibility === 'public') {
|
||||
stateVariableArray.push(variable);
|
||||
}
|
||||
}
|
||||
},
|
||||
FunctionDefinition(node: FunctionDefinition) {
|
||||
if (!node.isConstructor && (node.visibility === 'public' || node.visibility === 'external')) {
|
||||
functionArray.push(node);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return { variables: stateVariableArray, functionsDefinitions: functionArray };
|
||||
}
|
||||
|
||||
function parseFileToAstNode(solFilePath: string) {
|
||||
const solFileContent = fs.readFileSync(solFilePath, 'utf8');
|
||||
return parse(solFileContent, {}) as SourceUnit;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Memento, window } from 'vscode';
|
||||
import { Constants } from '../Constants';
|
||||
import {
|
||||
// getWorkspaceRoot,
|
||||
// outputCommandHelper,
|
||||
// showNotificationConfirmationDialog,
|
||||
userSettings,
|
||||
} from '../helpers';
|
||||
import {
|
||||
IExtensionAdapter,
|
||||
OpenZeppelinExtensionAdapter,
|
||||
TruffleExtensionAdapter,
|
||||
} from '../services/extensionAdapter';
|
||||
|
||||
class SdkCoreCommands {
|
||||
// @ts-ignore
|
||||
private globalState?: Memento;
|
||||
private extensionAdapter!: IExtensionAdapter;
|
||||
|
||||
public async initialize(globalState: Memento): Promise<void> {
|
||||
this.globalState = globalState;
|
||||
|
||||
const sdk = await this.getCoreSdk();
|
||||
this.extensionAdapter = this.getExtensionAdapter(sdk.userValue ? sdk.userValue : sdk.defaultValue);
|
||||
this.extensionAdapter.validateExtension().catch((error) => {
|
||||
window.showErrorMessage(error.message);
|
||||
});
|
||||
}
|
||||
|
||||
public async build(): Promise<void> {
|
||||
// await this.notifyAboutOpenZeppelinSdk();
|
||||
return this.extensionAdapter.build();
|
||||
}
|
||||
|
||||
public async deploy(): Promise<void> {
|
||||
// await this.notifyAboutOpenZeppelinSdk();
|
||||
return this.extensionAdapter.deploy();
|
||||
}
|
||||
|
||||
private async getCoreSdk() {
|
||||
return userSettings.getConfigurationAsync(Constants.userSettings.coreSdkSettingsKey);
|
||||
}
|
||||
|
||||
private getExtensionAdapter(sdk: string): IExtensionAdapter {
|
||||
switch (sdk) {
|
||||
case Constants.coreSdk.openZeppelin:
|
||||
return new OpenZeppelinExtensionAdapter();
|
||||
default:
|
||||
return new TruffleExtensionAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: uncomment this once openzeppelin extension is ready
|
||||
/* private async notifyAboutOpenZeppelinSdk() {
|
||||
const isNotified = this.globalState!.get(Constants.globalStateKeys.isNotifiedAboutOZSdk);
|
||||
|
||||
if (!isNotified) {
|
||||
const sdk = await this.getCoreSdk();
|
||||
if (sdk.userValue !== Constants.coreSdk.openZeppelin) {
|
||||
const answer = await showNotificationConfirmationDialog(
|
||||
Constants.informationMessage.ozFrameworkIsAvailableNow,
|
||||
Constants.installationDialogResult.install,
|
||||
Constants.installationDialogResult.cancel);
|
||||
if (answer) {
|
||||
await outputCommandHelper.executeCommand(
|
||||
getWorkspaceRoot(true),
|
||||
`code --install-extension ${Constants.externalExtensions.openZeppelin.name}@'+
|
||||
`${Constants.externalExtensions.openZeppelin.supportedVersion}`);
|
||||
await userSettings.updateConfigurationAsync(
|
||||
Constants.userSettings.coreSdkSettingsKey,
|
||||
Constants.coreSdk.openZeppelin);
|
||||
}
|
||||
}
|
||||
|
||||
await this.globalState!.update(Constants.globalStateKeys.isNotifiedAboutOZSdk, true);
|
||||
await this.initialize(this.globalState!);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
export const sdkCoreCommands = new SdkCoreCommands();
|
|
@ -10,3 +10,4 @@ export * from './OpenZeppelinCommands';
|
|||
export * from './ProjectCommands';
|
||||
export * from './ServiceCommands';
|
||||
export * from './TruffleCommands';
|
||||
export * from './SdkCoreCommands';
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export * from './ContractCommands';
|
||||
export * from './DebuggerCommands';
|
||||
export * from './GanacheCommands';
|
||||
export * from './InfuraCommands';
|
||||
export * from './LogicAppCommands';
|
||||
export * from './OpenZeppelinCommands';
|
||||
export * from './ProjectCommands';
|
||||
export * from './ServiceCommands';
|
||||
export * from './TruffleCommands';
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { commands, ExtensionContext, Uri, window } from 'vscode';
|
||||
import { commands, ExtensionContext, Uri, window, workspace } from 'vscode';
|
||||
import {
|
||||
ContractCommands,
|
||||
DebuggerCommands,
|
||||
|
@ -10,6 +10,7 @@ import {
|
|||
LogicAppCommands,
|
||||
OpenZeppelinCommands,
|
||||
ProjectCommands,
|
||||
sdkCoreCommands,
|
||||
ServiceCommands,
|
||||
TruffleCommands,
|
||||
} from './commands';
|
||||
|
@ -44,6 +45,7 @@ export async function activate(context: ExtensionContext) {
|
|||
MnemonicRepository.initialize(context.globalState);
|
||||
TreeManager.initialize(context.globalState);
|
||||
TreeService.initialize('AzureBlockchain');
|
||||
await sdkCoreCommands.initialize(context.globalState);
|
||||
|
||||
setCommandContext(CommandContext.Enabled, true);
|
||||
setCommandContext(CommandContext.IsWorkspaceOpen, isWorkspaceOpen());
|
||||
|
@ -84,11 +86,11 @@ export async function activate(context: ExtensionContext) {
|
|||
const newSolidityProject = commands.registerCommand('truffle.newSolidityProject', async () => {
|
||||
await tryExecute(() => ProjectCommands.newSolidityProject());
|
||||
});
|
||||
const buildContracts = commands.registerCommand('truffle.buildContracts', async () => {
|
||||
await tryExecute(() => TruffleCommands.buildContracts());
|
||||
const buildContracts = commands.registerCommand('azureBlockchainService.buildContracts', async () => {
|
||||
await tryExecute(() => sdkCoreCommands.build());
|
||||
});
|
||||
const deployContracts = commands.registerCommand('truffle.deployContracts', async () => {
|
||||
await tryExecute(() => TruffleCommands.deployContracts());
|
||||
const deployContracts = commands.registerCommand('azureBlockchainService.deployContracts', async () => {
|
||||
await tryExecute(() => sdkCoreCommands.deploy());
|
||||
});
|
||||
const copyByteCode = commands.registerCommand('contract.copyByteCode', async (uri: Uri) => {
|
||||
await tryExecute(() => TruffleCommands.writeBytecodeToBuffer(uri));
|
||||
|
@ -186,6 +188,14 @@ export async function activate(context: ExtensionContext) {
|
|||
});
|
||||
//#endregion
|
||||
|
||||
//#region other subscriptions
|
||||
const changeCoreSdkConfigurationListener = workspace.onDidChangeConfiguration(async (event) => {
|
||||
if (event.affectsConfiguration(Constants.userSettings.coreSdkSettingsKey)) {
|
||||
await sdkCoreCommands.initialize(context.globalState);
|
||||
}
|
||||
});
|
||||
//#endregion
|
||||
|
||||
const subscriptions = [
|
||||
showWelcomePage,
|
||||
showRequirementsPage,
|
||||
|
@ -216,6 +226,7 @@ export async function activate(context: ExtensionContext) {
|
|||
showProjectsFromInfuraAccount,
|
||||
openZeppelinAddCategory,
|
||||
openAtAzurePortal,
|
||||
changeCoreSdkConfigurationListener,
|
||||
];
|
||||
context.subscriptions.push(...subscriptions);
|
||||
|
||||
|
|
|
@ -0,0 +1,257 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { commands, ExtensionContext, Uri, window } from 'vscode';
|
||||
import {
|
||||
ContractCommands,
|
||||
DebuggerCommands,
|
||||
GanacheCommands,
|
||||
InfuraCommands,
|
||||
LogicAppCommands,
|
||||
OpenZeppelinCommands,
|
||||
ProjectCommands,
|
||||
ServiceCommands,
|
||||
TruffleCommands,
|
||||
} from './commands';
|
||||
import { Constants } from './Constants';
|
||||
import { CommandContext, isWorkspaceOpen, openZeppelinHelper, required, setCommandContext } from './helpers';
|
||||
import { CancellationEvent } from './Models';
|
||||
import { Output } from './Output';
|
||||
import { ChangelogPage, RequirementsPage, WelcomePage } from './pages';
|
||||
import {
|
||||
AdapterType,
|
||||
ContractDB,
|
||||
GanacheService,
|
||||
InfuraServiceClient,
|
||||
MnemonicRepository,
|
||||
TreeManager,
|
||||
TreeService,
|
||||
} from './services';
|
||||
import { Telemetry } from './TelemetryClient';
|
||||
import { NetworkNodeView, ProjectView } from './ViewItems';
|
||||
|
||||
import { DebuggerConfiguration } from './debugAdapter/configuration/debuggerConfiguration';
|
||||
|
||||
export async function activate(context: ExtensionContext) {
|
||||
if (process.env.CODE_TEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
Constants.initialize(context);
|
||||
DebuggerConfiguration.initialize(context);
|
||||
await ContractDB.initialize(AdapterType.IN_MEMORY);
|
||||
await InfuraServiceClient.initialize(context.globalState);
|
||||
MnemonicRepository.initialize(context.globalState);
|
||||
TreeManager.initialize(context.globalState);
|
||||
TreeService.initialize('AzureBlockchain');
|
||||
|
||||
setCommandContext(CommandContext.Enabled, true);
|
||||
setCommandContext(CommandContext.IsWorkspaceOpen, isWorkspaceOpen());
|
||||
|
||||
const welcomePage = new WelcomePage(context);
|
||||
const requirementsPage = new RequirementsPage(context);
|
||||
const changelogPage = new ChangelogPage(context);
|
||||
|
||||
await welcomePage.checkAndShow();
|
||||
await changelogPage.checkAndShow();
|
||||
|
||||
//#region azureBlockchain extension commands
|
||||
const refresh = commands.registerCommand('azureBlockchainService.refresh', (element) => {
|
||||
TreeService.refresh(element);
|
||||
});
|
||||
const showWelcomePage = commands.registerCommand('azureBlockchainService.showWelcomePage', async () => {
|
||||
return welcomePage.show();
|
||||
});
|
||||
const showRequirementsPage = commands.registerCommand('azureBlockchainService.showRequirementsPage',
|
||||
async (checkShowOnStartup: boolean) => {
|
||||
return checkShowOnStartup ? await requirementsPage.checkAndShow() : await requirementsPage.show();
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region Ganache extension commands
|
||||
const startGanacheServer = commands.registerCommand('azureBlockchainService.startGanacheServer',
|
||||
async (viewItem?: ProjectView) => {
|
||||
await tryExecute(() => GanacheCommands.startGanacheCmd(viewItem));
|
||||
});
|
||||
|
||||
const stopGanacheServer = commands.registerCommand('azureBlockchainService.stopGanacheServer',
|
||||
async (viewItem?: ProjectView) => {
|
||||
await tryExecute(() => GanacheCommands.stopGanacheCmd(viewItem));
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region truffle commands
|
||||
const newSolidityProject = commands.registerCommand('truffle.newSolidityProject', async () => {
|
||||
await tryExecute(() => ProjectCommands.newSolidityProject());
|
||||
});
|
||||
const buildContracts = commands.registerCommand('truffle.buildContracts', async () => {
|
||||
await tryExecute(() => TruffleCommands.buildContracts());
|
||||
});
|
||||
const deployContracts = commands.registerCommand('truffle.deployContracts', async () => {
|
||||
await tryExecute(() => TruffleCommands.deployContracts());
|
||||
});
|
||||
const copyByteCode = commands.registerCommand('contract.copyByteCode', async (uri: Uri) => {
|
||||
await tryExecute(() => TruffleCommands.writeBytecodeToBuffer(uri));
|
||||
});
|
||||
const copyDeployedByteCode = commands.registerCommand('contract.copyDeployedByteCode', async (uri: Uri) => {
|
||||
await tryExecute(() => TruffleCommands.writeDeployedBytecodeToBuffer(uri));
|
||||
});
|
||||
const copyABI = commands.registerCommand('contract.copyABI', async (uri: Uri) => {
|
||||
await tryExecute(() => TruffleCommands.writeAbiToBuffer(uri));
|
||||
});
|
||||
const copyRPCEndpointAddress = commands.registerCommand('azureBlockchainService.copyRPCEndpointAddress',
|
||||
async (viewItem: NetworkNodeView) => {
|
||||
await tryExecute(() => TruffleCommands.writeRPCEndpointAddressToBuffer(viewItem));
|
||||
});
|
||||
const getPrivateKeyFromMnemonic = commands.registerCommand('azureBlockchainService.getPrivateKey', async () => {
|
||||
await tryExecute(() => TruffleCommands.getPrivateKeyFromMnemonic());
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region services with dialog
|
||||
const createProject = commands.registerCommand('azureBlockchainService.createProject', async () => {
|
||||
await tryExecute(() => ServiceCommands.createProject());
|
||||
});
|
||||
const connectProject = commands.registerCommand('azureBlockchainService.connectProject', async () => {
|
||||
await tryExecute(() => ServiceCommands.connectProject());
|
||||
});
|
||||
const disconnectProject = commands.registerCommand('azureBlockchainService.disconnectProject',
|
||||
async (viewItem: ProjectView) => {
|
||||
await tryExecute(() => ServiceCommands.disconnectProject(viewItem));
|
||||
});
|
||||
const openAtAzurePortal = commands.registerCommand('azureBlockchainService.openAtAzurePortal',
|
||||
async (viewItem: NetworkNodeView) => ServiceCommands.openAtAzurePortal(viewItem));
|
||||
//#endregion
|
||||
|
||||
//#region Infura commands
|
||||
const signInToInfuraAccount = commands.registerCommand('azureBlockchainService.signInToInfuraAccount', async () => {
|
||||
await tryExecute(() => InfuraCommands.signIn());
|
||||
});
|
||||
const signOutOfInfuraAccount = commands.registerCommand('azureBlockchainService.signOutOfInfuraAccount', async () => {
|
||||
await tryExecute(() => InfuraCommands.signOut());
|
||||
});
|
||||
const showProjectsFromInfuraAccount = commands.registerCommand(
|
||||
'azureBlockchainService.showProjectsFromInfuraAccount',
|
||||
async () => {
|
||||
await tryExecute(() => InfuraCommands.showProjectsFromAccount());
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region contract commands
|
||||
const showSmartContractPage = commands.registerCommand(
|
||||
'azureBlockchainService.showSmartContractPage',
|
||||
async (contractPath: Uri) => {
|
||||
await tryExecute(() => ContractCommands.showSmartContractPage(context, contractPath));
|
||||
});
|
||||
const createNewBDMApplication = commands.registerCommand('azureBlockchainService.createNewBDMApplication',
|
||||
async (viewItem: ProjectView) => {
|
||||
await tryExecute(() => ServiceCommands.createNewBDMApplication(viewItem));
|
||||
});
|
||||
const deleteBDMApplication = commands.registerCommand('azureBlockchainService.deleteBDMApplication',
|
||||
async (viewItem: NetworkNodeView) => await tryExecute(() => ServiceCommands.deleteBDMApplication(viewItem)));
|
||||
//#endregion
|
||||
|
||||
//#region open zeppelin commands
|
||||
const openZeppelinAddCategory = commands.registerCommand('openZeppelin.addCategory', async () => {
|
||||
await tryExecute(() => OpenZeppelinCommands.addCategory());
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region logic app commands
|
||||
const generateMicroservicesWorkflows = commands.registerCommand(
|
||||
'azureBlockchainService.generateMicroservicesWorkflows',
|
||||
async (filePath: Uri | undefined) => {
|
||||
await tryExecute(async () => await LogicAppCommands.generateMicroservicesWorkflows(filePath));
|
||||
});
|
||||
const generateDataPublishingWorkflows = commands.registerCommand(
|
||||
'azureBlockchainService.generateDataPublishingWorkflows',
|
||||
async (filePath: Uri | undefined) => {
|
||||
await tryExecute(async () => await LogicAppCommands.generateDataPublishingWorkflows(filePath));
|
||||
});
|
||||
const generateEventPublishingWorkflows = commands.registerCommand(
|
||||
'azureBlockchainService.generateEventPublishingWorkflows',
|
||||
async (filePath: Uri | undefined) => {
|
||||
await tryExecute(async () => await LogicAppCommands.generateEventPublishingWorkflows(filePath));
|
||||
});
|
||||
const generateReportPublishingWorkflows = commands.registerCommand(
|
||||
'azureBlockchainService.generateReportPublishingWorkflows',
|
||||
async (filePath: Uri | undefined) => {
|
||||
await tryExecute(async () => await LogicAppCommands.generateReportPublishingWorkflows(filePath));
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region debugger commands
|
||||
const startDebugger = commands.registerCommand('extension.truffle.debugTransaction', async () => {
|
||||
await tryExecute(() => DebuggerCommands.startSolidityDebugger());
|
||||
});
|
||||
//#endregion
|
||||
|
||||
const subscriptions = [
|
||||
showWelcomePage,
|
||||
showRequirementsPage,
|
||||
showSmartContractPage,
|
||||
refresh,
|
||||
newSolidityProject,
|
||||
buildContracts,
|
||||
deployContracts,
|
||||
createNewBDMApplication,
|
||||
createProject,
|
||||
connectProject,
|
||||
deleteBDMApplication,
|
||||
disconnectProject,
|
||||
copyByteCode,
|
||||
copyDeployedByteCode,
|
||||
copyABI,
|
||||
copyRPCEndpointAddress,
|
||||
startGanacheServer,
|
||||
stopGanacheServer,
|
||||
generateMicroservicesWorkflows,
|
||||
generateDataPublishingWorkflows,
|
||||
generateEventPublishingWorkflows,
|
||||
generateReportPublishingWorkflows,
|
||||
getPrivateKeyFromMnemonic,
|
||||
startDebugger,
|
||||
signInToInfuraAccount,
|
||||
signOutOfInfuraAccount,
|
||||
showProjectsFromInfuraAccount,
|
||||
openZeppelinAddCategory,
|
||||
openAtAzurePortal,
|
||||
];
|
||||
context.subscriptions.push(...subscriptions);
|
||||
|
||||
required.checkAllApps();
|
||||
|
||||
Telemetry.sendEvent(Constants.telemetryEvents.extensionActivated);
|
||||
|
||||
checkAndUpgradeOpenZeppelinAsync();
|
||||
}
|
||||
|
||||
export async function deactivate(): Promise<void> {
|
||||
// This method is called when your extension is deactivated
|
||||
// To dispose of all extensions, vscode provides 5 sec.
|
||||
// Therefore, please, call important dispose functions first and don't use await
|
||||
// For more information see https://github.com/Microsoft/vscode/issues/47881
|
||||
GanacheService.dispose();
|
||||
ContractDB.dispose();
|
||||
Telemetry.dispose();
|
||||
TreeManager.dispose();
|
||||
Output.dispose();
|
||||
}
|
||||
|
||||
async function tryExecute(func: () => Promise<any>, errorMessage: string | null = null): Promise<void> {
|
||||
try {
|
||||
await func();
|
||||
} catch (error) {
|
||||
if (error instanceof CancellationEvent) {
|
||||
return;
|
||||
}
|
||||
window.showErrorMessage(errorMessage || error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function checkAndUpgradeOpenZeppelinAsync(): Promise<void> {
|
||||
if (await openZeppelinHelper.shouldUpgradeOpenZeppelinAsync()) {
|
||||
await openZeppelinHelper.upgradeOpenZeppelinUserSettingsAsync();
|
||||
await openZeppelinHelper.upgradeOpenZeppelinContractsAsync();
|
||||
}
|
||||
}
|
|
@ -151,6 +151,19 @@ export async function showIgnorableNotification(message: string, fn: () => Promi
|
|||
});
|
||||
}
|
||||
|
||||
export async function showNotificationConfirmationDialog(
|
||||
message: string,
|
||||
positiveAnswer: string,
|
||||
cancel: string): Promise<boolean> {
|
||||
const answer = await window.showInformationMessage(
|
||||
message,
|
||||
positiveAnswer,
|
||||
cancel,
|
||||
);
|
||||
|
||||
return answer === positiveAnswer;
|
||||
}
|
||||
|
||||
namespace Notification {
|
||||
export const types = {
|
||||
error: window.showErrorMessage,
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { InputBoxOptions, ProgressLocation, QuickPickItem, QuickPickOptions, Uri, window, workspace } from 'vscode';
|
||||
import { Constants, NotificationOptions } from '../Constants';
|
||||
import { CancellationEvent } from '../Models';
|
||||
import { Telemetry } from '../TelemetryClient';
|
||||
import { DialogResultValidator } from '../validators/DialogResultValidator';
|
||||
|
||||
export async function showInputBox(options: InputBoxOptions): Promise<string> {
|
||||
const result = await window.showInputBox(options);
|
||||
|
||||
if (result === undefined) {
|
||||
Telemetry.sendEvent('userInteraction.showInputBox.userCancellation', { prompt: options.prompt || '' });
|
||||
throw new CancellationEvent();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function showQuickPickMany<T extends QuickPickItem>(
|
||||
items: T[] | Promise<T[]>,
|
||||
options: QuickPickOptions & { canPickMany: true; },
|
||||
): Promise<T[]> {
|
||||
const result = await window.showQuickPick(items, options);
|
||||
|
||||
if (result === undefined) {
|
||||
Telemetry.sendEvent(
|
||||
'userInteraction.showQuickPickMany.userCancellation',
|
||||
{ placeHolder: options.placeHolder || '' },
|
||||
);
|
||||
throw new CancellationEvent();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function showQuickPick<T extends QuickPickItem>(items: T[] | Promise<T[]>, options: QuickPickOptions)
|
||||
: Promise<T> {
|
||||
const result = await window.showQuickPick(items, options);
|
||||
|
||||
if (result === undefined) {
|
||||
Telemetry.sendEvent('userInteraction.showQuickPick.userCancellation', { placeHolder: options.placeHolder || '' });
|
||||
throw new CancellationEvent();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function showConfirmPaidOperationDialog() {
|
||||
const answer = await showInputBox({
|
||||
ignoreFocusOut: true,
|
||||
prompt: Constants.placeholders.confirmPaidOperation,
|
||||
validateInput: DialogResultValidator.validateConfirmationResult,
|
||||
});
|
||||
|
||||
if (answer.toLowerCase() !== Constants.confirmationDialogResult.yes.toLowerCase()) {
|
||||
Telemetry.sendEvent(
|
||||
'userInteraction.showConfirmPaidOperationDialog.userCancellation',
|
||||
{ prompt: Constants.placeholders.confirmPaidOperation });
|
||||
throw new CancellationEvent();
|
||||
}
|
||||
}
|
||||
|
||||
export async function showOpenFolderDialog(): Promise<string> {
|
||||
const folder = await window.showOpenDialog({
|
||||
canSelectFiles: false,
|
||||
canSelectFolders: true,
|
||||
canSelectMany: false,
|
||||
openLabel: Constants.placeholders.selectNewProjectPath,
|
||||
});
|
||||
|
||||
if (!folder) {
|
||||
Telemetry.sendEvent(
|
||||
'userInteraction.showOpenFolderDialog.userCancellation',
|
||||
{ label: Constants.placeholders.selectNewProjectPath });
|
||||
throw new CancellationEvent();
|
||||
}
|
||||
|
||||
return folder[0].fsPath;
|
||||
}
|
||||
|
||||
export async function showOpenFileDialog(): Promise<string> {
|
||||
const defaultFolder = workspace.workspaceFolders ? workspace.workspaceFolders[0].uri.fsPath : '';
|
||||
const folder = await window.showSaveDialog({
|
||||
defaultUri: Uri.parse(defaultFolder),
|
||||
saveLabel: Constants.placeholders.selectMnemonicStorage,
|
||||
});
|
||||
|
||||
if (!folder) {
|
||||
Telemetry.sendEvent(
|
||||
'userInteraction.showOpenFileDialog.userCancellation',
|
||||
{ label: Constants.placeholders.selectMnemonicStorage });
|
||||
throw new CancellationEvent();
|
||||
}
|
||||
|
||||
return folder.fsPath;
|
||||
}
|
||||
|
||||
export async function saveTextInFile(
|
||||
text: string,
|
||||
defaultFilename: string,
|
||||
ext?: { [name: string]: string[] },
|
||||
): Promise<string> {
|
||||
const file = await window.showSaveDialog({
|
||||
defaultUri: Uri.file(defaultFilename),
|
||||
filters: ext,
|
||||
});
|
||||
|
||||
if (!file) {
|
||||
Telemetry.sendEvent('userInteraction.saveTextInFile.userCancellation', { label: 'fileNotSelected' });
|
||||
throw new CancellationEvent();
|
||||
}
|
||||
|
||||
fs.writeFileSync(file.fsPath, text);
|
||||
return file.fsPath;
|
||||
}
|
||||
|
||||
export async function showConfirmationDialog(message: string): Promise<boolean> {
|
||||
const answer = await window.showInformationMessage(
|
||||
message,
|
||||
Constants.confirmationDialogResult.yes,
|
||||
Constants.confirmationDialogResult.no,
|
||||
);
|
||||
|
||||
return answer === Constants.confirmationDialogResult.yes;
|
||||
}
|
||||
|
||||
export async function showNotification(options: Notification.IShowNotificationOptions): Promise<void> {
|
||||
options.type = options.type || NotificationOptions.info;
|
||||
|
||||
Notification.types[options.type](options.message);
|
||||
}
|
||||
|
||||
export async function showIgnorableNotification(message: string, fn: () => Promise<any>): Promise<void> {
|
||||
const ignoreNotification = workspace.getConfiguration('azureBlockchainService').get('ignoreLongRunningTaskNotification');
|
||||
|
||||
await window.withProgress({
|
||||
location: ProgressLocation.Window,
|
||||
title: message,
|
||||
}, async () => {
|
||||
if (ignoreNotification) {
|
||||
await fn();
|
||||
} else {
|
||||
await window.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title: message,
|
||||
}, fn);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
namespace Notification {
|
||||
export const types = {
|
||||
error: window.showErrorMessage,
|
||||
info: window.showInformationMessage,
|
||||
warning: window.showWarningMessage,
|
||||
};
|
||||
|
||||
export interface IShowNotificationOptions {
|
||||
type?: NotificationOptions.error | NotificationOptions.warning | NotificationOptions.info;
|
||||
message: string;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export interface IExtensionAdapter {
|
||||
validateExtension: () => Promise<void>;
|
||||
build: () => Promise<void>;
|
||||
deploy: () => Promise<void>;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as semver from 'semver';
|
||||
import { commands, Extension, extensions } from 'vscode';
|
||||
import { Constants } from '../../Constants';
|
||||
import { IExtensionAdapter } from './IExtensionAdapter';
|
||||
|
||||
export class OpenZeppelinExtensionAdapter implements IExtensionAdapter {
|
||||
private extensionInfo: any;
|
||||
private extension: Extension<any> | undefined;
|
||||
|
||||
constructor() {
|
||||
this.extensionInfo = Constants.externalExtensions[Constants.coreSdk.openZeppelin];
|
||||
this.extension = extensions.getExtension(this.extensionInfo.name);
|
||||
}
|
||||
|
||||
public async validateExtension(): Promise<void> {
|
||||
if (!this.extension) {
|
||||
throw new Error(Constants.errorMessageStrings.ExtensionNotInstalled(this.extensionInfo.name));
|
||||
}
|
||||
|
||||
const version = this.extension.packageJSON.version;
|
||||
if (!semver.eq(version, this.extensionInfo.supportedVersion)) {
|
||||
throw new Error(Constants.informationMessage.unsupportedVersionOfExternalExtension(
|
||||
this.extensionInfo.name, version, this.extensionInfo.supportedVersion));
|
||||
}
|
||||
|
||||
if (!this.extension.isActive) {
|
||||
await this.extension.activate();
|
||||
}
|
||||
}
|
||||
|
||||
public async build(): Promise<void> {
|
||||
return commands.executeCommand(this.extensionInfo.commands.buildContracts);
|
||||
}
|
||||
|
||||
public async deploy(): Promise<void> {
|
||||
return commands.executeCommand(this.extensionInfo.commands.deployContracts);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TruffleCommands } from '../../commands/TruffleCommands';
|
||||
import { IExtensionAdapter } from './IExtensionAdapter';
|
||||
|
||||
export class TruffleExtensionAdapter implements IExtensionAdapter {
|
||||
// tslint:disable-next-line:no-empty
|
||||
public async validateExtension(): Promise<void> {}
|
||||
|
||||
public async build(): Promise<void> {
|
||||
return TruffleCommands.buildContracts();
|
||||
}
|
||||
|
||||
public async deploy() {
|
||||
return TruffleCommands.deployContracts();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export * from './IExtensionAdapter';
|
||||
export * from './TruffleExtensionAdapter';
|
||||
export * from './OpenZeppelinExtensionAdapter';
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,227 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as sinon from 'sinon';
|
||||
import uuid = require('uuid');
|
||||
import { generateFlowAppForMicroservice, generateLogicAppForMicroservice } from '../../src/Generators/CodeGenerator/CodeGenerator';
|
||||
|
||||
describe('CodeGenerator', () => {
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('generateLogicAppForMicroservice should return logic app data for microservice.', async () => {
|
||||
// Arrange
|
||||
sinon.stub(fs, 'readFileSync').returns(contractWithDifferentTypeOfVariableAndFunction);
|
||||
|
||||
// Act
|
||||
const logicAppData = generateLogicAppForMicroservice('abi', 'contract address', 'subscriptionId', 'location', '');
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(
|
||||
Object.keys((logicAppData.definition as any).actions.Switch.cases).length,
|
||||
12,
|
||||
'logicAppData should have special count of cases.');
|
||||
});
|
||||
|
||||
it('generateFlowAppForMicroservice should return flow app data for microservice.', async () => {
|
||||
// Arrange
|
||||
sinon.stub(fs, 'readFileSync').returns(contractWithDifferentTypeOfVariableAndFunction);
|
||||
const testContractName = uuid.v4().toString();
|
||||
|
||||
// Act
|
||||
const flowAppData = generateFlowAppForMicroservice(testContractName, '[]', 'contract address', '');
|
||||
const clientData = JSON.parse(flowAppData.clientdata);
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(
|
||||
Object.keys(clientData.properties.definition.actions.Switch.cases).length,
|
||||
12,
|
||||
'flowAppData should have special count of cases');
|
||||
assert.strictEqual(flowAppData.name, testContractName, 'Name should equals parameter which we send to function.');
|
||||
});
|
||||
|
||||
it('generateFlowAppForMicroservice should return flow app data with special operationId for functions.',
|
||||
async () => {
|
||||
// Arrange
|
||||
sinon.stub(fs, 'readFileSync').returns(contractWithDifferentAccessOfFunctions);
|
||||
const testContractName = uuid.v4().toString();
|
||||
|
||||
// Act
|
||||
const flowAppData = generateFlowAppForMicroservice(testContractName, '[]', 'contract address', '');
|
||||
|
||||
// Assert
|
||||
const cases = JSON.parse(flowAppData.clientdata).properties.definition.actions.Switch.cases;
|
||||
const casesPropertyNames = Object.getOwnPropertyNames(cases);
|
||||
|
||||
const simpleFunctionNames = casesPropertyNames.filter((name) => !name.includes('View') && !name.includes('Pure'));
|
||||
const viewPureFunctionNames = casesPropertyNames.filter((name) => name.includes('View') || name.includes('Pure'));
|
||||
const viewPureFunctionNamesWithParameters = viewPureFunctionNames.filter((name) => !name.includes('NOTParam'));
|
||||
const viewPureFunctionNamesWithoutParameters = viewPureFunctionNames.filter((name) => name.includes('NOTParam'));
|
||||
|
||||
const functionNamesWithReturnValue = casesPropertyNames.filter((name) => !name.includes('NOTReturn'));
|
||||
const functionNamesWithoutReturnValue = casesPropertyNames.filter((name) => name.includes('NOTReturn'));
|
||||
|
||||
viewPureFunctionNamesWithParameters.forEach((name) => {
|
||||
const functionName = name.replace(/Case_/, '');
|
||||
assert.strictEqual(
|
||||
cases[name].actions[functionName].inputs.host.operationId,
|
||||
'ExecuteSmartContractFunction',
|
||||
'Case should have operationId equals `ExecuteSmartContractFunction`, when function has parameters and modifier access equal `view` or `pure`');
|
||||
});
|
||||
|
||||
viewPureFunctionNamesWithoutParameters.forEach((name) => {
|
||||
const functionName = name.replace(/Case_/, '');
|
||||
assert.strictEqual(
|
||||
cases[name].actions[functionName].inputs.host.operationId,
|
||||
'GetSmartContractProperties',
|
||||
'Case should have operationId equals `GetSmartContractProperties`, when function without parameters has modifier access equal `view` or `pure`');
|
||||
});
|
||||
|
||||
simpleFunctionNames.forEach((name) => {
|
||||
const functionName = name.replace(/Case_/, '');
|
||||
assert.strictEqual(
|
||||
cases[name].actions[functionName].inputs.host.operationId,
|
||||
'ExecuteContractFunction',
|
||||
'Case should have operationId equals `ExecuteContractFunction`, when function does not have modifier access equal `view` or `pure`');
|
||||
});
|
||||
|
||||
functionNamesWithReturnValue.forEach((name) => {
|
||||
const functionName = name.replace(/Case_/, '');
|
||||
assert.strictEqual(
|
||||
cases[name].actions[`${functionName}Response`].inputs.body,
|
||||
`@outputs('${functionName}')?['body/Function Output']`,
|
||||
'Case should have response with body, which return Function Output, when function has return value');
|
||||
});
|
||||
|
||||
functionNamesWithoutReturnValue.forEach((name) => {
|
||||
const functionName = name.replace(/Case_/, '');
|
||||
assert.strictEqual(
|
||||
cases[name].actions[`${functionName}Response`].inputs.body,
|
||||
`@body('${functionName}')`,
|
||||
'Case should have response with body, which return function body, when function does not have return value');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const contractWithDifferentTypeOfVariableAndFunction = `pragma solidity ^0.5.0;
|
||||
|
||||
contract TestContract
|
||||
{
|
||||
enum StateType { Request, Respond }
|
||||
StateType public State;
|
||||
|
||||
address public Responder;
|
||||
string public RequestMessage;
|
||||
|
||||
event StateChanged(string stateData);
|
||||
|
||||
uint public publicVariable;
|
||||
uint private privateVariable;
|
||||
uint internal internalVariable;
|
||||
|
||||
constructor(string memory message) public
|
||||
{
|
||||
RequestMessage = message;
|
||||
State = StateType.Request;
|
||||
|
||||
emit StateChanged('Request');
|
||||
}
|
||||
|
||||
function public1(uint a) public { a + 1; }
|
||||
function public2(uint a) public returns(bool) { a + 1; return true; }
|
||||
function public3(uint a) public pure { a + 1; }
|
||||
function public4(uint a) public view { a + 1; }
|
||||
function public5(uint a) public payable { a + 1; }
|
||||
|
||||
function private1(uint a) private { a + 1; }
|
||||
function private2(uint a) private pure { a + 1; }
|
||||
function private3(uint a) private view { a + 1; }
|
||||
|
||||
function internal1(uint a) internal { a + 1; }
|
||||
function internal2(uint a) internal pure { a + 1; }
|
||||
function internal3(uint a) internal view { a + 1; }
|
||||
|
||||
function ext1(uint a) external { a + 1; }
|
||||
function ext2(uint a) external pure { a + 1; }
|
||||
function ext3(uint a) external view {a + 1; }
|
||||
}`;
|
||||
|
||||
const contractWithDifferentAccessOfFunctions = `pragma solidity ^0.5.0;
|
||||
|
||||
contract TestContract {
|
||||
constructor() public {}
|
||||
|
||||
function functionNOTParamNOTReturn() public {}
|
||||
|
||||
function functionNOTParamNOTReturnView() public view {}
|
||||
|
||||
function functionNOTParamNOTReturnPure() public pure {}
|
||||
|
||||
function functionNOTParamNOTReturnPayable() public payable {}
|
||||
|
||||
|
||||
function functionParamNOTReturn(uint a) public { a + 1; }
|
||||
|
||||
function functionParamNOTReturnView(uint a) public view { a + 1; }
|
||||
|
||||
function functionParamNOTReturnPure(uint a) public pure { a + 1; }
|
||||
|
||||
function functionParamNOTReturnPayable(uint a) public payable { a + 1; }
|
||||
|
||||
|
||||
function functionNOTParamReturn() public returns (uint) { return 1; }
|
||||
|
||||
function functionNOTParamReturnView() public view returns (uint) { return 1; }
|
||||
|
||||
function functionNOTParamReturnPure() public pure returns (uint) { return 1; }
|
||||
|
||||
function functionNOTParamReturnPayable() public payable returns (uint) { return 1; }
|
||||
|
||||
|
||||
function functionParamReturn(uint input) public returns (uint) { return input; }
|
||||
|
||||
function functionParamReturnView(uint input) public view returns (uint) { return input; }
|
||||
|
||||
function functionParamReturnPure(uint input) public pure returns (uint) { return input; }
|
||||
|
||||
function functionParamReturnPayable(uint input) public payable returns (uint) { return input; }
|
||||
|
||||
|
||||
function externalfunctionNOTParamNOTReturn() external {}
|
||||
|
||||
function externalfunctionNOTParamNOTReturnView() external view {}
|
||||
|
||||
function externalfunctionNOTParamNOTReturnPure() external pure {}
|
||||
|
||||
function externalfunctionNOTParamNOTReturnPayable() external payable {}
|
||||
|
||||
|
||||
function externalfunctionParamNOTReturn(uint a) external { a + 1; }
|
||||
|
||||
function externalfunctionParamNOTReturnView(uint a) external view { a + 1; }
|
||||
|
||||
function externalfunctionParamNOTReturnPure(uint a) external pure { a + 1; }
|
||||
|
||||
function externalfunctionParamNOTReturnPayable(uint a) external payable { a + 1; }
|
||||
|
||||
|
||||
function externalfunctionNOTParamReturn() external returns (uint) { return 1; }
|
||||
|
||||
function externalfunctionNOTParamReturnView() external view returns (uint) { return 1; }
|
||||
|
||||
function externalfunctionNOTParamReturnPure() external pure returns (uint) { return 1; }
|
||||
|
||||
function externalfunctionNOTParamReturnPayable() external payable returns (uint) { return 1; }
|
||||
|
||||
|
||||
function externalfunctionParamReturn(uint input) external returns (uint) { return input; }
|
||||
|
||||
function externalfunctionParamReturnView(uint input) external view returns (uint) { return input; }
|
||||
|
||||
function externalfunctionParamReturnPure(uint input) external pure returns (uint) { return input; }
|
||||
|
||||
function externalfunctionParamReturnPayable(uint input) external payable returns (uint) { return input; }
|
||||
}`;
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as sinon from 'sinon';
|
||||
import { parseSolidityContract } from '../../src/Generators/CodeGenerator/ContractParser';
|
||||
|
||||
describe('ContractParser', () => {
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('parser should return necessary functions and variables.', async () => {
|
||||
// Arrange
|
||||
sinon.stub(fs, 'readFileSync').returns(contractMetadata);
|
||||
|
||||
// Act
|
||||
const { variables, functionsDefinitions } = parseSolidityContract('');
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(functionsDefinitions.length, 8, 'Array should have only public and external functions');
|
||||
assert.strictEqual(variables.length, 4, 'Array should have only public variables');
|
||||
});
|
||||
});
|
||||
|
||||
const contractMetadata = `pragma solidity ^0.5.0;
|
||||
|
||||
contract TestContract
|
||||
{
|
||||
enum StateType { Request, Respond }
|
||||
StateType public State;
|
||||
|
||||
address public Responder;
|
||||
string public RequestMessage;
|
||||
|
||||
event StateChanged(string stateData);
|
||||
|
||||
uint public publicVariable;
|
||||
uint private privateVariable;
|
||||
uint internal internalVariable;
|
||||
|
||||
// constructor function
|
||||
constructor(string memory message) public
|
||||
{
|
||||
RequestMessage = message;
|
||||
State = StateType.Request;
|
||||
|
||||
emit StateChanged('Request');
|
||||
}
|
||||
|
||||
function public1(uint a) public { a + 1; }
|
||||
function public2(uint a) public returns(bool) { a + 1; return true; }
|
||||
function public3(uint a) public pure { a + 1; }
|
||||
function public4(uint a) public view { a + 1; }
|
||||
function public5(uint a) public payable { a + 1; }
|
||||
|
||||
function private1(uint a) private { a + 1; }
|
||||
function private2(uint a) private pure { a + 1; }
|
||||
function private3(uint a) private view { a + 1; }
|
||||
|
||||
function internal1(uint a) internal { a + 1; }
|
||||
function internal2(uint a) internal pure { a + 1; }
|
||||
function internal3(uint a) internal view { a + 1; }
|
||||
|
||||
function ext1(uint a) external { a + 1; }
|
||||
function ext2(uint a) external pure { a + 1; }
|
||||
function ext3(uint a) external view {a + 1; }
|
||||
}`;
|
|
@ -0,0 +1,99 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as semver from 'semver';
|
||||
import * as sinon from 'sinon';
|
||||
import * as uuid from 'uuid';
|
||||
import { commands, extensions } from 'vscode';
|
||||
import { OpenZeppelinExtensionAdapter } from '../src/services/extensionAdapter';
|
||||
|
||||
describe('sdkService', () => {
|
||||
let executeCommandMock: sinon.SinonStub<any>;
|
||||
let getExtensionMock: sinon.SinonStub<any>;
|
||||
let eqMock: sinon.SinonStub<any>;
|
||||
|
||||
let openZeppelinExtensionAdapter: OpenZeppelinExtensionAdapter;
|
||||
|
||||
beforeEach(() => {
|
||||
executeCommandMock = sinon.stub(commands, 'executeCommand');
|
||||
getExtensionMock = sinon.stub(extensions, 'getExtension');
|
||||
eqMock = sinon.stub(semver, 'eq');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
describe('validateExtension', () => {
|
||||
it('should throw exception when extension not found', async () => {
|
||||
// Arrange
|
||||
getExtensionMock.returns(undefined);
|
||||
openZeppelinExtensionAdapter = new OpenZeppelinExtensionAdapter();
|
||||
|
||||
// Act and assert
|
||||
assert.rejects(openZeppelinExtensionAdapter.validateExtension());
|
||||
});
|
||||
|
||||
it('should throw exception when extension version not supported', async () => {
|
||||
// Arrange
|
||||
getExtensionMock.returns({
|
||||
isActive: true,
|
||||
packageJSON: {
|
||||
value: uuid.v4(),
|
||||
},
|
||||
});
|
||||
eqMock.returns(false);
|
||||
openZeppelinExtensionAdapter = new OpenZeppelinExtensionAdapter();
|
||||
|
||||
// Act and assert
|
||||
assert.rejects(openZeppelinExtensionAdapter.validateExtension());
|
||||
});
|
||||
});
|
||||
|
||||
describe('build', () => {
|
||||
it('should execute extension command', async () => {
|
||||
// Arrange
|
||||
getExtensionMock.returns({
|
||||
isActive: true,
|
||||
packageJSON: {
|
||||
value: uuid.v4(),
|
||||
},
|
||||
});
|
||||
openZeppelinExtensionAdapter = new OpenZeppelinExtensionAdapter();
|
||||
|
||||
// Act
|
||||
await openZeppelinExtensionAdapter.build();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(
|
||||
executeCommandMock.calledOnce,
|
||||
true,
|
||||
'executeCommand should called once',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deploy', () => {
|
||||
it('should execute extension command', async () => {
|
||||
// Arrange
|
||||
getExtensionMock.returns({
|
||||
isActive: true,
|
||||
packageJSON: {
|
||||
value: uuid.v4(),
|
||||
},
|
||||
});
|
||||
openZeppelinExtensionAdapter = new OpenZeppelinExtensionAdapter();
|
||||
|
||||
// Act
|
||||
await openZeppelinExtensionAdapter.deploy();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(
|
||||
executeCommandMock.calledOnce,
|
||||
true,
|
||||
'executeCommand should called once',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -8,7 +8,7 @@ import rewire = require('rewire');
|
|||
import * as sinon from 'sinon';
|
||||
import uuid = require('uuid');
|
||||
import * as vscode from 'vscode';
|
||||
import { TruffleCommands } from '../../src/commands';
|
||||
import { TruffleCommands } from '../../src/commands/TruffleCommands';
|
||||
import { Constants } from '../../src/Constants';
|
||||
import * as helpers from '../../src/helpers';
|
||||
import { openZeppelinHelper, TruffleConfiguration } from '../../src/helpers';
|
||||
|
|
|
@ -0,0 +1,746 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import rewire = require('rewire');
|
||||
import * as sinon from 'sinon';
|
||||
import uuid = require('uuid');
|
||||
import * as vscode from 'vscode';
|
||||
import { TruffleCommands } from '../../src/commands';
|
||||
import { Constants } from '../../src/Constants';
|
||||
import * as helpers from '../../src/helpers';
|
||||
import { openZeppelinHelper, TruffleConfiguration } from '../../src/helpers';
|
||||
import * as commands from '../../src/helpers/command';
|
||||
import { CancellationEvent, ItemType } from '../../src/Models';
|
||||
import {
|
||||
AzureBlockchainNetworkNode,
|
||||
AzureBlockchainProject,
|
||||
AzureBlockchainService,
|
||||
BlockchainDataManagerNetworkNode,
|
||||
BlockchainDataManagerProject,
|
||||
BlockchainDataManagerService,
|
||||
IExtensionItem,
|
||||
InfuraNetworkNode,
|
||||
InfuraProject,
|
||||
InfuraService,
|
||||
LocalNetworkNode,
|
||||
LocalProject,
|
||||
LocalService,
|
||||
Member,
|
||||
Service,
|
||||
} from '../../src/Models/TreeItems';
|
||||
import { ConsortiumResourceExplorer } from '../../src/resourceExplorers';
|
||||
import { GanacheService, MnemonicRepository, OpenZeppelinMigrationsService, TreeManager } from '../../src/services';
|
||||
import { OpenZeppelinService } from '../../src/services';
|
||||
import { OZContractValidated } from '../../src/services/openZeppelin/models';
|
||||
import { TestConstants } from '../TestConstants';
|
||||
import { AzureAccountHelper } from '../testHelpers/AzureAccountHelper';
|
||||
const { service } = Constants.treeItemData;
|
||||
|
||||
describe('TruffleCommands', () => {
|
||||
describe('Integration test', async () => {
|
||||
describe('deployContracts', () => {
|
||||
let requiredMock: sinon.SinonMock;
|
||||
let checkAppsSilentMock: sinon.SinonExpectation;
|
||||
let installTruffleMock: sinon.SinonExpectation;
|
||||
let isHdWalletProviderRequiredMock: sinon.SinonExpectation;
|
||||
let checkHdWalletProviderVersionMock: sinon.SinonExpectation;
|
||||
let installTruffleHdWalletProviderMock: sinon.SinonExpectation;
|
||||
|
||||
let getWorkspaceRootMock: any;
|
||||
|
||||
let windowMock: sinon.SinonMock;
|
||||
let showQuickPickMock: any;
|
||||
let showInputBoxMock: any;
|
||||
let showSaveDialogMock: sinon.SinonExpectation;
|
||||
let showInformationMessageMock: any;
|
||||
|
||||
let ganacheServiceMock: sinon.SinonMock;
|
||||
let startGanacheServerMock: sinon.SinonExpectation;
|
||||
|
||||
let getItemsMock: sinon.SinonStub<[], IExtensionItem[]>;
|
||||
let loadStateMock: sinon.SinonStub<[], IExtensionItem[]>;
|
||||
let servicesItems: Service[];
|
||||
|
||||
let truffleConfigSetNetworkMock: any;
|
||||
let truffleConfigGetNetworkMock: any;
|
||||
let truffleConfigGenerateMnemonicMock: any;
|
||||
|
||||
let commandContextMock: sinon.SinonMock;
|
||||
let executeCommandMock: sinon.SinonExpectation;
|
||||
|
||||
let mnemonicRepositoryMock: sinon.SinonMock;
|
||||
let getMnemonicMock: sinon.SinonStub<any[], any>;
|
||||
let getAllMnemonicPathsMock: sinon.SinonStub<any[], any>;
|
||||
let saveMnemonicPathMock: sinon.SinonExpectation;
|
||||
|
||||
let writeFileSyncMock: any;
|
||||
|
||||
let getAccessKeysMock: any;
|
||||
|
||||
let getExtensionMock: any;
|
||||
|
||||
let openZeppelinvalidateContractsAsyncMock: any;
|
||||
let projectJsonExistsStub: sinon.SinonStub<[], boolean>;
|
||||
let shouldUpgradeOpenZeppelinAsyncStub: sinon.SinonStub<[], Promise<boolean>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
sinon.stub(helpers.openZeppelinHelper, 'tryGetCurrentOpenZeppelinVersionAsync');
|
||||
sinon.stub(helpers.openZeppelinHelper, 'defineContractRequiredParameters');
|
||||
sinon.stub(OpenZeppelinMigrationsService, 'generateMigrations');
|
||||
getWorkspaceRootMock = sinon.stub(helpers, 'getWorkspaceRoot');
|
||||
|
||||
requiredMock = sinon.mock(helpers.required);
|
||||
checkAppsSilentMock = requiredMock.expects('checkAppsSilent');
|
||||
installTruffleMock = requiredMock.expects('installTruffle');
|
||||
isHdWalletProviderRequiredMock = requiredMock.expects('isHdWalletProviderRequired');
|
||||
checkHdWalletProviderVersionMock = requiredMock.expects('checkHdWalletProviderVersion');
|
||||
installTruffleHdWalletProviderMock = requiredMock.expects('installTruffleHdWalletProvider');
|
||||
isHdWalletProviderRequiredMock.returns(false);
|
||||
checkHdWalletProviderVersionMock.returns(false);
|
||||
|
||||
windowMock = sinon.mock(vscode.window);
|
||||
showQuickPickMock = sinon.stub(vscode.window, 'showQuickPick');
|
||||
showInputBoxMock = sinon.stub(vscode.window, 'showInputBox');
|
||||
showSaveDialogMock = windowMock.expects('showSaveDialog');
|
||||
sinon.stub(vscode.window, 'showErrorMessage');
|
||||
showInformationMessageMock = sinon.stub(vscode.window, 'showInformationMessage');
|
||||
|
||||
ganacheServiceMock = sinon.mock(GanacheService);
|
||||
startGanacheServerMock = ganacheServiceMock.expects('startGanacheServer');
|
||||
|
||||
getItemsMock = sinon.stub(TreeManager, 'getItems');
|
||||
loadStateMock = sinon.stub(TreeManager, 'loadState');
|
||||
servicesItems = await createTestServicesItems();
|
||||
getItemsMock.returns(servicesItems);
|
||||
loadStateMock.returns(servicesItems);
|
||||
|
||||
truffleConfigSetNetworkMock = sinon.stub(TruffleConfiguration.TruffleConfig.prototype, 'setNetworks');
|
||||
truffleConfigGetNetworkMock = sinon.stub(TruffleConfiguration.TruffleConfig.prototype, 'getNetworks');
|
||||
truffleConfigGetNetworkMock.returns(getTestTruffleNetworks());
|
||||
truffleConfigGenerateMnemonicMock = sinon.stub(TruffleConfiguration, 'generateMnemonic');
|
||||
truffleConfigGenerateMnemonicMock.returns(TestConstants.testMnemonic);
|
||||
|
||||
commandContextMock = sinon.mock(commands);
|
||||
executeCommandMock = commandContextMock.expects('executeCommand');
|
||||
|
||||
mnemonicRepositoryMock = sinon.mock(MnemonicRepository);
|
||||
getMnemonicMock = mnemonicRepositoryMock.expects('getMnemonic').returns(TestConstants.testMnemonic);
|
||||
getAllMnemonicPathsMock = mnemonicRepositoryMock.expects('getAllMnemonicPaths').returns([] as string []);
|
||||
saveMnemonicPathMock = mnemonicRepositoryMock.expects('saveMnemonicPath');
|
||||
|
||||
writeFileSyncMock = sinon.stub(fs, 'writeFileSync');
|
||||
|
||||
getAccessKeysMock = sinon.stub(ConsortiumResourceExplorer.prototype, 'getAccessKeys');
|
||||
|
||||
getExtensionMock = sinon.stub(vscode.extensions, 'getExtension').returns(AzureAccountHelper.mockExtension);
|
||||
|
||||
projectJsonExistsStub = sinon.stub(OpenZeppelinService, 'projectJsonExists').returns(false);
|
||||
shouldUpgradeOpenZeppelinAsyncStub = sinon.stub(openZeppelinHelper, 'shouldUpgradeOpenZeppelinAsync')
|
||||
.resolves(false);
|
||||
|
||||
const openZeppelinServiceMock = sinon.mock(OpenZeppelinService);
|
||||
openZeppelinvalidateContractsAsyncMock = openZeppelinServiceMock.expects('validateContractsAsync')
|
||||
.resolves([]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('should throw exception when config file not found', async () => {
|
||||
// Arrange
|
||||
getWorkspaceRootMock.returns(__dirname);
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
|
||||
// Act and assert
|
||||
await assert.rejects(TruffleCommands.deployContracts(),
|
||||
Error,
|
||||
Constants.errorMessageStrings.TruffleConfigIsNotExist);
|
||||
});
|
||||
|
||||
it('should throw cancellationEvent when showQuickPick return undefined', async () => {
|
||||
// Arrange
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
showQuickPickMock.returns(undefined);
|
||||
|
||||
// Act and assert
|
||||
await assert.rejects(TruffleCommands.deployContracts(), CancellationEvent);
|
||||
});
|
||||
|
||||
it('should install TruffleHdWalletProvider when it required', async () => {
|
||||
// Arrange
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
isHdWalletProviderRequiredMock.returns(true);
|
||||
checkHdWalletProviderVersionMock.returns(false);
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
showInformationMessageMock.returns(Constants.informationMessage.installButton);
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === TestConstants.servicesNames.development);
|
||||
});
|
||||
|
||||
// Act
|
||||
await TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showQuickPickMock.calledOnce, true, 'showQuickPick should be called once');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, true, 'startGanacheServer should be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, false, 'truffleConfig.setNetwork should not be called');
|
||||
assert.strictEqual(
|
||||
isHdWalletProviderRequiredMock.calledOnce,
|
||||
true,
|
||||
'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
true,
|
||||
'checkHdWalletProviderVersion should be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
true,
|
||||
'installTruffleHdWalletProvider should be called');
|
||||
});
|
||||
|
||||
it('should not install TruffleHdWalletProvider when it version correct', async () => {
|
||||
// Arrange
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
isHdWalletProviderRequiredMock.returns(true);
|
||||
checkHdWalletProviderVersionMock.returns(true);
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === TestConstants.servicesNames.development);
|
||||
});
|
||||
|
||||
// Act
|
||||
await TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showQuickPickMock.calledOnce, true, 'showQuickPick should be called once');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, true, 'startGanacheServer should be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, false, 'truffleConfig.setNetwork should not be called');
|
||||
assert.strictEqual(isHdWalletProviderRequiredMock.calledOnce, true, 'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
true,
|
||||
'checkHdWalletProviderVersion should be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('to development should complete successfully with updating OpenZeppelin', async () => {
|
||||
// Arrange
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
isHdWalletProviderRequiredMock.returns(false);
|
||||
projectJsonExistsStub.returns(true);
|
||||
shouldUpgradeOpenZeppelinAsyncStub.resolves(true);
|
||||
|
||||
const updateOpenZeppelinInUserSettingsSpy =
|
||||
sinon.stub(helpers.openZeppelinHelper, 'upgradeOpenZeppelinUserSettingsAsync').resolves();
|
||||
const updateOpenZeppelinContractsSpy =
|
||||
sinon.stub(helpers.openZeppelinHelper, 'upgradeOpenZeppelinContractsAsync').resolves();
|
||||
|
||||
const truffleCommandsRewire = rewire('../../src/commands/TruffleCommands');
|
||||
truffleCommandsRewire.__set__('validateOpenZeppelinContracts', sinon.mock());
|
||||
const validateOpenZeppelinContractsMock = truffleCommandsRewire.__get__('validateOpenZeppelinContracts');
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === TestConstants.servicesNames.development);
|
||||
});
|
||||
|
||||
// Act
|
||||
await truffleCommandsRewire.TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showQuickPickMock.calledOnce, true, 'showQuickPick should be called once');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, true, 'startGanacheServer should be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, false, 'truffleConfig.setNetwork should not be called');
|
||||
assert.strictEqual(isHdWalletProviderRequiredMock.calledOnce, true, 'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(updateOpenZeppelinInUserSettingsSpy.called, true, 'updateOpenZeppelinInUserSettings should be called');
|
||||
assert.strictEqual(updateOpenZeppelinContractsSpy.called, true, 'updateOpenZeppelinContracts should be called');
|
||||
assert.strictEqual(validateOpenZeppelinContractsMock.calledOnce, true, 'validateOpenZeppelinContracts should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
false,
|
||||
'checkHdWalletProviderVersion should not be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('to development should throw exception when there is an error on command execution', async () => {
|
||||
// Arrange
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.throws(TestConstants.testError);
|
||||
|
||||
showQuickPickMock.callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === TestConstants.servicesNames.development);
|
||||
});
|
||||
|
||||
// Act and assert
|
||||
await assert.rejects(TruffleCommands.deployContracts(), Error);
|
||||
|
||||
assert.strictEqual(showQuickPickMock.calledOnce, true, 'showQuickPick should be called once');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, true, 'startGanacheServer should be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, false, 'truffleConfig.setNetwork should not be called');
|
||||
assert.strictEqual(isHdWalletProviderRequiredMock.calledOnce, true, 'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
false,
|
||||
'checkHdWalletProviderVersion should not be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('to network should complete successfully', async () => {
|
||||
// Arrange
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === TestConstants.servicesNames.testNetwork);
|
||||
});
|
||||
|
||||
// Act
|
||||
await TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showQuickPickMock.calledOnce, true, 'showQuickPick should be called once');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, false, 'startGanacheServer should not be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, false, 'truffleConfig.setNetwork should not be called');
|
||||
assert.strictEqual(isHdWalletProviderRequiredMock.calledOnce, true, 'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
false,
|
||||
'checkHdWalletProviderVersion should not be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('to network should throw exception when there is an error on command execution', async () => {
|
||||
// Arrange
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.throws(TestConstants.testError);
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === TestConstants.servicesNames.testNetwork);
|
||||
});
|
||||
|
||||
// Act and assert
|
||||
await assert.rejects(TruffleCommands.deployContracts());
|
||||
assert.strictEqual(showQuickPickMock.calledOnce, true, 'showQuickPick should be called once');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, false, 'startGanacheServer should not be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, false, 'truffleConfig.setNetwork should not be called');
|
||||
assert.strictEqual(isHdWalletProviderRequiredMock.calledOnce, true, 'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
false,
|
||||
'checkHdWalletProviderVersion should not be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('to local network should complete successfully', async () => {
|
||||
// Arrange
|
||||
const { local } = TestConstants.consortiumTestNames;
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
|
||||
const networkNodeName = getDeployName(service.local.prefix, local, local);
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === networkNodeName);
|
||||
});
|
||||
|
||||
// Act
|
||||
await TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showQuickPickMock.calledOnce, true, 'showQuickPick should be called once');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, true, 'startGanacheServer should be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, true, 'truffleConfig.setNetwork should be called');
|
||||
assert.strictEqual(
|
||||
isHdWalletProviderRequiredMock.calledOnce,
|
||||
true,
|
||||
'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
false,
|
||||
'checkHdWalletProviderVersion should not be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('to local network should throw exception when there is an error on command execution', async () => {
|
||||
// Arrange
|
||||
const { local } = TestConstants.consortiumTestNames;
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.throws(TestConstants.testError);
|
||||
|
||||
const networkNodeName = getDeployName(service.local.prefix, local, local);
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === networkNodeName);
|
||||
});
|
||||
|
||||
// Act and assert
|
||||
await assert.rejects(TruffleCommands.deployContracts());
|
||||
assert.strictEqual(showQuickPickMock.calledOnce, true, 'showQuickPick should be called once');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, true, 'startGanacheServer should be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, true, 'truffleConfig.setNetwork should be called');
|
||||
assert.strictEqual(
|
||||
isHdWalletProviderRequiredMock.calledOnce,
|
||||
true,
|
||||
'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
false,
|
||||
'checkHdWalletProviderVersion should not be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('to AzureBlockchainService should generate mnemonic and complete successfully', async () => {
|
||||
// Arrange
|
||||
const { consortium, member, transactionNode } = azureNames;
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
getAccessKeysMock.returns(uuid.v4());
|
||||
|
||||
const networkNodeName = getDeployName(service.azure.prefix, consortium, transactionNode, [member]);
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === networkNodeName);
|
||||
});
|
||||
|
||||
showQuickPickMock.onCall(1).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === Constants.placeholders.generateMnemonic);
|
||||
});
|
||||
|
||||
showSaveDialogMock.returns(uuid.v4());
|
||||
|
||||
// Act
|
||||
await TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showQuickPickMock.called, true, 'showQuickPick should be called');
|
||||
assert.strictEqual(showQuickPickMock.callCount, 2, 'showQuickPick should be called twice');
|
||||
assert.strictEqual(getAccessKeysMock.called, true, 'getAccessKeys should be called');
|
||||
assert.strictEqual(showInputBoxMock.called, false, 'showInputBox should not be called');
|
||||
assert.strictEqual(getMnemonicMock.called, false, 'getMnemonic should not be called');
|
||||
assert.strictEqual(getAllMnemonicPathsMock.called, true, 'getAllMnemonicPaths should be called');
|
||||
assert.strictEqual(saveMnemonicPathMock.called, true, 'saveMnemonicPath should be called');
|
||||
assert.strictEqual(writeFileSyncMock.called, true, 'writeFileSync should be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, false, 'startGanacheServer should not be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, true, 'truffleConfig.setNetwork should be called');
|
||||
assert.strictEqual(getExtensionMock.called, true, 'getExtension should be called');
|
||||
assert.strictEqual(
|
||||
isHdWalletProviderRequiredMock.calledOnce,
|
||||
true,
|
||||
'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
false,
|
||||
'checkHdWalletProviderVersion should not be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('to AzureBlockchainService should complete successfully when user paste mnemonic', async () => {
|
||||
// Arrange
|
||||
const { consortium, member, transactionNode } = azureNames;
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
getAccessKeysMock.returns(uuid.v4());
|
||||
|
||||
const networkNodeName = getDeployName(service.azure.prefix, consortium, transactionNode, [member]);
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === networkNodeName);
|
||||
});
|
||||
|
||||
showQuickPickMock.onCall(1).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === Constants.placeholders.pasteMnemonic);
|
||||
});
|
||||
|
||||
showInputBoxMock.onCall(0).returns(TestConstants.testMnemonic);
|
||||
showSaveDialogMock.returns(uuid.v4());
|
||||
|
||||
// Act
|
||||
await TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showQuickPickMock.called, true, 'showQuickPick should be called');
|
||||
assert.strictEqual(showQuickPickMock.callCount, 2, 'showQuickPick should be called twice');
|
||||
assert.strictEqual(getAccessKeysMock.called, true, 'getAccessKeys should be called');
|
||||
assert.strictEqual(showInputBoxMock.calledOnce, true, 'showInputBox should be called once');
|
||||
assert.strictEqual(getMnemonicMock.called, false, 'getMnemonic should not be called');
|
||||
assert.strictEqual(getAllMnemonicPathsMock.called, true, 'getAllMnemonicPaths should be called');
|
||||
assert.strictEqual(saveMnemonicPathMock.called, true, 'saveMnemonicPath should be called');
|
||||
assert.strictEqual(writeFileSyncMock.called, true, 'writeFileSync should be called');
|
||||
assert.strictEqual(checkAppsSilentMock.calledOnce, true, 'checkAppsSilent should be called once');
|
||||
assert.strictEqual(installTruffleMock.called, false, 'installTruffle should not be called');
|
||||
assert.strictEqual(getWorkspaceRootMock.called, true, 'getWorkspaceRoot should be called');
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
assert.strictEqual(startGanacheServerMock.called, false, 'startGanacheServer should not be called');
|
||||
assert.strictEqual(truffleConfigSetNetworkMock.called, true, 'truffleConfig.setNetwork should be called');
|
||||
assert.strictEqual(getExtensionMock.called, true, 'getExtension should be called');
|
||||
assert.strictEqual(
|
||||
isHdWalletProviderRequiredMock.calledOnce,
|
||||
true,
|
||||
'isHdWalletProviderRequired should be called');
|
||||
assert.strictEqual(
|
||||
checkHdWalletProviderVersionMock.calledOnce,
|
||||
false,
|
||||
'checkHdWalletProviderVersion should not be called');
|
||||
assert.strictEqual(
|
||||
installTruffleHdWalletProviderMock.calledOnce,
|
||||
false,
|
||||
'installTruffleHdWalletProvider should not be called');
|
||||
});
|
||||
|
||||
it('Blockchain Data Manager should be ignored in deploy destination list', async () => {
|
||||
// Arrange
|
||||
let isBDMExist = false;
|
||||
const { local } = TestConstants.consortiumTestNames;
|
||||
checkAppsSilentMock.returns(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
|
||||
const networkNodeName = getDeployName(service.local.prefix, local, local);
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
isBDMExist = items.some((item: any) => item.detail === Constants.treeItemData.service.bdm.label);
|
||||
return items.find((item: any) => item.label === networkNodeName);
|
||||
});
|
||||
|
||||
// Act
|
||||
await TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(isBDMExist, false, 'deploy destination list should not have Blockchain Data Manager');
|
||||
});
|
||||
|
||||
describe('validating openZeppelin contracts before deploy', () => {
|
||||
beforeEach(() => {
|
||||
checkAppsSilentMock.resolves(true);
|
||||
getWorkspaceRootMock.returns(path.join(__dirname, TestConstants.truffleCommandTestDataFolder));
|
||||
showInputBoxMock.returns(Constants.confirmationDialogResult.yes);
|
||||
executeCommandMock.returns(uuid.v4());
|
||||
|
||||
showQuickPickMock.onCall(0).callsFake((items: any) => {
|
||||
return items.find((item: any) => item.label === TestConstants.servicesNames.testNetwork);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('should pass when openZeppelin contracts are valid', async () => {
|
||||
// Arrange
|
||||
projectJsonExistsStub.returns(true);
|
||||
openZeppelinvalidateContractsAsyncMock.resolves([ new OZContractValidated('1', true, true) ]);
|
||||
|
||||
// Act
|
||||
await TruffleCommands.deployContracts();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(executeCommandMock.called, true, 'executeCommand should be called');
|
||||
});
|
||||
|
||||
it('should throw error when downloaded openZeppelin contract has invalid hash', async () => {
|
||||
// Arrange
|
||||
projectJsonExistsStub.returns(true);
|
||||
openZeppelinvalidateContractsAsyncMock.resolves([ new OZContractValidated('1', true, false) ]);
|
||||
|
||||
// Act and Assert
|
||||
await assert.rejects(TruffleCommands.deployContracts(), Error);
|
||||
});
|
||||
|
||||
it('should throw error when downloaded openZeppelin contract doesn\'t exist on the disk', async () => {
|
||||
// Arrange
|
||||
projectJsonExistsStub.returns(true);
|
||||
openZeppelinvalidateContractsAsyncMock.resolves([ new OZContractValidated('1', false) ]);
|
||||
|
||||
// Act and Assert
|
||||
await assert.rejects(TruffleCommands.deployContracts(), Error);
|
||||
});
|
||||
|
||||
it('should throw error when any downloaded openZeppelin contract is invalid', async () => {
|
||||
// Arrange
|
||||
projectJsonExistsStub.returns(true);
|
||||
openZeppelinvalidateContractsAsyncMock.resolves([
|
||||
new OZContractValidated('1', true, false),
|
||||
new OZContractValidated('2', true, true),
|
||||
]);
|
||||
|
||||
// Act and Assert
|
||||
await assert.rejects(TruffleCommands.deployContracts(), Error);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const azureNames = {
|
||||
consortium: uuid.v4(),
|
||||
member: uuid.v4(),
|
||||
transactionNode: TestConstants.servicesNames.testConsortium,
|
||||
};
|
||||
|
||||
async function createTestServicesItems(): Promise<Service[]> {
|
||||
const services: Service[] = [];
|
||||
|
||||
const azureBlockchainService = new AzureBlockchainService();
|
||||
const localService = new LocalService();
|
||||
const infuraService = new InfuraService();
|
||||
const bdmService = new BlockchainDataManagerService();
|
||||
|
||||
const azureBlockchainProject = new AzureBlockchainProject(
|
||||
azureNames.consortium,
|
||||
uuid.v4(),
|
||||
uuid.v4(),
|
||||
[azureNames.member],
|
||||
);
|
||||
const member = new Member(azureNames.member);
|
||||
const transactionNode
|
||||
= new AzureBlockchainNetworkNode(azureNames.transactionNode, uuid.v4(), '*', '', '', azureNames.member);
|
||||
member.addChild(transactionNode);
|
||||
azureBlockchainProject.addChild(member);
|
||||
|
||||
const defaultPort = 8545;
|
||||
const defaultLabel = TestConstants.consortiumTestNames.local;
|
||||
const localProject = new LocalProject(defaultLabel, defaultPort);
|
||||
const defaultUrl = `${Constants.networkProtocols.http}${Constants.localhost}:${defaultPort}`;
|
||||
const localNetworkNode = new LocalNetworkNode(defaultLabel, defaultUrl, '*');
|
||||
localProject.addChild(localNetworkNode);
|
||||
|
||||
const infuraProject = new InfuraProject(uuid.v4(), uuid.v4());
|
||||
const infuraNetworkNode = new InfuraNetworkNode(uuid.v4(), uuid.v4(), uuid.v4());
|
||||
infuraProject.addChild(infuraNetworkNode);
|
||||
|
||||
const bdmProject = new BlockchainDataManagerProject(uuid.v4(), uuid.v4(), uuid.v4());
|
||||
const bdmNetworkNode = new BlockchainDataManagerNetworkNode(
|
||||
uuid.v4(),
|
||||
'*',
|
||||
uuid.v4(),
|
||||
uuid.v4(),
|
||||
[],
|
||||
ItemType.BLOCKCHAIN_DATA_MANAGER_APPLICATION,
|
||||
uuid.v4());
|
||||
bdmProject.addChild(bdmNetworkNode);
|
||||
|
||||
azureBlockchainService.addChild(azureBlockchainProject);
|
||||
localService.addChild(localProject);
|
||||
infuraService.addChild(infuraProject);
|
||||
bdmService.addChild(bdmProject);
|
||||
|
||||
services.push(azureBlockchainService, localService, infuraService, bdmService);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
function getTestTruffleNetworks(): TruffleConfiguration.INetwork[] {
|
||||
const networks: TruffleConfiguration.INetwork[] = [];
|
||||
|
||||
networks.push({
|
||||
name: TestConstants.servicesNames.development,
|
||||
options: {
|
||||
host: '127.0.0.1',
|
||||
network_id: '*',
|
||||
port: 8545,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: TestConstants.servicesNames.testNetwork,
|
||||
options: {
|
||||
gas: 4712388,
|
||||
gasPrice: 100000000000,
|
||||
network_id: 2,
|
||||
},
|
||||
});
|
||||
|
||||
return networks;
|
||||
}
|
||||
|
||||
function getDeployName(prefix: string, projectName: string, nodeName: string, args?: string[]): string {
|
||||
if (args) {
|
||||
return [prefix, projectName, ...args, nodeName].join('_');
|
||||
}
|
||||
|
||||
return [prefix, projectName, nodeName].join('_');
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as sinon from 'sinon';
|
||||
import { TruffleCommands } from '../src/commands/TruffleCommands';
|
||||
import { TruffleExtensionAdapter } from '../src/services/extensionAdapter';
|
||||
|
||||
describe('TruffleExtensionAdapter', () => {
|
||||
let buildContractsMock: sinon.SinonStub<any>;
|
||||
let deployContractsMock: sinon.SinonStub<any>;
|
||||
let truffleExtensionAdapter: TruffleExtensionAdapter;
|
||||
|
||||
beforeEach(() => {
|
||||
buildContractsMock = sinon.stub(TruffleCommands, 'buildContracts');
|
||||
deployContractsMock = sinon.stub(TruffleCommands, 'deployContracts');
|
||||
|
||||
truffleExtensionAdapter = new TruffleExtensionAdapter();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('build method should call truffleCommands.buildContracts', async () => {
|
||||
// Act
|
||||
await truffleExtensionAdapter.build();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(
|
||||
buildContractsMock.calledOnce,
|
||||
true,
|
||||
'TruffleCommands.buildContracts should be called once',
|
||||
);
|
||||
});
|
||||
|
||||
it('deploy method should call truffleCommands.buildContracts', async () => {
|
||||
// Act
|
||||
await truffleExtensionAdapter.deploy();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(
|
||||
deployContractsMock.calledOnce,
|
||||
true,
|
||||
'TruffleCommands.deployContracts should be called once',
|
||||
);
|
||||
});
|
||||
});
|
|
@ -179,7 +179,7 @@ describe('OpenZeppelinCommands tests', () => {
|
|||
// Arrange
|
||||
const showQuickPick = sinon.stub(helpers, 'showQuickPick');
|
||||
showQuickPick.callsFake(async (...args: any[]) => {
|
||||
return args[0];
|
||||
return args[0].find((arg: any) => arg.label === selectedCategory.name);
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
|
@ -0,0 +1,362 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as path from 'path';
|
||||
import rewire = require('rewire');
|
||||
import * as sinon from 'sinon';
|
||||
import uuid = require('uuid');
|
||||
import {
|
||||
CancellationToken,
|
||||
MessageItem,
|
||||
MessageOptions,
|
||||
Progress,
|
||||
ProgressOptions,
|
||||
QuickPickItem,
|
||||
QuickPickOptions,
|
||||
window,
|
||||
} from 'vscode';
|
||||
import { Constants } from '../../src/Constants';
|
||||
import * as helpers from '../../src/helpers';
|
||||
import { openZeppelinHelper } from '../../src/helpers';
|
||||
import { TruffleConfiguration } from '../../src/helpers/truffleConfig';
|
||||
import { CancellationEvent } from '../../src/Models';
|
||||
import {
|
||||
OpenZeppelinMigrationsService,
|
||||
OpenZeppelinService,
|
||||
} from '../../src/services';
|
||||
import {
|
||||
IDownloadingResult,
|
||||
IOZAsset,
|
||||
IOZContractCategory,
|
||||
OZAssetType,
|
||||
PromiseState,
|
||||
} from '../../src/services/openZeppelin/models';
|
||||
import { OpenZeppelinManifest } from '../../src/services/openZeppelin/OpenZeppelinManifest';
|
||||
|
||||
describe('OpenZeppelinCommands tests', () => {
|
||||
let testCategories: IOZContractCategory[];
|
||||
let getCategoriesStub: sinon.SinonSpy<[], IOZContractCategory[]>;
|
||||
let collectAssetsWithDependenciesStub: sinon.SinonSpy<[(string[] | undefined)?], IOZAsset[]>;
|
||||
let downloadAssetsAsyncStub: sinon.SinonStub<
|
||||
[string, IOZAsset[], (boolean | undefined)?, (string | undefined)?],
|
||||
Promise<IDownloadingResult[]>>;
|
||||
let getAssetsStatusStub: sinon.SinonStub<any>;
|
||||
let generateMigrationsStub: sinon.SinonStub<[IOZAsset[]], Promise<void>>;
|
||||
let getCategoryApiDocumentationUrlStub: sinon.SinonStub<any>;
|
||||
let updateProjectJsonAsyncStub: sinon.SinonStub<[string, IOZContractCategory, IOZAsset[]], Promise<void>>;
|
||||
|
||||
let withProgressStub: sinon.SinonStub<[ProgressOptions,
|
||||
(progress: Progress<any>, token: CancellationToken) => any], any>;
|
||||
let showQuickPickStub: sinon.SinonStub<
|
||||
[QuickPickItem[] | Thenable<QuickPickItem[]>, (QuickPickOptions | undefined)?, (CancellationToken | undefined)?],
|
||||
any>;
|
||||
let showInformationMessageStub: sinon.SinonStub<[string, MessageOptions, ...MessageItem[]], any>;
|
||||
let showErrorMessageStub: sinon.SinonStub<[string, MessageOptions, ...MessageItem[]], any>;
|
||||
|
||||
let selectedCategory: IOZContractCategory;
|
||||
let testAssets: IOZAsset[];
|
||||
|
||||
let openZeppelinCommandsRewire: any;
|
||||
|
||||
let openStub: sinon.SinonStub<any[], any>;
|
||||
|
||||
beforeEach(() => {
|
||||
const numberOfCategory = 2;
|
||||
testCategories = getTestCategories();
|
||||
selectedCategory = testCategories[numberOfCategory];
|
||||
testAssets = getTestAssetsWithDependencies(selectedCategory.assets);
|
||||
const mockOpenZeppelinManifest = {
|
||||
collectAssetsWithDependencies: (_assetIds: string[]) => testAssets,
|
||||
getAssets: () => [] as IOZAsset[],
|
||||
getBaseUrlToContractsSource: () => 'http://test.com',
|
||||
getCategories: () => testCategories,
|
||||
getCategoryApiDocumentationUrl: (_category: IOZContractCategory) => '',
|
||||
getVersion: () => '1.0.0',
|
||||
} as OpenZeppelinManifest;
|
||||
|
||||
const getWorkspaceRootMock = sinon.stub(helpers, 'getWorkspaceRoot');
|
||||
getWorkspaceRootMock.returns(path.join(__filename, '../../TruffleCommandsTests/testData'));
|
||||
|
||||
sinon.stub(TruffleConfiguration.TruffleConfig.prototype, 'getConfiguration')
|
||||
.returns(Promise.resolve({ contracts_directory: uuid.v4() } as TruffleConfiguration.IConfiguration));
|
||||
|
||||
getAssetsStatusStub = sinon.stub(OpenZeppelinService, 'getAssetsStatus');
|
||||
downloadAssetsAsyncStub = sinon.stub(OpenZeppelinService, 'downloadAssetsAsync');
|
||||
updateProjectJsonAsyncStub = sinon.stub(OpenZeppelinService, 'updateProjectJsonAsync')
|
||||
.resolves();
|
||||
generateMigrationsStub = sinon.stub(OpenZeppelinMigrationsService, 'generateMigrations')
|
||||
.resolves();
|
||||
getCategoriesStub = sinon.spy(mockOpenZeppelinManifest, 'getCategories');
|
||||
collectAssetsWithDependenciesStub = sinon.spy(mockOpenZeppelinManifest, 'collectAssetsWithDependencies');
|
||||
getCategoryApiDocumentationUrlStub = sinon.stub(mockOpenZeppelinManifest, 'getCategoryApiDocumentationUrl');
|
||||
|
||||
sinon.stub(openZeppelinHelper, 'tryGetCurrentOpenZeppelinVersionAsync').resolves('version');
|
||||
sinon.stub(openZeppelinHelper, 'createManifestAsync').resolves(mockOpenZeppelinManifest);
|
||||
|
||||
getAssetsStatusStub.returns({ existing: [], missing: testAssets });
|
||||
|
||||
showQuickPickStub = sinon.stub(window, 'showQuickPick');
|
||||
showInformationMessageStub = sinon.stub(window, 'showInformationMessage');
|
||||
showErrorMessageStub = sinon.stub(window, 'showErrorMessage');
|
||||
withProgressStub = sinon.stub(window, 'withProgress');
|
||||
withProgressStub.callsFake(async (...args: any[]) => {
|
||||
return args[1]();
|
||||
});
|
||||
|
||||
showQuickPickStub.callsFake(async (...args: any[]) => {
|
||||
return args[0].find((arg: any) => arg.label === selectedCategory.name);
|
||||
});
|
||||
|
||||
const testDownloadingResult: IDownloadingResult[] = [];
|
||||
testAssets.forEach((asset) => {
|
||||
testDownloadingResult.push({
|
||||
asset,
|
||||
state: PromiseState.fulfilled,
|
||||
});
|
||||
});
|
||||
downloadAssetsAsyncStub.resolves(testDownloadingResult);
|
||||
|
||||
openStub = sinon.stub().resolves();
|
||||
openZeppelinCommandsRewire = rewire('../../src/commands/OpenZeppelinCommands');
|
||||
openZeppelinCommandsRewire.__set__('open', openStub);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('addCategory should complete basic pipeline', async () => {
|
||||
// Arrange
|
||||
getCategoryApiDocumentationUrlStub.returns('testUrl');
|
||||
const wereDownloadedMessage = Constants.openZeppelin.wereDownloaded(selectedCategory.assets.length);
|
||||
showInformationMessageStub.onCall(0).returns(Constants.openZeppelin.moreDetailsButtonTitle);
|
||||
|
||||
// Act
|
||||
await openZeppelinCommandsRewire.OpenZeppelinCommands.addCategory();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(getCategoriesStub.called, true, 'getCategories should be called.');
|
||||
assert.strictEqual(showQuickPickStub.calledOnce, true, 'showQuickPick should called once.');
|
||||
assert.deepStrictEqual(
|
||||
showQuickPickStub.args[0][1],
|
||||
{
|
||||
ignoreFocusOut: true,
|
||||
placeHolder: Constants.openZeppelin.selectCategoryForDownloading,
|
||||
},
|
||||
'selectCategory should ask for category.',
|
||||
);
|
||||
assert.strictEqual(collectAssetsWithDependenciesStub.calledOnce,
|
||||
true, 'collectAssetsWithDependencies should called once.');
|
||||
assert.deepStrictEqual(
|
||||
collectAssetsWithDependenciesStub.args[0][0],
|
||||
selectedCategory.assets,
|
||||
'collectAssetsWithDependencies should called once with asserts from selected category.',
|
||||
);
|
||||
assert.strictEqual(downloadAssetsAsyncStub.calledOnce, true, 'downloadAssetsAsync should be called');
|
||||
assert.strictEqual(showInformationMessageStub.calledTwice,
|
||||
true, 'showInformationMessage should be called twice');
|
||||
assert.strictEqual(
|
||||
showInformationMessageStub.args[0][0],
|
||||
wereDownloadedMessage,
|
||||
'should be displayed message with number of downloaded items',
|
||||
);
|
||||
assert.strictEqual(
|
||||
showInformationMessageStub.args[1][0],
|
||||
Constants.openZeppelin.exploreDownloadedContractsInfo,
|
||||
'should be displayed message with information about downloaded category',
|
||||
);
|
||||
assert.strictEqual(updateProjectJsonAsyncStub.calledOnce, true, 'updateProjectJsonAsync should be called once');
|
||||
assert.strictEqual(
|
||||
getCategoryApiDocumentationUrlStub.calledOnce,
|
||||
true,
|
||||
'getCategoryApiDocumentationUrl should be called',
|
||||
);
|
||||
assert.strictEqual(generateMigrationsStub.called, true, 'generateMigrations should be called');
|
||||
});
|
||||
|
||||
it('addCategory should downloads selected category', async () => {
|
||||
// Arrange
|
||||
const showQuickPick = sinon.stub(helpers, 'showQuickPick');
|
||||
showQuickPick.callsFake(async (...args: any[]) => {
|
||||
return args[0];
|
||||
});
|
||||
|
||||
// Act
|
||||
await openZeppelinCommandsRewire.OpenZeppelinCommands.addCategory();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(downloadAssetsAsyncStub.args[0][1], testAssets, 'downloadAssetsAsync should called for selected asset');
|
||||
});
|
||||
|
||||
it('addCategory throws cancellation event when user don`t select category', async () => {
|
||||
// Arrange
|
||||
const notExistingCategoryName = 'notExistingCategoryName';
|
||||
|
||||
showQuickPickStub.callsFake(async (...args: any[]) => {
|
||||
return args[0].find((arg: any) => arg.label === notExistingCategoryName);
|
||||
});
|
||||
|
||||
// Act and Assert
|
||||
await assert.rejects(
|
||||
async () => await openZeppelinCommandsRewire.OpenZeppelinCommands.addCategory(),
|
||||
CancellationEvent,
|
||||
'addCategory should throw cancellation event.');
|
||||
assert.strictEqual(getCategoriesStub.calledOnce, true, 'getCategories should called once.');
|
||||
assert.strictEqual(showQuickPickStub.calledOnce, true, 'showQuickPick should called once.');
|
||||
assert.strictEqual(
|
||||
collectAssetsWithDependenciesStub.notCalled,
|
||||
true,
|
||||
'collectAssetsWithDependencies should not called.');
|
||||
assert.strictEqual(withProgressStub.notCalled, true, 'withProgress should not called.');
|
||||
});
|
||||
|
||||
it('addCategory should ask for overwrite existing files and overwrite on positive answer', async () => {
|
||||
// Arrange
|
||||
const existingAsset = testAssets.slice(3, 4);
|
||||
const missingAsset = testAssets.slice(0, 3);
|
||||
getAssetsStatusStub
|
||||
.returns({
|
||||
existing: existingAsset,
|
||||
missing: missingAsset,
|
||||
});
|
||||
showInformationMessageStub.onCall(0).returns(Constants.openZeppelin.replaceButtonTitle);
|
||||
|
||||
// Act
|
||||
await openZeppelinCommandsRewire.OpenZeppelinCommands.addCategory();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showInformationMessageStub.calledTwice, true, 'showInformationMessage should called twice');
|
||||
assert.strictEqual(
|
||||
showInformationMessageStub.args[0][0],
|
||||
Constants.openZeppelin.alreadyExisted(existingAsset),
|
||||
'alreadyExisted message should displayed once.',
|
||||
);
|
||||
assert.strictEqual(downloadAssetsAsyncStub.args[0][2], true, 'downloading should be called with overwrite flag');
|
||||
assert.strictEqual(downloadAssetsAsyncStub.args[0][1].length, testAssets.length, 'downloading full asset of items');
|
||||
});
|
||||
|
||||
it('addCategory should ask for overwrite existed files and skip files on negative answer', async () => {
|
||||
// Arrange
|
||||
const existingAsset = testAssets.slice(3, 4);
|
||||
const missingAsset = testAssets.slice(0, 3);
|
||||
getAssetsStatusStub
|
||||
.returns({
|
||||
existing: existingAsset,
|
||||
missing: missingAsset,
|
||||
});
|
||||
showInformationMessageStub.onCall(0).returns(Constants.openZeppelin.skipButtonTitle);
|
||||
|
||||
// Act
|
||||
await openZeppelinCommandsRewire.OpenZeppelinCommands.addCategory();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(showInformationMessageStub.calledTwice, true, 'showInformationMessage should called twice');
|
||||
assert.strictEqual(
|
||||
showInformationMessageStub.args[0][0],
|
||||
Constants.openZeppelin.alreadyExisted(existingAsset),
|
||||
'showQuickPick should called once.',
|
||||
);
|
||||
assert.strictEqual(downloadAssetsAsyncStub.args[0][2], false,
|
||||
'downloading should be called without overwrite flag');
|
||||
assert.strictEqual(downloadAssetsAsyncStub.args[0][1].length, missingAsset.length,
|
||||
'downloading only missing assets');
|
||||
});
|
||||
|
||||
it('addCategory should show error message if some files failed on downloading and allow to retry', async () => {
|
||||
// Arrange
|
||||
const rejectedAssets = [
|
||||
{ asset: {} as IOZAsset, state: PromiseState.rejected },
|
||||
{ asset: {} as IOZAsset, state: PromiseState.rejected },
|
||||
];
|
||||
downloadAssetsAsyncStub.resolves([
|
||||
{ asset: {} as IOZAsset, state: PromiseState.fulfilled },
|
||||
...rejectedAssets,
|
||||
]);
|
||||
showErrorMessageStub
|
||||
.onCall(0).returns(Constants.openZeppelin.retryButtonTitle)
|
||||
.onCall(1).returns(Constants.openZeppelin.cancelButtonTitle);
|
||||
|
||||
// Act
|
||||
await openZeppelinCommandsRewire.OpenZeppelinCommands.addCategory();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(
|
||||
showErrorMessageStub.args[0][0],
|
||||
Constants.openZeppelin.wereNotDownloaded(rejectedAssets.length),
|
||||
'showErrorMessageStub should called with exact message',
|
||||
);
|
||||
assert.strictEqual(downloadAssetsAsyncStub.calledTwice, true, 'downloadFiles should be retried');
|
||||
});
|
||||
|
||||
it('addCategory should open documentation for chosen category after downloading', async () => {
|
||||
// Arrange
|
||||
const testDocumentationUrl = 'testUrl';
|
||||
getCategoryApiDocumentationUrlStub.returns(testDocumentationUrl);
|
||||
generateMigrationsStub.resolves();
|
||||
showInformationMessageStub.onCall(1).returns(Constants.openZeppelin.moreDetailsButtonTitle);
|
||||
|
||||
// Act
|
||||
await openZeppelinCommandsRewire.OpenZeppelinCommands.addCategory();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(getCategoryApiDocumentationUrlStub.calledWithMatch(selectedCategory), true,
|
||||
'getCategoryApiDocumentationUrl should be called with chosen category');
|
||||
assert.strictEqual(openStub.calledWith(testDocumentationUrl), true,
|
||||
`open should be called with ${testDocumentationUrl}`);
|
||||
assert.strictEqual(openStub.calledAfter(downloadAssetsAsyncStub), true,
|
||||
'open should be called after downloadFiles');
|
||||
});
|
||||
|
||||
it('addCategory should not ask and open category documentation if it doesn\'t exist', async () => {
|
||||
// Arrange
|
||||
getCategoryApiDocumentationUrlStub.returns(undefined);
|
||||
generateMigrationsStub.resolves();
|
||||
|
||||
// Act
|
||||
await openZeppelinCommandsRewire.OpenZeppelinCommands.addCategory();
|
||||
|
||||
// Assert
|
||||
assert.strictEqual(
|
||||
showInformationMessageStub.calledWith(Constants.openZeppelin.exploreDownloadedContractsInfo),
|
||||
false,
|
||||
'showInformationMessageStub should not be called with explore contracts info message');
|
||||
assert.strictEqual(openStub.called, false, 'open should not be called');
|
||||
});
|
||||
});
|
||||
|
||||
function getTestCategories(): IOZContractCategory[] {
|
||||
const testCategories: IOZContractCategory[] = [{
|
||||
assets: [uuid.v4()],
|
||||
id: uuid.v4(),
|
||||
name: uuid.v4(),
|
||||
},
|
||||
{
|
||||
assets: [uuid.v4(), uuid.v4()],
|
||||
id: uuid.v4(),
|
||||
name: uuid.v4(),
|
||||
},
|
||||
{
|
||||
assets: [uuid.v4(), uuid.v4(), uuid.v4(), uuid.v4()],
|
||||
id: uuid.v4(),
|
||||
name: uuid.v4(),
|
||||
}];
|
||||
|
||||
return testCategories;
|
||||
}
|
||||
|
||||
function getTestAssetsWithDependencies(assets: string[]): IOZAsset[] {
|
||||
const assetsWithDependencies: IOZAsset[] = [];
|
||||
|
||||
assets.forEach((asset) => {
|
||||
assetsWithDependencies.push({
|
||||
dependencies: [uuid.v4()],
|
||||
hash: uuid.v4(),
|
||||
id: asset,
|
||||
name: uuid.v4(),
|
||||
type: OZAssetType.contract,
|
||||
});
|
||||
});
|
||||
|
||||
return assetsWithDependencies;
|
||||
}
|
|
@ -28,10 +28,18 @@
|
|||
"./src/debugger/types"
|
||||
]
|
||||
},
|
||||
"include": ["src/**/*.js", "src/**/*.ts", "src/**/*.json", "test/**/*.js", "test/**/*.ts", "test/**/*.json"],
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.json",
|
||||
"test/**/*.js",
|
||||
"test/**/*.ts",
|
||||
"test/**/*.json"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
".vscode-test",
|
||||
"drizzleUI"
|
||||
"drizzleUI",
|
||||
"ui-test"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"outDir": "out",
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"rootDir": ".",
|
||||
"strict": true,
|
||||
/* enable all strict type-checking options */
|
||||
/* Additional Checks */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitReturns": true,
|
||||
"strictNullChecks": true,
|
||||
"noUnusedParameters": true,
|
||||
"allowJs": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/@machinomy",
|
||||
"./src/debugger/types"
|
||||
]
|
||||
},
|
||||
"include": ["src/**/*.js", "src/**/*.ts", "src/**/*.json", "test/**/*.js", "test/**/*.ts", "test/**/*.json"],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
".vscode-test",
|
||||
"drizzleUI"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
out
|
||||
node_modules
|
||||
.vscode-test/
|
||||
*.vsix
|
||||
test-resources/
|
||||
package-lock.json
|
|
@ -0,0 +1 @@
|
|||
test-resources/**
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "ui-test",
|
||||
"version": "1.0.0",
|
||||
"description": "End-to-end tests for azure blockchain extension",
|
||||
"main": "index.js",
|
||||
"publisher": "AzBlockchain",
|
||||
"engines": {
|
||||
"vscode": "^1.43.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "npx rimraf -- ./out/*",
|
||||
"compile": "npm run clean && tsc -p ./",
|
||||
"lint": "tslint -p ./",
|
||||
"watch": "tsc -watch -p ./",
|
||||
"download": "download --out test-resources --filename azure-blockchain.vsix https://marketplace.visualstudio.com/_apis/public/gallery/publishers/AzBlockchain/vsextensions/azure-blockchain/1.2.0/vspackage",
|
||||
"prepare-ui-test": "npm run compile && npm run download && extest get-vscode && extest get-chromedriver && extest install-vsix -f test-resources/azure-blockchain.vsix",
|
||||
"ui-test": "npm run prepare-ui-test && extest run-tests out/*.test.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.11",
|
||||
"@types/fs-extra": "^7.0.0",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"chai": "^4.2.0",
|
||||
"download-cli": "^1.1.1",
|
||||
"fs-extra": "^7.0.0",
|
||||
"mocha": "^7.1.1",
|
||||
"tslint": "^5.18.0",
|
||||
"tslint-microsoft-contrib": "^6.2.0",
|
||||
"typescript": "^3.3.1",
|
||||
"vscode-extension-tester": "^2.6.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export const testProjectDirectory = '';
|
||||
export const commonTestTimeout = 120000;
|
||||
export const setupTimeout = 300000;
|
|
@ -0,0 +1,269 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { expect } from 'chai';
|
||||
import * as clipboard from 'clipboardy';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import {
|
||||
ActivityBar,
|
||||
BottomBarPanel,
|
||||
CustomTreeSection,
|
||||
DefaultTreeSection,
|
||||
DialogHandler,
|
||||
InputBox,
|
||||
OutputView,
|
||||
SideBarView,
|
||||
TreeItem,
|
||||
VSBrowser,
|
||||
WebDriver,
|
||||
Workbench,
|
||||
} from 'vscode-extension-tester';
|
||||
import { commonTestTimeout, setupTimeout, testProjectDirectory } from './config';
|
||||
|
||||
|
||||
const tempProjectPrefix = 'ui-test-';
|
||||
|
||||
describe('Truffle tests', function() {
|
||||
this.timeout(setupTimeout);
|
||||
let driver: WebDriver;
|
||||
let workbench: Workbench;
|
||||
let testDir: string;
|
||||
|
||||
before(async () => {
|
||||
testDir = testProjectDirectory || createTempFolder();
|
||||
driver = VSBrowser.instance.driver;
|
||||
await driver.manage().timeouts().implicitlyWait(30000);
|
||||
await driver.manage().timeouts().setScriptTimeout(30000);
|
||||
await driver.manage().timeouts().pageLoadTimeout(30000);
|
||||
|
||||
workbench = new Workbench();
|
||||
|
||||
await createNewSolidityProject(driver, workbench, testDir);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await openWorkspace(workbench, os.tmpdir());
|
||||
await reload(workbench);
|
||||
await removeTempFolder(testDir);
|
||||
});
|
||||
|
||||
describe('Truffle tests', () => {
|
||||
it('Create new network', async () => {
|
||||
const testNetworkName = 'testnetwork';
|
||||
|
||||
await workbench.executeCommand('Azure Blockchain: Create a new network');
|
||||
const serviceTypeInput = await driver.wait(() => new InputBox(), 5000);
|
||||
await serviceTypeInput.setText('Local Service');
|
||||
await serviceTypeInput.confirm();
|
||||
|
||||
const networkNameInput = await driver.wait(() => new InputBox(), 5000);
|
||||
await networkNameInput.setText(testNetworkName);
|
||||
await networkNameInput.confirm();
|
||||
|
||||
const networkPortInput = await driver.wait(() => new InputBox(), 5000);
|
||||
await networkPortInput.setText('8535');
|
||||
await networkPortInput.confirm();
|
||||
|
||||
const azureBlockchainSection = <CustomTreeSection> await new SideBarView()
|
||||
.getContent()
|
||||
.getSection('Azure Blockchain');
|
||||
await azureBlockchainSection.expand();
|
||||
|
||||
const localServiceSection = await azureBlockchainSection.findItem('Local Service');
|
||||
|
||||
expect(localServiceSection).instanceOf(TreeItem);
|
||||
|
||||
const localServices = await localServiceSection?.getChildren();
|
||||
const localServicesNames = localServices?.map((service) => service.getLabel());
|
||||
|
||||
expect(localServicesNames?.includes(testNetworkName)).equals(true, 'New network name should appear in the tree');
|
||||
}).timeout(commonTestTimeout);
|
||||
|
||||
it('Build contracts', async () => {
|
||||
const output = await driver.wait(() => new BottomBarPanel().openOutputView(), 5000);
|
||||
await output.selectChannel('Azure Blockchain');
|
||||
await output.clearText();
|
||||
|
||||
await workbench.executeCommand('Azure Blockchain: Build Contracts');
|
||||
|
||||
await scanOutput(driver, output, 'Compiled successfully using', 60000, 2000, 5000);
|
||||
|
||||
const directoryFiles = fs.readdirSync(path.join(testDir, 'build', 'contracts'));
|
||||
|
||||
expect(directoryFiles.length).not.equals(0);
|
||||
}).timeout(commonTestTimeout);
|
||||
|
||||
it('Deploy contracts', async () => {
|
||||
const output = await driver.wait(() => new BottomBarPanel().openOutputView(), 5000);
|
||||
await output.selectChannel('Azure Blockchain');
|
||||
await output.clearText();
|
||||
|
||||
await workbench.executeCommand('Azure Blockchain: Deploy Contracts');
|
||||
|
||||
const destinationInput = await driver.wait(() => new InputBox(), 60000);
|
||||
await destinationInput.setText('loc_testnetwork_testnetwork');
|
||||
await destinationInput.confirm();
|
||||
|
||||
await scanOutput(driver, output, 'Deploy succeeded', 60000, 2000, 5000);
|
||||
}).timeout(commonTestTimeout);
|
||||
|
||||
describe('Abi and bytecode tests', () => {
|
||||
let buildContract: string;
|
||||
let contract: TreeItem | undefined;
|
||||
|
||||
before(async () => {
|
||||
const workspaceSection = <DefaultTreeSection> await new SideBarView().getContent().getSection('Untitled (Workspace)');
|
||||
const projectName = testDir.match(new RegExp(`(${tempProjectPrefix}).*$`))![0];
|
||||
const project = await workspaceSection.findItem(projectName);
|
||||
await project?.click();
|
||||
|
||||
const buildFolder = await project?.findChildItem('build');
|
||||
await buildFolder?.click();
|
||||
|
||||
contract = await workspaceSection.findItem('HelloBlockchain.json');
|
||||
await contract?.select();
|
||||
|
||||
buildContract = fs.readFileSync(path.join(testDir, 'build', 'contracts', 'HelloBlockchain.json')).toString();
|
||||
});
|
||||
|
||||
it('Copy Contract ABI command should be executed', async () => {
|
||||
const menu = await contract?.openContextMenu();
|
||||
const menuItem = await menu?.getItem('Copy Contract ABI');
|
||||
await menuItem?.select();
|
||||
await driver.sleep(1000);
|
||||
|
||||
const abiBuffer = clipboard.readSync();
|
||||
|
||||
expect(JSON.stringify(JSON.parse(buildContract)['abi'])).equals(abiBuffer);
|
||||
}).timeout(commonTestTimeout);
|
||||
|
||||
it('Copy Transaction Bytecode command should be executed', async () => {
|
||||
const menu = await contract?.openContextMenu();
|
||||
const menuItem = await menu?.getItem('Copy Transaction Bytecode');
|
||||
await menuItem?.select();
|
||||
|
||||
const destinationInput = await driver.wait(() => new InputBox(), 60000);
|
||||
await destinationInput.setText('loc_testnetwork_testnetwork');
|
||||
await destinationInput.confirm();
|
||||
|
||||
const notifications = await new Workbench().getNotifications();
|
||||
const notification = notifications[0];
|
||||
|
||||
const message = await notification.getMessage();
|
||||
|
||||
const deployedBytecode = clipboard.readSync();
|
||||
|
||||
expect(message.includes('Transaction Bytecode was copied to clipboard')).equals(true, 'Notification should appear');
|
||||
expect(deployedBytecode).not.equals(undefined, 'Bytecode should be copied to clipboard');
|
||||
}).timeout(commonTestTimeout);
|
||||
|
||||
it('Copy Constructor Bytecode command should be executed', async () => {
|
||||
const menu = await contract?.openContextMenu();
|
||||
const menuItem = await menu?.getItem('Copy Constructor Bytecode');
|
||||
await menuItem?.select();
|
||||
await driver.sleep(1000);
|
||||
|
||||
const bytecode = clipboard.readSync();
|
||||
|
||||
expect(JSON.parse(buildContract)['bytecode']).equals(bytecode);
|
||||
}).timeout(commonTestTimeout);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function scanOutput(
|
||||
driver: WebDriver,
|
||||
output: OutputView,
|
||||
successMessage: string,
|
||||
maxWait: number,
|
||||
timeout: number,
|
||||
initialWait: number) {
|
||||
return driver.wait(async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(async function waiter() {
|
||||
try {
|
||||
const text = await output.getText();
|
||||
if (text.includes(successMessage)) {
|
||||
return resolve('Done');
|
||||
}
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
||||
setTimeout(waiter, timeout);
|
||||
}, initialWait);
|
||||
});
|
||||
}, maxWait);
|
||||
}
|
||||
|
||||
function createTempFolder() {
|
||||
return fs.mkdtempSync(path.join(os.tmpdir(), tempProjectPrefix));
|
||||
}
|
||||
|
||||
async function removeTempFolder(directory: string) {
|
||||
await fs.remove(directory);
|
||||
}
|
||||
|
||||
async function openWorkspace(workbench: Workbench, directory: string): Promise<void> {
|
||||
await workbench.executeCommand('Extest: Open Folder');
|
||||
const input = await InputBox.create();
|
||||
await input.setText(directory);
|
||||
await input.confirm();
|
||||
}
|
||||
|
||||
async function reload(workbench: Workbench) {
|
||||
await workbench.executeCommand('Developer: Reload Window');
|
||||
}
|
||||
|
||||
async function createNewSolidityProject(
|
||||
driver: WebDriver,
|
||||
workbench: Workbench,
|
||||
testDirectory: string): Promise<void> {
|
||||
// we should close all previous notification because they can affect command execution
|
||||
// notification center work very slow
|
||||
const notificationCenter = await driver.wait(() => workbench.openNotificationsCenter(), 30000);
|
||||
await notificationCenter.clearAllNotifications();
|
||||
const activityBar = new ActivityBar();
|
||||
const explorer = await activityBar.getViewControl('Explorer');
|
||||
await explorer.openView();
|
||||
|
||||
await workbench.executeCommand('Azure Blockchain: New Solidity Project');
|
||||
const input = await driver.wait(() => new InputBox(), 60000);
|
||||
await input.setText('Create basic project');
|
||||
await input.confirm();
|
||||
|
||||
const dialog = await driver.wait(() => DialogHandler.getOpenDialog(), 5000);
|
||||
await dialog.selectPath(testDirectory);
|
||||
await dialog.confirm();
|
||||
|
||||
const output = await driver.wait(() => new BottomBarPanel().openOutputView(), 5000);
|
||||
await output.selectChannel('Azure Blockchain');
|
||||
|
||||
await driver.wait(async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(async function waitForUnboxing() {
|
||||
try {
|
||||
const text = await output.getText();
|
||||
|
||||
if (text.includes('Error')) {
|
||||
return reject(new Error('Error on unboxing'));
|
||||
}
|
||||
|
||||
if (fs.existsSync(path.join(testDirectory, 'package-lock.json')) ||
|
||||
text.includes('Initialized empty Git repository')) {
|
||||
return resolve('Done');
|
||||
}
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
||||
setTimeout(waitForUnboxing, 3000);
|
||||
}, 20000);
|
||||
});
|
||||
}, 120000);
|
||||
|
||||
// wait for change directory during project creation
|
||||
await driver.sleep(10000);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES6",
|
||||
"outDir": "out",
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"rootDir": "src",
|
||||
"allowJs": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.json"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"vscode-test",
|
||||
"test-resources"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"extends": ["tslint-microsoft-contrib/recommended"],
|
||||
"rules": {
|
||||
"no-string-throw": true,
|
||||
"no-unused-expression": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-namespace": false,
|
||||
"no-relative-imports": false,
|
||||
"no-function-expression": false,
|
||||
"non-literal-fs-path": false,
|
||||
"mocha-no-side-effect-code": false,
|
||||
"curly": true,
|
||||
"class-name": true,
|
||||
"semicolon": [
|
||||
true,
|
||||
"always"
|
||||
],
|
||||
"triple-equals": true,
|
||||
"variable-name": [
|
||||
true,
|
||||
"ban-keywords",
|
||||
"check-format",
|
||||
"allow-leading-underscore"
|
||||
],
|
||||
"whitespace": [
|
||||
true,
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-operator",
|
||||
"check-module",
|
||||
"check-separator",
|
||||
"check-rest-spread",
|
||||
"check-type",
|
||||
"check-typecast",
|
||||
"check-type-operator"
|
||||
],
|
||||
"quotemark": [
|
||||
true,
|
||||
"single",
|
||||
"avoid-escape",
|
||||
"avoid-template"
|
||||
]
|
||||
},
|
||||
"linterOptions": {
|
||||
"exclude": [
|
||||
"node_modules/**",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
},
|
||||
"defaultSeverity": "warning"
|
||||
}
|
Загрузка…
Ссылка в новой задаче