diff --git a/package.json b/package.json index b8cca894..a562ebd1 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "ethereumjs-util": "^5.1.5", "ethereumjs-vm": "~2.3.3", "file-saver": "^2.0.0-rc.4", + "ipfs-api": "^26.1.2", "jszip": "^3.1.5", "jszip-utils": "^0.0.2", "less": "^3.8.1", @@ -113,6 +114,7 @@ "react-splitter-layout": "^3.0.1", "react-switch": "^3.0.4", "react-tippy": "^1.2.3", + "react-toastify": "^4.5.2", "redux": "^4.0.0", "redux-observable": "^1.0.0", "redux-persist": "^5.10.0", diff --git a/src/actions/index.js b/src/actions/index.js index 61f1d980..7c2b05bf 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,6 +1,8 @@ export * from './app.actions'; export * from './panes.actions'; -export * from './projects.actions'; +export * from './project.actions'; export * from './explorer.actions'; export * from './sidePanels.actions'; export * from './settings.actions'; +export * from './ipfs.actions'; +export * from './toast.actions'; diff --git a/src/actions/ipfs.actions.js b/src/actions/ipfs.actions.js new file mode 100644 index 00000000..4f83c287 --- /dev/null +++ b/src/actions/ipfs.actions.js @@ -0,0 +1,123 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export const ipfsActions = { + UPLOAD_TO_IPFS: 'UPLOAD_TO_IPFS', + uploadToIPFS(uploadSettings) { + return { + type: ipfsActions.UPLOAD_TO_IPFS, + data: { uploadSettings } + }; + }, + UPLOAD_TO_IPFS_SUCCESS: 'UPLOAD_TO_IPFS_SUCCESS', + uploadToIPFSSuccess({ timestamp, shareURL }) { + return { + type: ipfsActions.UPLOAD_TO_IPFS_SUCCESS, + data: { timestamp, shareURL } + } + }, + UPLOAD_TO_IPFS_FAIL: 'UPLOAD_TO_IPFS_FAIL', + uploadToIPFSFail(error) { + return { + type: ipfsActions.UPLOAD_TO_IPFS_FAIL, + data: error + } + }, + RESTORE_IPFS_STATE_SUCCESS: 'RESTORE_IPFS_STATE_SUCCESS', + restoreIPFSStateSuccess({ timestamp, shareURL }) { + return { + type: ipfsActions.RESTORE_IPFS_STATE_SUCCESS, + data: { timestamp, shareURL } + } + }, + RESTORE_IPFS_STATE_FAIL: 'RESTORE_IPFS_STATE_FAIL', + restoreIPFSStateFail() { + return { + type: ipfsActions.RESTORE_IPFS_STATE_FAIL, + } + }, + SHOW_UPLOAD_SETTINGS: 'SHOW_UPLOAD_SETTINGS', + showUploadSettings() { + return { + type: ipfsActions.SHOW_UPLOAD_SETTINGS, + } + }, + HIDE_UPLOAD_SETTINGS: 'HIDE_UPLOAD_SETTINGS', + hideUploadSettings() { + return { + type: ipfsActions.HIDE_UPLOAD_SETTINGS, + } + }, + UPLOAD_SETTINGS_CHANGED: 'UPLOAD_SETTINGS_CHANGED', + uploadSettingsChanged(uploadSettings) { + return { + type: ipfsActions.UPLOAD_SETTINGS_CHANGED, + data: uploadSettings + } + }, + HIDE_UPLOAD_DIALOG: 'HIDE_UPLOAD_DIALOG', + hideUploadDialog() { + return { + type: ipfsActions.HIDE_UPLOAD_DIALOG, + } + }, + FORK_PROJECT: 'FORK_PROJECT', + forkProject() { + return { + type: ipfsActions.FORK_PROJECT, + } + }, + FORK_PROJECT_SUCCESS: 'FORK_PROJECT_SUCCESS', + forkProjectSuccess() { + return { + type: ipfsActions.FORK_PROJECT_SUCCESS, + } + }, + FORK_PROJECT_FAIL: 'FORK_PROJECT_FAIL', + forkProjectFail(error) { + return { + type: ipfsActions.FORK_PROJECT_FAIL, + data: error + } + }, + IMPORT_PROJECT_FROM_IPFS: 'IMPORT_PROJECT_FROM_IPFS', + importProjectFromIpfs(hash) { + return { + type: ipfsActions.IMPORT_PROJECT_FROM_IPFS, + data: hash + } + }, + IMPORT_PROJECT_FROM_IPFS_SUCCESS: 'IMPORT_PROJECT_FROM_IPFS_SUCCESS', + importProjectFromIpfsSuccess() { + return { + type: ipfsActions.IMPORT_PROJECT_FROM_IPFS_SUCCESS, + } + }, + IMPORT_PROJECT_FROM_IPFS_FAIL: 'IMPORT_PROJECT_FROM_IPFS_FAIL', + importProjectFromIpfsFail(error) { + return { + type: ipfsActions.IMPORT_PROJECT_FROM_IPFS_FAIL, + data: error + } + }, + UPDATE_IPFS_ACTION_BUTTONS: 'UPDATE_IPFS_ACTION_BUTTONS', + updateIpfsActionButtons({ showUploadButton, showForkButton }) { + return { + type: ipfsActions.UPDATE_IPFS_ACTION_BUTTONS, + data: { showUploadButton, showForkButton } + } + } +} diff --git a/src/actions/project.actions.js b/src/actions/project.actions.js new file mode 100644 index 00000000..0d1eb05a --- /dev/null +++ b/src/actions/project.actions.js @@ -0,0 +1,48 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export const projectActions = { + SELECT_PROJECT: 'SELECT_PROJECT', + selectProject(project) { + return { + type: projectActions.SELECT_PROJECT, + data: project + }; + }, + UPDATE_PROJECT_SETTINGS: 'UPDATE_PROJECT_SETTINGS', + updateProjectSettings(projectSettings) { + return { + type: projectActions.UPDATE_PROJECT_SETTINGS, + data: projectSettings + }; + }, + UPDATE_PROJECT_SETTINGS_SUCCESS: 'UPDATE_PROJECT_SETTINGS_SUCCESS', + updateProjectSettingsSuccess(newProjectSettings) { + return { + type: projectActions.UPDATE_PROJECT_SETTINGS_SUCCESS, + data: newProjectSettings, + }; + }, + UPDATE_PROJECT_SETTINGS_FAIL: 'UPDATE_PROJECT_SETTINGS_FAIL', + updateProjectSettingsFail(error) { + return { + type: projectActions.UPDATE_PROJECT_SETTINGS_FAIL, + error: error + }; + } +} + + diff --git a/src/actions/projects.actions.js b/src/actions/projects.actions.js deleted file mode 100644 index 71a07679..00000000 --- a/src/actions/projects.actions.js +++ /dev/null @@ -1,6 +0,0 @@ -export function selectProject(project) { - return { - type: 'SELECT_PROJECT', - data: project - }; -} diff --git a/src/actions/toast.actions.js b/src/actions/toast.actions.js new file mode 100644 index 00000000..da13b6d1 --- /dev/null +++ b/src/actions/toast.actions.js @@ -0,0 +1,25 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export const toastActions = { + TOAST_DISMISSED: 'TOAST_DISMISSED', + toastDismissed(id) { + return { + type: toastActions.TOAST_DISMISSED, + data: id + }; + } +} diff --git a/src/actions/view.js b/src/actions/view.js new file mode 100644 index 00000000..b83ab555 --- /dev/null +++ b/src/actions/view.js @@ -0,0 +1,20 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export const closeAllPanels = () => ({ type: 'CLOSE_ALL_PANELS' }); +export const toggleTransactionsHistoryPanel = () => ({ type: 'TOGGLE_TRANSACTIONS_HISTORY_PANEL' }); +export const openTransactionsHistoryPanel = () => ({ type: 'OPEN_TRANSACTIONS_HISTORY_PANEL' }); +export const closeTransactionsHistoryPanel = () => ({ type: 'CLOSE_TRANSACTIONS_HISTORY_PANEL' }); diff --git a/src/assets/static/img/icon-information.svg b/src/assets/static/img/icon-information.svg new file mode 100644 index 00000000..0575adb1 --- /dev/null +++ b/src/assets/static/img/icon-information.svg @@ -0,0 +1 @@ + diff --git a/src/assets/static/img/img-ipfs-logo.svg b/src/assets/static/img/img-ipfs-logo.svg new file mode 100644 index 00000000..0b9b67de --- /dev/null +++ b/src/assets/static/img/img-ipfs-logo.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/app/App.js b/src/components/app/App.js index c4f52617..ad2fdc1a 100644 --- a/src/components/app/App.js +++ b/src/components/app/App.js @@ -17,7 +17,6 @@ import React, { Component } from 'react'; import classNames from 'classnames'; import PropTypes from 'prop-types'; - import Backend from '../projecteditor/control/backend'; import Modal from '../modal'; import ProjectEditor from '../projecteditor'; @@ -25,9 +24,10 @@ import { Wallet } from '../projecteditor/wallet'; import Solc from '../solc'; import EVM from '../evm'; import Networks from '../../networks'; -import { previewService } from '../../services'; +import { previewService, ipfsService } from '../../services'; import AnalyticsDialog from '../analyticsDialog'; import OnlyIf from '../onlyIf'; +import ToastContainer from "../toasts/toastcontainer"; export default class App extends Component { @@ -39,16 +39,14 @@ export default class App extends Component { constructor(props) { super(props); this.idCounter = 0; + this.isImportedProject = false; + this.backend = new Backend(); this.session = { start_time: Date.now(), }; - // Used to communicate between components, events is probably a better way of doing this. - this.router = { - register: this.register, - }; - + this.router = this.props.router; this.router.register('app', this); this.functions = { @@ -94,8 +92,7 @@ export default class App extends Component { } _convertProjects = cb => { - const backend = new Backend(); - backend.convertProjects(status => { + this.backend.convertProjects(status => { if (status == 1) { const modalData = { title: 'Projects converted', @@ -137,10 +134,6 @@ export default class App extends Component { this.forceUpdate(); }; - register = (name, obj) => { - this.router[name] = obj; - }; - _init = () => { let { appVersion } = this.props; const modalData = { @@ -162,12 +155,15 @@ export default class App extends Component { this.functions.EVM = new EVM({ id: this.generateId() }); previewService.init(this.functions.wallet); + ipfsService.init(this.backend); const fn = () => { if (this.functions.compiler && this.functions.EVM) { console.log('Superblocks Lab ' + appVersion + ' Ready.'); this.functions.modal.close(); + + this._checkIpfsOnUrl(); } else { setTimeout(fn, 500); } @@ -175,6 +171,15 @@ export default class App extends Component { fn(); }; + _checkIpfsOnUrl = () => { + const a = document.location.href.match("^.*/ipfs/(.+)$"); + if (a) { + // TODO: pop modal about importing being processed. + this.isImportedProject = true; + this.props.importProjectFromIpfs(a[1]); + } + }; + session_start_time = () => { return this.session.start_time; }; @@ -261,10 +266,12 @@ export default class App extends Component { router={this.router} functions={this.functions} knownWalletSeed={this.knownWalletSeed} + isImportedProject={this.isImportedProject} /> + @@ -277,6 +284,7 @@ export default class App extends Component { } App.propTypes = { + router: PropTypes.object.isRequired, appVersion: PropTypes.string.isRequired, notifyAppStart: PropTypes.func.isRequired } diff --git a/src/components/app/index.js b/src/components/app/index.js index 73fc4a26..d5a6eed8 100644 --- a/src/components/app/index.js +++ b/src/components/app/index.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import { appActions } from '../../actions'; +import { appActions, ipfsActions } from '../../actions'; import { getShowAnalyticsTrackingDialog } from '../../selectors/settings'; import { getAppVersion } from '../../selectors/app'; import App from './App'; @@ -13,7 +13,10 @@ const mapDispatchToProps = dispatch => { return { notifyAppStart: () => { dispatch(appActions.notifyAppStart()); - } + }, + importProjectFromIpfs: (hash) => { + dispatch(ipfsActions.importProjectFromIpfs(hash)); + }, }; }; diff --git a/src/components/bottomBar/BottomBar.js b/src/components/bottomBar/BottomBar.js index c724f1a9..57cc3163 100644 --- a/src/components/bottomBar/BottomBar.js +++ b/src/components/bottomBar/BottomBar.js @@ -17,6 +17,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import style from './style.less'; +import Note from '../note'; export default class BottomBar extends Component { @@ -31,8 +32,10 @@ export default class BottomBar extends Component { return (
- Note - All files are stored in the browser only, download to backup +
Gas Limit: {networkPreferences.gasLimit} diff --git a/src/components/bottomBar/style.less b/src/components/bottomBar/style.less index 8fb9119e..aa1d972a 100644 --- a/src/components/bottomBar/style.less +++ b/src/components/bottomBar/style.less @@ -69,18 +69,4 @@ } } } - .note { - background-color: #F8E71C; - color: #262E33; - font-weight: 600; - padding: 1px 8px 1px 8px; - border-radius: 4px; - - span { - font-size: 10px; - } - } - .noteText { - margin-left: 10px; - } } diff --git a/src/components/common/dropdown/index.js b/src/components/common/dropdown/index.js index a94740c9..ec4a89bb 100644 --- a/src/components/common/dropdown/index.js +++ b/src/components/common/dropdown/index.js @@ -22,34 +22,48 @@ Dropdown.proptypes = { * Helper component to handle the state of showing/hiding a dropdown */ export class DropdownContainer extends Component { + + state = { + showMenu: this.props.showMenu, + } + constructor(props) { super(props); - this.state = { - menuVisible: false, - }; - // the ignore class name should be specific only this instance of the component // in order to close other dropdown in case a new one is opened this.ignoreClassName = 'ignore-react-onclickoutside' + Date.now(); } + componentDidUpdate(prevProps) { + if (prevProps.showMenu !== this.props.showMenu) { + this.setState({ + showMenu: {...this.props.showMenu} + }); + } + } + showMenu = () => { - this.setState({ menuVisible: true }); + this.setState({ showMenu: true }); }; toggleMenu = (e) => { e.stopPropagation(); - this.setState((state) => ({ menuVisible: !state.menuVisible })); + this.setState((state) => ({ showMenu: !state.showMenu })); }; closeMenu = e => { e.stopPropagation(); - this.setState({ menuVisible: false }); + + if (this.props.onCloseMenu) { + this.props.onCloseMenu(); + } + + this.setState({ showMenu: false }); }; render() { - const { dropdownContent, useRightClick, ...props } = this.props; + const { dropdownContent, useRightClick, enableClickInside, className } = this.props; let main; if (useRightClick) { @@ -59,13 +73,13 @@ export class DropdownContainer extends Component { } return ( -
+
{main} - { this.state.menuVisible && + { this.state.showMenu && {dropdownContent} } @@ -73,3 +87,11 @@ export class DropdownContainer extends Component { ); } } + +DropdownContainer.proptypes = { + enableClickInside: PropTypes.bool, + dropdownContent: PropTypes.object, + className: PropTypes.string.object, + showMenu: PropTypes.bool, + onCloseMenu: PropTypes.func, +}; diff --git a/src/components/icons/index.js b/src/components/icons/index.js index 93a1d055..df51ef34 100644 --- a/src/components/icons/index.js +++ b/src/components/icons/index.js @@ -46,6 +46,7 @@ import {faPencilAlt as iconPencil} from '@fortawesome/free-solid-svg-icons/faPen import {faArrowAltCircleDown as iconDownload} from '@fortawesome/free-regular-svg-icons/faArrowAltCircleDown'; import {faThLarge as iconMosaic} from '@fortawesome/free-solid-svg-icons/faThLarge'; import {faLink as iconChain} from '@fortawesome/free-solid-svg-icons/faLink'; +import {faShareAlt as iconShare} from '@fortawesome/free-solid-svg-icons/faShareAlt'; import {faCopy as iconCopy} from '@fortawesome/free-regular-svg-icons/faCopy'; class IconImg extends Component { @@ -64,6 +65,7 @@ class IconImg extends Component { export const IconDeployGreen = ({...props}) => ; export const IconAddFile = ({...props}) => ; export const IconAddFolder = ({...props}) => ; +export const IconInformation = ({...props}) => ; export const IconRun = () => ; export const IconSave = () => ; export const IconCompile = () => ; @@ -75,7 +77,6 @@ export const IconInteract = ({ ...props }) => ( ); export const IconTrash = () => ; -export const IconCopy = () => ; export const IconGem = () => ; export const IconFile = () => ; export const IconFileAlt = () => ; @@ -99,7 +100,6 @@ export const IconClone = () => ; export const IconDownload = ({ ...props }) => ( ); -export const IconUpload = () => ; export const IconDropdown = ({ ...props }) => ( ); @@ -126,6 +126,11 @@ export const IconPublicAddress = ({ ...props }) => ( export const IconMosaic = ({ ...props }) => ( ); +export const IconCopy = ({ ...props }) => ( + +); +export const IconBack= ({...props}) => +export const IconWarning = ({...props}) => // Top Bar export const IconTransactions = ({ ...props }) => @@ -137,6 +142,9 @@ export const IconProjectSelector = ({ ...props }) => ( ); export const IconHelp = () => ; export const IconCheck = () => ; +export const IconShare = () => ; +export const IconUpload = ({...props}) => ; +export const IconFork = ({...props}) => // File types export const IconContract = ({...props}) => ; diff --git a/src/components/newdapp/index.js b/src/components/newdapp/index.js index 04942a5a..65c2deb6 100644 --- a/src/components/newdapp/index.js +++ b/src/components/newdapp/index.js @@ -19,7 +19,7 @@ import Proptypes from 'prop-types'; import SelectedTemplate from './selectTemplate'; import ProjectDetails from './projectDetails'; import Templates from '../../templates'; -import { logEvent, Analytics, LogOnMount } from "../../utils/analytics"; +import { logEvent } from "../../utils/analytics"; import DappfileItem from '../projecteditor/control/item/dappfileItem'; import JSZipUtils from 'jszip-utils'; diff --git a/src/components/note/index.js b/src/components/note/index.js new file mode 100644 index 00000000..4e2acad8 --- /dev/null +++ b/src/components/note/index.js @@ -0,0 +1,42 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import React from 'react'; +import Proptypes from 'prop-types'; +import classNames from 'classnames'; +import style from './style.less'; + +const Note = ({ + title, + text, + backgroundColor = "#F8E71C", + color = "#262E33", + textClassName = {}, +} = props) => ( +
+ {title} + { text && {text} } +
+); + +export default Note; + +Note.propTypes = { + title: Proptypes.string.isRequired, + text: Proptypes.string, + backgroundColor: Proptypes.string, + color: Proptypes.string +} diff --git a/src/components/note/style.less b/src/components/note/style.less new file mode 100644 index 00000000..102d2582 --- /dev/null +++ b/src/components/note/style.less @@ -0,0 +1,12 @@ +.note { + padding: 1px 8px 1px 8px; + border-radius: 4px; + font-size: 12px; + + span { + font-size: 10px; + } +} +.noteText { + margin-left: 10px; +} diff --git a/src/components/projecteditor/ProjectEditor.js b/src/components/projecteditor/ProjectEditor.js index 58fc6642..43145a22 100644 --- a/src/components/projecteditor/ProjectEditor.js +++ b/src/components/projecteditor/ProjectEditor.js @@ -151,6 +151,7 @@ export default class ProjectEditor extends Component {
diff --git a/src/components/projecteditor/control/backend.js b/src/components/projecteditor/control/backend.js index 7b984c54..ed58432d 100644 --- a/src/components/projecteditor/control/backend.js +++ b/src/components/projecteditor/control/backend.js @@ -14,18 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Superblocks Lab. If not, see . -const JSZip = require("jszip"); -const FileSaver = require('file-saver'); +import JSZip from 'jszip'; +import FileSaver from 'file-saver'; -const DAPP_FORMAT_VERSION = 'dapps1.1.0'; export default class Backend { - constructor() {} + + static DAPP_FORMAT_VERSION = 'dapps1.1.0'; // Make sure projects created for an older version are converted to the current format. // dapps1.0 is the 1.0 BETA which is deprecated. // dapps1.0.0 is the released 1.0 format and will be converted into 1.1.0. convertProjects = cb => { - if (!localStorage.getItem(DAPP_FORMAT_VERSION)) { + if (!localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) { if (localStorage.getItem('dapps1.0.0')) { // Convert from 1.0 (beta) to 1.0.0. const data = JSON.parse(localStorage.getItem('dapps1.0.0')); @@ -49,7 +49,7 @@ export default class Backend { // store projects. const newData = { projects: newProjects }; localStorage.setItem( - DAPP_FORMAT_VERSION, + Backend.DAPP_FORMAT_VERSION, JSON.stringify(newData) ); cb(1); // Indicate that there are converted projects. @@ -137,7 +137,7 @@ export default class Backend { }); const dappfile2 = { - format: DAPP_FORMAT_VERSION.substr(5), // IMPORTANT: if the format of this variable changes this must be updated. We only want the "x.y.z" part. + format: Backend.DAPP_FORMAT_VERSION.substr(5), // IMPORTANT: if the format of this variable changes this must be updated. We only want the "x.y.z" part. project: dappfile.project, environments: dappfile.environments, wallets: wallets, @@ -388,13 +388,60 @@ export default class Backend { return newProject; }; + // Add a new inode number to the project + assignNewInode = (inode, cb) => { + const data = + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; + if (!data.projects) data.projects = []; + + const projects = data.projects.map(project => { + if (project.inode === inode) { + project.inode = this.generateRandomInode(data.projects); + return project; + } else { + return project; + } + }); + + data.projects = projects; + localStorage.setItem(Backend.DAPP_FORMAT_VERSION, JSON.stringify(data)); + cb(); + }; + + // Add additional text to dappfile when forking + modifyDappFile(files) { + let root = files['/'].children; + let dappfile = JSON.parse(root['dappfile.json'].contents); + let name = dappfile.project.info.name; + dappfile.project.info.name = `${name}_copy`; + let contents = JSON.stringify(dappfile); + root["dappfile.json"].contents = contents; + + return files; + } + + /** + * Like the newFile method but actually wrapped around a promise + */ + newFilePromise = (inode, patch, file) => { + return new Promise((resolve, reject) => { + this.newFile(inode, patch, file, status => { + if (status !== 0) { + reject(status); + } else { + resolve(); + } + }); + }) + } + /** * Create a new file for a project. * */ newFile = (inode, path, file, cb) => { const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; @@ -403,7 +450,7 @@ export default class Backend { })[0]; if (!project) { - setTimeout(() => cb(3), 1); + setTimeout(() => cb(2), 1); return; } @@ -412,7 +459,7 @@ export default class Backend { } if (path[0] != '/') { - setTimeout(() => cb(3), 1); + setTimeout(() => cb(2), 1); return; } if (!project.files) @@ -433,14 +480,14 @@ export default class Backend { file = file.substring(0, file.length - 1); } if (folder.children[file]) { - setTimeout(() => cb(3), 1); + setTimeout(() => cb(1), 1); return; } folder.children[file] = { type: type, children: type == 'd' ? {} : null, }; - localStorage.setItem(DAPP_FORMAT_VERSION, JSON.stringify(data)); + localStorage.setItem(Backend.DAPP_FORMAT_VERSION, JSON.stringify(data)); setTimeout(() => cb(0), 1); }; @@ -485,7 +532,7 @@ export default class Backend { } const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; @@ -549,7 +596,7 @@ export default class Backend { targetFolder.children[b[2]] = o; - localStorage.setItem(DAPP_FORMAT_VERSION, JSON.stringify(data)); + localStorage.setItem(Backend.DAPP_FORMAT_VERSION, JSON.stringify(data)); setTimeout(() => cb(0), 1); } catch(e) { setTimeout(() => cb(6), 1); @@ -563,7 +610,7 @@ export default class Backend { */ deleteFile = (inode, path, cb) => { const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; @@ -594,7 +641,7 @@ export default class Backend { folder = folder2; } delete folder.children[parts[parts.length - 1]]; - localStorage.setItem(DAPP_FORMAT_VERSION, JSON.stringify(data)); + localStorage.setItem(Backend.DAPP_FORMAT_VERSION, JSON.stringify(data)); if (cb) setTimeout(() => cb(0), 1); }; @@ -604,7 +651,7 @@ export default class Backend { */ listFiles = (inode, path, cb) => { const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; @@ -653,7 +700,7 @@ export default class Backend { */ deleteProject = (inode, cb) => { const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; const projects = data.projects.filter(item => { @@ -661,7 +708,7 @@ export default class Backend { }); data.projects = projects; - localStorage.setItem(DAPP_FORMAT_VERSION, JSON.stringify(data)); + localStorage.setItem(Backend.DAPP_FORMAT_VERSION, JSON.stringify(data)); cb(); }; @@ -671,7 +718,7 @@ export default class Backend { */ loadProjects = cb => { const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; const projects = []; (data.projects || []).map(project => { // We need to parse the `/dappfile.json` @@ -692,21 +739,58 @@ export default class Backend { setTimeout(() => cb(0, projects), 1); }; - createProject = (files, cb) => { + + /** + * Get Files belonging to a given inode + */ + getProjectFiles = (inode) => { + return new Promise((resolve, reject) => { + const data = + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; + if (!data.projects) data.projects = []; + + const project = data.projects.filter(item => { + return item.inode === inode; + }); + + if (project.length) { + resolve(project[0].files); + } else { + reject("Project with given inode doesn't exist"); + } + }) + } + + createProject = (files, cb, isTemporary) => { const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; - const inode = Math.floor(Math.random() * 10000000); - // TODO: check if project with this inode already exists. - const project = { + let inode = 1; + + if (isTemporary) { + if (this.isDuplicateInode(data.projects, inode)) { + // if duplicate with inode == 1, overwrite + data.projects = data.projects.filter(function( project ) { + return project.inode !== inode; + }); + } + } + else { + // smallest random number to be generated is 2, 1 is reserved for temporary projects + inode = this.generateRandomInode(data.projects); + } + + let project = { inode: inode, files: files, }; + data.projects.push(project); + try { - localStorage.setItem(DAPP_FORMAT_VERSION, JSON.stringify(data)); + localStorage.setItem(Backend.DAPP_FORMAT_VERSION, JSON.stringify(data)); } catch(e) { alert("Error: The browser local storage exceeded it's quota. Please delete some projects to make room for new ones."); @@ -716,13 +800,28 @@ export default class Backend { setTimeout(() => cb(0), 1); }; + /** + * Like the newFile method but actually wrapped around a promise + */ + saveFilePromise = (inode, payload) => { + return new Promise((resolve, reject) => { + this.saveFile(inode, payload, ({ status }) => { + if (status !== 0) { + reject(status); + } else { + resolve(); + } + }); + }) + } + /** * Save the contents of a file within a project. * */ saveFile = (inode, payload, cb) => { const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; @@ -756,7 +855,7 @@ export default class Backend { contents: payload.contents, }; try { - localStorage.setItem(DAPP_FORMAT_VERSION, JSON.stringify(data)); + localStorage.setItem(Backend.DAPP_FORMAT_VERSION, JSON.stringify(data)); } catch (e) { console.error(e); setTimeout(() => cb({ status: 1 }), 1); @@ -765,13 +864,29 @@ export default class Backend { setTimeout(() => cb({ status: 0 }), 1); }; + + /** + * Like the loadFile method but actually wrapped around a promise + */ + loadFilePromise = (inode, patch) => { + return new Promise((resolve, reject) => { + this.loadFile(inode, patch, ({ status, contents }) => { + if (status !== 0) { + reject(status); + } else { + resolve(contents); + } + }); + }) + } + /** * Load the contents of a file within a project. * */ loadFile = (inode, path, cb) => { const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; @@ -809,13 +924,27 @@ export default class Backend { else setTimeout(() => cb({ status: 1 }), 1); }; + isDuplicateInode (projects, inode) { + return projects.find((project) => project.inode === inode); + } + + generateRandomInode(projects) { + let inode = 0; + do { + inode = Math.floor(Math.random() * 10000000 + 2); + } + while (this.isDuplicateInode(projects, inode)); + + return inode; + } + downloadProject = (item, keepState) => { const exportName = 'superblocks_project_' + item.getName() + '.zip'; const zip = new JSZip(); const data = - JSON.parse(localStorage.getItem(DAPP_FORMAT_VERSION)) || {}; + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; if (!data.projects) data.projects = []; @@ -950,5 +1079,5 @@ export default class Backend { reject(); }); }); - } + }; } diff --git a/src/components/projecteditor/control/control.js b/src/components/projecteditor/control/control.js index 7d772c4b..c5bb623b 100644 --- a/src/components/projecteditor/control/control.js +++ b/src/components/projecteditor/control/control.js @@ -23,8 +23,7 @@ import Backend from './backend'; import NewDapp from '../../newdapp'; import NetworkAccountSelector from '../../networkAccountSelector'; import LearnAndResources from '../../learnAndResources'; -import { previewService } from '../../../services'; - +import { ipfsService, previewService } from '../../../services'; import { IconCube, } from '../../icons'; @@ -56,7 +55,7 @@ export default class Control extends Component { this.state = { activeProject: null, menu: menu - } + }; props.router.register('control', this); } @@ -64,8 +63,12 @@ export default class Control extends Component { componentDidMount() { this._loadProjects(status => { if (status == 0) { - if (!this._openLastProject()) { - this._showWelcome(); + // Make sure no project gets loaded if we are importing one from IPFS + if (!this.props.isImportedProject) { + if (!this._openLastProject()) { + this._setProjectActive(null); + this._showWelcome(); + } } } }); @@ -103,7 +106,7 @@ export default class Control extends Component { lightProjects.map(lightProject => { const exists = this._projectsList.filter(project => { - if (project.getInode() == lightProject.inode) { + if (project.getInode() === lightProject.inode && lightProject.inode !== 1) { projectsList.push(project); return true; } @@ -137,7 +140,7 @@ export default class Control extends Component { let { selectedProjectId } = this.props; let found = false; this._projectsList.forEach(project => { - if (selectedProjectId && selectedProjectId === project.getInode()) { + if (selectedProjectId && selectedProjectId === project.getInode() && selectedProjectId !== 1) { this.openProject(project); found = true; } @@ -191,6 +194,11 @@ export default class Control extends Component { return; } + // if we switch from temporary project, discard it + if (project.getInode() !== 1) { + ipfsService.clearTempProject(); + } + this._closeProject(status => { if (status == 0) { project.load(status => { @@ -386,7 +394,7 @@ export default class Control extends Component { if (cb) cb(1); }; - importProject = files => { + importProject = (files, isTemporary) => { const cb = status => { if (status == 0) { this._loadProjects(() => { @@ -406,7 +414,7 @@ export default class Control extends Component { } }; - this.props.router.control.backend.createProject(files, cb); + this.props.router.control.backend.createProject(files, cb, isTemporary); }; deleteProject = (project, cb) => { @@ -595,9 +603,7 @@ export default class Control extends Component { ); render() { - //const item=this._renderItem(0, 0, this.state.menu); const item = this.state.menu.render(); - //item.key="controltree"; return (
diff --git a/src/components/projecteditor/control/index.js b/src/components/projecteditor/control/index.js index 9b45aea2..3d7b609f 100644 --- a/src/components/projecteditor/control/index.js +++ b/src/components/projecteditor/control/index.js @@ -1,19 +1,18 @@ import { connect } from 'react-redux'; - import Control from './control'; import { getAppVersion } from '../../../selectors/app'; -import { getSelectedProjectId } from '../../../selectors/projects'; -import { selectProject, explorerActions, sidePanelsActions } from '../../../actions'; +import { projectSelectors } from '../../../selectors'; +import { projectActions, explorerActions, sidePanelsActions } from '../../../actions'; const mapStateToProps = state => ({ appVersion: getAppVersion(state), - selectedProjectId: getSelectedProjectId(state), + selectedProjectId: projectSelectors.getSelectedProjectId(state) }); const mapDispatchToProps = dispatch => { return { selectProject: (id, name) => { - dispatch(selectProject(id, name)); + dispatch(projectActions.selectProject(id, name)); }, closeAllPanels: () => { dispatch(sidePanelsActions.closeAllPanels()) diff --git a/src/components/projecteditor/control/item/dappfileItem.js b/src/components/projecteditor/control/item/dappfileItem.js index f2af96b5..a95d9c5f 100644 --- a/src/components/projecteditor/control/item/dappfileItem.js +++ b/src/components/projecteditor/control/item/dappfileItem.js @@ -34,6 +34,9 @@ export default class DappfileItem extends FileItem { this._save = this.save; this.save = this.__save; delete this.__save; + this._setContents = this.setContents; + this.setContents = this.__setContents; + delete this.__setContents; } /** @@ -60,7 +63,7 @@ export default class DappfileItem extends FileItem { }) .catch(() => { this.props.state.dappfile = new Dappfile( - this.getDefaultDappfile() + DappfileItem.getDefaultDappfile() ); this.save() .then(() => { @@ -79,10 +82,27 @@ export default class DappfileItem extends FileItem { * */ __save = () => { - this.setContents(this.getDappfile().dump()); + this._setContents(this.getDappfile().dump()); return this._save(); }; + /** + * Note: This actually shadows super.setContents. + */ + __setContents = (contents) => { + try { + const obj = JSON.parse(contents); + if (DappfileItem.validateDappfile(obj)) { + this.props.state.dappfile = new Dappfile(obj); + this._setContents(JSON.stringify(obj, null, 4)); + return; + } + } + catch(e) { + } + console.error('Dappfile data invalid.'); + }; + getDappfile = () => { return this.props.state.dappfile; }; @@ -105,6 +125,8 @@ export default class DappfileItem extends FileItem { if (!dappfile.accounts) { dappfile.accounts = defDappfile.accounts; } + + return true; }; static getDefaultDappfile = () => { diff --git a/src/components/projecteditor/control/item/fileItem/directoryEntry.js b/src/components/projecteditor/control/item/fileItem/directoryEntry.js index 78169b32..a7805600 100644 --- a/src/components/projecteditor/control/item/fileItem/directoryEntry.js +++ b/src/components/projecteditor/control/item/fileItem/directoryEntry.js @@ -20,7 +20,6 @@ import { IconEdit, IconAddFile, IconAddFolder, - IconImportFile } from '../../../../icons'; import style from '../../style.less'; import { DropdownContainer } from '../../../../common'; @@ -35,12 +34,11 @@ export class DirectoryEntry extends Component { title, angleClicked, clickNewFile, - clickImportFile, clickNewFolder, clickRenameFile, clickDeleteFile, fullPath, - icons + icons, } = this.props; const alwaysVisible = fullPath === "/"; @@ -53,12 +51,6 @@ export class DirectoryEntry extends Component {
Create File
-
-
- -
- Import File -
@@ -129,4 +121,3 @@ export class DirectoryEntry extends Component { ); } } - diff --git a/src/components/projecteditor/control/item/projectItem.js b/src/components/projecteditor/control/item/projectItem.js index 89f4f51b..e6452cf6 100644 --- a/src/components/projecteditor/control/item/projectItem.js +++ b/src/components/projecteditor/control/item/projectItem.js @@ -26,7 +26,7 @@ import WalletsItem from './walletsItem'; import WalletItem from './walletItem'; import EnvironmentsItem from './environmentsItem'; import EnvironmentItem from './environmentItem'; -import { IconShowPreview } from '../../../icons'; +import { IconConfigure } from '../../../icons'; import Backend from '../backend'; import TransactionLogData from '../../sidePanels/blockexplorer/transactionlogdata'; @@ -63,6 +63,14 @@ export default class ProjectItem extends Item { return this.props.state.title || ''; }; + getHeaderTitle = () => { + return 'Project Settings'; + } + + getIcon = () => { + return ; + }; + getName = () => { const dappfile = this._getDappfile(); if (dappfile) { diff --git a/src/components/projecteditor/control/style.less b/src/components/projecteditor/control/style.less index 1e020879..df6f0d3e 100644 --- a/src/components/projecteditor/control/style.less +++ b/src/components/projecteditor/control/style.less @@ -38,6 +38,7 @@ select { text-decoration: none; } } + .treemenu { display: block; overflow-y: auto; diff --git a/src/components/projecteditor/deployer/mainnetWarning/index.js b/src/components/projecteditor/deployer/mainnetWarning/index.js index 5fa9f5b8..bfa04e53 100644 --- a/src/components/projecteditor/deployer/mainnetWarning/index.js +++ b/src/components/projecteditor/deployer/mainnetWarning/index.js @@ -15,11 +15,11 @@ // along with Superblocks Lab. If not, see . import { connect } from 'react-redux'; -import { getSelectedProject } from '../../../../selectors/projects'; +import { projectSelectors } from '../../../../selectors'; import MainnetWarning from './MainnetWarning'; const mapStateToProps = state => ({ - selectedProject: getSelectedProject(state), + selectedProject: projectSelectors.getSelectedProject(state), }); export default connect(mapStateToProps, null)(MainnetWarning); diff --git a/src/components/projecteditor/editors/editor.js b/src/components/projecteditor/editors/editor/Editor.js similarity index 93% rename from src/components/projecteditor/editors/editor.js rename to src/components/projecteditor/editors/editor/Editor.js index fc1ddcc7..e0e747e4 100644 --- a/src/components/projecteditor/editors/editor.js +++ b/src/components/projecteditor/editors/editor/Editor.js @@ -23,8 +23,8 @@ import { IconDeploy, IconConfigure, IconInteract, -} from '../../icons'; -import Tooltip from '../../tooltip'; +} from '../../../icons'; +import Tooltip from '../../../tooltip'; export default class Editor extends Component { constructor(props) { @@ -91,11 +91,17 @@ export default class Editor extends Component { save = e => { if (e) e.preventDefault(); + const routerControl = this.props.router.control; this.props.item .save() .then(() => { - // Trigger other windows to refresh. - this.props.parent.props.parent.props.parent.redraw(); + // if save action is triggered, move temporary to normal projects + if (routerControl.getActiveProject().getInode() === 1) { + this.props.forkProject(); + } else { + // Trigger other windows to refresh. + this.props.parent.props.parent.props.parent.redraw(); + } }) .catch(() => { alert('Error: Could not save file.'); @@ -285,6 +291,13 @@ export default class Editor extends Component { this.currentEditorWidth = width; setTimeout(this.updateLayout, 1); } + + const requireConfig = { + paths: { vs: "vs" }, + url: "/vs/loader.js", + baseUrl: "/" + }; + return (
{toolbar} @@ -299,6 +312,7 @@ export default class Editor extends Component { editorDidMount={(obj, monaco) => this.editorDidMount(obj, monaco) } + requireConfig={requireConfig} />
); diff --git a/src/components/projecteditor/editors/editor/index.js b/src/components/projecteditor/editors/editor/index.js new file mode 100644 index 00000000..cbb358b8 --- /dev/null +++ b/src/components/projecteditor/editors/editor/index.js @@ -0,0 +1,13 @@ +import { connect } from 'react-redux'; +import { ipfsActions } from '../../../../actions'; +import Editor from './Editor'; + +const mapDispatchToProps = dispatch => { + return { + forkProject: () => { + dispatch(ipfsActions.forkProject()) + }, + }; +}; + +export default connect(null,mapDispatchToProps)(Editor); diff --git a/src/components/projecteditor/editors/style-editor.less b/src/components/projecteditor/editors/editor/style-editor.less similarity index 100% rename from src/components/projecteditor/editors/style-editor.less rename to src/components/projecteditor/editors/editor/style-editor.less diff --git a/src/components/projecteditor/editors/index.js b/src/components/projecteditor/editors/index.js index 5386d98e..bc50a2c9 100644 --- a/src/components/projecteditor/editors/index.js +++ b/src/components/projecteditor/editors/index.js @@ -1,4 +1,4 @@ export { default as AccountEditor } from './editor-account'; -export { default as AppEditor } from './editor-app'; +export { default as ProjectSettings } from './projectSettings'; export { default as ContractEditor } from './editor-contract'; -export { default as Editor } from './editor'; \ No newline at end of file +export { default as Editor } from './editor'; diff --git a/src/components/projecteditor/editors/editor-app.js b/src/components/projecteditor/editors/projectSettings/ProjectSettings.js similarity index 88% rename from src/components/projecteditor/editors/editor-app.js rename to src/components/projecteditor/editors/projectSettings/ProjectSettings.js index 9757feba..c8a429a2 100644 --- a/src/components/projecteditor/editors/editor-app.js +++ b/src/components/projecteditor/editors/projectSettings/ProjectSettings.js @@ -15,11 +15,11 @@ // along with Superblocks Lab. If not, see . import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import classNames from 'classnames'; -import style from './style-editor-contract.less'; -import Backend from '../control/backend'; +import style from '../style-editor-contract.less'; -export default class AppEditor extends Component { +export default class ProjecSettings extends Component { state = { form: null, @@ -28,7 +28,6 @@ export default class AppEditor extends Component { constructor(props) { super(props); - this.backend = new Backend(); this.id = props.id + '_editor'; this.props.parent.childComponent = this; } @@ -73,15 +72,12 @@ export default class AppEditor extends Component { ); return false; } - this.props.item.getProject().setName(this.state.form.name); - this.props.item.getProject().setTitle(this.state.form.title); - this.props.item - .getProject() - .saveDappfile() - .then(() => { - this.setState({ isDirty: false }); - this.props.router.control.redrawMain(true); - }); + + this.props.updateProjectSettings({ + name: this.state.form.name, + title: this.state.form.title + }); + this.setState({ isDirty: false }); }; onChange = (e, key) => { @@ -97,7 +93,7 @@ export default class AppEditor extends Component {
-

Edit DApp Configuration

+

Project Settings

@@ -146,3 +142,7 @@ export default class AppEditor extends Component { ); } } + +ProjecSettings.propTypes = { + updateProjectSettings: PropTypes.func.isRequired +} diff --git a/src/components/projecteditor/editors/projectSettings/index.js b/src/components/projecteditor/editors/projectSettings/index.js new file mode 100644 index 00000000..1f51d5db --- /dev/null +++ b/src/components/projecteditor/editors/projectSettings/index.js @@ -0,0 +1,13 @@ +import { connect } from 'react-redux'; +import { projectActions } from '../../../../actions'; +import ProjectSettings from './ProjectSettings'; + +const mapDispatchToProps = dispatch => { + return { + updateProjectSettings: (newProjectSettings) => { + dispatch(projectActions.updateProjectSettings(newProjectSettings)) + }, + }; +}; + +export default connect(null,mapDispatchToProps)(ProjectSettings); diff --git a/src/components/projecteditor/editors/projectSettings/style.less b/src/components/projecteditor/editors/projectSettings/style.less new file mode 100644 index 00000000..b9ce1ad8 --- /dev/null +++ b/src/components/projecteditor/editors/projectSettings/style.less @@ -0,0 +1,116 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +.main { + background-color: #1e1e1e; + width: 100%; + height: 100%; + color: #eee; + .inner { + padding: 16px 10px 80px 50px; + } + .title { + font-weight: 700; + } + .form { + display: inline-block; + width: 100%; + margin: 10px auto; + .field { + display: block; + button { + margin-top: 12px; + } + } + .arguments { + select, input { + display: inline-block; + width: auto; + min-width: 100px; + margin-right: 5px; + } + + } + .networkContainer { + margin-top: 40px; + + .titleContainer { + display: flex; + margin: 10px 0; + align-content: center; + align-items: center; + .title { + margin-right: 10px; + } + } + .subtitle { + a { + color: #8641F2; + } + } + .networkHeader { + margin-top: 50px; + margin-bottom: 20px; + } + .networkSelector { + display: flex; + margin-top: 40px; + .networks { + width: 20%; + border-right: 1px solid #565656; + max-width: 300px; + p { + display: block; + + } + a { + color: #333; + font-size: 1.2em; + } + ul { + list-style: none; + margin: 0; + padding: 0; + color: #b1b1b1; + li { + line-height: 40px; + border-left: 2px solid; + border-color: transparent; + &:hover { + background-color: rgba(128, 46, 255, 0.22); + cursor: pointer; + color: #fff; + border-color: #7237CF; + } + .networkName { + padding: 0 16px; + } + } + .active { + background-color: rgba(128, 46, 255, 0.32); + color: #fff; + border-color: #8641F2; + } + } + } + .networkInfo { + width: 80%; + margin-left: 40px; + } + } + } + } +} diff --git a/src/components/projecteditor/window.js b/src/components/projecteditor/window.js index 1b056ea7..a4304aee 100644 --- a/src/components/projecteditor/window.js +++ b/src/components/projecteditor/window.js @@ -17,7 +17,7 @@ import React, { Component } from 'react'; import classnames from 'classnames'; import style from './style.less'; -import { Editor, ContractEditor, AppEditor, AccountEditor } from './editors'; +import { Editor, ContractEditor, ProjectSettings, AccountEditor } from './editors'; import Compiler from './compiler'; import Deployer from './deployer'; import TutorialsManual from '../tutorials/manual'; @@ -116,7 +116,7 @@ export class Window { ); } else if (this.props.item.getType() == 'project') { return ( - . + +import React from 'react'; +import PropTypes from 'prop-types'; +import * as ReactSwitch from "react-switch"; + +const Switch = ({checked, onChange, className}) => { + return ( + + ) +}; + +export default Switch; + +Switch.propTypes = { + checked: PropTypes.bool.isRequired, + onChange: PropTypes.func.isRequired, + className: PropTypes.string +} diff --git a/src/components/textInput/index.js b/src/components/textInput/index.js index 062fa072..32215037 100644 --- a/src/components/textInput/index.js +++ b/src/components/textInput/index.js @@ -61,7 +61,7 @@ export default class TextInput extends PureComponent { TextInput.propTypes = { id: PropTypes.string.isRequired, - onChangeText: PropTypes.func.isRequired, + onChangeText: PropTypes.func, type: PropTypes.string, label: PropTypes.string, defaultValue: PropTypes.any, diff --git a/src/components/textInput/style.less b/src/components/textInput/style.less index 613df107..9c4eeac4 100644 --- a/src/components/textInput/style.less +++ b/src/components/textInput/style.less @@ -15,8 +15,6 @@ // along with Superblocks Lab. If not, see . .container { - margin-top: 25px; - .error { border: 1px solid rgba(255, 46, 72, 0.5) !important; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 46, 72, 0.6) !important; diff --git a/src/components/toasts/index.js b/src/components/toasts/index.js new file mode 100644 index 00000000..c7cc8dd2 --- /dev/null +++ b/src/components/toasts/index.js @@ -0,0 +1,65 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import React from 'react'; +import classNames from 'classnames'; +import { ipfsActions, projectActions } from '../../actions'; +import { + IconInformation, + IconWarning, + IconClose +} from '../icons'; + +export const CloseButton = ({ closeToast }) => ( + +); + +const info = (text) => ({ + ToastComponent: () => +
+ + {text} +
+ , + className: classNames(['body', 'info']) +}); + +const error = (text) => ({ + ToastComponent: () => +
+ + {text} +
+ , + className: classNames(['body', 'error']) +}); + +export const getToastComponent = (type) => { + switch(type) { + case ipfsActions.FORK_PROJECT_SUCCESS: + return info('Project Forked!'); + case ipfsActions.FORK_PROJECT_FAIL: + return error('Error while forking!'); + case ipfsActions.IMPORT_PROJECT_FROM_IPFS_SUCCESS: + return info('Project Downloaded!'); + case ipfsActions.IMPORT_PROJECT_FROM_IPFS_FAIL: + return error('Error importing project!'); + case projectActions.UPDATE_PROJECT_SETTINGS_FAIL: + return error('Error updating project settings'); + } +} diff --git a/src/components/toasts/toastcontainer/ToastContainer.js b/src/components/toasts/toastcontainer/ToastContainer.js new file mode 100644 index 00000000..e3c3884e --- /dev/null +++ b/src/components/toasts/toastcontainer/ToastContainer.js @@ -0,0 +1,55 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import React, { Component } from 'react'; +import { toast, ToastContainer as ReactToastContainer } from 'react-toastify'; +import { CloseButton, getToastComponent } from '../index'; + +export default class ToastContainer extends Component { + + componentDidUpdate(prevProps) { + this.renderToast(prevProps); + } + + renderToast(prevProps) { + this.props.toasts.map(toastItem => { + // New toast + if (!(prevProps.toasts.some(toast => toast.id === toastItem.id))) { + const { ToastComponent, className } = getToastComponent(toastItem.type); + toast(, { + className: className, + onClose: ({ id }) => this.props.toastDismissed(id) + }); + } + }) + } + + render() { + return } + /> + } +} diff --git a/src/components/toasts/toastcontainer/index.js b/src/components/toasts/toastcontainer/index.js new file mode 100644 index 00000000..fba2d1a1 --- /dev/null +++ b/src/components/toasts/toastcontainer/index.js @@ -0,0 +1,34 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { connect } from 'react-redux'; +import { toastSelectors } from '../../../selectors/toast.selectors'; +import { toastActions } from '../../../actions'; +import ToastContainer from './ToastContainer'; + +const mapStateToProps = state => ({ + toasts: toastSelectors.getToasts(state), +}); + +function mapDispatchToProps(dispatch) { + return { + toastDismissed: (index) => { + dispatch(toastActions.toastDismissed(index)) + }, + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(ToastContainer); diff --git a/src/components/topbar/Topbar.js b/src/components/topbar/Topbar.js new file mode 100644 index 00000000..18ebb1ca --- /dev/null +++ b/src/components/topbar/Topbar.js @@ -0,0 +1,573 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import style from './style.less'; +import { DropdownContainer } from '../common/dropdown'; +import Backend from '../projecteditor/control/backend'; +import Modal from '../modal'; +import Tooltip from '../tooltip'; +import PreferencessModal from '../preferences'; +import UploadDialog from './upload'; +import Note from '../note'; +import { + IconDownload, + IconTrash, + IconConfigure, + IconHelp, + IconProjectSelector, + IconDropdown, + IconDiscord, + IconCheck, + IconUpload, + IconFork +} from '../icons'; +import Dappfile from '../projecteditor/control/item/dappfileItem'; +import OnlyIf from '../onlyIf'; + +const PreferencesAction = () => ( +
+ +
+); + +const HelpDropdownAction = () => ( +
+ +
+); + +const UploadDrowdownAction = () => ( +
+ + +
+); + +const ForkDropdownAction = (props) => { + const { onForkClicked } = props; + return( +
+ +
+ ) +}; + +const HelpDropdownDialog = () => ( + +); + +const ProjectSelector = ({ title } = props) => ( +
+ +
+); + +class ProjectDialog extends Component { + openProject = (e, project, cb) => { + this.props.router.control.openProject(project, cb); + this.props.onProjectSelected(); + }; + + openProjectConfig = (e, project) => { + this.openProject(e, project, status => { + if (status == 0) { + this.props.router.control.openProjectConfig(); + } + }); + }; + + downloadProject = (e, project) => { + e.stopPropagation(); + + const keepState = prompt( + 'Do you also want to save the project state (current contract addresses, ABIs, etc)?', + 'yes' + ); + if (!keepState) { + return; + } + const s = keepState.toLowerCase(); + if (s != 'yes' && s != 'no') { + alert('Download aborted. Yes or No answer expected.'); + return; + } + const backend = new Backend(); + backend.downloadProject(project, keepState.toLowerCase() == 'yes'); + }; + + importProject = e => { + // Thanks to Richard Bondi for contributing with this upload code. + e.preventDefault(); + var uploadAnchorNode = document.createElement('input'); + uploadAnchorNode.setAttribute('id', 'importFileInput'); + uploadAnchorNode.setAttribute('type', 'file'); + uploadAnchorNode.onchange = this.importProject2; + document.body.appendChild(uploadAnchorNode); // required for firefox + uploadAnchorNode.click(); + uploadAnchorNode.remove(); + }; + + importProject2 = e => { + var file = e.target.files[0]; + var reader = new FileReader(); + + reader.onloadend = evt => { + var project; + if (evt.target.readyState == FileReader.DONE) { + if (evt.target.result.length > 1024**2) { + alert('File to big to be handled. Max size in 1 MB.'); + return; + } + + const backend = new Backend(); + backend.unZip(evt.target.result).then( (project) => { + this.importProject3(project); + }) + .catch( () => { + console.log("Could not parse import as zip, trying JSON."); + try { + const obj = JSON.parse(evt.target.result); + if (!obj.files) { + alert('Error: Invalid project file. Must be ZIP-file (or legacy JSON format).'); + return; + } + project = obj; + } catch (e) { + alert('Error: Invalid project file. Must be ZIP-file (or legacy JSON format).'); + return; + } + this.importProject3(project); + }); + + } + }; + var blob = file.slice(0, file.size); + reader.readAsBinaryString(blob); + }; + + importProject3 = project => { + const backend = new Backend(); + backend.convertProject(project, (status, project2) => { + if (status > 1) { + const modalData = { + title: 'Project converted', + body: ( +
+
+ The imported project has been converted to the + new Superblocks Lab format. +
+ You might need to reconfigure your accounts and + contract arguments due to these changes. We are + sorry for any inconvenience. +
+
+ Please see the Superblocks Lab help center for + more information on this topic. +
+
+ ), + style: { width: '680px' }, + }; + const modal = ; + this.props.functions.modal.show({ + cancel: () => { + this.importProject4(project2.files); + return true; + }, + render: () => { + return modal; + }, + }); + } else if (status == -1) { + alert('Error: Could not import project.'); + } else { + this.importProject4(project.files); + } + }); + }; + + importProject4 = files => { + var title = ''; + var name = ''; + var dappfile; + + // Try to decode the `/dappfile.json`. + try { + dappfile = JSON.parse( + files['/'].children['dappfile.json'].contents + ); + } catch (e) { + // Create a default dappfile. + console.log('Create default dappfile.json for import'); + dappfile = Dappfile.getDefaultDappfile(); + files['/'].children['dappfile.json'] = {type: 'f'}; + } + + try { + title = dappfile.project.info.title || ''; + name = dappfile.project.info.name || ''; + } catch (e) { + dappfile.project = { info: {} }; + } + + // This will make sure the dappfile has a sane state. + Dappfile.validateDappfile(dappfile); + + do { + var name2 = prompt('Please give the project a name.', name); + if (!name2) { + alert('Import cancelled.'); + return; + } + if (!name2.match(/^([a-zA-Z0-9-]+)$/) || name2.length > 30) { + alert( + 'Illegal projectname. Only A-Za-z0-9 and dash (-) allowed. Max 30 characters.' + ); + continue; + } + name = name2; + break; + } while (true); + + do { + var title2 = prompt( + 'Please give the project a snappy title.', + title + ); + if (!title2) { + alert('Import cancelled.'); + return; + } + if (title2.match(/([\"\'\\]+)/) || title2.length > 100) { + alert( + 'Illegal title. No special characters allowed. Max 100 characters.' + ); + continue; + } + title = title2; + break; + } while (true); + + try { + dappfile.project.info.name = name; + dappfile.project.info.title = title; + files['/'].children['dappfile.json'].contents = JSON.stringify( + dappfile, null, 4 + ); + } catch (e) { + console.error(e); + alert('Error: could not import project.'); + return; + } + + this.props.router.control.importProject(files); + }; + + deleteProject = (e, project) => { + e.stopPropagation(); + + this.props.router.control.deleteProject(project, () => { + this.forceUpdate(); + }); + }; + + getProjectItems = () => { + if (this.props.router.control) { + const openProject = this.props.router.control.getActiveProject(); + + const items = this.props.router.control + .getProjects() + .slice(0) + .reverse() + .map(project => { + const isActive = openProject === project; + const isTemporaryProject = project.getInode() === 1; + return ( + !isTemporaryProject && +
  • { + this.openProject(e, project); + }} + > +
    + {isActive ? ( +
    + +
    + ) : null} +
    +
    + {project.getName()} -   + {project.getTitle()} +
    +
    +
    + + + +
    +
    +
  • + ); + }); + + return items; + } + }; + + render() { + const projectItems = this.getProjectItems(); + return ( +
    +
    +
    + +
    +
    +
    +
      + {projectItems} +
    +
    +
    +
    +
    + +
    + +
    +
    + ); + } +} + +ProjectDialog.propTypes = { + onProjectSelected: PropTypes.func.isRequired, + router: PropTypes.object.isRequired, + functions: PropTypes.object.isRequired, +}; + +export default class TopBar extends Component { + + state = { + selectedProjectName: this.props.selectedProjectName, + ipfsActions: { + showUploadDialog: this.props.ipfsActions.showUploadDialog, + showUploadButton: this.props.ipfsActions.showUploadButton, + showForkButton: this.props.ipfsActions.showForkButton + } + } + + componentDidUpdate(prevProps) { + if (prevProps.ipfsActions !== this.props.ipfsActions) { + this.setState({ + ipfsActions: this.props.ipfsActions + }); + } + + if (prevProps.selectedProjectName !== this.props.selectedProjectName) { + this.setState({ + selectedProjectName: this.props.selectedProjectName + }); + } + } + + onSettingsModalClose = () => { + this.props.functions.modal.close(); + }; + + showPreferencesModal = () => { + const modal = ( + + ); + this.props.functions.modal.show({ + cancel: () => { + return false; + }, + render: () => { + return modal; + } + }); + }; + + onForkClicked = () => { + this.props.forkProject(); + } + + onCloseUploadDialog = () => { + this.props.hideUploadDialog() + } + + render() { + const { showUploadDialog, showUploadButton, showForkButton } = this.state.ipfsActions; + const { selectedProjectName } = this.state; + + return ( +
    + Superblocks Lab logo + + } + enableClickInside={true} + showMenu={showUploadDialog} + onCloseMenu={this.onCloseUploadDialog} + > + + + + + + + + } + > + + + +
    +
    + +
    + + } > + + +
    +
    + ); + } +} + +TopBar.propTypes = { + onProjectSelected: PropTypes.func.isRequired, + router: PropTypes.object.isRequired, + functions: PropTypes.object.isRequired, + selectedProjectName: PropTypes.string, + ipfsActions: PropTypes.shape({ + showUploadDialog: PropTypes.bool.isRequired, + showUploadButton: PropTypes.bool.isRequired, + showForkButton: PropTypes.bool.isRequired, + }), +}; diff --git a/src/components/topbar/index.js b/src/components/topbar/index.js index d76eec4b..4a7e8172 100644 --- a/src/components/topbar/index.js +++ b/src/components/topbar/index.js @@ -1,478 +1,43 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import style from './style.less'; -import { DropdownContainer } from '../common'; -import Backend from '../projecteditor/control/backend'; -import Modal from '../modal'; -import Tooltip from '../tooltip'; -import PreferencessModal from '../preferences'; -import { - IconDownload, - IconTrash, - IconConfigure, - IconHelp, - IconProjectSelector, - IconDropdown, - IconDiscord, - IconCheck -} from '../icons'; -import JSZip from 'jszip'; -import Dappfile from '../projecteditor/control/item/dappfileItem'; - -const PreferencesAction = () => ( -
    - -
    -); - -const HelpDropdownAction = () => ( -
    - -
    -); - -const HelpDropdownDialog = () => ( - -); - -const ProjectSelector = ({ title } = props) => ( -
    - -
    -); - -class ProjectDialog extends Component { - openProject = (e, project, cb) => { - this.props.router.control.openProject(project, cb); - this.props.onProjectSelected(); - }; - - openProjectConfig = (e, project) => { - this.openProject(e, project, status => { - if (status == 0) { - this.props.router.control.openProjectConfig(); - } - }); - }; - - downloadProject = (e, project) => { - e.stopPropagation(); - - const keepState = prompt( - 'Do you also want to save the project state (current contract addresses, ABIs, etc)?', - 'yes' - ); - if (!keepState) { - return; - } - const s = keepState.toLowerCase(); - if (s != 'yes' && s != 'no') { - alert('Download aborted. Yes or No answer expected.'); - return; - } - const backend = new Backend(); - backend.downloadProject(project, keepState.toLowerCase() == 'yes'); - }; - - importProject = e => { - // Thanks to Richard Bondi for contributing with this upload code. - e.preventDefault(); - var uploadAnchorNode = document.createElement('input'); - uploadAnchorNode.setAttribute('id', 'importFileInput'); - uploadAnchorNode.setAttribute('type', 'file'); - uploadAnchorNode.onchange = this.importProject2; - document.body.appendChild(uploadAnchorNode); // required for firefox - uploadAnchorNode.click(); - uploadAnchorNode.remove(); - }; - - importProject2 = e => { - var file = e.target.files[0]; - var reader = new FileReader(); - - reader.onloadend = evt => { - var project; - if (evt.target.readyState == FileReader.DONE) { - if (evt.target.result.length > 1024**2) { - alert('File to big to be handled. Max size in 1 MB.'); - return; - } - - const backend = new Backend(); - backend.unZip(evt.target.result).then( (project) => { - this.importProject3(project); - }) - .catch( () => { - console.log("Could not parse import as zip, trying JSON."); - try { - const obj = JSON.parse(evt.target.result); - if (!obj.files) { - alert('Error: Invalid project file. Must be ZIP-file (or legacy JSON format).'); - return; - } - project = obj; - } catch (e) { - alert('Error: Invalid project file. Must be ZIP-file (or legacy JSON format).'); - return; - } - this.importProject3(project); - }); - - } - }; - var blob = file.slice(0, file.size); - reader.readAsBinaryString(blob); - }; - - importProject3 = project => { - const backend = new Backend(); - backend.convertProject(project, (status, project2) => { - if (status > 1) { - const modalData = { - title: 'Project converted', - body: ( -
    -
    - The imported project has been converted to the - new Superblocks Lab format. -
    - You might need to reconfigure your accounts and - contract arguments due to these changes. We are - sorry for any inconvenience. -
    -
    - Please see the Superblocks Lab help center for - more information on this topic. -
    -
    - ), - style: { width: '680px' }, - }; - const modal = ; - this.props.functions.modal.show({ - cancel: () => { - this.importProject4(project2.files); - return true; - }, - render: () => { - return modal; - }, - }); - } else if (status == -1) { - alert('Error: Could not import project.'); - } else { - this.importProject4(project.files); - } - }); - }; - - importProject4 = files => { - var title = ''; - var name = ''; - var dappfile; - - // Try to decode the `/dappfile.json`. - try { - dappfile = JSON.parse( - files['/'].children['dappfile.json'].contents - ); - } catch (e) { - // Create a default dappfile. - console.log('Create default dappfile.json for import'); - dappfile = Dappfile.getDefaultDappfile(); - files['/'].children['dappfile.json'] = {type: 'f'}; - } - - try { - title = dappfile.project.info.title || ''; - name = dappfile.project.info.name || ''; - } catch (e) { - dappfile.project = { info: {} }; - } - - // This will make sure the dappfile has a sane state. - Dappfile.validateDappfile(dappfile); - - do { - var name2 = prompt('Please give the project a name.', name); - if (!name2) { - alert('Import cancelled.'); - return; - } - if (!name2.match(/^([a-zA-Z0-9-]+)$/) || name2.length > 30) { - alert( - 'Illegal projectname. Only A-Za-z0-9 and dash (-) allowed. Max 30 characters.' - ); - continue; - } - name = name2; - break; - } while (true); - - do { - var title2 = prompt( - 'Please give the project a snappy title.', - title - ); - if (!title2) { - alert('Import cancelled.'); - return; - } - if (title2.match(/([\"\'\\]+)/) || title2.length > 100) { - alert( - 'Illegal title. No special characters allowed. Max 100 characters.' - ); - continue; - } - title = title2; - break; - } while (true); - - try { - dappfile.project.info.name = name; - dappfile.project.info.title = title; - files['/'].children['dappfile.json'].contents = JSON.stringify( - dappfile, null, 4 - ); - } catch (e) { - console.error(e); - alert('Error: could not import project.'); - return; - } - - this.props.router.control.importProject(files); - }; - - deleteProject = (e, project) => { - e.stopPropagation(); - - this.props.router.control.deleteProject(project, () => { - this.forceUpdate(); - }); - }; - - getProjectItems = () => { - if (this.props.router.control) { - const openProject = this.props.router.control.getActiveProject(); - - const items = this.props.router.control - .getProjects() - .slice(0) - .reverse() - .map(project => { - const isActive = openProject === project; - return ( -
  • { - this.openProject(e, project); - }} - > -
    - {isActive ? ( -
    - -
    - ) : null} -
    -
    - {project.getName()} -   - {project.getTitle()} -
    -
    -
    - - - -
    -
    -
  • - ); - }); - - return items; - } - }; - - render() { - const projectItems = this.getProjectItems(); - return ( -
    -
    -
    - -
    -
    -
    -
      - {projectItems} -
    -
    -
    -
    -
    - -
    - -
    -
    - ); +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { connect } from 'react-redux'; +import TopBar from './Topbar'; +import { ipfsSelectors } from '../../selectors'; +import { projectSelectors } from '../../selectors'; +import { ipfsActions } from '../../actions'; + +const mapStateToProps = state => ({ + selectedProjectName: projectSelectors.getSelectedProjectName(state), + ipfsActions: { + showUploadDialog: ipfsSelectors.getShowUploadDialog(state), + showUploadButton: ipfsSelectors.getShowUploadButton(state), + showForkButton: ipfsSelectors.getShowForkButton(state), } -} +}); -ProjectDialog.propTypes = { - onProjectSelected: PropTypes.func.isRequired, - router: PropTypes.object.isRequired, - functions: PropTypes.object.isRequired, -}; - -export default class TopBar extends Component { - - onSettingsModalClose = () => { - this.props.functions.modal.close(); - } - - showPreferencesModal = () => { - const modal = ( - - ); - this.props.functions.modal.show({ - cancel: () => { - return false; - }, - render: () => { - return modal; - } - }); - } - - render() { - var title = ''; - - if (this.props.router.control) { - const openProject = this.props.router.control.getActiveProject(); - if (openProject) { - title = openProject.getName(); - } - } - - return ( -
    - Superblocks Lab logo - - } - > - - - -
    -
    - -
    - - } > - - -
    -
    - ); - } +function mapDispatchToProps(dispatch) { + return { + hideUploadDialog: () => { + dispatch(ipfsActions.hideUploadDialog()) + }, + forkProject: () => { + dispatch(ipfsActions.forkProject()) + }, + }; } -TopBar.propTypes = { - onProjectSelected: PropTypes.func.isRequired, - router: PropTypes.object.isRequired, - functions: PropTypes.object.isRequired, -}; +export default connect(mapStateToProps, mapDispatchToProps)(TopBar); diff --git a/src/components/topbar/style.less b/src/components/topbar/style.less index 5502ae45..24200dca 100644 --- a/src/components/topbar/style.less +++ b/src/components/topbar/style.less @@ -63,6 +63,7 @@ .actionHelp { display: flex; margin-left: 10px; + height: 100%; } .action { display: flex; diff --git a/src/components/topbar/upload/UploadDialog.js b/src/components/topbar/upload/UploadDialog.js new file mode 100644 index 00000000..4af7dfb9 --- /dev/null +++ b/src/components/topbar/upload/UploadDialog.js @@ -0,0 +1,180 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import copy from 'copy-to-clipboard'; +import classNames from 'classnames'; +import style from './style.less'; +import { + IconCopy, + IconConfigure +} from '../../icons'; +import Note from '../../note'; +import TextInput from '../../textInput'; +import Tooltip from '../../tooltip'; +import UploadSettings from './settings'; + +class UploadDialog extends Component { + + state = { + ipfs: { + uploading: this.props.ipfs.uploading, + shareURL: this.props.ipfs.shareURL, + lastUploadTimestamp: this.props.ipfs.lastUploadTimestamp, + error: this.props.ipfs.error, + showUploadSettings: this.props.ipfs.showUploadSettings, + uploadSettings: this.props.ipfs.uploadSettings, + }, + } + + componentDidUpdate(prevProps) { + if (prevProps.ipfs !== this.props.ipfs) { + this.setState({ + ipfs: {...this.props.ipfs} + }); + } + } + + ipfsSyncUp = () => { + const { ipfs } = this.state; + const { uploadToIPFS } = this.props; + + uploadToIPFS(ipfs.uploadSettings); + } + + copyShareUrl = () => { + const { shareURL } = this.state.ipfs; + copy(shareURL); + } + + uploadSettingsClick = () => { + this.props.showUploadSettings(); + } + + onUploadSettingsBackClicked = () => { + this.props.hideUploadSettings(); + } + + onUploadSettingsChanged = (uploadSettings) => { + this.props.uploadSettingsChanged(uploadSettings); + } + + renderDialog() { + return ( +
    + +

    Upload project to IPFS

    +
    Backup and share your project by uploading it to IPFS. Remember to not include any personal data, and enjoy decentralization!
    +
    +
    + + +
    +
    + +
    + ); + } + + renderUploading() { + return( +
    + +
    +

    Uploading project to IPFS

    +
    +
    +
    +
    +
    +
    You can keep working while your project is being uploaded.
    +
    +
    + ); + } + + renderShareURL(shareURL, lastUploadTimestamp) { + return ( +
    + +
    + + +
    +
    + + +
    + +
    + ); + } + + render() { + const { ipfs } = this.state; + return ( +
    + { ipfs.uploading ? + this.renderUploading() + : + ipfs.showUploadSettings ? + + : + ipfs.shareURL ? + this.renderShareURL(ipfs.shareURL, ipfs.lastUploadTimestamp) + : + this.renderDialog() + } +
    + ) + } +} + +export default UploadDialog; + +UploadDialog.propTypes = { + ipfs: PropTypes.object.isRequired, + uploadToIPFS: PropTypes.func.isRequired, + showUploadSettings: PropTypes.func.isRequired, + hideUploadSettings: PropTypes.func.isRequired, + uploadSettingsChanged: PropTypes.func.isRequired, +} diff --git a/src/components/topbar/upload/index.js b/src/components/topbar/upload/index.js new file mode 100644 index 00000000..73aad326 --- /dev/null +++ b/src/components/topbar/upload/index.js @@ -0,0 +1,50 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { connect } from 'react-redux'; +import { ipfsActions } from '../../../actions'; +import UploadDialog from './UploadDialog'; +import { ipfsSelectors } from '../../../selectors'; + +const mapStateToProps = state => ({ + ipfs: { + uploading: ipfsSelectors.getUploadingToIPFS(state), + shareURL: ipfsSelectors.getShareURL(state), + lastUploadTimestamp: ipfsSelectors.getLastUploadTimestamp(state), + error: ipfsSelectors.getUploadToIPFSError(state), + showUploadSettings: ipfsSelectors.getShowUploadSettings(state), + uploadSettings: ipfsSelectors.getUploadSettings(state) + } +}); + +function mapDispatchToProps(dispatch) { + return { + uploadToIPFS: (uploadSettings) => { + dispatch(ipfsActions.uploadToIPFS(uploadSettings)) + }, + showUploadSettings: () => { + dispatch(ipfsActions.showUploadSettings()) + }, + hideUploadSettings: () => { + dispatch(ipfsActions.hideUploadSettings()) + }, + uploadSettingsChanged: (uploadSettings) => { + dispatch(ipfsActions.uploadSettingsChanged(uploadSettings)) + }, + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(UploadDialog); diff --git a/src/components/topbar/upload/settings/index.js b/src/components/topbar/upload/settings/index.js new file mode 100644 index 00000000..8ba97183 --- /dev/null +++ b/src/components/topbar/upload/settings/index.js @@ -0,0 +1,103 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import style from './style.less'; +import { + IconBack +} from '../../../icons'; +import Switch from '../../../switch'; + +export default class UploadSettings extends Component { + + state = { + includeBuildInfo: this.props.uploadSettings.includeBuildInfo, + includeProjectConfig: this.props.uploadSettings.includeProjectConfig, + } + + onBackClicked = () => { + this.props.onBackClicked(); + } + + onIncludeBuildChange = (checked) => { + const { onChange } = this.props; + const newState = { + ...this.state, + includeBuildInfo: checked + } + this.setState(newState); + + // Make sure to notify also the parent + onChange(newState); + } + + onIncludeProjectConfigChange = (checked) => { + const { onChange } = this.props; + const newState = { + ...this.state, + includeProjectConfig: checked + } + this.setState(newState); + + // Make sure to notify also the parent + onChange(newState); + } + + render() { + const { includeBuildInfo, includeProjectConfig } = this.state; + return ( +
    +
    + +
    Upload Settings
    +
    +
    +
    Include build information
    +
    +
    This will upload the content of your build folder.
    + +
    +
    +
    +
    Upload project settings
    +
    +
    This will upload the content of your .super folder which contain project specific settings.
    + +
    +
    +
    + + ) + } +}; + +UploadSettings.propTypes = { + uploadSettings: PropTypes.object.isRequired, + onBackClicked: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired +} + diff --git a/src/components/topbar/upload/settings/style.less b/src/components/topbar/upload/settings/style.less new file mode 100644 index 00000000..4de4ee90 --- /dev/null +++ b/src/components/topbar/upload/settings/style.less @@ -0,0 +1,47 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . +.container { + min-height: 200px; + padding: 0 0 10px 0; + .header { + display: flex; + align-content: center; + align-items: flex-end; + .text { + margin-left: 10px; + font-weight: 600; + } + } + .buildInfo { + margin-top: 25px; + .title { + font-weight: 600; + } + .descContainer { + display: flex; + align-items: center; + .description { + line-height: 1.5em; + color: #BCBCBC; + margin-right: 25px; + } + .switch { + margin-left: auto; + } + } + } +} + diff --git a/src/components/topbar/upload/style.less b/src/components/topbar/upload/style.less new file mode 100644 index 00000000..c90e39bf --- /dev/null +++ b/src/components/topbar/upload/style.less @@ -0,0 +1,110 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +.shareDialogContainer { + display: block; + position: absolute; + left: 70px; + top: 45px; + border-radius: 4px; + background-color: #2B2B2B; + min-width: 436px; + max-width: 436px; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 2; + color: #fff; + padding: 10px 0; + transition: visibility 0s, opacity 0.2s ease; + padding: 15px; + + .content { + display: flex; + flex-direction: column; + align-items: center; + align-content: center; + line-height: 1.5em; + + input { + width: 350px; + } + .logo { + height: 66px; + widows: 66px; + } + .description { + text-align: center; + } + .uploadSettings { + margin-left: 10px; + } + .note { + font-size: 12px; + color: #A5A5A5; + } + .uploadingContainer { + text-align: center; + .loadBar { + position: relative; + margin: 25px 80px; + width: 60%; + height: 4px; + background-color: #5BB8BA; + } + .bar { + content: ""; + display: inline; + position: absolute; + width: 0; + height: 100%; + left: 50%; + text-align: center; + } + .bar:nth-child(1) { + background-color: #8641F2; + animation: loading 3s linear infinite; + } + .bar:nth-child(2) { + background-color: #3b78e7; + animation: loading 3s linear 1s infinite; + } + .bar:nth-child(3) { + background-color: #5BB8BA; + animation: loading 3s linear 2s infinite; + } + @keyframes loading { + from {left: 50%; width: 0;z-index:100;} 33.3333% {left: 0; width: 100%;z-index: 10;} + to {left: 0; width: 100%;} + } + } + .share { + display: flex; + align-items: flex-end; + margin-top: 10px; + button { + margin-bottom: 5px; + margin-left: 10px; + } + } + .lastUpdate { + color: #A5A5A5; + margin: 15px 0; + } + .newUploadContainer { + margin-top: 20px; + padding-bottom: 10px; + } + } +} diff --git a/src/epics/index.js b/src/epics/index.js index a308644f..b3be3f88 100644 --- a/src/epics/index.js +++ b/src/epics/index.js @@ -1,7 +1,27 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { ipfsEpics } from './ipfs'; import { settingsEpics } from './settings'; import { sidePanelsEpics } from './sidePanels'; +import { projectEpics } from './project'; export const epics = [ + ...ipfsEpics, ...settingsEpics, - ...sidePanelsEpics + ...sidePanelsEpics, + ...projectEpics ]; diff --git a/src/epics/ipfs/forkProject.epic.js b/src/epics/ipfs/forkProject.epic.js new file mode 100644 index 00000000..8cb21257 --- /dev/null +++ b/src/epics/ipfs/forkProject.epic.js @@ -0,0 +1,106 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { from, of, empty } from 'rxjs'; +import { switchMap, withLatestFrom, map, catchError, tap } from 'rxjs/operators'; +import { ofType } from 'redux-observable'; +import { projectSelectors } from '../../selectors'; +import { ipfsActions } from '../../actions'; +import { ipfsService } from '../../services'; + +/** + * Add the current temporary project to the user's list. This way the project will be actually + * stored and displayed in the projects list. + * + * @param {*} backend - The Backend.js to perform file operations + * @param {*} control - the Control.js to perform project operations + */ +const addProjectToUserList = (backend, control) => { + return new Promise((resolve, reject) => { + backend.assignNewInode(1, () => { + control._loadProjects(() => { + control._closeProject(status => { + if (status == 0) { + // Open last project + control.openProject( + control._projectsList[ + control._projectsList.length - 1 + ] + ); + resolve(); + } else { + reject("Couldn't close the project") + } + }) + }) + }) + }) +}; + +const forkTempProject$ = (backend, router) => from(addProjectToUserList(backend, router.control)).pipe( + tap(() => ipfsService.clearTempProject()) +); + +const forkOwnProject$ = (projectId, backend, router) => of(projectId).pipe( + switchMap(() => { + if(confirm('Are you sure you want to fork your own project?')) { + return from(backend.getProjectFiles(projectId)).pipe( + map(backend.modifyDappFile), + tap(modifiedFiles => router.control.importProject(modifiedFiles, false)) + ) + } else { + return empty(); + } + }) +); + +/** + * Epic in charge of forking the current project: + * + * There are 2 case scenarios: + * + * 1. A temporary project is created when downloading a project from ipfs. This project is + * not actually added to the user's project list until a fork occurrs, therefore we avoid + * spamming the user's project list with projects they just openned to consult something and then + * discarded. + * + * 2. A user is trying to fork it's own project. When done so, we will ammend a unique identifier, making + * sure the new project is easy to distinguish from the previous one. + */ +const forkProject = (action$, state$, { backend, router }) => action$.pipe( + ofType(ipfsActions.FORK_PROJECT), + withLatestFrom(state$), + switchMap(([,state]) => { + const projectId = projectSelectors.getSelectedProjectId(state); + return of(projectId) + .pipe( + switchMap(projectId => { + if (ipfsService.isTemporaryProject(projectId)) { + return forkTempProject$(backend, router); + } else { + return forkOwnProject$(projectId, backend, router); + } + }), + map(ipfsActions.forkProjectSuccess), + catchError((error) => { + console.log("There was an issue forking the project: " + error); + return of(ipfsActions.forkProjectFail()) + }) + ) + }) +); + +export default forkProject; diff --git a/src/epics/ipfs/importProjectFromIPFS.epic.js b/src/epics/ipfs/importProjectFromIPFS.epic.js new file mode 100644 index 00000000..9b061fa8 --- /dev/null +++ b/src/epics/ipfs/importProjectFromIPFS.epic.js @@ -0,0 +1,99 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { from, of, interval } from 'rxjs'; +import { switchMap, + withLatestFrom, + map, + catchError, + tap, + delayWhen, + retry, + take + } from 'rxjs/operators'; +import { ofType } from 'redux-observable'; +import { ipfsActions } from '../../actions'; +import { ipfsService } from '../../services'; + +const files = { + '/': { + type: 'd', + children: {} + } +}; + +/** + * Convert IPFS result into our internal files/dir format. + * + * @param {*} file - A file object in IPFS format + */ +const convertFile = (file) => { + if (file.content) { + const a = file.path.match("[^/]+(.*/)([^/]+)$"); + const fragments = a[1].split('/'); + let node = files['/'].children; + for(let i = 1; i < fragments.length - 1; i++) { + if (!node[fragments[i]]) { + node[fragments[i]] = { + type: 'd', + children: {}, + }; + } + node = node[fragments[i]].children; + } + node[a[2]] = { + type: 'f', + contents: file.content.toString(), + }; + } +} + +/** + * Simple Observable which will only finish once the router.control is actually available + * + * @param {*} router - The router object containing the control.js reference + */ +const controlAvailable$ = (router) => interval(100) + .pipe( + map(() => router.control), + retry(), + take(1) + ) + +/** + * Epic in charge of importing a project from IPFS. + */ +const importProjectFromIPFS = (action$, state$, { router }) => action$.pipe( + ofType(ipfsActions.IMPORT_PROJECT_FROM_IPFS), + withLatestFrom(state$), + switchMap(([action,]) => { + const hash = action.data; + return from(ipfsService.ipfsFetchFiles(hash)) + .pipe( + delayWhen(() => controlAvailable$(router)), + map(response => response.map(f => convertFile(f))), + tap(() => router.control.importProject(files, true)), + map(ipfsActions.importProjectFromIpfsSuccess), + catchError((error) => { + console.log("There was an issue importing the project from IPFS: " + error); + ipfsService.clearTempProject(); + return of(ipfsActions.importProjectFromIpfsFail()) + }) + ) + }) +); + +export default importProjectFromIPFS; diff --git a/src/epics/ipfs/index.js b/src/epics/ipfs/index.js new file mode 100644 index 00000000..ada9d11a --- /dev/null +++ b/src/epics/ipfs/index.js @@ -0,0 +1,31 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import restoreIPFSState from './restoreIPFSState.epic'; +import uploadToIPFS from './uploadToIPFS.epic'; +import forkProject from './forkProject.epic'; +import importProjectFromIPFS from './importProjectFromIPFS.epic'; +import updateIPFSActionButtons from './updateIPFSActionButtons.epic'; +import reportIPFSEvents from './reportIPFSEvents.epic'; + +export const ipfsEpics = [ + restoreIPFSState, + uploadToIPFS, + forkProject, + importProjectFromIPFS, + updateIPFSActionButtons, + reportIPFSEvents +]; diff --git a/src/epics/ipfs/reportIPFSEvents.epic.js b/src/epics/ipfs/reportIPFSEvents.epic.js new file mode 100644 index 00000000..7f66c513 --- /dev/null +++ b/src/epics/ipfs/reportIPFSEvents.epic.js @@ -0,0 +1,43 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { empty } from 'rxjs'; +import { switchMap, withLatestFrom } from 'rxjs/operators'; +import { ofType } from 'redux-observable'; +import { ipfsActions } from '../../actions'; +import { logEvent } from '../../utils/analytics'; +import { ipfsService } from '../../services'; +import { projectSelectors } from '../../selectors'; + +const reportIPFSEvents = (action$, state$) => action$.pipe( + ofType( + ipfsActions.UPLOAD_TO_IPFS, + ipfsActions.FORK_PROJECT, + ipfsActions.IMPORT_PROJECT_FROM_IPFS), + withLatestFrom(state$), + switchMap(([action, state]) => { + if (action.type === ipfsActions.FORK_PROJECT) { + const projectId = projectSelectors.getSelectedProjectId(state); + logEvent(action.type, { ownProject: !ipfsService.isTemporaryProject(projectId)}); + } else { + logEvent(action.type); + } + + return empty(); + }) +); + +export default reportIPFSEvents; diff --git a/src/epics/ipfs/restoreIPFSState.epic.js b/src/epics/ipfs/restoreIPFSState.epic.js new file mode 100644 index 00000000..2629c3ab --- /dev/null +++ b/src/epics/ipfs/restoreIPFSState.epic.js @@ -0,0 +1,41 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { from, of } from 'rxjs'; +import { switchMap, withLatestFrom, map, catchError, first, tap } from 'rxjs/operators'; +import { ofType } from 'redux-observable'; +import { projectSelectors } from '../../selectors'; +import { ipfsActions, projectActions } from '../../actions'; + +const restoreIPFSState = (action$, state$, { backend }) => action$.pipe( + ofType(projectActions.SELECT_PROJECT), + withLatestFrom(state$), + switchMap(([,state]) => { + const projectId = projectSelectors.getSelectedProjectId(state); + return from(backend.loadFilePromise(projectId, '/.super/ipfs.json')) + .pipe( + switchMap(file => from(JSON.parse(file))), + first(), + map(ipfsActions.restoreIPFSStateSuccess), + catchError(() => { + console.log("IPFS backup information not available"); + return of(ipfsActions.restoreIPFSStateFail()) + }) + ) + }) +); + +export default restoreIPFSState; diff --git a/src/epics/ipfs/updateIPFSActionButtons.epic.js b/src/epics/ipfs/updateIPFSActionButtons.epic.js new file mode 100644 index 00000000..aaf2ede6 --- /dev/null +++ b/src/epics/ipfs/updateIPFSActionButtons.epic.js @@ -0,0 +1,58 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { of, empty } from 'rxjs'; +import { switchMap, withLatestFrom, map, catchError } from 'rxjs/operators'; +import { ofType } from 'redux-observable'; +import { projectSelectors } from '../../selectors'; +import { ipfsActions, projectActions } from '../../actions'; +import { ipfsService } from '../../services'; + +const updateIPFSActionButtons = (action$, state$) => action$.pipe( + ofType(projectActions.SELECT_PROJECT), + withLatestFrom(state$), + switchMap(([,state]) => { + const projectId = projectSelectors.getSelectedProjectId(state); + return of(projectId) + .pipe( + map(projectId => { + if (ipfsService.isTemporaryProject(projectId)) { + return ipfsActions.updateIpfsActionButtons({ + showUploadButton: false, + showForkButton: true, + }); + } else if(projectId === 0) { // Welcome screen + return ipfsActions.updateIpfsActionButtons({ + showUploadButton: false, + showForkButton: false, + }); + } + else { + return ipfsActions.updateIpfsActionButtons({ + showUploadButton: true, + showForkButton: true, + }); + } + }), + catchError(() => { + console.log("Fail silently"); + return empty() + }) + ) + }) +); + +export default updateIPFSActionButtons; diff --git a/src/epics/ipfs/uploadToIPFS.epic.js b/src/epics/ipfs/uploadToIPFS.epic.js new file mode 100644 index 00000000..51637350 --- /dev/null +++ b/src/epics/ipfs/uploadToIPFS.epic.js @@ -0,0 +1,93 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { from, of } from 'rxjs'; +import { switchMap, withLatestFrom, map, catchError, tap, delayWhen } from 'rxjs/operators'; +import { ofType } from 'redux-observable'; +import { projectSelectors } from '../../selectors'; +import { ipfsActions } from '../../actions'; +import { ipfsService } from '../../services'; + +/** + * Add a timestamp to the upload object we are about to save in order to have the possibility to build a timeline + * of backups + * @param {string} shareURL The share URL given to the user + */ +const addTimeStamp = (shareURL) => { + return { shareURL: shareURL, timestamp: Date.now() } +} + +/** + * This is needed becase atm the file explorer has no way to auto update itself when the + * underlying state has actually changed (per example by using the backend.js class) + * + * @param {ProjectItem} activeProject - The current active project to update the state + * @returns {Promise} A promise which will only resolve once the file system has successfully updated + * the state + */ +const updateFileSystemState = (activeProject) => { + return new Promise((resolve) => { + activeProject.getChildren()[0].getChildren(true, () => { + resolve(); + }); + }); +} + +const uploadToIPFS = (action$, state$, { backend, router }) => action$.pipe( + ofType(ipfsActions.UPLOAD_TO_IPFS), + withLatestFrom(state$), + switchMap(([action, state]) => { + const projectId = projectSelectors.getSelectedProjectId(state); + const { uploadSettings } = action.data; + return from(ipfsService.ipfsSyncUp(projectId, uploadSettings)) + .pipe( + map(hash => document.location.href + 'ipfs/' + hash), + map(addTimeStamp), + switchMap(({shareURL, timestamp}) => from( backend.loadFilePromise(projectId, '/.super/ipfs.json')) + .pipe( + map(JSON.parse), + catchError(() => { + console.log("Wrong format or missing ipfs.json. Creating a new one"); + // Make sure that if there is any error while reading the file (ex. does not exists), we can continue + return of([]); + }), + map(array => { + // Keep the history from top to bottom (most recent in the beginning of the array) + array.unshift({ timestamp: timestamp, shareURL: shareURL }); + return array; + }), + switchMap(array => from(backend.saveFilePromise(projectId, { + path: '/.super/ipfs.json', + contents: JSON.stringify(array, null, 4) + }))), + delayWhen(() => from(updateFileSystemState(router.control.getActiveProject()))), + map(() => ({shareURL, timestamp})), // Finally simply return the original object we are interested on for the UI + catchError(error => { + console.log(error); + return of('Error saving the file ipfs.json file.') + }), + ) + ), + map(ipfsActions.uploadToIPFSSuccess), + catchError(error => { + console.log(error); + return of(ipfsActions.uploadToIPFSFail(error)) + }) + ) + }) +); + +export default uploadToIPFS; diff --git a/src/epics/project/index.js b/src/epics/project/index.js new file mode 100644 index 00000000..38420f9a --- /dev/null +++ b/src/epics/project/index.js @@ -0,0 +1,21 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { updateProjectSettings } from './updateProjectSettings.epic'; + +export const projectEpics = [ + updateProjectSettings, +]; diff --git a/src/epics/project/updateProjectSettings.epic.js b/src/epics/project/updateProjectSettings.epic.js new file mode 100644 index 00000000..2605ad85 --- /dev/null +++ b/src/epics/project/updateProjectSettings.epic.js @@ -0,0 +1,42 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { from } from 'rxjs'; +import { switchMap, tap, map, catchError, withLatestFrom } from 'rxjs/operators'; +import { ofType } from 'redux-observable'; +import { projectActions } from '../../actions'; + +export const updateProjectSettings = (action$, state$, { router }) => action$.pipe( + ofType(projectActions.UPDATE_PROJECT_SETTINGS), + withLatestFrom(state$), + switchMap(([action, ]) => { + const activeProject = router.control.getActiveProject(); + + // TODO - This is some legacy code that could be moved to redux state + activeProject.setName(action.data.name); + activeProject.setTitle(action.data.title); + + return from(activeProject.saveDappfile()) + .pipe( + map(() => projectActions.updateProjectSettingsSuccess(action.data)), + // This should not be here but for simplicity lets leave it here + tap(() => router.control.redrawMain(true)), + catchError(error => { + console.log("Error saving the DappFile: " + error); + return of(ipfsActions.updateProjectSettingsFail(error)) + }) + ); + })); diff --git a/src/epics/settings/initTrackingAnalytics.epic.js b/src/epics/settings/initTrackingAnalytics.epic.js index 4ee06632..83d522d2 100644 --- a/src/epics/settings/initTrackingAnalytics.epic.js +++ b/src/epics/settings/initTrackingAnalytics.epic.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import { empty } from 'rxjs'; import { switchMap, withLatestFrom } from 'rxjs/operators'; import { ofType } from 'redux-observable'; diff --git a/src/epics/settings/reportSettings.epic.js b/src/epics/settings/reportSettings.epic.js index 2283cf4a..3e0aed98 100644 --- a/src/epics/settings/reportSettings.epic.js +++ b/src/epics/settings/reportSettings.epic.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import { empty } from 'rxjs'; import { switchMap, withLatestFrom } from 'rxjs/operators'; import { ofType } from 'redux-observable'; @@ -22,4 +38,3 @@ const reportSettings = (action$, state$) => action$.pipe( })); export default reportSettings; - diff --git a/src/epics/sidePanels/download.epic.js b/src/epics/sidePanels/download.epic.js index 6934dddc..c8ff0f73 100644 --- a/src/epics/sidePanels/download.epic.js +++ b/src/epics/sidePanels/download.epic.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import { map } from 'rxjs/operators'; import { ofType } from 'redux-observable'; import { sidePanelsActions } from '../../actions'; diff --git a/src/epics/sidePanels/index.js b/src/epics/sidePanels/index.js index 4352db61..5d375dba 100644 --- a/src/epics/sidePanels/index.js +++ b/src/epics/sidePanels/index.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import { downloadEpic } from './download.epic'; import { toggleWeb3AccountsEpic } from './toggleWeb3Accounts.epic'; diff --git a/src/epics/sidePanels/toggleWeb3Accounts.epic.js b/src/epics/sidePanels/toggleWeb3Accounts.epic.js index 18cec2e2..e09d42a7 100644 --- a/src/epics/sidePanels/toggleWeb3Accounts.epic.js +++ b/src/epics/sidePanels/toggleWeb3Accounts.epic.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import { empty } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { ofType } from 'redux-observable'; diff --git a/src/index.js b/src/index.js index fdf49adb..7755aba6 100644 --- a/src/index.js +++ b/src/index.js @@ -24,11 +24,16 @@ import { AnalyticsProvider, Analytics, LogOnMount } from './utils/analytics'; // Load generic CSS import './style/index.less'; +import 'react-toastify/dist/ReactToastify.min.css'; -// TODO - Components -// import Loading from './components/Loading'; +// Used to communicate between components, events is probably a better way of doing this. +const router = { + register: (name, obj) => { + router[name] = obj; + } +}; -const { persistor, store } = configureStore(); +const { persistor, store } = configureStore(router); // persistor.purge(); // Debug to clear persist ReactDOM.render(( @@ -36,7 +41,7 @@ ReactDOM.render(( - + diff --git a/src/reducers/app.reducer.js b/src/reducers/app.reducer.js index 8e3c128e..66e17d81 100644 --- a/src/reducers/app.reducer.js +++ b/src/reducers/app.reducer.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + export const initialState = { version: '1.4.3', }; diff --git a/src/reducers/index.js b/src/reducers/index.js index cacd699e..00712bcc 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,8 +1,27 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import app from './app.reducer'; -import projects from './projects.reducer'; +import project from './project.reducer'; import settings from './settings.reducer'; import sidePanels from './sidePanels.reducer'; import panes from './panes.reducer'; +import ipfs from './ipfs.reducer'; +import toast from './toast.reducer'; +import view from './view.reducer'; const rehydrated = (state = false, action) => { switch (action.type) { @@ -17,7 +36,10 @@ export default { rehydrated, app, settings, - projects, - sidePanels, - panes + project, + view, + panes, + ipfs, + toast, + sidePanels }; diff --git a/src/reducers/ipfs.reducer.js b/src/reducers/ipfs.reducer.js new file mode 100644 index 00000000..47a2d923 --- /dev/null +++ b/src/reducers/ipfs.reducer.js @@ -0,0 +1,94 @@ +import { ipfsActions, projectActions } from '../actions'; + +export const initialState = { + uploading: false, + shareURL: null, + timestamp: null, + error: null, + showUploadButton: false, + showForkButton: true, + showUploadSettings: false, + showUploadDialog: false, + uploadSettings: { + includeBuildInfo: false, + includeProjectConfig: false + }, +}; + +export default function panesReducer(state = initialState, action) { + switch (action.type) { + case ipfsActions.UPLOAD_TO_IPFS: + return { + ...state, + uploading: true + }; + case ipfsActions.UPLOAD_TO_IPFS_SUCCESS: + return { + ...state, + uploading: false, + timestamp: action.data.timestamp, + shareURL: action.data.shareURL, + showUploadDialog: true, + uploadSettings: initialState.uploadSettings // Make we reset the settigs on every upload + }; + case ipfsActions.UPLOAD_TO_IPFS_FAIL: { + return { + ...state, + uploading: false, + error: action.data + }; + } + case ipfsActions.RESTORE_IPFS_STATE_SUCCESS: { + return { + ...state, + timestamp: action.data.timestamp, + shareURL: action.data.shareURL + }; + } + case ipfsActions.RESTORE_IPFS_STATE_FAIL: { + return { + ...state, + shareURL: null, + timestamp: null + }; + } + case ipfsActions.SHOW_UPLOAD_SETTINGS: { + return { + ...state, + showUploadSettings: true, + }; + } + case ipfsActions.HIDE_UPLOAD_SETTINGS: { + return { + ...state, + showUploadSettings: false, + }; + } + case ipfsActions.UPLOAD_SETTINGS_CHANGED: { + return { + ...state, + uploadSettings: action.data, + }; + } + case ipfsActions.HIDE_UPLOAD_DIALOG: { + return { + ...state, + showUploadDialog: false, + }; + } + case ipfsActions.UPDATE_IPFS_ACTION_BUTTONS: { + return { + ...state, + showUploadButton: action.data.showUploadButton, + showForkButton: action.data.showForkButton, + }; + } + case projectActions.SELECT_PROJECT: { + return { + ...initialState, // Make we reset the state when changing projects + }; + } + default: + return state; + } +} diff --git a/src/reducers/project.reducer.js b/src/reducers/project.reducer.js new file mode 100644 index 00000000..01090e7f --- /dev/null +++ b/src/reducers/project.reducer.js @@ -0,0 +1,46 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { projectActions } from '../actions'; + +export const initialState = { + selectedProject: { + id: 0, + name: '' + }, +}; + +export default function projectsReducer(state = initialState, action) { + switch (action.type) { + case projectActions.SELECT_PROJECT: { + return { + ...state, + selectedProject: action.data ? { ...action.data } : initialState.selectedProject, + }; + } + case projectActions.UPDATE_PROJECT_SETTINGS_SUCCESS: { + return { + ...state, + selectedProject: { + ...state.selectedProject, + name: action.data.name + }, + }; + } + default: + return state; + } +} diff --git a/src/reducers/projects.reducer.js b/src/reducers/projects.reducer.js deleted file mode 100644 index 01fde3c0..00000000 --- a/src/reducers/projects.reducer.js +++ /dev/null @@ -1,16 +0,0 @@ -import Store from '../store/projects'; - -export const initialState = Store; - -export default function projectsReducer(state = initialState, action) { - switch (action.type) { - case 'SELECT_PROJECT': { - return { - ...state, - selectedProject: action.data ? { ...action.data } : Store.selectedProject, - }; - } - default: - return state; - } -} diff --git a/src/reducers/toast.reducer.js b/src/reducers/toast.reducer.js new file mode 100644 index 00000000..2e594220 --- /dev/null +++ b/src/reducers/toast.reducer.js @@ -0,0 +1,49 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import { ipfsActions, projectActions, toastActions } from '../actions'; + +export const initialState = { + toasts: [], +}; + +var counter = 0; +export default function toastsReducer(state = initialState, action) { + switch (action.type) { + case projectActions.UPDATE_PROJECT_SETTINGS_FAIL: + case ipfsActions.IMPORT_PROJECT_FROM_IPFS_SUCCESS: + case ipfsActions.IMPORT_PROJECT_FROM_IPFS_FAIL: + case ipfsActions.FORK_PROJECT_SUCCESS: + case ipfsActions.FORK_PROJECT_FAIL: + counter += 1; + const toast = { + id: counter, + type: action.type + } + return { + ...state, + toasts: state.toasts.concat(toast) + } + case toastActions.TOAST_DISMISSED: + return { + ...state, + toasts: state.toasts.filter(toast => action.data !== toast.id), + + } + default: + return state; + } +} diff --git a/src/reducers/view.reducer.js b/src/reducers/view.reducer.js new file mode 100644 index 00000000..b98a5f80 --- /dev/null +++ b/src/reducers/view.reducer.js @@ -0,0 +1,59 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import View from '../store/view'; + +export const initialState = View; + +export default function viewReducers(state = initialState, action) { + switch (action.type) { + case 'CLOSE_ALL_PANELS': { + return { + ...state, + panel: { + showTransactionsHistory: false + } + }; + } + case 'TOGGLE_TRANSACTIONS_HISTORY_PANEL': { + return { + ...state, + panel: { + showTransactionsHistory: !state.panel.showTransactionsHistory, + } + }; + } + case 'OPEN_TRANSACTIONS_HISTORY_PANEL': { + return { + ...state, + panel: { + showTransactionsHistory: true, + } + + }; + } + case 'CLOSE_TRANSACTIONS_HISTORY_PANEL': { + return { + ...state, + panel: { + showTransactionsHistory: false, + } + }; + } + default: + return state; + } +} diff --git a/src/selectors/app.js b/src/selectors/app.js index 03f79120..0c7f783b 100644 --- a/src/selectors/app.js +++ b/src/selectors/app.js @@ -1 +1,17 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + export const getAppVersion = state => state.app.version || ''; diff --git a/src/selectors/index.js b/src/selectors/index.js new file mode 100644 index 00000000..8f123d55 --- /dev/null +++ b/src/selectors/index.js @@ -0,0 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export * from './ipfs.selectors'; +export * from './toast.selectors'; +export * from './project.selectors'; diff --git a/src/selectors/ipfs.selectors.js b/src/selectors/ipfs.selectors.js new file mode 100644 index 00000000..d9fbda9f --- /dev/null +++ b/src/selectors/ipfs.selectors.js @@ -0,0 +1,27 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export const ipfsSelectors = { + getUploadingToIPFS: state => state.ipfs.uploading, + getShareURL: state => state.ipfs.shareURL, + getLastUploadTimestamp: state => state.ipfs.timestamp, + getUploadToIPFSError: state => state.ipfs.error, + getShowUploadSettings: state => state.ipfs.showUploadSettings, + getUploadSettings: state => state.ipfs.uploadSettings, + getShowUploadDialog: state => state.ipfs.showUploadDialog, + getShowUploadButton: state => state.ipfs.showUploadButton, + getShowForkButton: state => state.ipfs.showForkButton, +} diff --git a/src/selectors/project.selectors.js b/src/selectors/project.selectors.js new file mode 100644 index 00000000..2e38f62d --- /dev/null +++ b/src/selectors/project.selectors.js @@ -0,0 +1,24 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export const projectSelectors = { + getSelectedProject: state => state.project.selectedProject, + getSelectedProjectId: state => state.project.selectedProject.id, + getSelectedProjectName: state => state.project.selectedProject.name, +} + + + diff --git a/src/selectors/projects.js b/src/selectors/projects.js deleted file mode 100644 index 3a20430a..00000000 --- a/src/selectors/projects.js +++ /dev/null @@ -1,3 +0,0 @@ -export const getSelectedProject = state => state.projects.selectedProject; -export const getSelectedProjectId = state => state.projects.selectedProject.id; - diff --git a/src/selectors/settings.js b/src/selectors/settings.js index 1ad7450f..22f43622 100644 --- a/src/selectors/settings.js +++ b/src/selectors/settings.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + export const getShowAnalyticsTrackingDialog = (state) => state.settings.showTrackingAnalyticsDialog; export const getPreferences = (state) => state.settings.preferences; export const getNetworkPreferences = (state) => state.settings.preferences.network; diff --git a/src/selectors/toast.selectors.js b/src/selectors/toast.selectors.js new file mode 100644 index 00000000..405418c9 --- /dev/null +++ b/src/selectors/toast.selectors.js @@ -0,0 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export const toastSelectors = { + getToasts: state => state.toast.toasts, +} diff --git a/src/services/index.js b/src/services/index.js index 4ff54dbf..056146cf 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -1 +1,18 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + export * from './preview.service'; +export * from './ipfs.service'; diff --git a/src/services/ipfs.service.js b/src/services/ipfs.service.js new file mode 100644 index 00000000..eeafa0ec --- /dev/null +++ b/src/services/ipfs.service.js @@ -0,0 +1,131 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +import IpfsAPI from 'ipfs-api'; +import Backend from '../components/projecteditor/control/backend'; + +let ipfs = null; +let backend = null; + +const TEMPORARY_PROJECT_ID = 1; + +export const ipfsService = { + + init(backendInstance) { + ipfs = new IpfsAPI({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' }) + backend = backendInstance; + }, + + isTemporaryProject(id) { + return id === TEMPORARY_PROJECT_ID; + }, + + clearTempProject() { + this._stripIpfsHash(); + backend.deleteProject(1, () => {}); + }, + + ipfsFetchFiles(hash, options) { + return ipfs.files.get(hash); + }, + + ipfsSyncUp(inode, { includeBuildInfo, includeProjectConfig }) { + return new Promise((resolve, reject) => { + const data = + JSON.parse(localStorage.getItem(Backend.DAPP_FORMAT_VERSION)) || {}; + + if (!data.projects) data.projects = []; + + var project = data.projects.filter(item2 => { + return inode == item2.inode; + })[0]; + + if (!project || !project.files) { + reject(); + return; + } + + const files = []; + var node = project.files['/']; + const fn = (node, path) => { + return new Promise( (resolve) => { + if (path === 'build/' && !includeBuildInfo) { + resolve(); + return; + } else if (path === '.super/' && !includeProjectConfig) { + resolve(); + return; + } + + if (node.children) { + const childrenKeys = Object.keys(node.children); + const fn2 = () => { + const childKey = childrenKeys.pop(); + if (childKey) { + const child = node.children[childKey]; + if (child.type == 'f') { + files.push({ + path: path + childKey, + content: ipfs.types.Buffer.from(child.contents), + }); + + fn2(); + return + } + else { + // Directory + fn(child, path + childKey + '/').then( () => { + fn2(); + return; + }); + } + } + else { + resolve(); + return; + } + }; + + fn2(); + } + else { + resolve(); + } + }); + }; + + fn(node, "").then( () => { + ipfs.files.add(files, {onlyHash: false, wrapWithDirectory: true}).then((res) => { + const hash = res.filter( (obj) => { + if (obj.path === "") return true; + })[0].hash; + + resolve(hash); + }) + .catch( (e) => { + reject(e); + }); + }) + .catch( (e) => { + reject(e); + }); + }); + }, + + _stripIpfsHash() { + history.pushState({}, '', '/'); + }, +}; diff --git a/src/services/preview.service.js b/src/services/preview.service.js index 5aab7e7a..2c4406a6 100644 --- a/src/services/preview.service.js +++ b/src/services/preview.service.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import { buildProjectHtml } from './utils/buildProjectHtml'; import SuperProvider from '../components/superprovider'; import Networks from '../networks'; @@ -36,7 +52,7 @@ export const previewService = { }, get projectItem() { return projectItem; }, - set projectItem(value) { + set projectItem(value) { projectItem = value; exportableDappHtml = null; }, diff --git a/src/services/utils/buildProjectHtml.js b/src/services/utils/buildProjectHtml.js index b9dea1b4..e4829bf7 100644 --- a/src/services/utils/buildProjectHtml.js +++ b/src/services/utils/buildProjectHtml.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import Networks from '../../networks'; function getProviderHTML(endpoint, accounts) { @@ -116,8 +132,8 @@ function getAccountAddress(project, wallet, disableAccounts) { /** * Create HTML page to preview and download a project - * @param {*} project - * @param {*} wallet + * @param {*} project + * @param {*} wallet * @param {*} disableAccounts */ export function buildProjectHtml(project, wallet, disableAccounts) { diff --git a/src/store/index.js b/src/store/index.js index caf8e833..d4266caf 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,3 +1,19 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + import { createStore, applyMiddleware, compose } from 'redux'; import { createMigrate, persistStore, persistCombineReducers } from 'redux-persist'; import { createEpicMiddleware, combineEpics } from 'redux-observable'; @@ -6,29 +22,43 @@ import thunk from 'redux-thunk'; import migrations from './migrations'; import reducers from '../reducers'; import { epics } from '../epics'; - +import Backend from '../components/projecteditor/control/backend'; // Redux Persist config const config = { key: 'root', storage, version: 5, - blacklist: ['app', 'sidePanels', 'view', 'panes'], + blacklist: ['app', 'sidePanels', 'panes', 'view', 'ipfs', 'explorer', 'toast'], migrate: createMigrate(migrations, { debug: true }) }; const reducer = persistCombineReducers(config, reducers); -const rootEpic = combineEpics(...epics); -const epicMiddleware = createEpicMiddleware(); -const middleware = [ - thunk, - epicMiddleware -]; + +const configureMiddleware = (router) => { + const rootEpic = combineEpics(...epics); + const epicMiddleware = createEpicMiddleware({ + dependencies: { + backend: new Backend(), + router: router + } + }); + + const middleware = [ + thunk, + epicMiddleware + ]; + + return { middleware, epicMiddleware, rootEpic }; +} const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; -const configureStore = () => { +const configureStore = (router) => { + + const { middleware, epicMiddleware, rootEpic } = configureMiddleware(router); + const store = createStore( reducer, composeEnhancers( diff --git a/src/store/projects.js b/src/store/projects.js deleted file mode 100644 index fb27d68f..00000000 --- a/src/store/projects.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - selectedProject: { - id: 0, - name: '' - } -}; diff --git a/src/store/view.js b/src/store/view.js new file mode 100644 index 00000000..cbc9da49 --- /dev/null +++ b/src/store/view.js @@ -0,0 +1,21 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +export default { + panel: { + showTransactionsHistory: false + } +}; diff --git a/src/style/index.less b/src/style/index.less index 197279a5..931e77a1 100644 --- a/src/style/index.less +++ b/src/style/index.less @@ -15,6 +15,7 @@ // along with Superblocks Lab. If not, see . @import './spacing'; +@import './toast'; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////// Variables ////////////////// @@ -266,6 +267,7 @@ a:active,a:focus { outline: none; } } + .btn1 { -webkit-border-radius: 17; -moz-border-radius: 17; @@ -285,8 +287,6 @@ a:active,a:focus { .btn2 { background-color: #8641f2; border-radius: 4px; - -webkit-border-radius: 4; - -moz-border-radius: 4; color: #fff; padding: 7px 20px; text-decoration: none; diff --git a/src/style/toast.less b/src/style/toast.less new file mode 100644 index 00000000..bdbf74cb --- /dev/null +++ b/src/style/toast.less @@ -0,0 +1,67 @@ +// Copyright 2018 Superblocks AB +// +// This file is part of Superblocks Lab. +// +// Superblocks Lab is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3 of the License. +// +// Superblocks Lab is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Superblocks Lab. If not, see . + +.toastContainer { + bottom: 2em; + right: 46px; + + .body { + display: flex; + align-items: center; + + .closeIcon { + align-self: flex-start; + margin-left: auto; + padding-right: 0; + color: #fff; + &:hover { + color: #c7c7c7; + } + .icon { + height: 20px; + width: 20px; + } + } + + .messageContainer { + display: flex; + align-items: center; + + svg { + margin-right: 20px; + margin-left: 15px; + } + + img { + transform: scale(1.4); + margin-right: 20px; + margin-left: 15px; + } + } + } + + .info { + background-color: #8641f2 !important; + color: #fff !important; + } + + .error { + background-color: red !important; + color: #fff !important; + } +} + + diff --git a/yarn.lock b/yarn.lock index 5a815170..d2fa8d4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1369,6 +1369,16 @@ asap@^2.0.6, asap@~2.0.3, asap@~2.0.6: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= +asn1.js@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-1.0.3.tgz#281ba3ec1f2448fe765f92a4eecf883fe1364b54" + integrity sha1-KBuj7B8kSP52X5Kk7s+IP+E2S1Q= + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + optionalDependencies: + bn.js "^1.0.0" + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1378,6 +1388,15 @@ asn1.js@^4.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" +asn1.js@^5.0.0, asn1.js@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.0.1.tgz#7668b56416953f0ce3421adbb3893ace59c96f59" + integrity sha512-aO8EaEgbgqq77IEw+1jfx5c9zTbzvkfuRBuZsSsPnTHMkmd5AI4J6OtITLZFa381jReeaQL67J0GBTUu0+ZTVw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -1434,7 +1453,7 @@ async@^1.4.2, async@^1.5.2: resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= -async@^2.0.1, async@^2.1.2, async@^2.1.4, async@^2.4.0, async@^2.5.0: +async@^2.0.1, async@^2.1.2, async@^2.1.4, async@^2.4.0, async@^2.5.0, async@^2.6.0, async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== @@ -2163,6 +2182,13 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base-x@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" + integrity sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA== + dependencies: + safe-buffer "^5.0.1" + base-x@^3.0.2: version "3.0.5" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.5.tgz#d3ada59afed05b921ab581ec3112e6444ba0795a" @@ -2215,11 +2241,21 @@ big.js@^3.1.3: resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + bignumber.js@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== +bignumber.js@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" + integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== + "bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git": version "2.0.7" resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" @@ -2234,6 +2270,11 @@ bindings@^1.2.1: resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" integrity sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw== +bindings@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5" + integrity sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew== + bip66@^1.1.3: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" @@ -2261,6 +2302,27 @@ bitcore-mnemonic@^1.5.0: bitcore-lib "^0.15.0" unorm "^1.3.3" +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bl@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-2.1.2.tgz#591182cb9f3f2eff3beb1e76dabedfb5c5fa9a26" + integrity sha512-DvC0x+PxmSJNx8wXoFV15pC2+GOJ3ohb4F1REq3X32a2Z3nEBpR1Guu740M7ouYAImFj4BXDNilLNZbygtG9lQ== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +blakejs@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.0.tgz#69df92ef953aa88ca51a32df6ab1c54a155fc7a5" + integrity sha1-ad+S75U6qIylGjLfarHFShVfx6U= + bluebird@^3.5.1: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" @@ -2275,6 +2337,11 @@ bn.js@=4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4 resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== +bn.js@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-1.3.0.tgz#0db4cbf96f8f23b742f5bcb9d1aa7a9994a05e83" + integrity sha1-DbTL+W+PI7dC9by50ap6mZSgXoM= + bn.js@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" @@ -2313,6 +2380,16 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +borc@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.4.tgz#52926dc561137188c6ca9fe01c9542576529a689" + integrity sha512-SCVjto/dbKfduyl+LDQ1Km28ly2aTIXtJbrYZWHFQAxkHph96I/zXTrTQXWuJobG8lQZjIA/dw9z7hmJHJhjMg== + dependencies: + bignumber.js "^7.2.1" + commander "^2.15.0" + ieee754 "^1.1.8" + json-text-sequence "^0.1" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2380,7 +2457,7 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.1.1, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -2526,7 +2603,7 @@ browserslist@^4.0.0, browserslist@^4.1.0, browserslist@^4.1.1, browserslist@^4.3 electron-to-chromium "^1.3.82" node-releases "^1.0.1" -bs58@=4.0.1: +bs58@4.0.1, bs58@=4.0.1, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= @@ -2540,11 +2617,29 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + buffer-compare@=1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" integrity sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY= +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2837,6 +2932,16 @@ ci-info@^1.5.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== +cids@~0.5.4, cids@~0.5.5, cids@~0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.5.7.tgz#bc5034bddcb9396fbf1cb60ad5498c976133de53" + integrity sha512-SlAz4p8XMEW3mhwiYbzfjn+5+Y//+kIuHqzRUytK0a3uGBnsjJb76xHliehv0HcVMCjRKv2vZnPTwd4QX+IcMA== + dependencies: + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "~0.2.7" + multihashes "~0.4.14" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -2850,6 +2955,11 @@ circular-json@^0.3.1: resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -2860,7 +2970,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.5: +classnames@^2.2.5, classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -3008,7 +3118,7 @@ commander@2.17.x, commander@~2.17.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.11.0: +commander@^2.11.0, commander@^2.15.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== @@ -3063,7 +3173,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@~1.6.0: +concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@^1.6.2, concat-stream@~1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -3666,6 +3776,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +delimit-stream@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" + integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -3807,6 +3922,13 @@ dom-converter@~0.2: dependencies: utila "~0.4" +dom-helpers@^3.3.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" + integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== + dependencies: + "@babel/runtime" "^7.1.2" + dom-serializer@0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -3991,7 +4113,7 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" -end-of-stream@^1.0.0, end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== @@ -4875,6 +4997,11 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" +flatmap@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4" + integrity sha1-Hxik2TgVLUlZZfnJWNkjqy3WabQ= + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -4956,6 +5083,11 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6" @@ -5626,7 +5758,7 @@ identity-obj-proxy@3.0.0: dependencies: harmony-reflect "^1.4.6" -ieee754@^1.1.4: +ieee754@^1.1.4, ieee754@^1.1.8: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== @@ -5821,6 +5953,19 @@ invert-kv@^2.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== +ip-address@^5.8.9: + version "5.8.9" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-5.8.9.tgz#6379277c23fc5adb20511e4d23ec2c1bde105dfd" + integrity sha512-7ay355oMN34iXhET1BmCJVsHjOTSItEEIIpOs38qUC23AIhOy+xIPnkrTuEFjeLMrTJ7m8KMXWgWfy/2Vn9sDw== + dependencies: + jsbn "1.1.0" + lodash.find "^4.6.0" + lodash.max "^4.0.1" + lodash.merge "^4.6.0" + lodash.padstart "^4.6.1" + lodash.repeat "^4.1.0" + sprintf-js "1.1.0" + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -5841,6 +5986,97 @@ ipaddr.js@^1.5.2: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.1.tgz#fa4b79fa47fd3def5e3b159825161c0a519c9427" integrity sha1-+kt5+kf9Pe9eOxWYJRYcClGclCc= +ipfs-api@^26.1.2: + version "26.1.2" + resolved "https://registry.yarnpkg.com/ipfs-api/-/ipfs-api-26.1.2.tgz#6b53d4720455060ad39784336234a4acc54d4332" + integrity sha512-HkM6vQOHL9z9ZCXIrbDXvAOsIzfWPaAac9kY+SjUuVqMydWHzP8qTxfv5jaXResGbmLcbwcROhuqgJU+HrclSg== + dependencies: + async "^2.6.1" + big.js "^5.2.2" + bl "^2.1.2" + bs58 "^4.0.1" + cids "~0.5.5" + concat-stream "^1.6.2" + debug "^4.1.0" + detect-node "^2.0.4" + end-of-stream "^1.4.1" + flatmap "0.0.3" + glob "^7.1.3" + ipfs-block "~0.8.0" + ipfs-unixfs "~0.1.16" + ipld-dag-cbor "~0.13.0" + ipld-dag-pb "~0.14.11" + is-ipfs "~0.4.7" + is-pull-stream "0.0.0" + is-stream "^1.1.0" + libp2p-crypto "~0.14.0" + lodash "^4.17.11" + lru-cache "^4.1.3" + multiaddr "^5.0.0" + multibase "~0.5.0" + multihashes "~0.4.14" + ndjson "^1.5.0" + once "^1.4.0" + peer-id "~0.12.0" + peer-info "~0.14.1" + promisify-es6 "^1.0.3" + pull-defer "~0.2.3" + pull-pushable "^2.2.0" + pull-stream-to-stream "^1.3.4" + pump "^3.0.0" + qs "^6.5.2" + readable-stream "^3.0.6" + stream-http "^3.0.0" + stream-to-pull-stream "^1.7.2" + streamifier "~0.1.1" + tar-stream "^1.6.2" + through2 "^2.0.3" + +ipfs-block@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/ipfs-block/-/ipfs-block-0.8.0.tgz#1004bcc67dad0413c70fc6d56e86537716debd7d" + integrity sha512-znNtFRxXlJYP1/Q4u0tGFJUceH9pNww8WA+zair6T3y7d28m+vtUDJGn96M7ZlFFSkByQyQsAiq2ssNhKtMzxw== + dependencies: + cids "~0.5.5" + class-is "^1.1.0" + +ipfs-unixfs@~0.1.16: + version "0.1.16" + resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-0.1.16.tgz#41140f4359f1b8fe7a970052663331091c5f54c4" + integrity sha512-TX9Dyu77MxpLzGh/LcQne95TofOyvOeW0oOi72aBMMcV1ItP3684e6NTG9KY1qzdrC+ZUR8kT7y18J058n8KXg== + dependencies: + protons "^1.0.1" + +ipld-dag-cbor@~0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/ipld-dag-cbor/-/ipld-dag-cbor-0.13.0.tgz#d1a258fcf7acd21a36993596ccfd1486dc5b9cca" + integrity sha512-74gtitUOWbLkGtqomhq7lDYwWzfFNwbwMXAj3jpti4ZtfM9VTJWVIQ+05u7NOCj8yaLwzFONHdcO0rJ+j/i0jA== + dependencies: + async "^2.6.1" + borc "^2.0.3" + bs58 "^4.0.1" + cids "~0.5.5" + is-circular "^1.0.2" + multihashes "~0.4.14" + multihashing-async "~0.5.1" + traverse "~0.6.6" + +ipld-dag-pb@~0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/ipld-dag-pb/-/ipld-dag-pb-0.14.11.tgz#df235a301fec8443cf933387cebb38e42c22c2a8" + integrity sha512-ja4FH6elDprVuJBkNObFlq7+9h1Q3aoQx5SSG/v3I9e7j19nwyuMhLJYwBhdv29LiqpyD2cEqNrJLm8lWn0lJg== + dependencies: + async "^2.6.1" + bs58 "^4.0.1" + cids "~0.5.4" + class-is "^1.1.0" + is-ipfs "~0.4.2" + multihashing-async "~0.5.1" + protons "^1.0.1" + pull-stream "^3.6.9" + pull-traverse "^1.0.3" + stable "~0.1.8" + is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" @@ -5901,6 +6137,11 @@ is-ci@^1.0.10: dependencies: ci-info "^1.5.0" +is-circular@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-circular/-/is-circular-1.0.2.tgz#2e0ab4e9835f4c6b0ea2b9855a84acd501b8366c" + integrity sha512-YttjnrswnUYRVJvxCvu8z+PGMUSzC2JttP0OEXezlAEdp3EXzhf7IZ3j0gRAybJBQupedIZFhY61Tga6E0qASA== + is-color-stop@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" @@ -6039,6 +6280,16 @@ is-hex-prefixed@1.0.0: resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= +is-ipfs@~0.4.2, is-ipfs@~0.4.7: + version "0.4.8" + resolved "https://registry.yarnpkg.com/is-ipfs/-/is-ipfs-0.4.8.tgz#ea229aef6230433ad1e8df930c49c5e773422c3f" + integrity sha512-xIKUeA24IFMfkmeAPEOZL448X7a08c/KzAGQp1e/QxC9bx/NNEdT/ohob3SW6eJO2UwJNjsbfMeNZ2B+Dk2Fdg== + dependencies: + bs58 "4.0.1" + cids "~0.5.6" + multibase "~0.6.0" + multihashes "~0.4.13" + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -6104,6 +6355,16 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= +is-promise@~1, is-promise@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-1.0.1.tgz#31573761c057e33c2e91aab9e96da08cefbe76e5" + integrity sha1-MVc3YcBX4zwukaq56W2gjO++duU= + +is-pull-stream@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/is-pull-stream/-/is-pull-stream-0.0.0.tgz#a3bc3d1c6d3055151c46bde6f399efed21440ca9" + integrity sha1-o7w9HG0wVRUcRr3m85nv7SFEDKk= + is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" @@ -6628,6 +6889,11 @@ js-sha3@^0.3.1: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" integrity sha1-hhIoAhQvCChQKg0d7h2V4lO7AkM= +js-sha3@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a" + integrity sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -6646,6 +6912,11 @@ js-yaml@^3.12.0, js-yaml@^3.7.0, js-yaml@^3.9.0: argparse "^1.0.7" esprima "^4.0.0" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + integrity sha1-sBMHyym2GKHtJux56RH4A8TaAEA= + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -6764,11 +7035,18 @@ json-stable-stringify@~0.0.0: dependencies: jsonify "~0.0.0" -json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json-text-sequence@^0.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" + integrity sha1-py8hfcSvxGKf/1/rME3BvVGi89I= + dependencies: + delimit-stream "0.1.0" + json3@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" @@ -6854,6 +7132,11 @@ keccakjs@^0.2.0: browserify-sha3 "^0.0.1" sha3 "^1.1.0" +keypair@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/keypair/-/keypair-1.0.1.tgz#7603719270afb6564ed38a22087a06fc9aa4ea1b" + integrity sha1-dgNxknCvtlZO04oiCHoG/Jqk6hs= + killable@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -7036,6 +7319,75 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +libp2p-crypto-secp256k1@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/libp2p-crypto-secp256k1/-/libp2p-crypto-secp256k1-0.2.2.tgz#0dd521f18abc4e36a152e24e9b36307b0ae9cf05" + integrity sha1-DdUh8Yq8TjahUuJOmzYwewrpzwU= + dependencies: + async "^2.5.0" + multihashing-async "~0.4.6" + nodeify "^1.0.1" + safe-buffer "^5.1.1" + secp256k1 "^3.3.0" + +libp2p-crypto@~0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/libp2p-crypto/-/libp2p-crypto-0.12.1.tgz#4a870d269ba3150dfe014e4f9aea1e55076015c8" + integrity sha512-1/z8rxZ0DcQNreZhEsl7PnLr7DWOioSvYbKBLGkRwNRiNh1JJLgh0PdTySBb44wkrOGT+TxcGRd7iq3/X6Wxwg== + dependencies: + asn1.js "^5.0.0" + async "^2.6.0" + browserify-aes "^1.1.1" + bs58 "^4.0.1" + keypair "^1.0.1" + libp2p-crypto-secp256k1 "~0.2.2" + multihashing-async "~0.4.7" + node-forge "^0.7.1" + pem-jwk "^1.5.1" + protons "^1.0.1" + rsa-pem-to-jwk "^1.1.3" + tweetnacl "^1.0.0" + webcrypto-shim "github:dignifiedquire/webcrypto-shim#master" + +libp2p-crypto@~0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/libp2p-crypto/-/libp2p-crypto-0.13.0.tgz#25404ea43bf2fd3802780d9ab87b5d2095d86f07" + integrity sha512-i3r1TBec/xYmC5bcpPiIs3OyUAU3iy53OdRdxqawKoWTQPjYB+TyQ4w+otT66Y0sMcw70O0wH3GFAfPmQgFn+g== + dependencies: + asn1.js "^5.0.0" + async "^2.6.0" + browserify-aes "^1.2.0" + bs58 "^4.0.1" + keypair "^1.0.1" + libp2p-crypto-secp256k1 "~0.2.2" + multihashing-async "~0.4.8" + node-forge "^0.7.5" + pem-jwk "^1.5.1" + protons "^1.0.1" + rsa-pem-to-jwk "^1.1.3" + tweetnacl "^1.0.0" + webcrypto-shim "github:dignifiedquire/webcrypto-shim#master" + +libp2p-crypto@~0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/libp2p-crypto/-/libp2p-crypto-0.14.1.tgz#c88e0cfb05c9fd877444b13baf5c45be5ca5c14e" + integrity sha512-JP3bfEzNik76fFIWOeU909+v76tjj5BMukbPCc61bgh1ixftcHkr4bH79duz+oSxRpGA+orCLxvkhgALV+pfwg== + dependencies: + asn1.js "^5.0.1" + async "^2.6.1" + browserify-aes "^1.2.0" + bs58 "^4.0.1" + keypair "^1.0.1" + libp2p-crypto-secp256k1 "~0.2.2" + multihashing-async "~0.5.1" + node-forge "~0.7.6" + pem-jwk "^1.5.1" + protons "^1.0.1" + rsa-pem-to-jwk "^1.1.3" + tweetnacl "^1.0.0" + ursa-optional "~0.9.9" + webcrypto-shim "github:dignifiedquire/webcrypto-shim#master" + lie@~3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" @@ -7122,6 +7474,26 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= +lodash.filter@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= + +lodash.find@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" + integrity sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E= + +lodash.map@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + +lodash.max@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.max/-/lodash.max-4.0.1.tgz#8735566c618b35a9f760520b487ae79658af136a" + integrity sha1-hzVWbGGLNan3YFILSHrnllivE2o= + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -7132,6 +7504,21 @@ lodash.memoize@~3.0.3: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= +lodash.merge@^4.6.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" + integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ== + +lodash.padstart@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" + integrity sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs= + +lodash.repeat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44" + integrity sha1-/H3oEx2MisB+S0n3T/6CnR8r7EQ= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -7157,12 +7544,17 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= +lodash.uniqby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" + integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= + lodash@=4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= -"lodash@>=3.5 <5", lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5: +"lodash@>=3.5 <5", lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== @@ -7172,6 +7564,11 @@ loglevel@^1.4.1: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" + integrity sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k= + loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -7197,6 +7594,13 @@ ltgt@~2.2.0: resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= +mafmt@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/mafmt/-/mafmt-6.0.3.tgz#aa918c60237b8a7c4bc3872666674460b3341bdb" + integrity sha512-VtaYiM1oQu3zmT9iejn2fFkAse1PtG1ytWr+AqeydTqpIpnYp9ycipQEJSP9yeZnQSqVmXVlErkgjG4WnAkk8A== + dependencies: + multiaddr "^6.0.0" + make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -7608,6 +8012,62 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== +multiaddr@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/multiaddr/-/multiaddr-4.0.0.tgz#70a8857c4f737350bc2c56914a70f1263889db33" + integrity sha512-zUatrOCfBd/tJNOSoJ10d2EI2FDXB9PyPZhqUMdXE9mOyR3C+HLuOjga2Ga/eChwvEHIpTYRMoIKF2Nv7af2qQ== + dependencies: + bs58 "^4.0.1" + class-is "^1.1.0" + ip "^1.1.5" + ip-address "^5.8.9" + lodash.filter "^4.6.0" + lodash.map "^4.6.0" + varint "^5.0.0" + xtend "^4.0.1" + +multiaddr@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/multiaddr/-/multiaddr-5.0.2.tgz#bffc4ebf0ef208ce40eab8cd6f146296b61aa0e3" + integrity sha512-dXz1chaUHV6L6okujDLS7uRA6NmCbitpikOJA0vMMnrwVyai5kC3ot2CSLrSfj3B8XIgNzpe/j5auSYrnbGGzA== + dependencies: + bs58 "^4.0.1" + class-is "^1.1.0" + ip "^1.1.5" + ip-address "^5.8.9" + lodash.filter "^4.6.0" + lodash.map "^4.6.0" + varint "^5.0.0" + xtend "^4.0.1" + +multiaddr@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/multiaddr/-/multiaddr-6.0.2.tgz#858843588393be65cb85d14658ac61bb0ec25901" + integrity sha512-yqnJt5BgO5tOutXgWHqwxchbUMjnQSVFxJMiRQa4itQInrq8ZM2ncM274tpDqA/JILleTTNKZGztu+WnW7ssMg== + dependencies: + bs58 "^4.0.1" + class-is "^1.1.0" + ip "^1.1.5" + ip-address "^5.8.9" + lodash.filter "^4.6.0" + lodash.map "^4.6.0" + varint "^5.0.0" + xtend "^4.0.1" + +multibase@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.5.0.tgz#45668ad138963d778bdf1f79da64f21caa7bb6eb" + integrity sha512-7epKiK8/UBzraYZvOuZa8FH/00hMfTnzTy1OQol1YBU2csAYA7rwWh+iue9plXRmVFBGvmVKMuo0oq5sD47kvw== + dependencies: + base-x "3.0.4" + +multibase@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.0.tgz#0216e350614c7456da5e8e5b20d3fcd4c9104f56" + integrity sha512-R9bNLQhbD7MsitPm1NeY7w9sDgu6d7cuj25snAWH7k5PSNPSwIQQBpcpj8jx1W96dLbdigZqmUWOdQRMnAmgjA== + dependencies: + base-x "3.0.4" + multicast-dns-service-types@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" @@ -7621,6 +8081,50 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" +multicodec@~0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.2.7.tgz#44dcb902b7ccd8065c4c348fe9987acf14a0679d" + integrity sha512-96xc9zs7bsclMW0Po9ERnRFqcsWHY8OZ8JW/I8DeHG58YYJZy3cBGI00Ze7hz9Ix56DNHMTSxEj9cgoZByruMg== + dependencies: + varint "^5.0.0" + +multihashes@~0.4.13, multihashes@~0.4.14: + version "0.4.14" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.14.tgz#774db9a161f81a8a27dc60788f91248e020f5244" + integrity sha512-V/g/EIN6nALXfS/xHUAgtfPP3mn3sPIF/i9beuGKf25QXS2QZYCpeVJbDPEannkz32B2fihzCe2D/KMrbcmefg== + dependencies: + bs58 "^4.0.1" + varint "^5.0.0" + +multihashing-async@~0.4.6, multihashing-async@~0.4.7, multihashing-async@~0.4.8: + version "0.4.8" + resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-0.4.8.tgz#41572b25a8fc68eb318b8562409fdd721a727ea1" + integrity sha512-LCc4lfxmTJOHKIjZjFNgvmfB6nXS/ErLInT9uwU8udFrRm2PH+aTPk3mfCREKmCiSHOlCWiv2O8rlnBx+OjlMw== + dependencies: + async "^2.6.0" + blakejs "^1.1.0" + js-sha3 "^0.7.0" + multihashes "~0.4.13" + murmurhash3js "^3.0.1" + nodeify "^1.0.1" + +multihashing-async@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-0.5.1.tgz#1fc563798f3777b43df0f77a0bf6474192687c0c" + integrity sha512-Ft5lQNcJCfsns1QN1TDXqPZrrNwBYqIokprYJR2h2Jj01x0GFcYmJYAqHvme6vJoyI3XptEcmZpdr9g5Oy7q3Q== + dependencies: + async "^2.6.1" + blakejs "^1.1.0" + js-sha3 "^0.7.0" + multihashes "~0.4.13" + murmurhash3js "^3.0.1" + nodeify "^1.0.1" + +murmurhash3js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/murmurhash3js/-/murmurhash3js-3.0.1.tgz#3e983e5b47c2a06f43a713174e7e435ca044b998" + integrity sha1-Ppg+W0fCoG9DpxMXTn5DXKBEuZg= + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -7631,16 +8135,16 @@ nan@2.10.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== +nan@^2.11.1, nan@^2.9.2: + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== + nan@^2.2.1: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== -nan@^2.9.2: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7663,6 +8167,16 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +ndjson@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ndjson/-/ndjson-1.5.0.tgz#ae603b36b134bcec347b452422b0bf98d5832ec8" + integrity sha1-rmA7NrE0vOw0e0UkIrC/mNWDLsg= + dependencies: + json-stringify-safe "^5.0.1" + minimist "^1.2.0" + split2 "^2.1.0" + through2 "^2.0.3" + needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" @@ -7707,6 +8221,11 @@ node-forge@0.7.5: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" integrity sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ== +node-forge@^0.7.1, node-forge@^0.7.5, node-forge@~0.7.6: + version "0.7.6" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" + integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -7774,6 +8293,14 @@ node-releases@^1.0.0-alpha.11, node-releases@^1.0.1: dependencies: semver "^5.3.0" +nodeify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nodeify/-/nodeify-1.0.1.tgz#64ab69a7bdbaf03ce107b4f0335c87c0b9e91b1d" + integrity sha1-ZKtpp7268DzhB7TwM1yHwLnpGx0= + dependencies: + is-promise "~1.0.0" + promise "~1.3.0" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -7878,6 +8405,11 @@ object-assign@4.1.1, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= +object-assign@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" + integrity sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo= + object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" @@ -8003,6 +8535,13 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" +optimist@~0.3.5: + version "0.3.7" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" + integrity sha1-yQlBrVnkJzMokjB00s8ufLxuwNk= + dependencies: + wordwrap "~0.0.2" + optimize-css-assets-webpack-plugin@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.1.tgz#9eb500711d35165b45e7fd60ba2df40cb3eb9159" @@ -8325,6 +8864,44 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +peer-id@~0.10.7: + version "0.10.7" + resolved "https://registry.yarnpkg.com/peer-id/-/peer-id-0.10.7.tgz#6c12634636fc90a0e7bc76360c95f73564461fdd" + integrity sha512-VEpMFcL9q0NQijmR0jsj38OGbY4yzaWMEareVkDahopmlNT+Cpsot8btPgsgBBApP9NiZj2Enwvh8rZN30ocQw== + dependencies: + async "^2.6.0" + libp2p-crypto "~0.12.1" + lodash "^4.17.5" + multihashes "~0.4.13" + +peer-id@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/peer-id/-/peer-id-0.12.0.tgz#a3ccc4badee5daf68c2c4e1e77045f1456ad8493" + integrity sha512-pPKk4IDBWGGzcjXe6zzngIwKmyadYNsIOUH1PKb7GYTVVTKHpHn78ljZNZdAXAWZ2V1TmlU2OS6d9MfW2E5DNA== + dependencies: + async "^2.6.1" + class-is "^1.1.0" + libp2p-crypto "~0.13.0" + lodash "^4.17.10" + multihashes "~0.4.13" + +peer-info@~0.14.1: + version "0.14.1" + resolved "https://registry.yarnpkg.com/peer-info/-/peer-info-0.14.1.tgz#ac5aec421e9965f7b0e7576d717941bb25676134" + integrity sha512-I9K+q7sisU0gg5ej6ekbhgolwlcm1tc2wDtLmumptoLYx0DkIT8WVHtgoTnupYwRRqcYADtwddFdiXfb8QFqzg== + dependencies: + lodash.uniqby "^4.7.0" + mafmt "^6.0.0" + multiaddr "^4.0.0" + peer-id "~0.10.7" + +pem-jwk@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pem-jwk/-/pem-jwk-1.5.1.tgz#7a8637fd2f67a827e57c0c42e1c23c3fd52cfb01" + integrity sha1-eoY3/S9nqCflfAxC4cI8P9Us+wE= + dependencies: + asn1.js "1.0.3" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -9100,6 +9677,18 @@ promise@^7.1.1: dependencies: asap "~2.0.3" +promise@~1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-1.3.0.tgz#e5cc9a4c8278e4664ffedc01c7da84842b040175" + integrity sha1-5cyaTIJ45GZP/twBx9qEhCsEAXU= + dependencies: + is-promise "~1" + +promisify-es6@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/promisify-es6/-/promisify-es6-1.0.3.tgz#b012668c4df3c965ce13daac2b3a4d1726a96346" + integrity sha512-N9iVG+CGJsI4b4ZGazjwLnxErD2d9Pe4DPvvXSxYA9tFNu8ymXME4Qs5HIQ0LMJpNM7zj+m0NlNnNeqFpKzqnA== + prompts@^0.1.9: version "0.1.14" resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2" @@ -9108,7 +9697,7 @@ prompts@^0.1.9: kleur "^2.0.1" sisteransi "^0.1.1" -prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2: +prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== @@ -9116,6 +9705,21 @@ prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2: loose-envify "^1.3.1" object-assign "^4.1.1" +protocol-buffers-schema@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz#00434f608b4e8df54c59e070efeefc37fb4bb859" + integrity sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w== + +protons@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/protons/-/protons-1.0.1.tgz#1c107144c07fc2d1cb8b6cb76451e6a938237676" + integrity sha512-+0ZKnfVs+4c43tbAQ5j0Mck8wPcLnlxUYzKQoB4iDW4ocdXGnN4P+0dDbgX1FTpoY9+7P2Tn2scJyHHqj+S/lQ== + dependencies: + protocol-buffers-schema "^3.3.1" + safe-buffer "^5.1.1" + signed-varint "^2.0.1" + varint "^5.0.0" + proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" @@ -9151,6 +9755,31 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" +pull-defer@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-pushable@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" + integrity sha1-Xy867UethpGfAbEqLpnW8b13ZYE= + +pull-stream-to-stream@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/pull-stream-to-stream/-/pull-stream-to-stream-1.3.4.tgz#3f81d8216bd18d2bfd1a198190471180e2738399" + integrity sha1-P4HYIWvRjSv9GhmBkEcRgOJzg5k= + +pull-stream@^3.2.3, pull-stream@^3.6.9: + version "3.6.9" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.6.9.tgz#c774724cd63bc0984c3695f74c819aa02e977320" + integrity sha512-hJn4POeBrkttshdNl0AoSCVjMVSuBwuHocMerUdoZ2+oIUzrWHFTwJMlbHND7OiKLVgvz6TFj8ZUVywUMXccbw== + +pull-traverse@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pull-traverse/-/pull-traverse-1.0.3.tgz#74fb5d7be7fa6bd7a78e97933e199b7945866938" + integrity sha1-dPtde+f6a9enjpeTPhmbeUWGaTg= + pump@^2.0.0, pump@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -9201,6 +9830,11 @@ qs@6.5.2, qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +qs@^6.5.2: + version "6.6.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.6.0.tgz#a99c0f69a8d26bf7ef012f871cdabb0aee4424c2" + integrity sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA== + querystring-es3@^0.2.0, querystring-es3@~0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -9362,7 +9996,7 @@ react-is@^16.3.2, react-is@^16.6.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.6.3.tgz#d2d7462fcfcbe6ec0da56ad69047e47e56e7eac0" integrity sha512-u7FDWtthB4rWibG/+mFbVd5FvdI20yde86qKGx4lVUTWmPlSWQ4QxbBIrrs+HnXGbxOUlUzTAP/VDmvCwaP2yA== -react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.2: +react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== @@ -9412,6 +10046,25 @@ react-tippy@^1.2.3: dependencies: popper.js "^1.11.1" +react-toastify@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-4.5.2.tgz#a75b5f8b6219f62d4aacd0455d578a53341e37ca" + integrity sha512-KymDDhkcX5EvFht17nO0MCsegM/Kdhyfxhi+WQl2tE3IxJrueOhY6TUnALTfvz7eDRUjPYBGb+ywWqWrGyvBnw== + dependencies: + classnames "^2.2.6" + prop-types "^15.6.0" + react-transition-group "^2.4.0" + +react-transition-group@^2.4.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.5.2.tgz#9457166a9ba6ce697a3e1b076b3c049b9fb2c408" + integrity sha512-vwHP++S+f6KL7rg8V1mfs62+MBKtbMeZDR8KiNmD7v98Gs3UPGsDZDahPJH2PVprFW5YHJfh6cbNim3zPndaSQ== + dependencies: + dom-helpers "^3.3.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react-lifecycles-compat "^3.0.4" + react@^16.5.2: version "16.6.3" resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c" @@ -9463,7 +10116,7 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -9904,6 +10557,21 @@ rlp@^2.0.0: dependencies: safe-buffer "^5.1.1" +rsa-pem-to-jwk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/rsa-pem-to-jwk/-/rsa-pem-to-jwk-1.1.3.tgz#245e76bdb7e7234cfee7ca032d31b54c38fab98e" + integrity sha1-JF52vbfnI0z+58oDLTG1TDj6uY4= + dependencies: + object-assign "^2.0.0" + rsa-unpack "0.0.6" + +rsa-unpack@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/rsa-unpack/-/rsa-unpack-0.0.6.tgz#f50ebd56a628378e631f297161026ce9ab4eddba" + integrity sha1-9Q69VqYoN45jHylxYQJs6atO3bo= + dependencies: + optimist "~0.3.5" + rsvp@^3.3.3: version "3.6.2" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" @@ -10024,6 +10692,20 @@ secp256k1@^3.0.1: nan "^2.2.1" safe-buffer "^5.1.0" +secp256k1@^3.3.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.6.0.tgz#26b44b0df3562319b20f5070efcdd4fa36112650" + integrity sha512-a+oKfu2XWhq6Zzj7TexlYpwdnCEtJUUdLaujUclplPkV+INdMaV9D+81wYldm/g4/2PTFoNYZf/+0rHhTPgzjQ== + dependencies: + bindings "^1.2.1" + bip66 "^1.1.3" + bn.js "^4.11.3" + create-hash "^1.1.2" + drbg.js "^1.0.1" + elliptic "^6.2.3" + nan "^2.2.1" + safe-buffer "^5.1.0" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -10203,6 +10885,13 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +signed-varint@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/signed-varint/-/signed-varint-2.0.1.tgz#50a9989da7c98c2c61dad119bc97470ef8528129" + integrity sha1-UKmYnafJjCxh2tEZvJdHDvhSgSk= + dependencies: + varint "~5.0.0" + simple-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" @@ -10407,6 +11096,18 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +split2@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" + integrity sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw== + dependencies: + through2 "^2.0.2" + +sprintf-js@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.0.tgz#cffcaf702daf65ea39bb4e0fa2b299cec1a1be46" + integrity sha1-z/yvcC2vZeo5u04PorKZzsGhvkY= + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -10441,7 +11142,7 @@ ssri@^6.0.0: dependencies: figgy-pudding "^3.5.1" -stable@~0.1.6: +stable@~0.1.6, stable@~0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== @@ -10509,6 +11210,16 @@ stream-http@^2.0.0, stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" +stream-http@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.0.0.tgz#bd6d3c52610098699e25eb2dfcd188e30e0d12e4" + integrity sha512-JELJfd+btL9GHtxU3+XXhg9NLYrKFnhybfvRuDghtyVkOFydz3PKNT1df07AMr88qW03WHF+FSV0PySpXignCA== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^3.0.6" + xtend "^4.0.0" + stream-shift@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" @@ -10522,6 +11233,19 @@ stream-splicer@^2.0.0: inherits "^2.0.1" readable-stream "^2.0.2" +stream-to-pull-stream@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.2.tgz#757609ae1cebd33c7432d4afbe31ff78650b9dde" + integrity sha1-dXYJrhzr0zx0MtSvvjH/eGULnd4= + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + +streamifier@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" + integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= + string-length@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" @@ -10723,6 +11447,19 @@ tapable@^1.0.0, tapable@^1.1.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.0.tgz#0d076a172e3d9ba088fd2272b2668fb8d194b78c" integrity sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA== +tar-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + tar@^4: version "4.4.8" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" @@ -10780,7 +11517,7 @@ throat@^4.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= -through2@^2.0.0: +through2@^2.0.0, through2@^2.0.2, through2@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -10834,6 +11571,11 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -10896,6 +11638,11 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +traverse@~0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -10938,6 +11685,11 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +tweetnacl@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.0.tgz#713d8b818da42068740bf68386d0479e66fc8a7b" + integrity sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins= + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -11122,6 +11874,14 @@ url@^0.11.0, url@~0.11.0: punycode "1.3.2" querystring "0.2.0" +ursa-optional@~0.9.9: + version "0.9.10" + resolved "https://registry.yarnpkg.com/ursa-optional/-/ursa-optional-0.9.10.tgz#f2eabfe0b6001dbf07a78740cd0a6e5ba6eb2554" + integrity sha512-RvEbhnxlggX4MXon7KQulTFiJQtLJZpSb9ZSa7ZTkOW0AzqiVTaLjI4vxaSzJBDH9dwZ3ltZadFiBaZslp6haA== + dependencies: + bindings "^1.3.0" + nan "^2.11.1" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -11194,6 +11954,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +varint@^5.0.0, varint@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" + integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -11294,6 +12059,10 @@ web3@0.20.2: xhr2 "*" xmlhttprequest "*" +"webcrypto-shim@github:dignifiedquire/webcrypto-shim#master": + version "0.1.1" + resolved "https://codeload.github.com/dignifiedquire/webcrypto-shim/tar.gz/190bc9ec341375df6025b17ae12ddb2428ea49c8" + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"