├── docs
├── 0.png
├── 1-1.png
├── 2-1.png
├── 2-2.png
├── 2-3.png
├── 2-4.png
├── 3-1.png
├── 3-2.png
├── 4-1.png
├── 4-2.png
├── 4-3.png
├── 4-4.png
├── 5-2.png
├── 5-3.png
├── 5-1-0.png
├── 5-1-1.png
└── features.md
├── screenshot.png
├── resources
├── icon.png
├── playground.png
├── add.svg
├── runTask.svg
├── add-black.svg
├── runTask-black.svg
├── apps.svg
├── apps-black.svg
├── play-black.svg
├── play.svg
├── stopProcess.svg
├── purgeChain.svg
├── stopProcess-black.svg
├── purgeChain-black.svg
├── check-black.svg
├── check.svg
├── home.svg
├── home-black.svg
├── book.svg
├── book-black.svg
├── startNode.svg
├── startNode-black.svg
├── compileStartNode.svg
├── compileStartNode-black.svg
├── gear.svg
├── gear-black.svg
├── substrate.svg
├── github.svg
├── github-black.svg
└── playground.png.base64
├── .gitignore
├── src
├── constants.ts
├── views
│ ├── marketplace
│ │ ├── types.ts
│ │ ├── substrateDeps.ts
│ │ ├── fetchCategories.ts
│ │ └── MarketplaceProvider.ts
│ ├── processes
│ │ └── ProcessesProvider.ts
│ ├── nodes
│ │ └── NodesProvider.ts
│ ├── accounts
│ │ └── AccountsProvider.ts
│ └── contracts
│ │ └── ContractsProvider.ts
├── common
│ ├── TreeDataProvider.ts
│ └── Substrate.ts
├── runtimes
│ ├── parseDepsFromFile.ts
│ └── Runtime.ts
├── processes
│ └── Processes.ts
├── extension.ts
├── util.ts
└── nodes
│ └── Nodes.ts
├── .vscode
├── extensions.json
├── tasks.json
├── settings.json
└── launch.json
├── .vscodeignore
├── .eslintrc.json
├── tsconfig.json
├── README.md
├── .github
└── workflows
│ └── release.yml
├── CHANGELOG.md
├── package.json
└── yarn.lock
/docs/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/0.png
--------------------------------------------------------------------------------
/docs/1-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/1-1.png
--------------------------------------------------------------------------------
/docs/2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/2-1.png
--------------------------------------------------------------------------------
/docs/2-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/2-2.png
--------------------------------------------------------------------------------
/docs/2-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/2-3.png
--------------------------------------------------------------------------------
/docs/2-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/2-4.png
--------------------------------------------------------------------------------
/docs/3-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/3-1.png
--------------------------------------------------------------------------------
/docs/3-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/3-2.png
--------------------------------------------------------------------------------
/docs/4-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/4-1.png
--------------------------------------------------------------------------------
/docs/4-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/4-2.png
--------------------------------------------------------------------------------
/docs/4-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/4-3.png
--------------------------------------------------------------------------------
/docs/4-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/4-4.png
--------------------------------------------------------------------------------
/docs/5-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/5-2.png
--------------------------------------------------------------------------------
/docs/5-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/5-3.png
--------------------------------------------------------------------------------
/docs/5-1-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/5-1-0.png
--------------------------------------------------------------------------------
/docs/5-1-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/docs/5-1-1.png
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/screenshot.png
--------------------------------------------------------------------------------
/resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/resources/icon.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | scratchpad
2 | out
3 | node_modules
4 | .vscode-test/
5 | *.vsix
6 | vsc-extension-quickstart.md
--------------------------------------------------------------------------------
/resources/playground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paritytech/vscode-substrate/HEAD/resources/playground.png
--------------------------------------------------------------------------------
/src/constants.ts:
--------------------------------------------------------------------------------
1 | // Source for the marketplace treeview
2 | export const GRAPHQL_API_ENDPOINT = 'https://marketplace-api-staging.substrate.dev/graphql';
--------------------------------------------------------------------------------
/resources/add.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/runTask.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/add-black.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/runTask-black.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "dbaeumer.vscode-eslint"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/test/**
4 | src/**
5 | .gitignore
6 | vsc-extension-quickstart.md
7 | **/tsconfig.json
8 | **/.eslintrc.json
9 | **/*.map
10 | **/*.ts
11 | scratchpad
12 | *.vsix
--------------------------------------------------------------------------------
/resources/apps.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/apps-black.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/play-black.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/play.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/stopProcess.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/purgeChain.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/stopProcess-black.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/purgeChain-black.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/check-black.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/check.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/views/marketplace/types.ts:
--------------------------------------------------------------------------------
1 | export interface Category {
2 | category: string;
3 | pallets: Pallet[];
4 | }
5 |
6 | export interface Pallet {
7 | id: number;
8 | name: string;
9 | description: string;
10 | homepage: string;
11 | github: string;
12 | documentation: string;
13 | icon: string;
14 | version: string;
15 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": "$tsc-watch",
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never"
13 | },
14 | "group": {
15 | "kind": "build",
16 | "isDefault": true
17 | }
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | },
9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10 | "typescript.tsc.autoDetect": "off"
11 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "parserOptions": {
5 | "ecmaVersion": 6,
6 | "sourceType": "module"
7 | },
8 | "plugins": [
9 | "@typescript-eslint"
10 | ],
11 | "rules": {
12 | "@typescript-eslint/class-name-casing": "warn",
13 | "@typescript-eslint/semi": "warn",
14 | "curly": "warn",
15 | "eqeqeq": "warn",
16 | "no-throw-literal": "warn",
17 | "semi": "off"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/resources/home.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/home-black.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/book.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/book-black.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/common/TreeDataProvider.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 |
3 | export abstract class TreeDataProvider implements vscode.TreeDataProvider {
4 | protected _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter();
5 | readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event;
6 |
7 | public refresh(): void {
8 | this._onDidChangeTreeData.fire();
9 | }
10 |
11 | public getTreeItem(element: T): vscode.TreeItem {
12 | return element;
13 | }
14 |
15 | abstract getChildren(element?: T): Thenable;
16 | }
17 |
--------------------------------------------------------------------------------
/resources/startNode.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/runtimes/parseDepsFromFile.ts:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const uniq = require('lodash/fp/uniq');
3 | const matchAll = require('string.prototype.matchall')
4 |
5 | /**
6 | * Given the contents of a Cargo.toml, extract the list of pallet names.
7 | */
8 | function parseDeps(text: string) : string[] {
9 | return uniq(Array.from(matchAll(text, /(pallet-[a-z-A-Z0-9-]+)/g)).map((match: any) => match[1]));
10 | }
11 |
12 | /**
13 | * Given a path to a Cargo.toml, extract the list of pallet names.
14 | */
15 | export default function parseDepsFromFile(file: string) {
16 | return parseDeps(fs.readFileSync(file).toString());
17 | }
--------------------------------------------------------------------------------
/resources/startNode-black.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/compileStartNode.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/compileStartNode-black.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/gear.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/gear-black.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "outDir": "out",
6 | "lib": [
7 | "es2019"
8 | ],
9 | "esModuleInterop": true,
10 | "sourceMap": true,
11 | "rootDir": "src",
12 | "strict": true /* enable all strict type-checking options */
13 | /* Additional Checks */
14 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
15 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
16 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
17 | },
18 | "exclude": [
19 | "node_modules",
20 | ".vscode-test"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/src/processes/Processes.ts:
--------------------------------------------------------------------------------
1 | import { BehaviorSubject} from 'rxjs';
2 | import * as vscode from 'vscode';
3 |
4 | export type Process = {nodePath: string; term: vscode.Terminal; command: string; termCloseHandlerDispose: any;}
5 |
6 | // Manages Substrate processes spawned through the extension
7 | export default class Processes {
8 |
9 | processes$: BehaviorSubject = new BehaviorSubject([] as Process[]);
10 |
11 | new(process: Process) {
12 | this.processes$.next(this.processes$.getValue().concat([process]));
13 | process.termCloseHandlerDispose = vscode.window.onDidCloseTerminal(t => {
14 | if (t === process.term) {
15 | process.termCloseHandlerDispose.dispose();
16 | console.log('Terminal closed; removing process.');
17 | this.del(process);
18 | }
19 | });
20 | }
21 |
22 | del(process: Process) {
23 | this.processes$.next(this.processes$.getValue().filter(p => p != process));
24 | }
25 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "runtimeExecutable": "${execPath}",
13 | "args": [
14 | "--extensionDevelopmentPath=${workspaceFolder}"
15 | ],
16 | "outFiles": [
17 | "${workspaceFolder}/out/**/*.js"
18 | ],
19 | "preLaunchTask": "${defaultBuildTask}"
20 | },
21 | {
22 | "name": "Extension Tests",
23 | "type": "extensionHost",
24 | "request": "launch",
25 | "runtimeExecutable": "${execPath}",
26 | "args": [
27 | "--extensionDevelopmentPath=${workspaceFolder}",
28 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
29 | ],
30 | "outFiles": [
31 | "${workspaceFolder}/out/test/**/*.js"
32 | ],
33 | "preLaunchTask": "${defaultBuildTask}"
34 | }
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | import 'array-flat-polyfill';
2 | import * as vscode from 'vscode';
3 | import { Substrate } from './common/Substrate';
4 | import Nodes from './nodes/Nodes';
5 | import Processes from './processes/Processes';
6 | import { setupAccountsTreeView } from './views/accounts/AccountsProvider';
7 | import { setupContractsTreeView } from './views/contracts/ContractsProvider';
8 | import { setUpMarketplaceTreeView } from './views/marketplace/MarketplaceProvider';
9 | import { setUpNodesTreeView } from './views/nodes/NodesProvider';
10 | import { setupProcessesTreeView } from './views/processes/ProcessesProvider';
11 |
12 | export async function activate(context: vscode.ExtensionContext) {
13 | const substrate = new Substrate(context)
14 |
15 | const nodes = new Nodes();
16 | const processes = new Processes();
17 |
18 | // Set up runtimes
19 | const { selectedNode$ } = setUpNodesTreeView(nodes, processes);
20 |
21 | // Set up marketplace
22 | setUpMarketplaceTreeView(nodes, selectedNode$);
23 |
24 | // Set up processes
25 | const selectedProcess$ = setupProcessesTreeView(substrate, processes);
26 |
27 | // Set up accounts
28 | setupAccountsTreeView(substrate, context);
29 |
30 | // Set up contracts
31 | setupContractsTreeView(substrate, selectedProcess$, context);
32 | }
33 |
34 | export function deactivate() { }
--------------------------------------------------------------------------------
/src/runtimes/Runtime.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import parseDepsFromFile from './parseDepsFromFile';
3 | import { BehaviorSubject } from 'rxjs';
4 | import { startWith, distinctUntilChanged, map } from 'rxjs/operators';
5 | import { vscToObservable } from '../util';
6 | const isEqual = require('lodash/fp/isEqual');
7 | const path = require('path');
8 |
9 | // Manages the auto-detection of a runtime's dependencies
10 | export default class Runtime {
11 |
12 | deps$: BehaviorSubject;
13 |
14 | _watcher: vscode.FileSystemWatcher;
15 |
16 | constructor(public runtimePath: string) {
17 | this._watcher = vscode.workspace.createFileSystemWatcher(
18 | path.join(runtimePath,'Cargo.toml'), true, false, true
19 | );
20 | // Note that moving Cargo.toml around (e.g. removing/adding) will mess up the events.
21 | // TODO listen to all three events? Probably sounder.
22 | const fileChange$ = vscToObservable(this._watcher.onDidChange.bind(this._watcher));
23 |
24 | this.deps$ = new BehaviorSubject([] as string[]);
25 | fileChange$
26 | .pipe(
27 | startWith(null),
28 | map(() => parseDepsFromFile(path.join(runtimePath,'Cargo.toml'))),
29 | distinctUntilChanged(isEqual)
30 | ).subscribe(this.deps$);
31 | }
32 |
33 | dispose() {
34 | this._watcher.dispose(); // can Runtime still be garbage collected?
35 | // todo use setinterval unref to check if old runtime gets gc'd
36 | }
37 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## DEPRECATION NOTICE
2 |
3 | This repo is not supported anymore. There are no replacement.
4 |
5 | # Substrate - VSCode extension
6 |
7 | Manage your node, runtime, browse and install pallets, manage your accounts and your smart contracts within VSCode.
8 |
9 | A complete list of features and walkthrough is available in [this document](./docs/features.md).
10 |
11 | Visit the extension's page on Visual Studio Marketplace: https://marketplace.visualstudio.com/items?itemName=paritytech.vscode-substrate
12 |
13 | 
14 |
15 | This extension is work in progress and is in active development. Please [report](https://github.com/paritytech/vscode-substrate/issues/new) any issues you encounter.
16 |
17 | ## Installation
18 |
19 | Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
20 |
21 | ```
22 | ext install paritytech.vscode-substrate
23 | ```
24 |
25 | Alternatively, search for "VSCode Substrate" in the extension marketplace.
26 |
27 | ## Development
28 |
29 | Clone, run `yarn` to install the dependencies, open the folder in VSCode, run the command "Debug: Start Debugging" to launch a new VSCode instance with the extension running.
30 |
31 | ## Publish
32 |
33 | Bump the version in `package.json`, tag your commit with the version number (`vX.X.X`) and push. This will trigger the GitHub Action and publish the new version on VSCode Marketplace as well as create a new release on GitHub. Release information can be edited manually and added to CHANGELOG.md
34 |
--------------------------------------------------------------------------------
/src/views/marketplace/substrateDeps.ts:
--------------------------------------------------------------------------------
1 |
2 | const child_process = require('child_process');
3 | import * as vscode from 'vscode';
4 | import { resolveWhenTerminalClosed } from '../../util';
5 |
6 | /**
7 | * Ensures that substrate-deps is installed; installs it otherwise.
8 | *
9 | * @return A promise that always resolves; either with true in case substrate-deps
10 | * is or got installed; false otherwise.
11 | */
12 | export async function substrateDepsInstalled(): Promise {
13 | try {
14 | child_process.execSync('substrate-deps --version');
15 | return true;
16 | } catch (e) {
17 | const clicked = await vscode.window.showWarningMessage(
18 | `substrate-deps is required for this extension to work but doesn't seem to be installed. Install it? This will run the following command: 'cargo install substrate-deps'`,
19 | { modal: true },
20 | 'Yes'
21 | );
22 |
23 | if (clicked !== 'Yes') {
24 | return false;
25 | }
26 |
27 | const term = vscode.window.createTerminal('Installing substrate-deps');
28 | term.sendText('cargo install substrate-deps && exit');
29 | term.show();
30 |
31 | await resolveWhenTerminalClosed(term);
32 |
33 | if (term.exitStatus?.code === 0) {
34 | vscode.window.showInformationMessage(`substrate-deps was successfully installed.`);
35 | return substrateDepsInstalled();
36 | } else {
37 | console.error('Terminal is closed; should have exit status; qed.')
38 | return false;
39 | }
40 |
41 | // TODO if users runs this function again with a terminal already running, we have two listeners, this is bad.
42 | }
43 | }
--------------------------------------------------------------------------------
/resources/substrate.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | # Sequence of patterns matched against refs/tags
4 | tags:
5 | - 'v[0-9]+.[0-9]+.[0-9]+'
6 |
7 | name: Upload Release Asset
8 |
9 | jobs:
10 | build:
11 | name: Upload Release Asset
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout code
15 | uses: actions/checkout@v2
16 | - name: Use Node.js 12.8.1
17 | uses: actions/setup-node@v1
18 | with:
19 | node-version: '12.8.1'
20 | - name: Build extension package
21 | run: |
22 | npm install
23 | npx vsce package -o vscode-substrate.vsix
24 | - name: Publish Extension to Visual Studio Marketplace
25 | run: npx vsce publish --pat ${{ secrets.MARKETPLACE_TOKEN }} --packagePath ./vscode-substrate.vsix
26 | - name: Create GitHub Release
27 | id: create_release
28 | uses: actions/create-release@v1
29 | env:
30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31 | with:
32 | tag_name: ${{ github.ref }}
33 | release_name: ${{ github.ref }}
34 | draft: false
35 | prerelease: false
36 | - name: Upload Release Asset
37 | id: upload-release-asset
38 | uses: actions/upload-release-asset@v1
39 | env:
40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41 | with:
42 | upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing its ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
43 | asset_path: ./vscode-substrate.vsix
44 | asset_name: vscode-substrate.vsix
45 | asset_content_type: application/vsix
--------------------------------------------------------------------------------
/src/util.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { Observable } from 'rxjs';
3 |
4 | const path = require('path');
5 |
6 | export function resolveWhenTerminalClosed(term: vscode.Terminal): Promise {
7 | return new Promise((resolve, reject) => {
8 | const disp = vscode.window.onDidCloseTerminal(t => {
9 | if (t === term) {
10 | disp.dispose();
11 | resolve();
12 | }
13 | });
14 | });
15 | }
16 |
17 | export function vscToObservable(fn: (arg0: ((x: T) => any)) => any): Observable {
18 | return new Observable((subscriber) => {
19 | return fn((x: T) => subscriber.next(x));
20 | });
21 | }
22 |
23 | // Convert a full path to a human-friendly shorter path to display
24 | export function tryShortname(fullPath: string) {
25 | const fsPaths = vscode.workspace.workspaceFolders?.map((x) => x.uri.fsPath) || [];
26 | if (fsPaths.length !== 1) return fullPath;
27 | return path.relative(fsPaths[0], fullPath);
28 | }
29 |
30 | export async function showInputBoxValidate(options: vscode.InputBoxOptions, validateFn: (x: any) => Promise) {
31 | do {
32 | const a = await vscode.window.showInputBox(options);
33 | if (a === undefined)
34 | return a;
35 | else {
36 | let err = await validateFn(a);
37 | if (err !== '')
38 | vscode.window.showErrorMessage(err);
39 | else
40 | return a;
41 | }
42 | } while (true);
43 | }
44 |
45 | const INSTANCE = process.env.SUBSTRATE_PLAYGROUND_INSTANCE;
46 | const HOST = process.env.SUBSTRATE_PLAYGROUND_HOSTNAME;
47 |
48 | export function wsEndpointFromCommand(command: string) {
49 | const port = command.match(/--ws-port[ =]\d+/)?.[0] || '9944';
50 | const wsEndpoint = INSTANCE ? `wss://${INSTANCE}.${HOST}${port !== '9944' ? `:${port}` : ''}/wss` : `ws://127.0.0.1:${port}/`;
51 | return wsEndpoint;
52 | }
--------------------------------------------------------------------------------
/src/views/marketplace/fetchCategories.ts:
--------------------------------------------------------------------------------
1 | import fetch from 'node-fetch';
2 | const flow = require('lodash/fp/flow');
3 | const get = require('lodash/fp/get');
4 | const invoke = require('lodash/fp/invoke');
5 | const isEqual = require('lodash/fp/isEqual');
6 | const map = require('lodash/fp/map');
7 | const remove = require('lodash/fp/remove');
8 |
9 | import { Category, Pallet } from './types';
10 | import { GRAPHQL_API_ENDPOINT } from '../../constants';
11 |
12 | /**
13 | * Executes the given GraphQL query on the Marketplace endpoint, returns
14 | * the deserialized response value
15 | *
16 | * @returns {Promise} A resolved promise with the deserialized response in
17 | * case of success; a rejected promise with the error message in case the
18 | * request failed or the response payload indicates an error.
19 | */
20 | const gq = (query: string) => (variables?: object): Promise =>
21 | fetch(
22 | GRAPHQL_API_ENDPOINT,
23 | {
24 | method: 'POST',
25 | headers: {
26 | 'Accept': 'application/json',
27 | 'Content-Type': 'application/json'
28 | },
29 | body: JSON.stringify({
30 | query,
31 | variables
32 | })
33 | }
34 | )
35 | .then(invoke('json'))
36 | .then((d: any) => d.data || Promise.reject(map('message')(d.errors)));
37 |
38 | /**
39 | * Fetches all the pallets for a given Marketplace category.
40 | */
41 | const fetchPallets = (category: string): Promise =>
42 | gq(`query($category: String!){
43 | search(type: PALLET query: "" category: $category) {
44 | results {
45 | ...on Pallet {
46 | id
47 | name
48 | description
49 | documentation
50 | homepage
51 | github: repository
52 | icon
53 | version
54 | repository
55 | }
56 | }
57 | }
58 | }`)({ category })
59 | .then(
60 | get('search.results'),
61 | );
62 |
63 | /**
64 | * Fetches a category with all its pallets.
65 | */
66 | const fetchCategory = (category: string): Promise =>
67 | fetchPallets(category).then((pallets: Pallet[]) => ({ category, pallets }))
68 |
69 | /**
70 | * Fetches the list of all categories and their pallets.
71 | */
72 | const fetchCategories = (): Promise =>
73 | gq('{ marketplaceCategories(type:PALLET) {name} }')()
74 | .then(flow(
75 | get('marketplaceCategories'),
76 | map('name'),
77 | remove(isEqual('tutorial')),
78 | map(fetchCategory),
79 | Promise.all.bind(Promise)
80 | ));
81 | export default fetchCategories;
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## v0.5.1
4 | * Remove Getting Started (Substrate Playground)
5 | * Remove Tasks
6 | * Remove built-in default process
7 |
8 | ## v0.5.0
9 | * Smart contracts and accounts support
10 |
11 | ## v0.4.11
12 | * "Purge chain" will run the binary directly (instead of potentially recompiling); same for "Start node".
13 | * Add command "Compile & start node" that behaves like "Start node" previously, i.e. using "cargo run".
14 |
15 | ## v0.4.10
16 | * Playground: Fix ws endpoint for apps
17 |
18 | ## v0.4.9
19 | * Add "Getting started" command
20 |
21 | ## v0.4.8
22 | * Fix icons for light theme
23 | * Always show marketplace treeview, even when no node is selected
24 | * Playground: don't show Getting Started when a file is already opened
25 |
26 | ## v0.4.7
27 | * Playground: fix for Workspace tasks.
28 |
29 | ## v0.4.6
30 | * Workspace tasks (tasks defined by the template) are now listed in a treeview
31 |
32 | ## v0.4.5
33 | * Playground: add Polkadot Apps link
34 | * Ask user for flags when launching node
35 |
36 | ## v0.4.4
37 | * List running nodes
38 |
39 | ## v0.4.3
40 | * The start node command now compiles in release mode.
41 |
42 | ## v0.4.2
43 | * Retain Getting started view in cache when the tab loses focus
44 |
45 | ## v0.4.1
46 | * Lint
47 |
48 | ## v0.4.0
49 | * Reorganized UI : now shows the list of nodes in the workspace. The marketplace is based on the runtime of the selected node.
50 | * Node commands accessible in the Command Palette.
51 |
52 | ## v0.3.4
53 | * Fix commands "Start node" and "Purge chain"
54 | * Remove playground-specific commands
55 |
56 | ## v0.3.2
57 | * Fix Playground detection
58 | * Fix pallets GitHub target
59 |
60 | ## v0.3.1
61 | * Marketplace is now loaded on startup
62 | * Selected runtime now highlighted
63 | * Fix parsing runtime pallets
64 |
65 | ## v0.3.0
66 | * Support multiple nodes
67 | * Execute operations on the selected node
68 | * Runtime is selected by user and isn't based on the active editor's path any longer.
69 |
70 | ## v0.2.0
71 | * Support multiple runtimes in the same workspace. Your active editor will determine the runtime used by the extension.
72 | * Display installed pallets.
73 | * Removed setting `substrateMarketplace.runtimeManifestPath` & removed Substrate Playground hardcoded path. Runtimes are now detected and updated automatically.
74 |
75 | ## v0.1.1
76 | * Your project's runtime manifest location can now be provided using the `substrateMarketplace.runtimeManifestPath` setting.
77 | * If this setting is not provided, the extension will try to use `./runtime/Cargo.toml` or `./Cargo.toml`.
--------------------------------------------------------------------------------
/src/nodes/Nodes.ts:
--------------------------------------------------------------------------------
1 | import { BehaviorSubject, merge, of } from 'rxjs';
2 | import { map, tap, throttleTime } from 'rxjs/operators';
3 | import * as vscode from 'vscode';
4 | import parseDepsFromFile from '../runtimes/parseDepsFromFile';
5 | import { vscToObservable } from '../util';
6 |
7 | const path = require('path');
8 | const fs = require('fs');
9 | const glob = require('glob');
10 |
11 | /**
12 | * Given a folder path, return a list of substrate nodes contained inside.
13 | */
14 | const findNodesInFolder = (roots: string): string[] => {
15 | // TODO use vscode.workspace.findFiles instead
16 | return glob.sync(path.join(roots, '**/Cargo.toml'), { ignore: '**/node_modules/**' }).filter((b: string) => {
17 | return fs.readFileSync(b).toString().includes('[[bin]]')
18 | }).map((nodeRs: string) => path.dirname(nodeRs)); // (todo transducers)
19 | }
20 |
21 | const findNodesInWorkspace = () => {
22 | return vscode.workspace.workspaceFolders?.map((x) => x.uri.fsPath).map(root => {
23 | return findNodesInFolder(root);
24 | }).flat() || [];
25 | }
26 |
27 | export type Node = {nodePath: string; runtimePath?: string; deps?: any[]}
28 |
29 | // Manages the auto-detection of nodes in the current workspace
30 | export default class Nodes {
31 |
32 | nodes$: BehaviorSubject;
33 |
34 | constructor() {
35 | // TODO add to the deactivate function of extension.ts? Not sure if vscode
36 | // does this automatically. Evtl add a dispose() function to the class.
37 | const watcher = vscode.workspace.createFileSystemWatcher('**/Cargo.toml');
38 |
39 | const nodesPath$ = merge(
40 | // Scan on startup
41 | of(null),
42 | // Scan on file changes involving build.rs
43 | merge(
44 | vscToObservable(watcher.onDidChange.bind(watcher)),
45 | vscToObservable(watcher.onDidCreate.bind(watcher)),
46 | vscToObservable(watcher.onDidDelete.bind(watcher))
47 | ).pipe(throttleTime(100)) // e.g. in case of renaming folders, we receive a delete + added event.
48 | ).pipe
49 | (
50 | map(() => findNodesInWorkspace()),
51 | // tap(r => console.log('Found nodes',r))
52 | ); // TODO have a rescan button
53 |
54 | this.nodes$ = new BehaviorSubject([]);
55 |
56 | nodesPath$.pipe(
57 | map(nodePaths => {
58 | return nodePaths.map(nodePath => {
59 | try{
60 | const cargoToml = fs.readFileSync(path.join(nodePath, 'Cargo.toml')).toString(); // TODO ASYNC
61 | const matches = cargoToml.match(/^(?:[^#].*)?path ?= ?"([a-zA-Z./-]*runtime[a-zA-Z./-]*)"|^(?:[^#].*)?path ?= ?'([a-zA-Z./-]*runtime[a-zA-Z./-]*)'/m)
62 | if (matches === null)
63 | return {nodePath} as Node;
64 | else {
65 | // Important that this be called on any dep change (Cargo.toml)
66 | const runtimePath = path.join(nodePath, matches[1] || matches[2]);
67 |
68 | return {
69 | nodePath,
70 | runtimePath: runtimePath,
71 | deps: parseDepsFromFile(path.join(runtimePath, 'Cargo.toml'))
72 | } as Node;
73 | }
74 | } catch (e) { console.error('error',e); return {nodePath: ''} }
75 | });
76 | }),
77 | // tap(r => console.log('Found nodes infos', r))
78 | ).subscribe(this.nodes$);
79 | this.nodes$.subscribe(x => {});
80 | }
81 | }
--------------------------------------------------------------------------------
/resources/github.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/github-black.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/views/processes/ProcessesProvider.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { BehaviorSubject, of, combineLatest } from 'rxjs';
3 | import { tryShortname, wsEndpointFromCommand } from '../../util';
4 | import { switchMap, tap, distinctUntilChanged } from 'rxjs/operators';
5 | import Nodes, {Node} from '../../nodes/Nodes';
6 | import Processes, { Process } from '../../processes/Processes';
7 | import { Substrate } from '../../common/Substrate';
8 |
9 | export class ProcessesProvider implements vscode.TreeDataProvider {
10 | ProcessTreeItems: ProcessTreeItem[] = [];
11 |
12 | private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter();
13 | readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event;
14 |
15 | constructor(processes: Processes) {
16 | processes.processes$.subscribe((processes: Process[]) => {
17 | this.ProcessTreeItems = processes.map((process: Process) => {
18 | return new ProcessTreeItem(process);
19 | });
20 |
21 | this._onDidChangeTreeData.fire();
22 | });
23 | }
24 |
25 | getTreeItem(element: ProcessTreeItem): ProcessTreeItem | Thenable {
26 | return element;
27 | }
28 |
29 | getChildren(element?: ProcessTreeItem | undefined): vscode.ProviderResult {
30 | if (element === undefined) {
31 | return this.ProcessTreeItems;
32 | }
33 | return element.children;
34 | }
35 | }
36 |
37 | const isTheia = process.env.SUBSTRATE_PLAYGROUND !== undefined;
38 |
39 | export class ProcessTreeItem extends vscode.TreeItem {
40 | children: undefined;
41 | process: Process;
42 |
43 | constructor(process: Process) {
44 | const { nodePath, command } = process;
45 | super(
46 | tryShortname(nodePath) + ' • ' + command,
47 | vscode.TreeItemCollapsibleState.None);
48 | this.process = process;
49 | this.command = {
50 | command: "substrate.selectProcess",
51 | title: "Select Process",
52 | arguments: [this]
53 | };
54 |
55 | this.contextValue = isTheia ? 'theia' : 'vscode'
56 | }
57 | }
58 |
59 |
60 | async function quickPickProcesses(_processes: Processes) {
61 | let processes = _processes.processes$.getValue();
62 |
63 | if (processes.length === 1)
64 | return processes[0];
65 |
66 | if (processes.length === 0) {
67 | vscode.window.showErrorMessage('No node was found in the workspace.');
68 | return Promise.reject();
69 | }
70 |
71 | const processesReadable = processes.map(n => tryShortname(n.nodePath));
72 |
73 | const pick = await vscode.window.showQuickPick(processesReadable, { placeHolder: "Please choose a node." });
74 | if (pick === undefined)
75 | return Promise.reject();
76 |
77 | return processes[processesReadable.findIndex(x => x === pick)];
78 | }
79 |
80 | const INSTANCE = process.env.SUBSTRATE_PLAYGROUND_INSTANCE;
81 | const HOST = process.env.SUBSTRATE_PLAYGROUND_HOSTNAME;
82 |
83 | export function setupProcessesTreeView(substrate: Substrate, processes: Processes) {
84 |
85 | vscode.commands.registerCommand("substrate.polkadotApps", async (processTreeItem?: ProcessTreeItem) => {
86 | const process = processTreeItem?.process || await quickPickProcesses(processes);
87 |
88 | const port = process.command.match(/--ws-port[ =]\d+/)?.[0] || '9944';
89 | const wsEndpoint = `wss://${INSTANCE}.${HOST}${port !== '9944' ? `:${port}` : ''}/wss`;
90 | const apps = `https://polkadot.js.org/apps/?rpc=${wsEndpoint}`;
91 | vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(apps));
92 | });
93 |
94 | const selectedProcess$ = new BehaviorSubject(null);
95 | vscode.commands.registerCommand("substrate.selectProcess", async (processTreeItem: ProcessTreeItem) => {
96 | selectedProcess$.next((processTreeItem as any).process || null);
97 | processTreeItem.process.term.show();
98 | });
99 |
100 | vscode.commands.registerCommand("substrate.stopProcess", async (processTreeItem?: ProcessTreeItem) => {
101 | const process = processTreeItem?.process || await quickPickProcesses(processes);
102 | processes.del(process);
103 | process.term.sendText('\x03');
104 | process.term.sendText('exit 0');
105 | });
106 |
107 | const treeDataProvider = new ProcessesProvider(processes);
108 | const treeView = vscode.window.createTreeView('substrateProcesses', { treeDataProvider });
109 |
110 | processes.processes$.subscribe((processes: Process[]) => {
111 | if (processes.length === 0 && isTheia)
112 | treeView.message = `No node is currently running.`;
113 | else
114 | treeView.message = undefined;
115 |
116 | if (!processes.find(process => process === selectedProcess$.getValue()))
117 | selectedProcess$.next(null);
118 |
119 |
120 | });
121 |
122 | selectedProcess$.pipe(distinctUntilChanged()).subscribe(process => {
123 | if (!process)
124 | substrate.disconnect();
125 | else {
126 | substrate.connectTo(wsEndpointFromCommand(process.command));
127 | }
128 | });
129 |
130 | return selectedProcess$;
131 | }
--------------------------------------------------------------------------------
/docs/features.md:
--------------------------------------------------------------------------------
1 | # Features
2 |
3 | - [Features](#features)
4 | * [1. Workspace actions](#1-workspace-actions)
5 | + [1.1 Run workspace actions](#11-run-workspace-actions)
6 | * [2. Node actions](#2-node-actions)
7 | + [2.1 Compile & run a node](#21-compile---run-a-node)
8 | + [2.2 Run an already compiled node](#22-run-an-already-compiled-node)
9 | + [2.3 Kill a process](#23-kill-a-process)
10 | + [2.4 Purge a node's chain](#24-purge-a-node-s-chain)
11 | * [3. Runtime actions](#3-runtime-actions)
12 | + [3.1 Get information on installed pallets](#31-get-information-on-installed-pallets)
13 | + [3.2 Add a new pallet](#32-add-a-new-pallet)
14 | * [4. Account management](#4-account-management)
15 | + [4.1 Import an account](#41-import-an-account)
16 | + [4.2 Import an account from JSON](#42-import-an-account-from-json)
17 | + [4.3 Generate a new account](#43-generate-a-new-account)
18 | + [4.4 Rename, copy address, export, remove account](#44-rename--copy-address--export--remove-account)
19 | * [5. Contracts](#5-contracts)
20 | + [5.1 Compile & deploy a contract](#51-compile---deploy-a-contract)
21 | + [5.2 Call a contract method](#52-call-a-contract-method)
22 | + [5.3 Copy hash, forget contract](#53-copy-hash--forget-contract)
23 |
24 | Access the extension's features by clicking the "Substrate" icon to the left.
25 |
26 | 
27 |
28 | ## 1. Workspace actions
29 | ### 1.1 Run workspace actions
30 | The extension will detect all VSCode actions provided in your workspace folders and list them under the "Actions" panel. Hover over an action and click the "Execute" icon to the right to run it.
31 |
32 | 
33 |
34 | ## 2. Node actions
35 | ### 2.1 Compile & run a node
36 | The extension will detect all nodes (binary Rust projects) in the workspace and list them in the "Nodes" panel. To compile and run a node, hover over the node in the list and click the corresponding icon. The new process will be listed under "Processes" and a new terminal will be opened with the process's ouput.
37 |
38 | 
39 |
40 | ### 2.2 Run an already compiled node
41 | If you have already compiled the node and which to run it again without compiling the new changes, click the "Start node" button. The new process will be listed under "Processes" and a new terminal will be opened with the process's ouput.
42 |
43 | 
44 |
45 | ### 2.3 Kill a process
46 | Once a node is running, you can exit it by clicking the "Stop process" icon.
47 |
48 | 
49 |
50 | ### 2.4 Purge a node's chain
51 | You can purge the chain of an already compiled node by clicking the "Purge chain" icon.
52 |
53 | 
54 |
55 | ## 3. Runtime actions
56 |
57 | ### 3.1 Get information on installed pallets
58 | First, select a node.
59 |
60 | 
61 |
62 | The runtime used by this node will be automatically detected and displayed in the "Marketplace" panel. The "Marketplace" panel will then list all pallets available, and add a checkmark next to those that are used by the runtime of the selected node. Hover over each pallet to get access to their homepage, documentation page and GitHub page.
63 |
64 | ### 3.2 Add a new pallet
65 | To add a pallet as a dependency of the runtime, click the "Add pallet" icon. This will install the pallet using the tool `substrate-deps`, installing it if necessary.
66 |
67 | 
68 |
69 | ## 4. Account management
70 | Please note that this extension's account management features are meant to be used for testing/development purposes only. The accounts are persisted across restarts.
71 |
72 | ### 4.1 Import an account
73 | To add an account, hover over the "Accounts" bar and click the "+" icon. You will then be asked for a human-friendly name, cryptographic type and the key to the account.
74 |
75 | 
76 |
77 | ### 4.2 Import an account from JSON
78 | You can also import an account from a JSON file by clicking on the "Next actions" icon next to the "+" icon, then choosing "Import account from JSON."
79 |
80 | 
81 |
82 | ### 4.3 Generate a new account
83 | You can also generate a new account with a random seed by clicking "Generate new account".
84 |
85 | 
86 |
87 | ### 4.4 Rename, copy address, export, remove account
88 | By right-clicking an account, you can rename it, copy its address, export it as a JSON file, or remove the account from the list.
89 |
90 | 
91 |
92 | ## 5. Contracts
93 | Contracts are persisted across restarts and are linked to a WebSocket endpoint (host and port). You need to have added an account in the extension in order to be able to deploy a contract.
94 |
95 | ### 5.1 Compile & deploy a contract
96 | Select a running process. This will list the contracts you already added to this endpoint in the extension (if any).
97 |
98 | 
99 |
100 | You can compile an __ink!__ project, upload its WASM code and instantiate the contract with one click by clicking the "..." icon after hovering over "Contracts", and then selecting "Compile & deploy contract". You will then be asked for the location of your __ink!__ project, a human-friendly name for the contract, the account (see section 4) with which to upload the WASM & deploy the contract, its password, the constructor to use when instantiating the contract, if necessary its arguments, the endowment and maximum amount of gas for the deployment. The contract will then be listed in the "Contracts" panel.
101 |
102 | 
103 |
104 | ### 5.2 Call a contract method
105 | Right-click a contract and click "Call contract method". You will then be asked various information and be informed of the progress of the transaction.
106 |
107 | 
108 |
109 | ### 5.3 Copy hash, forget contract
110 | By right-clicking a contract, you can also copy its hash or remove the contract from the list.
111 |
112 | 
--------------------------------------------------------------------------------
/src/common/Substrate.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { Keyring } from '@polkadot/keyring';
3 | import { KeyringPair$Json } from '@polkadot/keyring/types';
4 | import { KeypairType } from '@polkadot/util-crypto/types';
5 | import { ApiPromise, WsProvider } from '@polkadot/api';
6 | const fs = require('fs');
7 |
8 | export type Contracts = { [index: string]: Contract[] };
9 |
10 | export type Contract = { name: string, address: string, abiJson: any };
11 |
12 | // Manages API connection and extension storage (accounts, contracts)
13 | export class Substrate {
14 | private keyring = new Keyring({ type: 'sr25519' });
15 | private api?: ApiPromise;
16 | private wsEndpoint?: string;
17 |
18 | getConnection(): ApiPromise | undefined {
19 | return this.api;
20 | }
21 |
22 | constructor(
23 | // Necessary to access the extension's persistent storage
24 | private context: vscode.ExtensionContext
25 | ) { }
26 |
27 | async connectTo(wsEndpoint: string) {
28 | this.disconnect();
29 | this.wsEndpoint = wsEndpoint;
30 | const api = new ApiPromise({provider: new WsProvider(wsEndpoint)});
31 | await api.isReady;
32 | this.api = api;
33 | }
34 |
35 | async disconnect() {
36 | if (this.api) {
37 | this.api!.disconnect();
38 | }
39 | this.wsEndpoint = undefined;
40 | this.api = undefined;
41 | }
42 |
43 | getAccounts(): KeyringPair$Json[] {
44 | const accounts = this.context.globalState.get('accounts');
45 | if (!accounts) {
46 | return [];
47 | }
48 | return JSON.parse(accounts);
49 | }
50 |
51 | getKeyring(): Keyring {
52 | return this.keyring;
53 | }
54 |
55 | // Verify if an account with the given name exists
56 | isAccountExists(name: string): boolean {
57 | const result = this.getAccounts();
58 | const exKey = result.find((val) => val.meta.name === name);
59 | if (!exKey) {
60 | return false;
61 | }
62 | return true;
63 | }
64 |
65 | // Replace all accounts with new accounts list
66 | async updateAccounts(accounts: KeyringPair$Json[]) {
67 | await this.context.globalState.update('accounts', JSON.stringify(accounts));
68 | }
69 |
70 | async createKeyringPair(key: string, name: string, type: KeypairType) {
71 | const pair = this.keyring.addFromUri(key, { name }, type);
72 | const accounts = this.getAccounts();
73 | accounts.push(pair.toJson());
74 | await this.updateAccounts(accounts);
75 | }
76 |
77 | async createKeyringPairWithPassword(key: string, name: string, type: KeypairType, pass: string) {
78 | const pair = this.keyring.addFromUri(key, { name }, type);
79 |
80 | const json = pair.toJson(pass);
81 | json.meta.whenEdited = Date.now();
82 |
83 | const accounts = this.getAccounts();
84 | accounts.push(json);
85 | await this.updateAccounts(accounts);
86 | }
87 |
88 | // Forget an account
89 | async removeAccount(name: string) {
90 | const accounts = this.getAccounts();
91 | const index = accounts.findIndex((val) => val.meta['name'] === name);
92 | accounts.splice(index, 1);
93 | await this.updateAccounts(accounts);
94 | }
95 |
96 | async renameAccount(oldName: string, newName: string) {
97 | const accounts = this.getAccounts();
98 | for (const account of accounts) {
99 | if (account.meta['name'] === oldName) {
100 | account.meta['name'] = newName;
101 | break;
102 | }
103 | }
104 | await this.updateAccounts(accounts);
105 | }
106 |
107 | // Import a new keyring pair globally
108 | // @TODO Keyring pairs are currently global, maybe scope them?
109 | async importKeyringPair(path: string) {
110 | const rawdata = fs.readFileSync(path);
111 | const pair: KeyringPair$Json = JSON.parse(rawdata.toString());
112 | if (this.isAccountExists(pair.meta['name'] as string)) {
113 | vscode.window.showWarningMessage('Account with same key already exists. Account not added');
114 | return;
115 | }
116 | const accounts = this.getAccounts();
117 | accounts.push(pair);
118 | await this.updateAccounts(accounts);
119 | }
120 |
121 | // Get the list of contracts for the current endpoint
122 | getConnectionContracts() : any[] {
123 | if (!this.wsEndpoint) return [];
124 | const contractCodes = this.getContracts();
125 | // @TODO Contracts are currently scoped to a websocket endpoint
126 | // We could use better heuristics instead
127 | const nodeContractCodes = contractCodes[this.wsEndpoint] || [];
128 | return nodeContractCodes;
129 | }
130 |
131 | // Get the list of all contracts for all endpoints
132 | getContracts() {
133 | const contractsString = this.context.globalState.get('contracts');
134 | if (!contractsString) {
135 | return {};
136 | }
137 | return JSON.parse(contractsString);
138 | }
139 |
140 | // Add a new contract for the current endpoint
141 | async saveContract(contractName: string, contractAddress: string, abiJson: any) {
142 | const contracts = this.getConnectionContracts();
143 | const existingContract = contracts.find(
144 | contract => contract.name === contractName || contract.address === contractAddress
145 | );
146 | if (existingContract) {
147 | existingContract.name = contractName;
148 | existingContract.address = contractAddress;
149 | existingContract.abiJson = abiJson;
150 | } else {
151 | contracts.push({
152 | name: contractName,
153 | address: contractAddress,
154 | abiJson: abiJson,
155 | });
156 | }
157 | await this.updateConnectionContracts(contracts);
158 | }
159 |
160 | // Update contracts for the current endpoint
161 | async updateConnectionContracts(codes: Contract[]) {
162 | const connectedNode = this.wsEndpoint;
163 | if (!connectedNode) {
164 | throw Error('Not connected to node');
165 | }
166 | const contracts = this.getContracts();
167 | contracts[connectedNode] = codes;
168 | await this.updateContracts(contracts);
169 | }
170 |
171 | async updateContracts(codes: Contracts) {
172 | await this.context.globalState.update('contracts', JSON.stringify(codes));
173 | await vscode.commands.executeCommand('substrate.refreshContracts'); // Refresh TreeView
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/src/views/marketplace/MarketplaceProvider.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { BehaviorSubject } from 'rxjs';
3 | import fetchCategories from './fetchCategories';
4 | import { substrateDepsInstalled } from './substrateDeps';
5 | import { Category, Pallet } from './types';
6 | import Nodes, { Node } from '../../nodes/Nodes';
7 | import { tryShortname } from '../../util';
8 |
9 | const path = require('path');
10 |
11 | type TreeItem = TreePallet | TreeCategory;
12 |
13 | export class TreeDataProvider implements vscode.TreeDataProvider {
14 | treeCategories: TreeCategory[];
15 |
16 | private _selectedNode$: any;
17 |
18 | private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter();
19 | readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event;
20 |
21 | constructor(data: any, selectedNode$: BehaviorSubject) {
22 | this.treeCategories = data.map((category: any) => {
23 | return new TreeCategory(category, category.pallets.map(TreePallet.create.bind(TreePallet)));
24 | });
25 |
26 | this._selectedNode$ = selectedNode$;
27 |
28 | // TODO Reinstantiating all pallets would be cleaner (shared logic when instantiating)
29 | selectedNode$.subscribe((node) => {
30 | this.treeCategories.forEach(treeCategory => {
31 | treeCategory.children?.forEach(treePallet => {
32 | treePallet.contextValue = node && node.deps && node.deps.includes(treePallet.name)
33 | ? 'palletInstalled' // TODO work from a single source of truth and have a clear mapping instead (see above comment); pure functions
34 | : node ? 'pallet' : 'palletNoNode';
35 | treePallet.iconPath = treePallet.contextValue === 'palletInstalled' ? path.join(__filename, '..', '..', '..', '..', 'resources', 'check.svg') : false;
36 | });
37 | });
38 | this._onDidChangeTreeData.fire();
39 | });
40 | }
41 |
42 | getTreeItem(element: TreeCategory): TreeCategory | Thenable {
43 | return element;
44 | }
45 |
46 | getChildren(element?: TreeItem | undefined): vscode.ProviderResult {
47 | if (element === undefined) {
48 | return this.treeCategories;
49 | }
50 | return element.children;
51 | }
52 | }
53 |
54 | export class TreeCategory extends vscode.TreeItem {
55 | children: TreePallet[] | undefined;
56 |
57 | constructor(info: Category, children?: TreePallet[]) {
58 | const { category: label } = info;
59 | super(
60 | label,
61 | children === undefined ? vscode.TreeItemCollapsibleState.None :
62 | vscode.TreeItemCollapsibleState.Expanded);
63 | this.children = children;
64 | this.contextValue = 'category';
65 | }
66 | }
67 |
68 | export class TreePallet extends vscode.TreeItem {
69 | children: TreeItem[] | undefined;
70 | name: string;
71 | github: string;
72 | documentation: string;
73 | homepage: string;
74 |
75 | static create(info: Pallet) {
76 | return new this(info);
77 | }
78 |
79 | constructor(info: Pallet) {
80 | const { name, description, github, documentation, homepage } = info;
81 | super(
82 | name,
83 | vscode.TreeItemCollapsibleState.None);
84 | this.name = name;
85 | this.description = description;
86 | this.tooltip = `${name} - ${description}`;
87 | this.contextValue = 'palletNoNode';
88 | this.github = github;
89 | this.documentation = documentation;
90 | this.homepage = homepage;
91 | }
92 | }
93 |
94 | type NodePath = string | null;
95 | export function setUpMarketplaceTreeView(nodes: Nodes, selectedNode$: BehaviorSubject) {
96 | fetchCategories().then((categories: Category[]) => {
97 | const treeView = vscode.window.createTreeView('substrateMarketplace', { treeDataProvider: new TreeDataProvider(categories, selectedNode$) });
98 | selectedNode$.subscribe((node) => {
99 | if (node && node.runtimePath)
100 | treeView.message = `Runtime: ${tryShortname(node.runtimePath)}`;
101 | else
102 | treeView.message = `No node selected`;
103 | });
104 |
105 | // Set up commands: documentation, github, homepage
106 | ([
107 | { command: 'substrateMarketplace.palletDocumentation', name: 'Documentation', property: 'documentation' },
108 | { command: 'substrateMarketplace.palletGithub', name: 'GitHub page', property: 'github' },
109 | { command: 'substrateMarketplace.palletHomepage', name: 'Homepage', property: 'homepage' }
110 | ] as const).forEach(({ command, name, property }) => {
111 | vscode.commands.registerCommand(command, (item: TreePallet) => {
112 | if (!item[property].startsWith('http')) { // Also acts as a safeguard
113 | vscode.window.showErrorMessage(`${name} is unavailable for this pallet.`);
114 | return;
115 | }
116 | vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(item[property]));
117 | });
118 | });
119 |
120 | // Set up command: install
121 | vscode.commands.registerCommand("substrateMarketplace.installPallet", async (item: vscode.TreeItem) => {
122 | // Install substrate-deps if needed
123 | if (!await substrateDepsInstalled()) {
124 | return;
125 | }
126 |
127 | // Verify pallet name to prevent shell injection & derive alias
128 | const palletName = item.label as string;
129 | if (!/^[a-z-]+$/.test(palletName)) {
130 | vscode.window.showErrorMessage('Pallet name is invalid.');
131 | return;
132 | }
133 | const alias = (alias => alias === palletName ? null : alias)(palletName.replace(/^pallet-/, ''));
134 |
135 | // Ask for user confirmation
136 | // TODO Indicate current runtime in the message in case we have more than
137 | // one runtime in the workspace.
138 | const clicked = await vscode.window.showInformationMessage(`Install the pallet ${palletName}?`, { modal: true }, 'Yes');
139 | if (clicked !== 'Yes') {
140 | return;
141 | }
142 |
143 | // Get manifest path
144 | let manifestPath: string;
145 | try {
146 | let selectedNodeRuntimePath = selectedNode$.getValue()?.runtimePath;
147 | if (!selectedNodeRuntimePath) {
148 | vscode.window.showErrorMessage('Please first select a node.');
149 | return;
150 | }
151 | manifestPath = path.join(selectedNodeRuntimePath, 'Cargo.toml');
152 | } catch (e) {
153 | return;
154 | }
155 |
156 | // Prepare command
157 | const termCommand = [
158 | 'substrate-deps',
159 | `add ${palletName}`,
160 | ...alias ? [`--alias ${alias}`] : [],
161 | `--manifest-path '${manifestPath.replace(/'/, `'\\''`)}'`, // Allow spaces in path, prevent command injection (TODO Windows?)
162 | `&& echo '${palletName} was successfully added to the project${alias ? ` as '${alias}'` : ''}.'`
163 | ].join(' ');
164 |
165 | // Create terminal and run command
166 | const term = vscode.window.createTerminal({ name: `Installing ${palletName}` });
167 | term.sendText(termCommand);
168 | term.show();
169 |
170 | });
171 | }, (async r => { // Offer to retry in case fetching the categories failed
172 | const clicked = await vscode.window.showErrorMessage(`An error occured when fetching the list of pallets from the Substrate Marketplace: ${r}`, 'Try again');
173 | if (clicked === 'Try again') {
174 | return setUpMarketplaceTreeView(nodes, selectedNode$);
175 | }
176 | }));
177 |
178 | }
--------------------------------------------------------------------------------
/src/views/nodes/NodesProvider.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { BehaviorSubject, of, combineLatest } from 'rxjs';
3 | import { tryShortname } from '../../util';
4 | import { switchMap, tap } from 'rxjs/operators';
5 | import Nodes, {Node} from '../../nodes/Nodes';
6 |
7 | const path = require('path');
8 | const fs = require('fs');
9 |
10 | export class NodesProvider implements vscode.TreeDataProvider {
11 | nodeTreeItems: NodeTreeItem[] = [];
12 |
13 | private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter();
14 | readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event;
15 |
16 | constructor(nodes: Nodes, selectedNode$: BehaviorSubject) {
17 | nodes.nodes$.subscribe((nodes: Node[]) => {
18 |
19 | this.nodeTreeItems = nodes.map((node: Node) => {
20 | return new NodeTreeItem(node);
21 | });
22 |
23 | this.changeSelected(selectedNode$.getValue()?.nodePath || null);
24 | this._onDidChangeTreeData.fire();
25 | });
26 |
27 | selectedNode$.subscribe(node => {
28 | this.changeSelected(node?.nodePath || null);
29 | });
30 | }
31 |
32 | changeSelected(selectedNodePath: string | null) {
33 | this.nodeTreeItems.forEach((nodeTreeItem) => {
34 | if (nodeTreeItem.nodePath === selectedNodePath)
35 | nodeTreeItem.select();
36 | else
37 | nodeTreeItem.unselect();
38 | });
39 | this._onDidChangeTreeData.fire();
40 |
41 | }
42 |
43 | getTreeItem(element: NodeTreeItem): NodeTreeItem | Thenable {
44 | return element;
45 | }
46 |
47 | getChildren(element?: NodeTreeItem | undefined): vscode.ProviderResult {
48 | if (element === undefined) {
49 | return this.nodeTreeItems;
50 | }
51 | return element.children;
52 | }
53 | }
54 |
55 | export class NodeTreeItem extends vscode.TreeItem {
56 | children: undefined;
57 | nodePath: string;
58 |
59 | static create(info: Node) {
60 | return new this(info);
61 | }
62 |
63 | constructor(node: Node) {
64 | const { nodePath } = node;
65 | super(
66 | tryShortname(nodePath),
67 | vscode.TreeItemCollapsibleState.None);
68 | this.nodePath = nodePath;
69 | this.command = {
70 | command: "substrateNodes.selectNode",
71 | title: "Select Node",
72 | arguments: [this]
73 | };
74 | }
75 |
76 | select() {
77 | this.label = '▶️ ' + tryShortname(this.nodePath);
78 | }
79 |
80 | unselect() {
81 | this.label = tryShortname(this.nodePath);
82 | }
83 | }
84 |
85 | // Prompt the user to select a node among a list
86 | async function quickPickNodePath(nodes: Nodes) {
87 | let nodePaths = nodes.nodes$.getValue().map((node: Node) => node.nodePath);
88 |
89 | if (nodePaths.length === 1)
90 | return nodePaths[0];
91 |
92 | if (nodePaths.length === 0) {
93 | vscode.window.showErrorMessage('No node was found in the workspace.');
94 | return Promise.reject();
95 | }
96 |
97 | const nodesReadable = nodePaths.map(n => tryShortname(n));
98 |
99 | const pick = await vscode.window.showQuickPick(nodesReadable, { placeHolder: "Please choose a node." });
100 | if (pick === undefined)
101 | return Promise.reject();
102 |
103 | return nodePaths[nodesReadable.findIndex(x => x === pick)];
104 | }
105 |
106 | function getCargoName(directory: string) {
107 | const toml = fs.readFileSync(path.join(directory,'Cargo.toml')).toString();
108 | const ap = toml.match(/name ?= ?'(.+)'/);
109 | if (ap)
110 | return ap[1];
111 | else return toml.match(/name ?= ?"(.+)"/)[1];
112 | }
113 |
114 | function getWorkspaceRoot(directory: string) {
115 | let currDir = directory;
116 | do {
117 | if (fs.existsSync(path.join(currDir, 'Cargo.lock')))
118 | return currDir;
119 | currDir = path.join(currDir, '..');
120 | } while (currDir.split(path.sep).length > 0)
121 | throw new Error('No workspace root was found');
122 | }
123 |
124 | export function setUpNodesTreeView(nodes: Nodes, processes: any) {
125 |
126 | // Can be called by the NodesProvider, in which case a NodeTreeItem is provided;
127 | // or remotely (across iframe in Substrate Playground), in which case we provide
128 | // the path of the node to run, and optional additional flags.
129 | vscode.commands.registerCommand("substrate.startNode", async (nodePathLike?: string | NodeTreeItem, _flags?: string | string[], options: any = {compile: false}) => {
130 | try {
131 | let nodePath = nodePathLike instanceof NodeTreeItem ? nodePathLike.nodePath : nodePathLike;
132 | if (nodePath) {
133 | selectedNodePath$.next(nodePath); // select the item we launch the command on
134 | }
135 | const defNodePath = nodePath || await quickPickNodePath(nodes); // e.g. When run through Command Palette
136 | const term = vscode.window.createTerminal({ name: 'Start node ' + tryShortname(defNodePath), cwd: defNodePath });
137 |
138 | const flags = _flags ? (Array.isArray(_flags) ? _flags.join(' ') : _flags) : await vscode.window.showInputBox({
139 | value: '--dev --ws-external',
140 | prompt: 'Flags to run Substrate with',
141 | ignoreFocusOut: true
142 | });
143 | if (!flags) return; // user cancelled
144 |
145 | // todo use ws port to use polkadot apps
146 | // does it make sense to have two different polkadot apps endpoints ? two processes, one polkadot app endpoint ?
147 |
148 | if (options.compile) {
149 | term.sendText(`cargo run --release -- ${flags}`);
150 | } else {
151 | term.sendText(path.join(getWorkspaceRoot(defNodePath),`target/release/${getCargoName(defNodePath)}`) + ' ' + flags);
152 | }
153 | term.show();
154 |
155 | processes.new({nodePath: defNodePath, command: flags, term: term});
156 | } catch (e) {
157 | vscode.window.showErrorMessage(e);
158 | console.error(e);
159 | }
160 | });
161 |
162 | vscode.commands.registerCommand("substrate.compileStartNode", async (nodePathLike?: string | NodeTreeItem, _flags?: string | string[]) => {
163 | vscode.commands.executeCommand("substrate.startNode", nodePathLike, _flags, {compile: true});
164 | });
165 |
166 | vscode.commands.registerCommand("substrate.purgeChain", async (nodePathLike?: string | NodeTreeItem) => {
167 | let nodePath = nodePathLike instanceof NodeTreeItem ? nodePathLike.nodePath : nodePathLike;
168 | if (nodePath) {
169 | selectedNodePath$.next(nodePath); // select the item we launch the command on
170 | }
171 | const defoNodePath = nodePath || await quickPickNodePath(nodes);
172 | const term = vscode.window.createTerminal({ name: 'Purge chain', cwd: defoNodePath });
173 |
174 | term.sendText(path.join(getWorkspaceRoot(defoNodePath), `target/release/${getCargoName(defoNodePath)}`) + ' purge-chain --dev'); // TODO s
175 | term.show();
176 | });
177 |
178 | const selectedNodePath$ = new BehaviorSubject(null); // TODO NULL ON UNSELECT
179 | const selectedNode$ = new BehaviorSubject(null);
180 |
181 | combineLatest(selectedNodePath$, nodes.nodes$)
182 | .pipe(
183 | switchMap(([nodePath, nodes]: [string | null, Node[]]) => {
184 | if (!nodePath) return of(null);
185 | const selectedNode = nodes.find(node => node.nodePath === nodePath);
186 | if (selectedNode === undefined) {
187 | console.error("Selected node but doesn't match any.");
188 | return of(null);
189 | }
190 | return of(selectedNode);
191 | }),
192 | // tap(r => console.log('Selected node \'changes\' fired with', r))
193 | ).subscribe(selectedNode$);
194 |
195 | const treeDataProvider = new NodesProvider(nodes, selectedNode$);
196 | vscode.window.createTreeView('substrateNodes', { treeDataProvider });
197 | vscode.commands.registerCommand("substrateNodes.selectNode", (item: vscode.TreeItem) => {
198 | selectedNodePath$.next((item as any).nodePath || null);
199 | });
200 |
201 | return { selectedNode$ };
202 | }
--------------------------------------------------------------------------------
/src/views/accounts/AccountsProvider.ts:
--------------------------------------------------------------------------------
1 | import { u8aToHex } from '@polkadot/util';
2 | import { mnemonicGenerate, randomAsU8a } from '@polkadot/util-crypto';
3 | import * as clipboard from 'clipboardy';
4 | import * as vscode from 'vscode';
5 | import { Substrate } from '../../common/Substrate';
6 | import { TreeDataProvider } from '../../common/TreeDataProvider';
7 | import { showInputBoxValidate } from '../../util';
8 |
9 | const fs = require('fs');
10 |
11 | type Account = any;
12 |
13 | export class AccountsProvider extends TreeDataProvider {
14 | substrate: Substrate;
15 |
16 | constructor(substrate: Substrate) {
17 | super();
18 | this.substrate = substrate;
19 | }
20 |
21 | getChildren(element?: AccountTreeItem): Thenable {
22 | if (element === undefined) {
23 | return Promise.resolve(this.substrate.getAccounts().map(a => new AccountTreeItem(a)));
24 | }
25 | return Promise.resolve(element.children);
26 | }
27 | }
28 |
29 | export class AccountTreeItem extends vscode.TreeItem {
30 | children: [] = [];
31 | account: Account;
32 |
33 | constructor(account: Account) {
34 | super(
35 | account.meta.name,
36 | vscode.TreeItemCollapsibleState.None);
37 | this.description = account.address;
38 | this.account = account;
39 | }
40 | }
41 |
42 | async function quickPickAccount(substrate: Substrate, placeholder: string) {
43 | const quickPickItem = await vscode.window.showQuickPick(substrate.getAccounts().map(pair => ({
44 | label: pair.address,
45 | decription: pair.meta.name,
46 | account: pair
47 | }),{placeHolder: placeholder}));
48 | return quickPickItem?.account;
49 | }
50 |
51 | export async function setupAccountsTreeView(substrate: Substrate, context: vscode.ExtensionContext) {
52 | const treeDataProvider = new AccountsProvider(substrate);
53 | vscode.window.createTreeView('substrateAccounts', { treeDataProvider });
54 |
55 | // Add an existing account
56 | vscode.commands.registerCommand("substrate.addAccount", async () => {
57 | const name: string | undefined = await showInputBoxValidate({
58 | ignoreFocusOut: true,
59 | prompt: 'Account name',
60 | placeHolder: 'ex. Alice'
61 | }, async (value: any) => {
62 | if (!value || !value.trim()) {
63 | return 'Name is required';
64 | }
65 | if (substrate.isAccountExists(value)) {
66 | return 'Account with same name already exists';
67 | }
68 | return '';
69 | });
70 | if (!name) return;
71 |
72 | const type: 'ed25519' | 'sr25519' | undefined = await vscode.window.showQuickPick(['ed25519', 'sr25519']) as 'ed25519' | 'sr25519' | undefined;
73 | if (!type) return;
74 |
75 | const key: string | undefined = await showInputBoxValidate({
76 | ignoreFocusOut: true,
77 | prompt: 'The key to the account',
78 | placeHolder: 'ex. //Alice'
79 | }, async (value: any) => {
80 | if (!value || !value.trim()) {
81 | return 'Key is required';
82 | }
83 | return '';
84 | });
85 | if (!key) return;
86 |
87 | await substrate.createKeyringPair(key, name, type);
88 |
89 | treeDataProvider.refresh();
90 | });
91 |
92 | // Generate a new account
93 | vscode.commands.registerCommand("substrate.createAccount", async () => {
94 | const name: string | undefined = await showInputBoxValidate({
95 | ignoreFocusOut: true,
96 | prompt: 'Account name',
97 | placeHolder: 'ex. Alice'
98 | }, async (value: any) => {
99 | if (!value || !value.trim()) {
100 | return 'Name is required';
101 | }
102 | if (substrate.isAccountExists(value)) {
103 | return 'Account with same name already exists';
104 | }
105 | return '';
106 | });
107 | if (!name) return;
108 |
109 | const cryptoType: 'ed25519' | 'sr25519' | undefined = await vscode.window.showQuickPick(['ed25519', 'sr25519']) as 'ed25519' | 'sr25519' | undefined;
110 | if (!cryptoType) return;
111 |
112 | const keyTypeR: 'Raw seed' | 'Mnemonic seed' | undefined = await vscode.window.showQuickPick(['Raw seed', 'Mnemonic seed']) as 'Raw seed' | 'Mnemonic seed' | undefined;
113 | if (!keyTypeR) return;
114 | const keyType = keyTypeR === 'Raw seed' ? 'seed' : 'mnemonic';
115 |
116 | const placeholder = keyType !== 'seed' ?
117 | 'crunch aspect strong flavor enable final display general shy debate stable final'
118 | : 'ex. 0x89abd2b6b79f4e2df7e89cb6b44c7f02d416719f6970b17d6ad34178423fa922';
119 | const seed = keyType !== 'seed' ?
120 | mnemonicGenerate()
121 | : u8aToHex(randomAsU8a());
122 | const key: string | undefined = await showInputBoxValidate({
123 | ignoreFocusOut: true,
124 | prompt: 'The key to the account',
125 | placeHolder: placeholder,
126 | value: seed
127 | }, async (value: any) => {
128 | if (!value || !value.trim()) {
129 | return 'Key is required';
130 | }
131 | return '';
132 | });
133 | if (!key) return;
134 |
135 | const password: string | undefined = await vscode.window.showInputBox({
136 | ignoreFocusOut: true,
137 | prompt: 'Account password',
138 | placeHolder: 'ex. StrongPassword',
139 | password: true,
140 | value: '',
141 | });
142 | if (typeof password === 'undefined') return;
143 |
144 | substrate.createKeyringPairWithPassword(key, name, cryptoType, password);
145 |
146 | treeDataProvider.refresh();
147 | });
148 |
149 | // Rename the selected account in the TreeView
150 | vscode.commands.registerCommand("substrate.renameAccount", async (item?: AccountTreeItem) => {
151 | let itemAccount = item?.account || await quickPickAccount(substrate, 'Please pick the account you want to rename');
152 | if (!itemAccount) return;
153 | const name: string | undefined = await showInputBoxValidate({
154 | ignoreFocusOut: true,
155 | prompt: 'Account name',
156 | value: itemAccount.meta.name,
157 | placeHolder: 'ex. Alice'
158 | }, async (value: any) => {
159 | if (!value || !value.trim()) {
160 | return 'Name is required';
161 | }
162 | if (substrate.isAccountExists(value) && value !== itemAccount.meta.name) {
163 | return 'Account with same name already exists';
164 | }
165 | return '';
166 | });
167 | if (!name) return;
168 |
169 | await substrate.renameAccount(itemAccount.meta.name, name);
170 |
171 | treeDataProvider.refresh();
172 | });
173 |
174 | // Remove the selected account in the TreeView
175 | vscode.commands.registerCommand("substrate.removeAccount", async (item?: AccountTreeItem) => {
176 | let itemAccount = item?.account || await quickPickAccount(substrate, 'Please pick the account you want to remove');
177 | if (!itemAccount) return;
178 | await substrate.removeAccount(itemAccount.meta.name);
179 | treeDataProvider.refresh();
180 | });
181 |
182 | // Copy the address of the selected account in the TreeView
183 | vscode.commands.registerCommand("substrate.copyAddress", async (item?: AccountTreeItem) => {
184 | let itemAccount = item?.account || await quickPickAccount(substrate, 'Please pick the account whose address you want to copy');
185 | if (!itemAccount) return;
186 | try {
187 | await clipboard.write(itemAccount.address);
188 | vscode.window.showInformationMessage(`Address copied to clipboard.`);
189 | } catch (err) {
190 | vscode.window.showErrorMessage(`Failed to copy address to clipboard: ${err.message}`);
191 | }
192 | });
193 |
194 | // Import a new account
195 | vscode.commands.registerCommand("substrate.importAccount", async () => {
196 | const res = await vscode.window.showOpenDialog({
197 | openLabel: 'Import',
198 | canSelectFiles: true,
199 | canSelectFolders: false,
200 | canSelectMany: false,
201 | filters: {
202 | 'JSON': ['json'],
203 | },
204 | });
205 | if (!res) return;
206 | await substrate.importKeyringPair(res[0].path);
207 |
208 | treeDataProvider.refresh();
209 | });
210 |
211 | // Export the selected account in the TreeView
212 | vscode.commands.registerCommand("substrate.exportAccount", async (item?: AccountTreeItem) => {
213 | let itemAccount = item?.account || await quickPickAccount(substrate,'Please pick an account to export');
214 | if (!itemAccount) return;
215 |
216 | const result = await vscode.window.showSaveDialog({});
217 | if (!result) return;
218 |
219 | fs.writeFileSync(result.fsPath, JSON.stringify(itemAccount), 'utf8');
220 | });
221 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vscode-substrate",
3 | "displayName": "VSCode Substrate",
4 | "description": "Manage your Substrate node and add pallets from the Marketplace to your runtime",
5 | "version": "0.5.2",
6 | "publisher": "paritytech",
7 | "icon": "resources/icon.png",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/paritytech/vscode-substrate.git"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/paritytech/vscode-substrate/issues"
14 | },
15 | "homepage": "https://github.com/paritytech/vscode-substrate/blob/master/README.md",
16 | "engines": {
17 | "vscode": "^1.42.0"
18 | },
19 | "keywords": [
20 | "pallets",
21 | "polkadot",
22 | "parity",
23 | "web3"
24 | ],
25 | "categories": [
26 | "Other"
27 | ],
28 | "activationEvents": [
29 | "*"
30 | ],
31 | "main": "./out/extension.js",
32 | "contributes": {
33 | "viewsWelcome": [
34 | {
35 | "view": "substrateAccounts",
36 | "contents": "No accounts found."
37 | },
38 | {
39 | "view": "substrateProcesses",
40 | "contents": "No node is currently running."
41 | },
42 | {
43 | "view": "substrateNodes",
44 | "contents": "No node was found in your current workspace.\n[Open folder](command:vscode.openFolder)"
45 | }
46 | ],
47 | "viewsContainers": {
48 | "activitybar": [
49 | {
50 | "id": "substrate",
51 | "title": "Substrate",
52 | "icon": "resources/substrate.svg"
53 | }
54 | ]
55 | },
56 | "views": {
57 | "substrate": [
58 | {
59 | "id": "substrateProcesses",
60 | "name": "Processes",
61 | "group": "@1"
62 | },
63 | {
64 | "id": "substrateNodes",
65 | "name": "Nodes",
66 | "group": "@2"
67 | },
68 | {
69 | "id": "substrateMarketplace",
70 | "name": "Marketplace",
71 | "group": "@3"
72 | },
73 | {
74 | "id": "substrateAccounts",
75 | "name": "Accounts",
76 | "group": "@4"
77 | },
78 | {
79 | "id": "substrateContracts",
80 | "name": "Contracts",
81 | "group": "@5"
82 | }
83 | ]
84 | },
85 | "commands": [
86 | {
87 | "command": "substrate.stopProcess",
88 | "title": "Substrate: Stop process",
89 | "icon": {
90 | "dark": "resources/stopProcess.svg",
91 | "light": "resources/stopProcess-black.svg"
92 | }
93 | },
94 | {
95 | "command": "substrate.polkadotApps",
96 | "title": "Substrate: Polkadot Apps",
97 | "icon": {
98 | "dark": "resources/apps.svg",
99 | "light": "resources/apps-black.svg"
100 | }
101 | },
102 | {
103 | "command": "substrate.purgeChain",
104 | "title": "Substrate: Purge chain",
105 | "icon": {
106 | "dark": "resources/purgeChain.svg",
107 | "light": "resources/purgeChain-black.svg"
108 | }
109 | },
110 | {
111 | "command": "substrate.startNode",
112 | "title": "Substrate: Start node",
113 | "icon": {
114 | "dark": "resources/startNode.svg",
115 | "light": "resources/startNode-black.svg"
116 | }
117 | },
118 | {
119 | "command": "substrate.compileStartNode",
120 | "title": "Substrate: Compile & start node",
121 | "icon": {
122 | "dark": "resources/compileStartNode.svg",
123 | "light": "resources/compileStartNode-black.svg"
124 | }
125 | },
126 | {
127 | "command": "substrateMarketplace.palletHomepage",
128 | "title": "Homepage",
129 | "icon": {
130 | "dark": "resources/home.svg",
131 | "light": "resources/home-black.svg"
132 | }
133 | },
134 | {
135 | "command": "substrateMarketplace.palletGithub",
136 | "title": "GitHub",
137 | "icon": {
138 | "dark": "resources/github.svg",
139 | "light": "resources/github-black.svg"
140 | }
141 | },
142 | {
143 | "command": "substrateMarketplace.palletDocumentation",
144 | "title": "Documentation",
145 | "icon": {
146 | "dark": "resources/book.svg",
147 | "light": "resources/book-black.svg"
148 | }
149 | },
150 | {
151 | "command": "substrateMarketplace.installPallet",
152 | "title": "Add pallet to runtime",
153 | "icon": {
154 | "dark": "resources/add.svg",
155 | "light": "resources/add-black.svg"
156 | }
157 | },
158 | {
159 | "command": "substrate.addAccount",
160 | "title": "Substrate: Add account",
161 | "icon": {
162 | "dark": "resources/add.svg",
163 | "light": "resources/add-black.svg"
164 | }
165 | },
166 | {
167 | "command": "substrate.createAccount",
168 | "title": "Generate new account"
169 | },
170 | {
171 | "command": "substrate.importAccount",
172 | "title": "Import account from JSON"
173 | },
174 | {
175 | "command": "substrate.removeAccount",
176 | "title": "Remove"
177 | },
178 | {
179 | "command": "substrate.exportAccount",
180 | "title": "Export"
181 | },
182 | {
183 | "command": "substrate.renameAccount",
184 | "title": "Change name"
185 | },
186 | {
187 | "command": "substrate.copyAddress",
188 | "title": "Copy address"
189 | },
190 | {
191 | "command": "substrate.compileAndDeploy",
192 | "title": "Compile & deploy contract"
193 | },
194 | {
195 | "command": "substrate.forgetContract",
196 | "title": "Forget contract"
197 | },
198 | {
199 | "command": "substrate.copyContractHash",
200 | "title": "Copy hash"
201 | },
202 | {
203 | "command": "substrate.callContractMethod",
204 | "title": "Call a contract method"
205 | },
206 | {
207 | "command": "substrate.refreshContracts",
208 | "title": "Refresh contracts list"
209 | }
210 | ],
211 | "menus": {
212 | "commandPalette": [
213 | {
214 | "command": "substrateMarketplace.palletHomepage",
215 | "when": "false"
216 | },
217 | {
218 | "command": "substrateMarketplace.palletGithub",
219 | "when": "false"
220 | },
221 | {
222 | "command": "substrateMarketplace.palletDocumentation",
223 | "when": "false"
224 | },
225 | {
226 | "command": "substrateMarketplace.installPallet",
227 | "when": "false"
228 | }
229 | ],
230 | "view/title": [
231 | {
232 | "command": "substrate.addAccount",
233 | "when": "view == substrateAccounts",
234 | "group": "navigation"
235 | },
236 | {
237 | "command": "substrate.createAccount",
238 | "when": "view == substrateAccounts"
239 | },
240 | {
241 | "command": "substrate.importAccount",
242 | "when": "view == substrateAccounts"
243 | },
244 | {
245 | "command": "substrate.compileAndDeploy",
246 | "when": "view == substrateContracts",
247 | "group": "section-1"
248 | }
249 | ],
250 | "view/item/context": [
251 | {
252 | "command": "substrate.polkadotApps",
253 | "when": "view == substrateProcesses && viewItem == theia",
254 | "group": "inline@0"
255 | },
256 | {
257 | "command": "substrate.stopProcess",
258 | "when": "view == substrateProcesses",
259 | "group": "inline@1"
260 | },
261 | {
262 | "command": "substrate.purgeChain",
263 | "when": "view == substrateNodes",
264 | "group": "inline@0"
265 | },
266 | {
267 | "command": "substrate.startNode",
268 | "when": "view == substrateNodes",
269 | "group": "inline@1"
270 | },
271 | {
272 | "command": "substrate.compileStartNode",
273 | "when": "view == substrateNodes",
274 | "group": "inline@2"
275 | },
276 | {
277 | "command": "substrateMarketplace.palletHomepage",
278 | "when": "view == substrateMarketplace && viewItem == pallet || view == substrateMarketplace && viewItem == palletInstalled || view == substrateMarketplace && viewItem == palletNoNode",
279 | "group": "inline@0"
280 | },
281 | {
282 | "command": "substrateMarketplace.palletGithub",
283 | "when": "view == substrateMarketplace && viewItem == pallet || view == substrateMarketplace && viewItem == palletInstalled || view == substrateMarketplace && viewItem == palletNoNode",
284 | "group": "inline@1"
285 | },
286 | {
287 | "command": "substrateMarketplace.palletDocumentation",
288 | "when": "view == substrateMarketplace && viewItem == pallet || view == substrateMarketplace && viewItem == palletInstalled || view == substrateMarketplace && viewItem == palletNoNode",
289 | "group": "inline@2"
290 | },
291 | {
292 | "command": "substrateMarketplace.installPallet",
293 | "when": "view == substrateMarketplace && viewItem == pallet",
294 | "group": "inline@3"
295 | },
296 | {
297 | "command": "substrate.removeAccount",
298 | "when": "view == substrateAccounts"
299 | },
300 | {
301 | "command": "substrate.exportAccount",
302 | "when": "view == substrateAccounts"
303 | },
304 | {
305 | "command": "substrate.renameAccount",
306 | "when": "view == substrateAccounts"
307 | },
308 | {
309 | "command": "substrate.copyAddress",
310 | "when": "view == substrateAccounts"
311 | },
312 | {
313 | "command": "substrate.callContractMethod",
314 | "when": "view == substrateContracts",
315 | "group": "section-1"
316 | },
317 | {
318 | "command": "substrate.copyContractHash",
319 | "when": "view == substrateContracts",
320 | "group": "section-1"
321 | },
322 | {
323 | "command": "substrate.forgetContract",
324 | "when": "view == substrateContracts",
325 | "group": "section-2"
326 | }
327 | ]
328 | }
329 | },
330 | "scripts": {
331 | "vscode:prepublish": "yarn run compile",
332 | "compile": "tsc -p ./",
333 | "watch": "tsc -watch -p ./"
334 | },
335 | "devDependencies": {
336 | "@types/node": "^10.12.21",
337 | "@types/vscode": "^1.42.0",
338 | "tslint": "^5.12.1",
339 | "typescript": "^3.5.1"
340 | },
341 | "dependencies": {
342 | "@polkadot/api": "^1.27.1",
343 | "@polkadot/api-contract": "^1.27.1",
344 | "@types/lodash": "^4.14.149",
345 | "@types/node-fetch": "^2.5.5",
346 | "array-flat-polyfill": "^1.0.1",
347 | "clipboardy": "^2.3.0",
348 | "glob": "^7.1.6",
349 | "lodash": "^4.17.19",
350 | "node-fetch": "^2.6.1",
351 | "rxjs": "^6.5.5",
352 | "string.prototype.matchall": "^4.0.2"
353 | }
354 | }
355 |
--------------------------------------------------------------------------------
/src/views/contracts/ContractsProvider.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { tryShortname, resolveWhenTerminalClosed, showInputBoxValidate, wsEndpointFromCommand } from '../../util';
3 | import { Abi } from '@polkadot/api-contract';
4 | import { compactAddLength } from '@polkadot/util';
5 |
6 | import * as clipboard from 'clipboardy';
7 | import { TreeDataProvider } from '../../common/TreeDataProvider';
8 | import { Substrate, Contract } from '../../common/Substrate';
9 | import { Process } from '../../processes/Processes';
10 |
11 | const fs = require('fs');
12 | const path = require('path');
13 |
14 | export class ContractsProvider extends TreeDataProvider {
15 | substrate: Substrate;
16 |
17 | constructor(substrate: Substrate) {
18 | super();
19 | this.substrate = substrate;
20 | }
21 |
22 | getChildren(element?: ContractTreeItem): Thenable {
23 | if (element === undefined) {
24 | return Promise.resolve(this.substrate.getConnectionContracts().map(a => new ContractTreeItem(a)));
25 | }
26 | return Promise.resolve(element.children);
27 | }
28 | }
29 |
30 | export class ContractTreeItem extends vscode.TreeItem {
31 | children: [] = [];
32 | contract: Contract;
33 |
34 | constructor(contract: Contract) {
35 | super(
36 | contract.name,
37 | vscode.TreeItemCollapsibleState.None);
38 | this.description = contract.address;
39 | this.contract = contract;
40 | }
41 | }
42 |
43 | export async function setupContractsTreeView(substrate: Substrate, selectedProcess$: any, context: vscode.ExtensionContext) {
44 | const treeDataProvider = new ContractsProvider(substrate);
45 | const treeView = vscode.window.createTreeView('substrateContracts', { treeDataProvider });
46 |
47 | selectedProcess$.subscribe((process: Process) => {
48 | if (process)
49 | treeView.message = `Connected to: ${wsEndpointFromCommand(process.command)} (${tryShortname(process.nodePath) + ' • ' + process.command})`;
50 | else
51 | treeView.message = `Not connected to any node.`;
52 | vscode.commands.executeCommand('substrate.refreshContracts');
53 | });
54 |
55 | vscode.commands.registerCommand("substrate.refreshContracts", async (contractItem: ContractTreeItem) => {
56 | treeDataProvider.refresh();
57 | });
58 |
59 | vscode.commands.registerCommand("substrate.callContractMethod", async (contractItem: ContractTreeItem) => {
60 | try {
61 | const api = substrate.getConnection();
62 | if (!api) {
63 | vscode.window.showErrorMessage(`Not connected to a node.`);
64 | return;
65 | }
66 |
67 | const abi = new Abi(api.registry, contractItem.contract.abiJson);
68 |
69 | const methods = abi.abi.contract.messages;
70 | const items = methods.map(method => {
71 | const args = method.args.map((arg) => `${arg.name}: ${arg.type}`);
72 | const retDisplayName = method.returnType && method.returnType.displayName;
73 | return {
74 | label: `🧭 ${method.name}(${args.join(', ')})${retDisplayName ? `: ${retDisplayName}` : ''}`,
75 | description: method.mutates ? 'will mutate storage' : 'won\'t mutate storage',
76 | detail: `Method selector: ${method.selector}`,
77 | method
78 | };
79 | });
80 | const pickedMessage = await vscode.window.showQuickPick(items, { placeHolder: 'ex. get(): bool' });
81 | if (!pickedMessage) return;
82 | const method = pickedMessage.method;
83 |
84 | const valueTo: string | undefined = await showInputBoxValidate({
85 | ignoreFocusOut: true,
86 | prompt: 'The allotted value for this contract, i.e. the amount transferred to the contract as part of this call',
87 | value: '1000000000000000',
88 | placeHolder: 'ex. 1000000000000000'
89 | }, async (value: any) => {
90 | if (!value || !value.trim()) {
91 | return 'Value is required';
92 | }
93 | if (!value.match(/^-{0,1}\d+$/)) {
94 | return 'The value specified is not a number';
95 | }
96 | return '';
97 | });
98 | if (!valueTo) return;
99 |
100 | const maxGas: string | undefined = await showInputBoxValidate({
101 | ignoreFocusOut: true,
102 | prompt: 'The maximum amount of gas that can be used by this call',
103 | value: '1000000000000', // too much?
104 | placeHolder: 'ex. 1000000000000'
105 | }, async (value: any) => {
106 | if (!value || !value.trim()) {
107 | return 'A value is required';
108 | }
109 | if (!value.match(/^-{0,1}\d+$/)) {
110 | return 'The maximum gas specified is not a number';
111 | }
112 | return '';
113 | });
114 | if (!maxGas) return;
115 |
116 | const argsVals = [];
117 | const argsDefs = pickedMessage.method.args;
118 |
119 | while (argsDefs.length > argsVals.length) {
120 | const i: number = argsVals.length;
121 | const prompt = `${argsDefs[i].name}: ${argsDefs[i].type.displayName}`;
122 |
123 | const vale = await showInputBoxValidate({
124 | ignoreFocusOut: true,
125 | prompt
126 | }, async (value: any) => {
127 | return ''
128 | });
129 | if (vale === undefined) return; // User cancelled
130 | argsVals.push(vale);
131 | }
132 |
133 | const accounts = substrate.getAccounts();
134 | const _account = await vscode.window.showQuickPick(substrate.getAccounts().map((x: any) => x.meta.name));
135 | if (!_account) return;
136 | const accountJson = accounts.find(a => a.meta.name === _account)!;
137 |
138 | const keyring = substrate.getKeyring();
139 | const account = keyring.addFromJson(accountJson);
140 |
141 | const password: string | undefined = await showInputBoxValidate({
142 | ignoreFocusOut: true,
143 | prompt: 'Account password',
144 | placeHolder: 'ex. StrongPassword',
145 | password: true,
146 | value: '',
147 | }, async (value: any) => {
148 | try {
149 | account.decodePkcs8(value);
150 | if (account.isLocked) {
151 | return 'Failed to decode account';
152 | }
153 | } catch (e) {
154 | return 'Failed to decode account';
155 | }
156 | return '';
157 | });
158 | if (typeof password === 'undefined') return;
159 |
160 | // METHOD CALL
161 |
162 | vscode.window.showInformationMessage('Calling contract method...');
163 |
164 | try {
165 | const { nonce } = await api.query.system.account(account.address);
166 | const contractApi = api.tx.contracts ? api.tx['contracts'] : api.tx['contract'];
167 |
168 | const methodExec = abi.messages[method.name];
169 | const unsignedTransaction = contractApi.call(
170 | contractItem.description,
171 | valueTo,
172 | maxGas,
173 | methodExec(...argsVals),
174 | );
175 |
176 | const cb = await unsignedTransaction.sign(account, { nonce: nonce as any }).send(({ events = [], status }: any) => {
177 | if (status.isFinalized) {
178 | const finalized = status.asFinalized.toHex();
179 | console.log(`Completed at block hash: ${finalized}`);
180 |
181 | console.log(`Events:`);
182 | let error: string = '';
183 | events.forEach(({ phase, event: { data, method, section } }: any) => {
184 | const res = `\t ${phase.toString()} : ${section}.${method} ${data.toString()}`;
185 | if (res.indexOf('Failed') !== -1) {
186 | error += res;
187 | }
188 | console.log(res);
189 | });
190 | if (error !== '') {
191 | // Todo: Get error
192 | vscode.window.showErrorMessage(`Failed on block "${finalized}" with error: ${error}`);
193 | return;
194 | }
195 | vscode.window.showInformationMessage(`Completed on block ${finalized}`);
196 | }
197 | });
198 | // TODO Get results from contract
199 | } catch (err) {
200 | vscode.window.showErrorMessage(`Error on put code: ${err.message}`);
201 | }
202 | }
203 | catch (err) {
204 | console.error(err);
205 | vscode.window.showErrorMessage(err);
206 | }
207 | });
208 |
209 | vscode.commands.registerCommand("substrate.forgetContract", async (contractItem: ContractTreeItem) => {
210 | try {
211 | const contracts = substrate.getConnectionContracts();
212 | for (let i = 0; i < contracts.length; i++) {
213 | const contract = contracts[i];
214 | if (contract.name === contractItem.label || contract.address === contractItem.description) {
215 | contracts.splice(i, 1);
216 | }
217 | }
218 | await substrate.updateConnectionContracts(contracts);
219 | } catch (err) {
220 | vscode.window.showErrorMessage('You are not connected to a node');
221 | }
222 | await vscode.commands.executeCommand('substrate.refreshContracts');
223 | vscode.window.showInformationMessage(`Successfully removed contract "${contractItem.label}"`);
224 | });
225 |
226 | vscode.commands.registerCommand("substrate.copyContractHash", async (contractItem: ContractTreeItem) => {
227 | try {
228 | await clipboard.write((contractItem as any).description);
229 | vscode.window.showInformationMessage('Hash copied to clipboard');
230 | } catch (err) {
231 | vscode.window.showErrorMessage(`Failed to copy hash to clipboard: ${err.message}`);
232 | }
233 | });
234 |
235 | vscode.commands.registerCommand("substrate.compileAndDeploy", async () => {
236 | try {
237 | const api = substrate.getConnection();
238 | if (!api) {
239 | vscode.window.showErrorMessage('Please connect to a node first.');
240 | return;
241 | }
242 | if (!api.tx.contracts && !api.tx.contract) {
243 | vscode.window.showErrorMessage('The selected process doesn\'t support smart contracts.');
244 | return;
245 | }
246 |
247 | const folders = await vscode.window.showOpenDialog({ canSelectFiles: false, canSelectFolders: true, canSelectMany: false, openLabel: 'Select contract folder' })
248 | if (folders === undefined) return;
249 |
250 | const term = vscode.window.createTerminal({ name: 'Compiling contract', cwd: folders[0] });
251 | term.sendText('cargo +nightly contract build && cargo +nightly contract generate-metadata && exit');
252 | term.show();
253 |
254 | await resolveWhenTerminalClosed(term);
255 |
256 | const wasmPath = path.join(folders[0].fsPath, 'target', path.basename(folders[0].fsPath) + '.wasm');
257 | const abiPath = path.join(folders[0].fsPath, 'target', 'metadata.json');
258 | const wasm: Uint8Array = await fs.promises.readFile(wasmPath);
259 | const isWasmValid = wasm.subarray(0, 4).join(',') === '0,97,115,109'; // '\0asm'
260 | if (!isWasmValid) {
261 | console.error('Invalid code');
262 | throw Error('Invalid code');
263 | }
264 | const compiledContract = compactAddLength(wasm);
265 |
266 | const name: string | undefined = await showInputBoxValidate({
267 | ignoreFocusOut: true,
268 | prompt: 'Contract name',
269 | placeHolder: 'ex. Flipper contract',
270 | value: 'flip'
271 | }, async (value: any) => {
272 | if (!value || !value.trim()) {
273 | return 'A name is required';
274 | }
275 | return '';
276 | });
277 | if (!name) return;
278 |
279 | const accounts = substrate.getAccounts();
280 | const _account = await vscode.window.showQuickPick(substrate.getAccounts().map((x: any) => x.meta.name));
281 | if (!_account) return;
282 | const accountJson = accounts.find(a => a.meta.name === _account)!;
283 |
284 | const keyring = substrate.getKeyring();
285 | const account = keyring.addFromJson(accountJson);
286 |
287 | const password: string | undefined = await showInputBoxValidate({
288 | ignoreFocusOut: true,
289 | prompt: 'Account password',
290 | placeHolder: 'ex. StrongPassword',
291 | password: true,
292 | value: '',
293 | }, async (value: any) => {
294 | try {
295 | account.decodePkcs8(value);
296 | if (account.isLocked) {
297 | return 'Failed to decode account';
298 | }
299 | } catch (e) {
300 | return 'Failed to decode account';
301 | }
302 | return '';
303 | });
304 | if (typeof password === 'undefined') return;
305 |
306 | const abiBytes: Uint8Array = await fs.promises.readFile(abiPath);
307 | const abiJson = JSON.parse(abiBytes.toString());
308 | const abi = new Abi(api.registry, abiJson);
309 | const constructors = abi.abi.contract.constructors;
310 | const _constructor = await vscode.window.showQuickPick(constructors.map((x: any) => x.name), { placeHolder: 'Choose constructor' });
311 | if (!_constructor) return;
312 | const constructorI = constructors.findIndex(x => x.name === _constructor)!;
313 | const constructor = constructors.find(x => x.name === _constructor)!;
314 | const args = constructor.args
315 |
316 | const constructorParams: any[] = [];
317 | while (args.length > constructorParams.length) {
318 | const i = constructorParams.length;
319 | const prompt = `${args[i].name}: ${args[i].type.displayName}`;
320 |
321 | constructorParams.push(await showInputBoxValidate({
322 | ignoreFocusOut: true,
323 | prompt
324 | }, async (value: any) => {
325 | return ''
326 | }));
327 | }
328 |
329 | const endowment: string | undefined = await showInputBoxValidate({
330 | ignoreFocusOut: true,
331 | prompt: 'The allotted endowment for this contract, i.e. the amount transferred to the contract upon instantiation.',
332 | value: '1000000000000000',
333 | placeHolder: 'ex. 1000000000000000'
334 | }, async (value: any) => {
335 | if (!value || !value.trim()) {
336 | return 'Endowment is required';
337 | }
338 | if (!value.match(/^-{0,1}\d+$/)) {
339 | return 'The endowment specified is not a number';
340 | }
341 | return '';
342 | });
343 | if (!endowment) return;
344 |
345 | const maxGasDeployment: string | undefined = await showInputBoxValidate({
346 | ignoreFocusOut: true,
347 | prompt: 'The maximum amount of gas that can be used for the deployment',
348 | value: '1000000000000',
349 | placeHolder: 'ex. 1000000000000'
350 | }, async (value: any) => {
351 | if (!value || !value.trim()) {
352 | return 'A value is required';
353 | }
354 | if (!value.match(/^-{0,1}\d+$/)) {
355 | return 'The maximum gas specified is not a number';
356 | }
357 | return '';
358 | });
359 | if (!maxGasDeployment) return;
360 |
361 | // PUT CODE
362 |
363 | vscode.window.showInformationMessage('Uploading WASM...');
364 |
365 | try {
366 | const { nonce } = await api.query.system.account(account.address);
367 | const contractApi = api.tx.contracts ? api.tx['contracts'] : api.tx['contract'];
368 | const unsignedTransaction = contractApi.putCode(compiledContract);
369 |
370 | let code_hash = '';
371 | unsignedTransaction.sign(account, { nonce: nonce as any }).send(async ({ events = [], status }: any) => {
372 | if (status.isFinalized) {
373 | const finalized = status.asFinalized.toHex();
374 | console.log(`Completed at block hash: ${finalized}`);
375 |
376 | console.log('Events:');
377 | let error: string = '';
378 | let resultHash: string = '';
379 | events.forEach(({ phase, event: { data, method, section } }: any) => {
380 | const res = `\t ${phase.toString()} : ${section}.${method} ${data.toString()}`;
381 | if (res.indexOf('Failed') !== -1) {
382 | error += res;
383 | }
384 | if (res.indexOf('contracts.CodeStored') !== -1) {
385 | resultHash = res.substring(
386 | res.lastIndexOf('["') + 2,
387 | res.lastIndexOf('"]'),
388 | );
389 | }
390 | console.log(res);
391 | });
392 | if (error !== '') {
393 | // Todo: Get error
394 | vscode.window.showErrorMessage(`Failed on block "${finalized}" with error: ${error}`);
395 | return;
396 | }
397 | if (resultHash === '') {
398 | vscode.window.showErrorMessage(`Completed on block "${finalized}" but failed to get event result`);
399 | return;
400 | }
401 | console.log(`Completed on block ${finalized} with code hash ${resultHash}`);
402 | code_hash = resultHash;
403 |
404 | // Deploying contract
405 |
406 | vscode.window.showInformationMessage('Instantiating contract...');
407 |
408 | // DEPLOY CONTRACT
409 | try {
410 | const { nonce } = await api.query.system.account(account.address);
411 | const unsignedTransaction = contractApi.instantiate(
412 | endowment, // +3 more 0's
413 | maxGasDeployment,
414 | code_hash,
415 | abi.constructors[constructorI](...constructorParams) // TODO test when passing parameters
416 | );
417 | await unsignedTransaction.sign(account, { nonce: nonce as any }).send(({ events = [], status }: any) => {
418 | if (status.isFinalized) {
419 | const finalized = status.asFinalized.toHex();
420 | console.log(`Completed at block hash: ${finalized}`);
421 |
422 | console.log('Events:');
423 | let error: string = '';
424 | let resultHash: string = '';
425 | events.forEach(({ phase, event: { data, method, section } }: any) => {
426 | const res = `\t ${phase.toString()} : ${section}.${method} ${data.toString()}`;
427 | if (res.indexOf('Failed') !== -1) {
428 | error += res;
429 | }
430 | if (res.indexOf('contracts.Instantiated') !== -1) {
431 | resultHash = res.substring(
432 | res.lastIndexOf('["') + 2,
433 | res.lastIndexOf('",'),
434 | );
435 | }
436 | console.log(res);
437 | });
438 | if (error !== '') {
439 | vscode.window.showErrorMessage(`Failed on block "${finalized}" with error: ${error}`);
440 | return;
441 | }
442 | if (resultHash === '') {
443 | vscode.window.showWarningMessage(`Completed on block "${finalized}" but failed to get event result`);
444 | return;
445 | }
446 | substrate.saveContract(name, resultHash, abiJson).catch(err => {
447 | vscode.window.showErrorMessage(`Failed to store contract: ${err.message}`);
448 | });
449 | vscode.window.showInformationMessage(`Completed on block ${finalized} with code hash ${resultHash}`);
450 | }
451 | });
452 | } catch (err) {
453 | vscode.window.showErrorMessage(`Error on deploy contract: ${err.message}`);
454 | }
455 | }
456 | });
457 | } catch (err) {
458 | vscode.window.showErrorMessage(`Error on put code: ${err.message}`);
459 | }
460 | } catch (surerr) {
461 | vscode.window.showErrorMessage(surerr);
462 | }
463 | });
464 | }
--------------------------------------------------------------------------------
/resources/playground.png.base64:
--------------------------------------------------------------------------------
1 | data:image/png;base64,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
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@babel/code-frame@^7.0.0":
6 | version "7.8.3"
7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
8 | integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==
9 | dependencies:
10 | "@babel/highlight" "^7.8.3"
11 |
12 | "@babel/highlight@^7.8.3":
13 | version "7.8.3"
14 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
15 | integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==
16 | dependencies:
17 | chalk "^2.0.0"
18 | esutils "^2.0.2"
19 | js-tokens "^4.0.0"
20 |
21 | "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.0":
22 | version "7.11.2"
23 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
24 | integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
25 | dependencies:
26 | regenerator-runtime "^0.13.4"
27 |
28 | "@polkadot/api-contract@^1.27.1":
29 | version "1.27.1"
30 | resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-1.27.1.tgz#52b45b7de8ce35b0d278f4c37eafdcd0b0b7b8c7"
31 | integrity sha512-4Md0LXysEctONz38u7TG9EEFHL2rd9s25nzskGOuFm3FoLomFrvUHGsheIr0zM6wDg8yScRh9zvdkc8EvG4sWQ==
32 | dependencies:
33 | "@babel/runtime" "^7.11.0"
34 | "@polkadot/api" "1.27.1"
35 | "@polkadot/rpc-core" "1.27.1"
36 | "@polkadot/types" "1.27.1"
37 | "@polkadot/util" "^3.0.1"
38 | bn.js "^5.1.2"
39 | rxjs "^6.6.2"
40 |
41 | "@polkadot/api-derive@1.27.1":
42 | version "1.27.1"
43 | resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-1.27.1.tgz#5001f19cb29ea4d7924412950b41e46fcca45d81"
44 | integrity sha512-WPZEZ9THeYOkkGzDDsCGSTrWJuWu6qegmWLo52pqD7enmP3dADDoKqPzszHVbEAfc+wYtc5Ye4EogUAiK30iMg==
45 | dependencies:
46 | "@babel/runtime" "^7.11.0"
47 | "@polkadot/api" "1.27.1"
48 | "@polkadot/rpc-core" "1.27.1"
49 | "@polkadot/rpc-provider" "1.27.1"
50 | "@polkadot/types" "1.27.1"
51 | "@polkadot/util" "^3.0.1"
52 | "@polkadot/util-crypto" "^3.0.1"
53 | bn.js "^5.1.2"
54 | memoizee "^0.4.14"
55 | rxjs "^6.6.2"
56 |
57 | "@polkadot/api@1.27.1", "@polkadot/api@^1.27.1":
58 | version "1.27.1"
59 | resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-1.27.1.tgz#dcd3ae5d8699ea5555369b9594888eb1008dd7fe"
60 | integrity sha512-ANMLmNR1PfXLoQ7Ysep9sM/2U3oh3fjFI+9P4Yy9Pv+XMvCROaGAcvxoG+hHfWFz6OAT7ABwyiocV93PuOpAww==
61 | dependencies:
62 | "@babel/runtime" "^7.11.0"
63 | "@polkadot/api-derive" "1.27.1"
64 | "@polkadot/keyring" "^3.0.1"
65 | "@polkadot/metadata" "1.27.1"
66 | "@polkadot/rpc-core" "1.27.1"
67 | "@polkadot/rpc-provider" "1.27.1"
68 | "@polkadot/types" "1.27.1"
69 | "@polkadot/types-known" "1.27.1"
70 | "@polkadot/util" "^3.0.1"
71 | "@polkadot/util-crypto" "^3.0.1"
72 | bn.js "^5.1.2"
73 | eventemitter3 "^4.0.4"
74 | rxjs "^6.6.2"
75 |
76 | "@polkadot/keyring@^3.0.1":
77 | version "3.0.1"
78 | resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-3.0.1.tgz#3944079697c15b2af81e1f57b1c4aeab703a4fef"
79 | integrity sha512-vAHSBnisiDYHsBbEzAgIpuwQp3vIDN2uWQ/1wAE2BrKzXCBQM7RrF3LRcLFySk0xzQoDs7AP1TlPoakxJ/C/Qw==
80 | dependencies:
81 | "@babel/runtime" "^7.10.5"
82 | "@polkadot/util" "3.0.1"
83 | "@polkadot/util-crypto" "3.0.1"
84 |
85 | "@polkadot/metadata@1.27.1":
86 | version "1.27.1"
87 | resolved "https://registry.yarnpkg.com/@polkadot/metadata/-/metadata-1.27.1.tgz#40b8e26f9eee30df5b6790aaab406dae1e6d3152"
88 | integrity sha512-jOsWvpGNFkV3NGSGVTzyir0PKinxoa97CYEQj8tJTU7iHDPnSs5R/BEmI0+1hg4ZM/47n+YU8d0lLktD6wbMOA==
89 | dependencies:
90 | "@babel/runtime" "^7.11.0"
91 | "@polkadot/types" "1.27.1"
92 | "@polkadot/types-known" "1.27.1"
93 | "@polkadot/util" "^3.0.1"
94 | "@polkadot/util-crypto" "^3.0.1"
95 | bn.js "^5.1.2"
96 |
97 | "@polkadot/rpc-core@1.27.1":
98 | version "1.27.1"
99 | resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-1.27.1.tgz#afe7d1890c779eaf2bec9bb1336b5ba2ff1ba15b"
100 | integrity sha512-HxLHHdV3bDqTltsEedCRGiZeTGmeahnk6OEGyysFOW3PFIrygwwuYa0Mo10lS93dwy9xZw4oE3h9qZqox2mGmQ==
101 | dependencies:
102 | "@babel/runtime" "^7.11.0"
103 | "@polkadot/metadata" "1.27.1"
104 | "@polkadot/rpc-provider" "1.27.1"
105 | "@polkadot/types" "1.27.1"
106 | "@polkadot/util" "^3.0.1"
107 | memoizee "^0.4.14"
108 | rxjs "^6.6.2"
109 |
110 | "@polkadot/rpc-provider@1.27.1":
111 | version "1.27.1"
112 | resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-1.27.1.tgz#c0307a9e9c658f4072ad94ac6e98e2bd78bb1ee6"
113 | integrity sha512-12lpsmHNYLZ3p0X0h643U+sw+WE/kzVB9Q0Y0RA9Recq794cBGiEgK/nmVjT5hrTEk+2+qdtu+CqficWt2FeQw==
114 | dependencies:
115 | "@babel/runtime" "^7.11.0"
116 | "@polkadot/metadata" "1.27.1"
117 | "@polkadot/types" "1.27.1"
118 | "@polkadot/util" "^3.0.1"
119 | "@polkadot/util-crypto" "^3.0.1"
120 | bn.js "^5.1.2"
121 | eventemitter3 "^4.0.4"
122 | isomorphic-fetch "^2.2.1"
123 | websocket "^1.0.31"
124 |
125 | "@polkadot/types-known@1.27.1":
126 | version "1.27.1"
127 | resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-1.27.1.tgz#d6c48c7b075cd0a9772fcc5df8d98f77b0da35f3"
128 | integrity sha512-9HzHJXznuuG0EQPR3XN931smIzA5usOP2D4Te/uyjiqHgXGUv1EU/vPYaacYYRrjLNdytNcF3HbW97fxu+fC6w==
129 | dependencies:
130 | "@babel/runtime" "^7.11.0"
131 | "@polkadot/types" "1.27.1"
132 | "@polkadot/util" "^3.0.1"
133 | bn.js "^5.1.2"
134 |
135 | "@polkadot/types@1.27.1":
136 | version "1.27.1"
137 | resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-1.27.1.tgz#243f796178f9308a8e58f13fa13d0f3ed1fd2bc8"
138 | integrity sha512-6sX+0/cBUEd/Pt6Y4JSjUI44nqH6qyuRcs6bte2OsEsm06XTEMoIqICPHoOS36Sd/ux7IA/gTZgEj39C9mJWBQ==
139 | dependencies:
140 | "@babel/runtime" "^7.11.0"
141 | "@polkadot/metadata" "1.27.1"
142 | "@polkadot/util" "^3.0.1"
143 | "@polkadot/util-crypto" "^3.0.1"
144 | "@types/bn.js" "^4.11.6"
145 | bn.js "^5.1.2"
146 | memoizee "^0.4.14"
147 | rxjs "^6.6.2"
148 |
149 | "@polkadot/util-crypto@3.0.1", "@polkadot/util-crypto@^3.0.1":
150 | version "3.0.1"
151 | resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-3.0.1.tgz#800746a39a00e5aa7dc7b901bbde0f5e3e0be60b"
152 | integrity sha512-4G5kzNfqa/nQGuTtoFsy3DESApc8BTgTHbAvLwSkxzM3j8YsvC5ayJ3AFYvM2UT2PDwXmrFx4cwRnYsYZvhC9A==
153 | dependencies:
154 | "@babel/runtime" "^7.10.5"
155 | "@polkadot/util" "3.0.1"
156 | "@polkadot/wasm-crypto" "^1.2.1"
157 | base-x "^3.0.8"
158 | bip39 "^3.0.2"
159 | blakejs "^1.1.0"
160 | bn.js "^5.1.2"
161 | elliptic "^6.5.3"
162 | js-sha3 "^0.8.0"
163 | pbkdf2 "^3.1.1"
164 | scryptsy "^2.1.0"
165 | tweetnacl "^1.0.3"
166 | xxhashjs "^0.2.2"
167 |
168 | "@polkadot/util@3.0.1", "@polkadot/util@^3.0.1":
169 | version "3.0.1"
170 | resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-3.0.1.tgz#f7ed9d81d745136aa6d6ad57277ee05c88f32784"
171 | integrity sha512-WvH+seT03YQ+6dWJqo285uYHsDvMEGzgYQILEclzQo8xExeCYLIX6GptpW0vGycVxdZmmCdDmUFbcQSRsFawYA==
172 | dependencies:
173 | "@babel/runtime" "^7.10.5"
174 | "@types/bn.js" "^4.11.6"
175 | bn.js "^5.1.2"
176 | camelcase "^5.3.1"
177 | chalk "^4.1.0"
178 | ip-regex "^4.1.0"
179 |
180 | "@polkadot/wasm-crypto@^1.2.1":
181 | version "1.2.1"
182 | resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-1.2.1.tgz#2189702447acd28d763886359576c87562241767"
183 | integrity sha512-nckIoZBV4nBZdeKwFwH5t7skS7L7GO5EFUl5B1F6uCjUfdNpDz3DtqbYQHcLdCZNmG4TDLg6w/1J+rkl2SiUZw==
184 |
185 | "@types/bn.js@^4.11.6":
186 | version "4.11.6"
187 | resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
188 | integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==
189 | dependencies:
190 | "@types/node" "*"
191 |
192 | "@types/color-name@^1.1.1":
193 | version "1.1.1"
194 | resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
195 | integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
196 |
197 | "@types/lodash@^4.14.149":
198 | version "4.14.149"
199 | resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440"
200 | integrity sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==
201 |
202 | "@types/node-fetch@^2.5.5":
203 | version "2.5.5"
204 | resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.5.tgz#cd264e20a81f4600a6c52864d38e7fef72485e92"
205 | integrity sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA==
206 | dependencies:
207 | "@types/node" "*"
208 | form-data "^3.0.0"
209 |
210 | "@types/node@*":
211 | version "13.9.1"
212 | resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.1.tgz#96f606f8cd67fb018847d9b61e93997dabdefc72"
213 | integrity sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==
214 |
215 | "@types/node@11.11.6":
216 | version "11.11.6"
217 | resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a"
218 | integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
219 |
220 | "@types/node@^10.12.21":
221 | version "10.17.18"
222 | resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.18.tgz#ae364d97382aacdebf583fa4e7132af2dfe56a0c"
223 | integrity sha512-DQ2hl/Jl3g33KuAUOcMrcAOtsbzb+y/ufakzAdeK9z/H/xsvkpbETZZbPNMIiQuk24f5ZRMCcZIViAwyFIiKmg==
224 |
225 | "@types/vscode@^1.42.0":
226 | version "1.43.0"
227 | resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.43.0.tgz#22276e60034c693b33117f1068ffaac0e89522db"
228 | integrity sha512-kIaR9qzd80rJOxePKpCB/mdy00mz8Apt2QA5Y6rdrKFn13QNFNeP3Hzmsf37Bwh/3cS7QjtAeGSK7wSqAU0sYQ==
229 |
230 | ansi-styles@^3.2.1:
231 | version "3.2.1"
232 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
233 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
234 | dependencies:
235 | color-convert "^1.9.0"
236 |
237 | ansi-styles@^4.1.0:
238 | version "4.2.1"
239 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
240 | integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
241 | dependencies:
242 | "@types/color-name" "^1.1.1"
243 | color-convert "^2.0.1"
244 |
245 | arch@^2.1.1:
246 | version "2.1.2"
247 | resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.2.tgz#0c52bbe7344bb4fa260c443d2cbad9c00ff2f0bf"
248 | integrity sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ==
249 |
250 | argparse@^1.0.7:
251 | version "1.0.10"
252 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
253 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
254 | dependencies:
255 | sprintf-js "~1.0.2"
256 |
257 | array-flat-polyfill@^1.0.1:
258 | version "1.0.1"
259 | resolved "https://registry.yarnpkg.com/array-flat-polyfill/-/array-flat-polyfill-1.0.1.tgz#1e3a4255be619dfbffbfd1d635c1cf357cd034e7"
260 | integrity sha512-hfJmKupmQN0lwi0xG6FQ5U8Rd97RnIERplymOv/qpq8AoNKPPAnxJadjFA23FNWm88wykh9HmpLJUUwUtNU/iw==
261 |
262 | asynckit@^0.4.0:
263 | version "0.4.0"
264 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
265 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
266 |
267 | balanced-match@^1.0.0:
268 | version "1.0.0"
269 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
270 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
271 |
272 | base-x@^3.0.8:
273 | version "3.0.8"
274 | resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d"
275 | integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==
276 | dependencies:
277 | safe-buffer "^5.0.1"
278 |
279 | bip39@^3.0.2:
280 | version "3.0.2"
281 | resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.2.tgz#2baf42ff3071fc9ddd5103de92e8f80d9257ee32"
282 | integrity sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==
283 | dependencies:
284 | "@types/node" "11.11.6"
285 | create-hash "^1.1.0"
286 | pbkdf2 "^3.0.9"
287 | randombytes "^2.0.1"
288 |
289 | blakejs@^1.1.0:
290 | version "1.1.0"
291 | resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.0.tgz#69df92ef953aa88ca51a32df6ab1c54a155fc7a5"
292 | integrity sha1-ad+S75U6qIylGjLfarHFShVfx6U=
293 |
294 | bn.js@^4.4.0:
295 | version "4.11.9"
296 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
297 | integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
298 |
299 | bn.js@^5.1.2:
300 | version "5.1.2"
301 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0"
302 | integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==
303 |
304 | brace-expansion@^1.1.7:
305 | version "1.1.11"
306 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
307 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
308 | dependencies:
309 | balanced-match "^1.0.0"
310 | concat-map "0.0.1"
311 |
312 | brorand@^1.0.1:
313 | version "1.1.0"
314 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
315 | integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
316 |
317 | builtin-modules@^1.1.1:
318 | version "1.1.1"
319 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
320 | integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
321 |
322 | camelcase@^5.3.1:
323 | version "5.3.1"
324 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
325 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
326 |
327 | chalk@^2.0.0, chalk@^2.3.0:
328 | version "2.4.2"
329 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
330 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
331 | dependencies:
332 | ansi-styles "^3.2.1"
333 | escape-string-regexp "^1.0.5"
334 | supports-color "^5.3.0"
335 |
336 | chalk@^4.1.0:
337 | version "4.1.0"
338 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
339 | integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
340 | dependencies:
341 | ansi-styles "^4.1.0"
342 | supports-color "^7.1.0"
343 |
344 | cipher-base@^1.0.1, cipher-base@^1.0.3:
345 | version "1.0.4"
346 | resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
347 | integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
348 | dependencies:
349 | inherits "^2.0.1"
350 | safe-buffer "^5.0.1"
351 |
352 | clipboardy@^2.3.0:
353 | version "2.3.0"
354 | resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290"
355 | integrity sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==
356 | dependencies:
357 | arch "^2.1.1"
358 | execa "^1.0.0"
359 | is-wsl "^2.1.1"
360 |
361 | color-convert@^1.9.0:
362 | version "1.9.3"
363 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
364 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
365 | dependencies:
366 | color-name "1.1.3"
367 |
368 | color-convert@^2.0.1:
369 | version "2.0.1"
370 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
371 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
372 | dependencies:
373 | color-name "~1.1.4"
374 |
375 | color-name@1.1.3:
376 | version "1.1.3"
377 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
378 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
379 |
380 | color-name@~1.1.4:
381 | version "1.1.4"
382 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
383 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
384 |
385 | combined-stream@^1.0.8:
386 | version "1.0.8"
387 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
388 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
389 | dependencies:
390 | delayed-stream "~1.0.0"
391 |
392 | commander@^2.12.1:
393 | version "2.20.3"
394 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
395 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
396 |
397 | concat-map@0.0.1:
398 | version "0.0.1"
399 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
400 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
401 |
402 | create-hash@^1.1.0, create-hash@^1.1.2:
403 | version "1.2.0"
404 | resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
405 | integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
406 | dependencies:
407 | cipher-base "^1.0.1"
408 | inherits "^2.0.1"
409 | md5.js "^1.3.4"
410 | ripemd160 "^2.0.1"
411 | sha.js "^2.4.0"
412 |
413 | create-hmac@^1.1.4:
414 | version "1.1.7"
415 | resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
416 | integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
417 | dependencies:
418 | cipher-base "^1.0.3"
419 | create-hash "^1.1.0"
420 | inherits "^2.0.1"
421 | ripemd160 "^2.0.0"
422 | safe-buffer "^5.0.1"
423 | sha.js "^2.4.8"
424 |
425 | cross-spawn@^6.0.0:
426 | version "6.0.5"
427 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
428 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
429 | dependencies:
430 | nice-try "^1.0.4"
431 | path-key "^2.0.1"
432 | semver "^5.5.0"
433 | shebang-command "^1.2.0"
434 | which "^1.2.9"
435 |
436 | cuint@^0.2.2:
437 | version "0.2.2"
438 | resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b"
439 | integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=
440 |
441 | d@1, d@^1.0.1:
442 | version "1.0.1"
443 | resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
444 | integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
445 | dependencies:
446 | es5-ext "^0.10.50"
447 | type "^1.0.1"
448 |
449 | debug@^2.2.0:
450 | version "2.6.9"
451 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
452 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
453 | dependencies:
454 | ms "2.0.0"
455 |
456 | define-properties@^1.1.2, define-properties@^1.1.3:
457 | version "1.1.3"
458 | resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
459 | integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
460 | dependencies:
461 | object-keys "^1.0.12"
462 |
463 | delayed-stream@~1.0.0:
464 | version "1.0.0"
465 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
466 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
467 |
468 | diff@^4.0.1:
469 | version "4.0.2"
470 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
471 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
472 |
473 | elliptic@^6.5.3:
474 | version "6.5.3"
475 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
476 | integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==
477 | dependencies:
478 | bn.js "^4.4.0"
479 | brorand "^1.0.1"
480 | hash.js "^1.0.0"
481 | hmac-drbg "^1.0.0"
482 | inherits "^2.0.1"
483 | minimalistic-assert "^1.0.0"
484 | minimalistic-crypto-utils "^1.0.0"
485 |
486 | encoding@^0.1.11:
487 | version "0.1.12"
488 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
489 | integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
490 | dependencies:
491 | iconv-lite "~0.4.13"
492 |
493 | end-of-stream@^1.1.0:
494 | version "1.4.4"
495 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
496 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
497 | dependencies:
498 | once "^1.4.0"
499 |
500 | es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.5:
501 | version "1.17.5"
502 | resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9"
503 | integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==
504 | dependencies:
505 | es-to-primitive "^1.2.1"
506 | function-bind "^1.1.1"
507 | has "^1.0.3"
508 | has-symbols "^1.0.1"
509 | is-callable "^1.1.5"
510 | is-regex "^1.0.5"
511 | object-inspect "^1.7.0"
512 | object-keys "^1.1.1"
513 | object.assign "^4.1.0"
514 | string.prototype.trimleft "^2.1.1"
515 | string.prototype.trimright "^2.1.1"
516 |
517 | es-to-primitive@^1.2.1:
518 | version "1.2.1"
519 | resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
520 | integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
521 | dependencies:
522 | is-callable "^1.1.4"
523 | is-date-object "^1.0.1"
524 | is-symbol "^1.0.2"
525 |
526 | es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
527 | version "0.10.53"
528 | resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
529 | integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
530 | dependencies:
531 | es6-iterator "~2.0.3"
532 | es6-symbol "~3.1.3"
533 | next-tick "~1.0.0"
534 |
535 | es6-iterator@^2.0.3, es6-iterator@~2.0.3:
536 | version "2.0.3"
537 | resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
538 | integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
539 | dependencies:
540 | d "1"
541 | es5-ext "^0.10.35"
542 | es6-symbol "^3.1.1"
543 |
544 | es6-symbol@^3.1.1, es6-symbol@~3.1.3:
545 | version "3.1.3"
546 | resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
547 | integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
548 | dependencies:
549 | d "^1.0.1"
550 | ext "^1.1.2"
551 |
552 | es6-weak-map@^2.0.2:
553 | version "2.0.3"
554 | resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53"
555 | integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==
556 | dependencies:
557 | d "1"
558 | es5-ext "^0.10.46"
559 | es6-iterator "^2.0.3"
560 | es6-symbol "^3.1.1"
561 |
562 | escape-string-regexp@^1.0.5:
563 | version "1.0.5"
564 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
565 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
566 |
567 | esprima@^4.0.0:
568 | version "4.0.1"
569 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
570 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
571 |
572 | esutils@^2.0.2:
573 | version "2.0.3"
574 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
575 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
576 |
577 | event-emitter@^0.3.5:
578 | version "0.3.5"
579 | resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
580 | integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=
581 | dependencies:
582 | d "1"
583 | es5-ext "~0.10.14"
584 |
585 | eventemitter3@^4.0.4:
586 | version "4.0.4"
587 | resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384"
588 | integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==
589 |
590 | execa@^1.0.0:
591 | version "1.0.0"
592 | resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
593 | integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
594 | dependencies:
595 | cross-spawn "^6.0.0"
596 | get-stream "^4.0.0"
597 | is-stream "^1.1.0"
598 | npm-run-path "^2.0.0"
599 | p-finally "^1.0.0"
600 | signal-exit "^3.0.0"
601 | strip-eof "^1.0.0"
602 |
603 | ext@^1.1.2:
604 | version "1.4.0"
605 | resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244"
606 | integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==
607 | dependencies:
608 | type "^2.0.0"
609 |
610 | form-data@^3.0.0:
611 | version "3.0.0"
612 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682"
613 | integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==
614 | dependencies:
615 | asynckit "^0.4.0"
616 | combined-stream "^1.0.8"
617 | mime-types "^2.1.12"
618 |
619 | fs.realpath@^1.0.0:
620 | version "1.0.0"
621 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
622 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
623 |
624 | function-bind@^1.1.1:
625 | version "1.1.1"
626 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
627 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
628 |
629 | get-stream@^4.0.0:
630 | version "4.1.0"
631 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
632 | integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
633 | dependencies:
634 | pump "^3.0.0"
635 |
636 | glob@^7.1.1, glob@^7.1.6:
637 | version "7.1.6"
638 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
639 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
640 | dependencies:
641 | fs.realpath "^1.0.0"
642 | inflight "^1.0.4"
643 | inherits "2"
644 | minimatch "^3.0.4"
645 | once "^1.3.0"
646 | path-is-absolute "^1.0.0"
647 |
648 | has-flag@^3.0.0:
649 | version "3.0.0"
650 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
651 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
652 |
653 | has-flag@^4.0.0:
654 | version "4.0.0"
655 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
656 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
657 |
658 | has-symbols@^1.0.0, has-symbols@^1.0.1:
659 | version "1.0.1"
660 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
661 | integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
662 |
663 | has@^1.0.3:
664 | version "1.0.3"
665 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
666 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
667 | dependencies:
668 | function-bind "^1.1.1"
669 |
670 | hash-base@^3.0.0:
671 | version "3.1.0"
672 | resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
673 | integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
674 | dependencies:
675 | inherits "^2.0.4"
676 | readable-stream "^3.6.0"
677 | safe-buffer "^5.2.0"
678 |
679 | hash.js@^1.0.0, hash.js@^1.0.3:
680 | version "1.1.7"
681 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
682 | integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
683 | dependencies:
684 | inherits "^2.0.3"
685 | minimalistic-assert "^1.0.1"
686 |
687 | hmac-drbg@^1.0.0:
688 | version "1.0.1"
689 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
690 | integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
691 | dependencies:
692 | hash.js "^1.0.3"
693 | minimalistic-assert "^1.0.0"
694 | minimalistic-crypto-utils "^1.0.1"
695 |
696 | iconv-lite@~0.4.13:
697 | version "0.4.24"
698 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
699 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
700 | dependencies:
701 | safer-buffer ">= 2.1.2 < 3"
702 |
703 | inflight@^1.0.4:
704 | version "1.0.6"
705 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
706 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
707 | dependencies:
708 | once "^1.3.0"
709 | wrappy "1"
710 |
711 | inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4:
712 | version "2.0.4"
713 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
714 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
715 |
716 | internal-slot@^1.0.2:
717 | version "1.0.2"
718 | resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3"
719 | integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==
720 | dependencies:
721 | es-abstract "^1.17.0-next.1"
722 | has "^1.0.3"
723 | side-channel "^1.0.2"
724 |
725 | ip-regex@^4.1.0:
726 | version "4.1.0"
727 | resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.1.0.tgz#5ad62f685a14edb421abebc2fff8db94df67b455"
728 | integrity sha512-pKnZpbgCTfH/1NLIlOduP/V+WRXzC2MOz3Qo8xmxk8C5GudJLgK5QyLVXOSWy3ParAH7Eemurl3xjv/WXYFvMA==
729 |
730 | is-callable@^1.1.4, is-callable@^1.1.5:
731 | version "1.1.5"
732 | resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
733 | integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==
734 |
735 | is-date-object@^1.0.1:
736 | version "1.0.2"
737 | resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
738 | integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
739 |
740 | is-docker@^2.0.0:
741 | version "2.0.0"
742 | resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b"
743 | integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==
744 |
745 | is-promise@^2.1:
746 | version "2.2.2"
747 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
748 | integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
749 |
750 | is-regex@^1.0.5:
751 | version "1.0.5"
752 | resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
753 | integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==
754 | dependencies:
755 | has "^1.0.3"
756 |
757 | is-stream@^1.0.1, is-stream@^1.1.0:
758 | version "1.1.0"
759 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
760 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
761 |
762 | is-symbol@^1.0.2:
763 | version "1.0.3"
764 | resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
765 | integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
766 | dependencies:
767 | has-symbols "^1.0.1"
768 |
769 | is-typedarray@^1.0.0:
770 | version "1.0.0"
771 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
772 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
773 |
774 | is-wsl@^2.1.1:
775 | version "2.2.0"
776 | resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
777 | integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
778 | dependencies:
779 | is-docker "^2.0.0"
780 |
781 | isexe@^2.0.0:
782 | version "2.0.0"
783 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
784 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
785 |
786 | isomorphic-fetch@^2.2.1:
787 | version "2.2.1"
788 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
789 | integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
790 | dependencies:
791 | node-fetch "^1.0.1"
792 | whatwg-fetch ">=0.10.0"
793 |
794 | js-sha3@^0.8.0:
795 | version "0.8.0"
796 | resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
797 | integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
798 |
799 | js-tokens@^4.0.0:
800 | version "4.0.0"
801 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
802 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
803 |
804 | js-yaml@^3.13.1:
805 | version "3.13.1"
806 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
807 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
808 | dependencies:
809 | argparse "^1.0.7"
810 | esprima "^4.0.0"
811 |
812 | lodash@^4.17.19:
813 | version "4.17.19"
814 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
815 | integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
816 |
817 | lru-queue@0.1:
818 | version "0.1.0"
819 | resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3"
820 | integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=
821 | dependencies:
822 | es5-ext "~0.10.2"
823 |
824 | md5.js@^1.3.4:
825 | version "1.3.5"
826 | resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
827 | integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
828 | dependencies:
829 | hash-base "^3.0.0"
830 | inherits "^2.0.1"
831 | safe-buffer "^5.1.2"
832 |
833 | memoizee@^0.4.14:
834 | version "0.4.14"
835 | resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57"
836 | integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==
837 | dependencies:
838 | d "1"
839 | es5-ext "^0.10.45"
840 | es6-weak-map "^2.0.2"
841 | event-emitter "^0.3.5"
842 | is-promise "^2.1"
843 | lru-queue "0.1"
844 | next-tick "1"
845 | timers-ext "^0.1.5"
846 |
847 | mime-db@1.43.0:
848 | version "1.43.0"
849 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
850 | integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==
851 |
852 | mime-types@^2.1.12:
853 | version "2.1.26"
854 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06"
855 | integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==
856 | dependencies:
857 | mime-db "1.43.0"
858 |
859 | minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
860 | version "1.0.1"
861 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
862 | integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
863 |
864 | minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
865 | version "1.0.1"
866 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
867 | integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
868 |
869 | minimatch@^3.0.4:
870 | version "3.0.4"
871 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
872 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
873 | dependencies:
874 | brace-expansion "^1.1.7"
875 |
876 | minimist@0.0.8:
877 | version "0.0.8"
878 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
879 | integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
880 |
881 | mkdirp@^0.5.1:
882 | version "0.5.1"
883 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
884 | integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
885 | dependencies:
886 | minimist "0.0.8"
887 |
888 | ms@2.0.0:
889 | version "2.0.0"
890 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
891 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
892 |
893 | nan@^2.14.0:
894 | version "2.14.1"
895 | resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
896 | integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
897 |
898 | next-tick@1:
899 | version "1.1.0"
900 | resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
901 | integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
902 |
903 | next-tick@~1.0.0:
904 | version "1.0.0"
905 | resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
906 | integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
907 |
908 | nice-try@^1.0.4:
909 | version "1.0.5"
910 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
911 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
912 |
913 | node-fetch@^1.0.1:
914 | version "1.7.3"
915 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
916 | integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
917 | dependencies:
918 | encoding "^0.1.11"
919 | is-stream "^1.0.1"
920 |
921 | node-fetch@^2.6.1:
922 | version "2.6.1"
923 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
924 | integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
925 |
926 | npm-run-path@^2.0.0:
927 | version "2.0.2"
928 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
929 | integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
930 | dependencies:
931 | path-key "^2.0.0"
932 |
933 | object-inspect@^1.7.0:
934 | version "1.7.0"
935 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
936 | integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==
937 |
938 | object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
939 | version "1.1.1"
940 | resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
941 | integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
942 |
943 | object.assign@^4.1.0:
944 | version "4.1.0"
945 | resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
946 | integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
947 | dependencies:
948 | define-properties "^1.1.2"
949 | function-bind "^1.1.1"
950 | has-symbols "^1.0.0"
951 | object-keys "^1.0.11"
952 |
953 | once@^1.3.0, once@^1.3.1, once@^1.4.0:
954 | version "1.4.0"
955 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
956 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
957 | dependencies:
958 | wrappy "1"
959 |
960 | p-finally@^1.0.0:
961 | version "1.0.0"
962 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
963 | integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
964 |
965 | path-is-absolute@^1.0.0:
966 | version "1.0.1"
967 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
968 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
969 |
970 | path-key@^2.0.0, path-key@^2.0.1:
971 | version "2.0.1"
972 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
973 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
974 |
975 | path-parse@^1.0.6:
976 | version "1.0.6"
977 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
978 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
979 |
980 | pbkdf2@^3.0.9, pbkdf2@^3.1.1:
981 | version "3.1.1"
982 | resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94"
983 | integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==
984 | dependencies:
985 | create-hash "^1.1.2"
986 | create-hmac "^1.1.4"
987 | ripemd160 "^2.0.1"
988 | safe-buffer "^5.0.1"
989 | sha.js "^2.4.8"
990 |
991 | pump@^3.0.0:
992 | version "3.0.0"
993 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
994 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
995 | dependencies:
996 | end-of-stream "^1.1.0"
997 | once "^1.3.1"
998 |
999 | randombytes@^2.0.1:
1000 | version "2.1.0"
1001 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
1002 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
1003 | dependencies:
1004 | safe-buffer "^5.1.0"
1005 |
1006 | readable-stream@^3.6.0:
1007 | version "3.6.0"
1008 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
1009 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
1010 | dependencies:
1011 | inherits "^2.0.3"
1012 | string_decoder "^1.1.1"
1013 | util-deprecate "^1.0.1"
1014 |
1015 | regenerator-runtime@^0.13.4:
1016 | version "0.13.5"
1017 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
1018 | integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
1019 |
1020 | regexp.prototype.flags@^1.3.0:
1021 | version "1.3.0"
1022 | resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75"
1023 | integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==
1024 | dependencies:
1025 | define-properties "^1.1.3"
1026 | es-abstract "^1.17.0-next.1"
1027 |
1028 | resolve@^1.3.2:
1029 | version "1.15.1"
1030 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"
1031 | integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==
1032 | dependencies:
1033 | path-parse "^1.0.6"
1034 |
1035 | ripemd160@^2.0.0, ripemd160@^2.0.1:
1036 | version "2.0.2"
1037 | resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
1038 | integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
1039 | dependencies:
1040 | hash-base "^3.0.0"
1041 | inherits "^2.0.1"
1042 |
1043 | rxjs@^6.5.5:
1044 | version "6.5.5"
1045 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
1046 | integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
1047 | dependencies:
1048 | tslib "^1.9.0"
1049 |
1050 | rxjs@^6.6.2:
1051 | version "6.6.2"
1052 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2"
1053 | integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==
1054 | dependencies:
1055 | tslib "^1.9.0"
1056 |
1057 | safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
1058 | version "5.2.1"
1059 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
1060 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
1061 |
1062 | "safer-buffer@>= 2.1.2 < 3":
1063 | version "2.1.2"
1064 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
1065 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
1066 |
1067 | scryptsy@^2.1.0:
1068 | version "2.1.0"
1069 | resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790"
1070 | integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==
1071 |
1072 | semver@^5.3.0, semver@^5.5.0:
1073 | version "5.7.1"
1074 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
1075 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
1076 |
1077 | sha.js@^2.4.0, sha.js@^2.4.8:
1078 | version "2.4.11"
1079 | resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
1080 | integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
1081 | dependencies:
1082 | inherits "^2.0.1"
1083 | safe-buffer "^5.0.1"
1084 |
1085 | shebang-command@^1.2.0:
1086 | version "1.2.0"
1087 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
1088 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
1089 | dependencies:
1090 | shebang-regex "^1.0.0"
1091 |
1092 | shebang-regex@^1.0.0:
1093 | version "1.0.0"
1094 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
1095 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
1096 |
1097 | side-channel@^1.0.2:
1098 | version "1.0.2"
1099 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947"
1100 | integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==
1101 | dependencies:
1102 | es-abstract "^1.17.0-next.1"
1103 | object-inspect "^1.7.0"
1104 |
1105 | signal-exit@^3.0.0:
1106 | version "3.0.3"
1107 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
1108 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
1109 |
1110 | sprintf-js@~1.0.2:
1111 | version "1.0.3"
1112 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
1113 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
1114 |
1115 | string.prototype.matchall@^4.0.2:
1116 | version "4.0.2"
1117 | resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e"
1118 | integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==
1119 | dependencies:
1120 | define-properties "^1.1.3"
1121 | es-abstract "^1.17.0"
1122 | has-symbols "^1.0.1"
1123 | internal-slot "^1.0.2"
1124 | regexp.prototype.flags "^1.3.0"
1125 | side-channel "^1.0.2"
1126 |
1127 | string.prototype.trimend@^1.0.0:
1128 | version "1.0.1"
1129 | resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913"
1130 | integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==
1131 | dependencies:
1132 | define-properties "^1.1.3"
1133 | es-abstract "^1.17.5"
1134 |
1135 | string.prototype.trimleft@^2.1.1:
1136 | version "2.1.2"
1137 | resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc"
1138 | integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==
1139 | dependencies:
1140 | define-properties "^1.1.3"
1141 | es-abstract "^1.17.5"
1142 | string.prototype.trimstart "^1.0.0"
1143 |
1144 | string.prototype.trimright@^2.1.1:
1145 | version "2.1.2"
1146 | resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3"
1147 | integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==
1148 | dependencies:
1149 | define-properties "^1.1.3"
1150 | es-abstract "^1.17.5"
1151 | string.prototype.trimend "^1.0.0"
1152 |
1153 | string.prototype.trimstart@^1.0.0:
1154 | version "1.0.1"
1155 | resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54"
1156 | integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==
1157 | dependencies:
1158 | define-properties "^1.1.3"
1159 | es-abstract "^1.17.5"
1160 |
1161 | string_decoder@^1.1.1:
1162 | version "1.3.0"
1163 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
1164 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
1165 | dependencies:
1166 | safe-buffer "~5.2.0"
1167 |
1168 | strip-eof@^1.0.0:
1169 | version "1.0.0"
1170 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
1171 | integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
1172 |
1173 | supports-color@^5.3.0:
1174 | version "5.5.0"
1175 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
1176 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
1177 | dependencies:
1178 | has-flag "^3.0.0"
1179 |
1180 | supports-color@^7.1.0:
1181 | version "7.1.0"
1182 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
1183 | integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
1184 | dependencies:
1185 | has-flag "^4.0.0"
1186 |
1187 | timers-ext@^0.1.5:
1188 | version "0.1.7"
1189 | resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6"
1190 | integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==
1191 | dependencies:
1192 | es5-ext "~0.10.46"
1193 | next-tick "1"
1194 |
1195 | tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
1196 | version "1.11.1"
1197 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
1198 | integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
1199 |
1200 | tslint@^5.12.1:
1201 | version "5.20.1"
1202 | resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.1.tgz#e401e8aeda0152bc44dd07e614034f3f80c67b7d"
1203 | integrity sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==
1204 | dependencies:
1205 | "@babel/code-frame" "^7.0.0"
1206 | builtin-modules "^1.1.1"
1207 | chalk "^2.3.0"
1208 | commander "^2.12.1"
1209 | diff "^4.0.1"
1210 | glob "^7.1.1"
1211 | js-yaml "^3.13.1"
1212 | minimatch "^3.0.4"
1213 | mkdirp "^0.5.1"
1214 | resolve "^1.3.2"
1215 | semver "^5.3.0"
1216 | tslib "^1.8.0"
1217 | tsutils "^2.29.0"
1218 |
1219 | tsutils@^2.29.0:
1220 | version "2.29.0"
1221 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
1222 | integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
1223 | dependencies:
1224 | tslib "^1.8.1"
1225 |
1226 | tweetnacl@^1.0.3:
1227 | version "1.0.3"
1228 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
1229 | integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
1230 |
1231 | type@^1.0.1:
1232 | version "1.2.0"
1233 | resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
1234 | integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
1235 |
1236 | type@^2.0.0:
1237 | version "2.0.0"
1238 | resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3"
1239 | integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==
1240 |
1241 | typedarray-to-buffer@^3.1.5:
1242 | version "3.1.5"
1243 | resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
1244 | integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
1245 | dependencies:
1246 | is-typedarray "^1.0.0"
1247 |
1248 | typescript@^3.5.1:
1249 | version "3.8.3"
1250 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
1251 | integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
1252 |
1253 | util-deprecate@^1.0.1:
1254 | version "1.0.2"
1255 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
1256 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
1257 |
1258 | websocket@^1.0.31:
1259 | version "1.0.31"
1260 | resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.31.tgz#e5d0f16c3340ed87670e489ecae6144c79358730"
1261 | integrity sha512-VAouplvGKPiKFDTeCCO65vYHsyay8DqoBSlzIO3fayrfOgU94lQN5a1uWVnFrMLceTJw/+fQXR5PGbUVRaHshQ==
1262 | dependencies:
1263 | debug "^2.2.0"
1264 | es5-ext "^0.10.50"
1265 | nan "^2.14.0"
1266 | typedarray-to-buffer "^3.1.5"
1267 | yaeti "^0.0.6"
1268 |
1269 | whatwg-fetch@>=0.10.0:
1270 | version "3.1.0"
1271 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.1.0.tgz#49d630cdfa308dba7f2819d49d09364f540dbcc6"
1272 | integrity sha512-pgmbsVWKpH9GxLXZmtdowDIqtb/rvPyjjQv3z9wLcmgWKFHilKnZD3ldgrOlwJoPGOUluQsRPWd52yVkPfmI1A==
1273 |
1274 | which@^1.2.9:
1275 | version "1.3.1"
1276 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
1277 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
1278 | dependencies:
1279 | isexe "^2.0.0"
1280 |
1281 | wrappy@1:
1282 | version "1.0.2"
1283 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
1284 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
1285 |
1286 | xxhashjs@^0.2.2:
1287 | version "0.2.2"
1288 | resolved "https://registry.yarnpkg.com/xxhashjs/-/xxhashjs-0.2.2.tgz#8a6251567621a1c46a5ae204da0249c7f8caa9d8"
1289 | integrity sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==
1290 | dependencies:
1291 | cuint "^0.2.2"
1292 |
1293 | yaeti@^0.0.6:
1294 | version "0.0.6"
1295 | resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577"
1296 | integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=
1297 |
--------------------------------------------------------------------------------