permission handler

pull/1917/head
bunsenstraat 3 years ago committed by yann300
parent 89adc8e18d
commit 6f1ea6e8e7
  1. 6
      apps/remix-ide/src/app.js
  2. 126
      apps/remix-ide/src/app/plugins/permission-handler-plugin.tsx
  3. 202
      apps/remix-ide/src/app/ui/persmission-handler.js
  4. 4
      apps/remix-ide/src/remixAppManager.js
  5. 2
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  6. 3
      libs/remix-ui/permission-handler/src/index.ts
  7. 8
      libs/remix-ui/permission-handler/src/interface/index.ts
  8. 4
      libs/remix-ui/permission-handler/src/lib/permission-dialog.css
  9. 34
      libs/remix-ui/permission-handler/src/lib/permission-dialog.tsx
  10. 25
      libs/remix-ui/permission-handler/src/lib/permission-handler.tsx
  11. 70
      package-lock.json
  12. 14
      package.json

@ -10,6 +10,7 @@ import { HiddenPanel } from './app/components/hidden-panel'
import { VerticalIcons } from './app/components/vertical-icons'
import { LandingPage } from './app/ui/landing-page/landing-page'
import { MainPanel } from './app/components/main-panel'
import { PermissionHandlerPlugin } from './app/plugins/permission-handler-plugin'
import { WalkthroughService } from './walkthroughService'
@ -191,8 +192,11 @@ class AppComponent {
const configPlugin = new ConfigPlugin()
self.layout = new Layout()
const permissionHandler = new PermissionHandlerPlugin()
self.engine.register([
permissionHandler,
self.layout,
self.modal,
self.gistHandler,
@ -317,7 +321,7 @@ class AppComponent {
await self.appManager.activatePlugin(['layout'])
await self.appManager.activatePlugin(['modal'])
await self.appManager.activatePlugin(['editor'])
await self.appManager.activatePlugin(['theme', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter'])
await self.appManager.activatePlugin(['permissionhandler', 'theme', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter'])
await self.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
await self.appManager.activatePlugin(['sidePanel']) // activating host plugin separately
await self.appManager.activatePlugin(['home'])

@ -0,0 +1,126 @@
import React from 'react' // eslint-disable-line
import { Plugin } from '@remixproject/engine'
import { AppModal } from 'libs/remix-ui/app/src'
import { PermissionHandlerDialog, PermissionHandlerValue } from 'libs/remix-ui/permission-handler/src'
import { Profile } from '@remixproject/plugin-utils'
const profile = {
name: 'permissionhandler',
displayName: 'permissionhandler',
description: 'permissionhandler',
methods: ['askPermission']
}
export class PermissionHandlerPlugin extends Plugin {
permissions: any
currentVersion: number
constructor() {
super(profile)
this.permissions = this._getFromLocal()
this.currentVersion = 1
// here we remove the old permissions saved before adding 'permissionVersion'
// since with v1 the structure has been changed because of new engine ^0.2.0-alpha.6 changes
if (!localStorage.getItem('permissionVersion')) {
localStorage.setItem('plugins/permissions', '')
localStorage.setItem('permissionVersion', this.currentVersion.toString())
}
}
_getFromLocal() {
const permission = localStorage.getItem('plugins/permissions')
return permission ? JSON.parse(permission) : {}
}
persistPermissions() {
const permissions = JSON.stringify(this.permissions)
localStorage.setItem('plugins/permissions', permissions)
}
switchMode (from: Profile, to: Profile, method: string, set: boolean) {
set
? this.permissions[to.name][method][from.name] = {}
: delete this.permissions[to.name][method][from.name]
}
clear() {
localStorage.removeItem('plugins/permissions')
}
notAllowWarning(from: Profile, to: Profile, method: string) {
return `${from.displayName || from.name} is not allowed to call ${method} method of ${to.displayName || to.name}.`
}
async getTheme() {
return (await this.call('theme', 'currentTheme')).quality
}
/**
* Check if a plugin has the permission to call another plugin and askPermission if needed
* @param {PluginProfile} from the profile of the plugin that make the call
* @param {ModuleProfile} to The profile of the module that receive the call
* @param {string} method The name of the function to be called
* @param {string} message from the caller plugin to add more details if needed
* @returns {Promise<boolean>}
*/
async askPermission(from: Profile, to: Profile, method: string, message: string) {
try {
this.permissions = this._getFromLocal()
if (!this.permissions[to.name]) this.permissions[to.name] = {}
if (!this.permissions[to.name][method]) this.permissions[to.name][method] = {}
if (!this.permissions[to.name][method][from.name]) return this.openPermission(from, to, method, message)
const { allow, hash } = this.permissions[to.name][method][from.name]
if (!allow) {
const warning = this.notAllowWarning(from, to, method)
this.call('modal', 'toast', warning)
return false
}
return hash === from.hash
? true // Allow
: await this.openPermission(from, to, method, message)
} catch (err) {
throw new Error(err)
}
}
async openPermission(from: Profile, to: Profile, method: string, message: string) {
const remember = this.permissions[to.name][method][from.name]
const value: PermissionHandlerValue = {
from,
to,
method,
message,
remember
}
const modal: AppModal = {
id: 'PermissionHandler',
title: `Permission needed for ${to.displayName || to.name}`,
message: <PermissionHandlerDialog plugin={this} theme={await this.getTheme()} value={value}></PermissionHandlerDialog>,
okLabel: 'sure',
cancelLabel: 'no'
}
const result = await this.call('modal', 'modal', modal)
return new Promise((resolve, reject) => {
if (result) {
if (this.permissions[to.name][method][from.name]) {
this.permissions[to.name][method][from.name] = {
allow: true,
hash: from.hash
}
this.persistPermissions()
}
resolve(true)
} else {
if (this.permissions[to.name][method][from.name]) {
this.permissions[to.name][method][from.name] = {
allow: false,
hash: from.hash
}
this.persistPermissions()
}
reject(this.notAllowWarning(from, to, method))
}
})
}
}

@ -1,202 +0,0 @@
import Registry from '../state/registry'
/* global localStorage */
const yo = require('yo-yo')
const csjs = require('csjs-inject')
const addTooltip = require('./tooltip')
const modalDialog = require('./modaldialog')
const css = csjs`
.permission h4 {
text-transform: uppercase;
text-align: center;
}
.permission h6 {
text-transform: uppercase;
}
.remember {
display: flex;
justify-content: space-between;
align-items: center;
}
.images {
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
}
.images img {
width: 40px;
height: 40px;
}
.images i {
margin: 0 20px;
}
`
function notAllowWarning (from, to, method) {
return `${from.displayName || from.name} is not allowed to call ${method} method of ${to.displayName || to.name}.`
}
export class PermissionHandler {
constructor () {
this.permissions = this._getFromLocal()
this.currentVersion = 1
// here we remove the old permissions saved before adding 'permissionVersion'
// since with v1 the structure has been changed because of new engine ^0.2.0-alpha.6 changes
if (!localStorage.getItem('permissionVersion')) {
localStorage.setItem('plugins/permissions', '')
localStorage.setItem('permissionVersion', this.currentVersion)
}
}
_getFromLocal () {
const permission = localStorage.getItem('plugins/permissions')
return permission ? JSON.parse(permission) : {}
}
persistPermissions () {
const permissions = JSON.stringify(this.permissions)
localStorage.setItem('plugins/permissions', permissions)
}
clear () {
localStorage.removeItem('plugins/permissions')
addTooltip('All Permissions have been reset')
}
/**
* Show a message to ask the user for a permission
* @param {PluginProfile} from The name and hash of the plugin that make the call
* @param {ModuleProfile} to The name of the plugin that receive the call
* @param {string} method The name of the function to be called
* @param {string} message from the caller plugin to add more details if needed
* @returns {Promise<{ allow: boolean; remember: boolean }} Answer from the user to the permission
*/
async openPermission (from, to, method, message) {
return new Promise((resolve, reject) => {
modalDialog(
`Permission needed for ${to.displayName || to.name}`,
this.form(from, to, method, message),
{
label: 'Accept',
fn: () => {
if (this.permissions[to.name][method][from.name]) {
this.permissions[to.name][method][from.name] = {
allow: true,
hash: from.hash
}
this.persistPermissions()
}
resolve(true)
}
},
{
label: 'Decline',
fn: () => {
if (this.permissions[to.name][method][from.name]) {
this.permissions[to.name][method][from.name] = {
allow: false,
hash: from.hash
}
this.persistPermissions()
}
reject(notAllowWarning(from, to, method))
}
}
)
})
}
/**
* Check if a plugin has the permission to call another plugin and askPermission if needed
* @param {PluginProfile} from the profile of the plugin that make the call
* @param {ModuleProfile} to The profile of the module that receive the call
* @param {string} method The name of the function to be called
* @param {string} message from the caller plugin to add more details if needed
* @returns {Promise<boolean>}
*/
async askPermission (from, to, method, message) {
try {
this.permissions = this._getFromLocal()
if (!this.permissions[to.name]) this.permissions[to.name] = {}
if (!this.permissions[to.name][method]) this.permissions[to.name][method] = {}
if (!this.permissions[to.name][method][from.name]) return this.openPermission(from, to, method, message)
const { allow, hash } = this.permissions[to.name][method][from.name]
if (!allow) {
const warning = notAllowWarning(from, to, method)
addTooltip(warning)
return false
}
return hash === from.hash
? true // Allow
: this.openPermission(from, to, method, message) // New version of a plugin
} catch (err) {
throw new Error(err)
}
}
/**
* The permission form
* @param {PluginProfile} from The name and hash of the plugin that make the call
* @param {ModuleProfile} to The name of the plugin that receive the call
* @param {string} method The name of te methode to be called
* @param {string} message from the caller plugin to add more details if needed
*/
form (from, to, method, message) {
const fromName = from.displayName || from.name
const toName = to.displayName || to.name
const remember = this.permissions[to.name][method][from.name]
const switchMode = (e) => {
e.target.checked
? this.permissions[to.name][method][from.name] = {}
: delete this.permissions[to.name][method][from.name]
}
const rememberSwitch = remember
? yo`<input type="checkbox" onchange="${switchMode}" checkbox class="form-check-input" id="remember" data-id="permissionHandlerRememberChecked">`
: yo`<input type="checkbox" onchange="${switchMode}" class="form-check-input" id="remember" data-id="permissionHandlerRememberUnchecked">`
const text = `"${fromName}" ${(remember ? 'has changed and' : '')} would like to access to "${method}" of "${toName}"`
const imgFrom = yo`<img id="permissionModalImagesFrom" src="${from.icon}" />`
const imgTo = yo`<img id="permissionModalImagesTo" src="${to.icon}" />`
const pluginsImages = yo`
<article class="${css.images}">
${imgFrom}
<i class="fas fa-arrow-right"></i>
${imgTo}
</article>
`
Registry.getInstance().get('themeModule').api.fixInvert(imgFrom)
Registry.getInstance().get('themeModule').api.fixInvert(imgTo)
const pluginMessage = message ? yo`
<div>
<h6>Description</h6>
<p>${message}</p>
</div>
` : ''
return yo`
<section class="${css.permission}">
${pluginsImages}
<article>
<h4 data-id="permissionHandlerMessage">${text} :</h4>
<h6>${fromName}</h6>
<p>${from.description || yo`<i>No description Provided</i>`}</p>
<h6>${toName} :</p>
<p>${to.description || yo`<i>No description Provided</i>`}</p>
${pluginMessage}
</article>
<article class="${css.remember}">
<div class="form-check">
${rememberSwitch}
<label class="form-check-label" for="remember" data-id="permissionHandlerRememberChoice">Remember this choice</label>
</div>
<button class="btn btn-sm" onclick="${_ => this.clear()}">Reset all Permissions</button>
</article>
</section>
`
}
}

@ -2,7 +2,6 @@
import { PluginManager } from '@remixproject/engine'
import { EventEmitter } from 'events'
import QueryParams from './lib/query-params'
import { PermissionHandler } from './app/ui/persmission-handler'
import { IframePlugin } from '@remixproject/engine-web'
const _paq = window._paq = window._paq || []
@ -40,7 +39,6 @@ export class RemixAppManager extends PluginManager {
this.event = new EventEmitter()
this.pluginsDirectory = 'https://raw.githubusercontent.com/ethereum/remix-plugins-directory/master/build/metadata.json'
this.pluginLoader = new PluginLoader()
this.permissionHandler = new PermissionHandler()
}
async canActivatePlugin (from, to) {
@ -72,7 +70,7 @@ export class RemixAppManager extends PluginManager {
return true
}
// ask the user for permission
return await this.permissionHandler.askPermission(this.profiles[from], this.profiles[to], method, message)
return await this.call('permissionhandler', 'askPermission', this.profiles[from], this.profiles[to], method, message)
}
onPluginActivated (plugin) {

@ -8,7 +8,6 @@ import DragBar from './components/dragbar/dragbar'
import { AppProvider } from './context/provider'
import AppDialogs from './components/modals/dialogs'
import DialogViewPlugin from './components/modals/dialogViewPlugin'
import { Permissionhandler } from '@remix-ui/permission-handler'
interface IRemixAppUi {
app: any
@ -105,7 +104,6 @@ const RemixApp = (props: IRemixAppUi) => {
{components.hiddenPanel}
<AppDialogs></AppDialogs>
<DialogViewPlugin></DialogViewPlugin>
<Permissionhandler></Permissionhandler>
</AppProvider>
)
}

@ -1 +1,2 @@
export { default as Permissionhandler } from './lib/permission-handler'
export { default as PermissionHandlerDialog } from './lib/permission-dialog'
export { PermissionHandlerValue, PermissionHandlerProps } from './interface/index'

@ -1,8 +1,8 @@
import { IconProfile } from 'libs/remix-ui/vertical-icons-panel/src/lib/components/Icon'
import { Profile } from '@remixproject/plugin-utils'
export interface PermissionHandlerValue {
from: IconProfile,
to: IconProfile,
from: Profile,
to: Profile,
remember: boolean,
method: string,
message: string
@ -10,4 +10,6 @@ export interface PermissionHandlerValue {
export interface PermissionHandlerProps {
value: PermissionHandlerValue
theme: string
plugin: any
}

@ -22,4 +22,8 @@
}
.images i {
margin: 0 20px;
}
.invert {
filter: invert(1);
}

@ -1,35 +1,38 @@
import React, { useContext, useEffect, useRef, useState } from 'react' // eslint-disable-line
import React, { ChangeEventHandler, useContext, useEffect, useRef, useState } from 'react' // eslint-disable-line
import { PermissionHandlerProps } from '../interface'
import './permission-dialog.css'
const PermissionHandlerDialog = (props: PermissionHandlerProps) => {
const { from, to, remember, method, message } = props.value
const [feedback, setFeedback] = useState<string>('')
const theme = props.theme
const switchMode = () => {
const switchMode = (e: any) => {
props.plugin.switchMode(from, to, method, e.target.checked)
}
const rememberSwitch = () => {
return <input type="checkbox" onChange={switchMode} className='form-check-input' id='remember' data-id={remember ? 'permissionHandlerRememberChecked' : 'permissionHandlerRememberUnchecked'}/>
}
const reset = () => {
props.plugin.clear()
setFeedback('All permisssions have been reset.')
}
const imgFrom = () => { return <img alt='' id='permissionModalImagesFrom' src={from.icon} /> }
const imgTo = () => { return <img alt='' id='permissionModalImagesTo' src={to.icon} /> }
const imgFrom = () => { return <img className={`${theme === 'dark' ? 'invert' : ''}`} alt='' id='permissionModalImagesFrom' src={from.icon} /> }
const imgTo = () => { return <img className={`${theme === 'dark' ? 'invert' : ''}`} alt='' id='permissionModalImagesTo' src={to.icon} /> }
const pluginsImages = () => {
return (
<article className='images'>
{imgFrom}
{imgFrom()}
<i className="fas fa-arrow-right"></i>
{imgTo}
{imgTo()}
</article>
)
}
const text = () => {
return `"${from.displayName}" ${(remember ? 'has changed and' : '')} would like to access to "${method}" of "${to.displayName}"`
return <>"{from.displayName}" {(remember ? 'has changed and' : '')} would like to access to "{method}" of "{to.displayName}"`</>
}
const pluginMessage = () => {
@ -41,22 +44,23 @@ const PermissionHandlerDialog = (props: PermissionHandlerProps) => {
}
return (<section className="permission">
{pluginsImages}
{pluginsImages()}
<article>
<h4 data-id="permissionHandlerMessage">{text} :</h4>
<h4 data-id="permissionHandlerMessage">{text()} :</h4>
<h6>{from.displayName}</h6>
<p> {from.description} || <i>No description Provided</i></p>
<p> {from.description || <i>No description Provided</i>}</p>
<h6>{to.displayName} :</h6>
<p> {to.description} || <i>No description Provided</i></p>
{pluginMessage}
<p> {to.description || <i>No description Provided</i>}</p>
{pluginMessage()}
</article>
<article className='remember'>
<div className='form-check'>
{rememberSwitch}
{rememberSwitch()}
<label className="form-check-label" data-id="permissionHandlerRememberChoice">Remember this choice</label>
</div>
<button className="btn btn-sm" onClick={reset}>Reset all Permissions</button>
</article>
<div>{feedback}</div>
</section>)
}

@ -1,25 +0,0 @@
import { useDialogDispatchers } from 'libs/remix-ui/app/src/lib/remix-app/context/provider'
import React, { useContext, useEffect, useRef, useState } from 'react' // eslint-disable-line
import { PermissionHandlerValue } from '../interface'
import PermissionHandlerDialog from './permission-dialog'
const PermissionHandler = () => {
const { alert, toast, modal } = useDialogDispatchers()
const [value, setValue] = useState<PermissionHandlerValue>()
useEffect(() => {
if (value) {
modal({
id: 'PermissionHandler',
title: 'permissions',
message: <PermissionHandlerDialog value={value}></PermissionHandlerDialog>,
okFn: () => {},
cancelFn: () => {},
okLabel: 'sure',
cancelLabel: 'no'
})
}
}, [value])
return (<></>)
}
export default PermissionHandler

70
package-lock.json generated

@ -9782,46 +9782,46 @@
"integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ=="
},
"@remixproject/engine": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/@remixproject/engine/-/engine-0.3.24.tgz",
"integrity": "sha512-XVPaRIAwxTxEmc+u+bq9nIqUcP1NDdQFTm/8xmw8HcZicgagUW/y0RuLEMBj5GTGXF+EsljY27t6bPy7fmVHWQ==",
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@remixproject/engine/-/engine-0.3.25.tgz",
"integrity": "sha512-6XaXZ6BHKEoYfnAQSN7Hy2UZt8M/rKA2Vfq6Wy2tYocfzHVRXb3PeZncdumeO4vdnTldbrrRhgn4i4/ORcYAnA==",
"requires": {
"@remixproject/plugin-api": "0.3.24",
"@remixproject/plugin-utils": "0.3.24"
"@remixproject/plugin-api": "0.3.25",
"@remixproject/plugin-utils": "0.3.25"
}
},
"@remixproject/engine-web": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/@remixproject/engine-web/-/engine-web-0.3.24.tgz",
"integrity": "sha512-6P2NLoL9KSa/84FumEM3QxvOW4g/hIEsq8NcbBA+/PHz9VnIRoxRg2K/jGJUHHqKw+dfoSdk5lQ+LkFQHcrp+w==",
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@remixproject/engine-web/-/engine-web-0.3.25.tgz",
"integrity": "sha512-RzmDDE7Eh+gW1A/pQkGovQA+A6dRPKGfFmkShXcCkKZghNKc+DSCCKkgVxfYu2ckgr5Q5N11tBiAA+5OFduLRg==",
"requires": {
"@remixproject/engine": "0.3.24",
"@remixproject/plugin-api": "0.3.24",
"@remixproject/plugin-utils": "0.3.24"
"@remixproject/engine": "0.3.25",
"@remixproject/plugin-api": "0.3.25",
"@remixproject/plugin-utils": "0.3.25"
}
},
"@remixproject/plugin": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/@remixproject/plugin/-/plugin-0.3.24.tgz",
"integrity": "sha512-nGtt3IZA5X2kcXauu5h5P8EEoMtHbVGm5wWnv0c7aYYWbffhQdK8dqtNNEAtQavWrsp5TL61zekqpkFzgxVv9w==",
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@remixproject/plugin/-/plugin-0.3.25.tgz",
"integrity": "sha512-EVFtZ42+BmfZ+6UWcTo7Ig+7RQ1LiaBe4hnM8lQVyVhKqsYnev7/NAQycDmrtTSZR7kaLhy/nH3vTfxryleqQw==",
"requires": {
"@remixproject/plugin-api": "0.3.24",
"@remixproject/plugin-utils": "0.3.24",
"@remixproject/plugin-api": "0.3.25",
"@remixproject/plugin-utils": "0.3.25",
"events": "3.2.0"
}
},
"@remixproject/plugin-api": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/@remixproject/plugin-api/-/plugin-api-0.3.24.tgz",
"integrity": "sha512-mBxou9OSsQt7ggMmKTJR433jJaSAckBmVj82Ek7i/+EGxEAxSqKhPfRlh5sFiTgvUmzHQzuvqa8ndyw0Bbcq4w==",
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@remixproject/plugin-api/-/plugin-api-0.3.25.tgz",
"integrity": "sha512-GPjPfGRv955En5AILLYf62zqZdALuDCJiq3DKR1XdkVukbI9Soc2FcGs8O2phNhqieIjgXMoUcl1Or6brfuLAw==",
"requires": {
"@remixproject/plugin-utils": "0.3.24"
"@remixproject/plugin-utils": "0.3.25"
}
},
"@remixproject/plugin-utils": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/@remixproject/plugin-utils/-/plugin-utils-0.3.24.tgz",
"integrity": "sha512-nMXGCgs6filbgUc/Zvh1gReGG5HN2Bq+AI4Q7Ao08Thhg5ALj1UsbzQf86Ya/L7Q+EF6Em1CbgPT0VhcGlP66A==",
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@remixproject/plugin-utils/-/plugin-utils-0.3.25.tgz",
"integrity": "sha512-FzOKItdfwbQBYlFcK+erLu/ol1htxjAYeuvpxZ1CzbuMXtupA/GW58vCYzIbNZqd0LlYGqIUgEY+fsm3QuU41w==",
"requires": {
"tslib": "2.0.1"
},
@ -9834,13 +9834,13 @@
}
},
"@remixproject/plugin-webview": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/@remixproject/plugin-webview/-/plugin-webview-0.3.24.tgz",
"integrity": "sha512-Wcyi+gGq1AYprE58vhQS181swAKZpoLAfKlKuHJ+ezbysUDuX8jgsEiQ6u1c17nQfy8Hp9sntK6VcCcDddn8gg==",
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@remixproject/plugin-webview/-/plugin-webview-0.3.25.tgz",
"integrity": "sha512-pjF1qAjgCFHciIDRKTsu2+9rdopjw6+H0GH5moUCGs9WsxmQT1NyfTxvJB+Qkf9GaWdak+ECBlrcn7DAX29BPA==",
"requires": {
"@remixproject/plugin": "0.3.24",
"@remixproject/plugin-api": "0.3.24",
"@remixproject/plugin-utils": "0.3.24",
"@remixproject/plugin": "0.3.25",
"@remixproject/plugin-api": "0.3.25",
"@remixproject/plugin-utils": "0.3.25",
"axios": "^0.21.1"
},
"dependencies": {
@ -9855,13 +9855,13 @@
}
},
"@remixproject/plugin-ws": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/@remixproject/plugin-ws/-/plugin-ws-0.3.24.tgz",
"integrity": "sha512-COIROJX61vS2TRH82MflIUlScxLauNtLkMRY7vzncVOIvufApvNc84Ua8Vr6vhSb2tZeWX+u4UTiFnpFDRL7xw==",
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@remixproject/plugin-ws/-/plugin-ws-0.3.25.tgz",
"integrity": "sha512-ligtZmDUUpEhtMjt6sD33ibFQmcP6qdybLMA6DL94wW5x6d+aM0K8+dtWYFnK3HPfgbpvqHFf/7A7ulFJphcPg==",
"requires": {
"@remixproject/plugin": "0.3.24",
"@remixproject/plugin-api": "0.3.24",
"@remixproject/plugin-utils": "0.3.24"
"@remixproject/plugin": "0.3.25",
"@remixproject/plugin-api": "0.3.25",
"@remixproject/plugin-utils": "0.3.25"
}
},
"@restart/context": {

@ -147,13 +147,13 @@
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"@monaco-editor/react": "^4.3.1",
"@remixproject/engine": "^0.3.24",
"@remixproject/engine-web": "^0.3.24",
"@remixproject/plugin": "^0.3.24",
"@remixproject/plugin-api": "^0.3.24",
"@remixproject/plugin-utils": "^0.3.24",
"@remixproject/plugin-webview": "^0.3.24",
"@remixproject/plugin-ws": "^0.3.24",
"@remixproject/engine": "^0.3.25",
"@remixproject/engine-web": "^0.3.25",
"@remixproject/plugin": "^0.3.25",
"@remixproject/plugin-api": "^0.3.25",
"@remixproject/plugin-utils": "^0.3.25",
"@remixproject/plugin-webview": "^0.3.25",
"@remixproject/plugin-ws": "^0.3.25",
"ansi-gray": "^0.1.1",
"async": "^2.6.2",
"axios": ">=0.21.1",

Loading…
Cancel
Save