diff --git a/packages/controllers/.eslintrc.js b/packages/controllers/.eslintrc.js index 5ddba4b3e5..42650ded8f 100644 --- a/packages/controllers/.eslintrc.js +++ b/packages/controllers/.eslintrc.js @@ -1,6 +1,10 @@ module.exports = { extends: ['../../.eslintrc.js'], + rules: { + '@typescript-eslint/consistent-type-definitions': 'off', + }, + overrides: [ { files: ['*.d.ts'], diff --git a/packages/controllers/package.json b/packages/controllers/package.json index ff29fbbeda..6adce52faf 100644 --- a/packages/controllers/package.json +++ b/packages/controllers/package.json @@ -26,6 +26,7 @@ "prepublishOnly": "yarn lint && yarn build" }, "dependencies": { + "@metamask/controllers": "^9.1.0", "@metamask/object-multiplex": "^1.1.0", "@metamask/obs-store": "^6.0.2", "@metamask/post-message-stream": "4.0.0", diff --git a/packages/controllers/src/plugins/PluginController.test.ts b/packages/controllers/src/plugins/PluginController.test.ts new file mode 100644 index 0000000000..ad7a1102a2 --- /dev/null +++ b/packages/controllers/src/plugins/PluginController.test.ts @@ -0,0 +1,102 @@ +import fs from 'fs'; +import { ControllerMessenger } from '@metamask/controllers/dist/ControllerMessenger'; +import { WorkerController } from '../workers/WorkerController'; +import { PluginController } from './PluginController'; + +const workerCode = fs.readFileSync( + require.resolve('@mm-snap/workers/dist/PluginWorker.js'), + 'utf8', +); + +describe('PluginController Controller', () => { + it('can create a worker and plugin controller', async () => { + const workerController = new WorkerController({ + setupWorkerConnection: jest.fn(), + workerUrl: new URL(URL.createObjectURL(new Blob([workerCode]))), + }); + const pluginController = new PluginController({ + command: workerController.command.bind(workerController), + createPluginWorker: workerController.createPluginWorker.bind( + workerController, + ), + terminateAll: workerController.terminateAll.bind(workerController), + terminateWorkerOf: workerController.terminateWorkerOf.bind( + workerController, + ), + startPlugin: workerController.startPlugin.bind(workerController), + removeAllPermissionsFor: jest.fn(), + getPermissions: jest.fn(), + hasPermission: jest.fn(), + requestPermissions: jest.fn(), + closeAllConnections: jest.fn(), + messenger: new ControllerMessenger().getRestricted({ + name: 'PluginController', + }), + state: { + inlinePluginIsRunning: false, + pluginStates: {}, + plugins: {}, + }, + }); + expect(pluginController).toBeDefined(); + }); + + it('can add a plugin and use its JSON-RPC api', async () => { + const workerController = new WorkerController({ + setupWorkerConnection: jest.fn(), + workerUrl: new URL(URL.createObjectURL(new Blob([workerCode]))), + }); + const pluginController = new PluginController({ + command: workerController.command.bind(workerController), + createPluginWorker: workerController.createPluginWorker.bind( + workerController, + ), + terminateAll: workerController.terminateAll.bind(workerController), + terminateWorkerOf: workerController.terminateWorkerOf.bind( + workerController, + ), + startPlugin: workerController.startPlugin.bind(workerController), + removeAllPermissionsFor: jest.fn(), + getPermissions: jest.fn(), + hasPermission: jest.fn(), + requestPermissions: jest.fn(), + closeAllConnections: jest.fn(), + messenger: new ControllerMessenger().getRestricted({ + name: 'PluginController', + }), + state: { + inlinePluginIsRunning: false, + pluginStates: {}, + plugins: {}, + }, + }); + const plugin = await pluginController.add({ + name: 'TestPlugin', + sourceCode: ` + wallet.registerRpcMessageHandler(async (origin, request) => { + const {method, params, id} = request; + wallet.request({method: 'setState'}) + return method + id; + }); + `, + manifest: { + web3Wallet: { + initialPermissions: {}, + }, + version: '0.0.0-development', + }, + }); + await pluginController.startPlugin(plugin.name); + const handle = pluginController.getRpcMessageHandler(plugin.name); + if (!handle) { + throw Error('rpc handler not found'); + } + const result = await handle('foo.com', { + jsonrpc: '2.0', + method: 'test', + params: {}, + id: 1, + }); + expect(result).toEqual('test1'); + }); +}); diff --git a/packages/controllers/src/plugins/PluginController.ts b/packages/controllers/src/plugins/PluginController.ts index 7192a31754..16ca8f2ecb 100644 --- a/packages/controllers/src/plugins/PluginController.ts +++ b/packages/controllers/src/plugins/PluginController.ts @@ -1,30 +1,29 @@ -import { ObservableStore } from '@metamask/obs-store'; -import EventEmitter from '@metamask/safe-event-emitter'; import { ethErrors, serializeError } from 'eth-rpc-errors'; import { IOcapLdCapability } from 'rpc-cap/dist/src/@types/ocap-ld'; -import { IRequestedPermissions } from 'rpc-cap/dist/src/@types'; import { nanoid } from 'nanoid'; import { - WorkerController, - SetupWorkerConnection, -} from '../workers/WorkerController'; + BaseControllerV2 as BaseController, + RestrictedControllerMessenger, +} from '@metamask/controllers'; +import { Json, JsonRpcRequest } from 'json-rpc-engine'; +import { PluginData } from '@mm-snap/types'; +import { PluginWorkerMetadata } from '../workers/WorkerController'; import { INLINE_PLUGINS } from './inlinePlugins'; export const PLUGIN_PREFIX = 'wallet_plugin_'; export const PLUGIN_PREFIX_REGEX = new RegExp(`^${PLUGIN_PREFIX}`, 'u'); - const SERIALIZABLE_PLUGIN_PROPERTIES = new Set([ 'initialPermissions', 'name', 'permissionName', ]); -interface InititalPermissions { - [permission: string]: Record; -} +type RequestedPluginPermissions = { + [permission: string]: Json; +}; export interface SerializablePlugin { - initialPermissions: InititalPermissions; + initialPermissions: RequestedPluginPermissions; name: string; permissionName: string; version: string; @@ -53,38 +52,49 @@ type RemoveAllPermissionsFunction = (pluginIds: string[]) => void; type CloseAllConnectionsFunction = (domain: string) => void; type RequestPermissionsFunction = ( domain: string, - requestedPermissions: IRequestedPermissions, -) => IOcapLdCapability[]; + requestedPermissions: RequestedPluginPermissions, +) => Promise; type HasPermissionFunction = ( domain: string, permissionName: string, ) => boolean; type GetPermissionsFunction = (domain: string) => IOcapLdCapability[]; +type TerminateWorkerOf = (pluginName: string) => void; +type Command = ( + workerId: string, + message: JsonRpcRequest, +) => Promise; +type TerminateAll = () => void; +type CreatePluginWorker = (metadate: PluginWorkerMetadata) => Promise; +type StartPlugin = ( + workerId: string, + pluginData: PluginData, +) => Promise; -interface StoredPlugins { - [pluginId: string]: Plugin; -} - -export interface PluginControllerState { - plugins: StoredPlugins; - pluginStates: Record; -} +type PluginId = string; +type StoredPlugins = Record; -export interface PluginControllerMemState { +export type PluginControllerState = { inlinePluginIsRunning: boolean; - plugins: { [pluginId: string]: SerializablePlugin }; - pluginStates: Record; -} + plugins: StoredPlugins; + pluginStates: { + [PluginId: string]: Json; + }; +}; interface PluginControllerArgs { - initState: Partial; + messenger: RestrictedControllerMessenger; + state: PluginControllerState; removeAllPermissionsFor: RemoveAllPermissionsFunction; - setupWorkerPluginProvider: SetupWorkerConnection; closeAllConnections: CloseAllConnectionsFunction; requestPermissions: RequestPermissionsFunction; getPermissions: GetPermissionsFunction; hasPermission: HasPermissionFunction; - workerUrl: URL; + terminateWorkerOf: TerminateWorkerOf; + command: Command; + terminateAll: TerminateAll; + createPluginWorker: CreatePluginWorker; + startPlugin: StartPlugin; } interface AddPluginBase { @@ -98,7 +108,7 @@ interface AddPluginByFetchingArgs extends AddPluginBase { // The parts of a plugin package.json file that we care about interface PluginManifest { version: string; - web3Wallet: { initialPermissions: InititalPermissions }; + web3Wallet: { initialPermissions: RequestedPluginPermissions }; } interface AddPluginDirectlyArgs extends AddPluginBase { @@ -108,6 +118,14 @@ interface AddPluginDirectlyArgs extends AddPluginBase { type AddPluginArgs = AddPluginByFetchingArgs | AddPluginDirectlyArgs; +const defaultState: PluginControllerState = { + inlinePluginIsRunning: false, + plugins: {}, + pluginStates: {}, +}; + +const name = 'PluginController'; + /* * A plugin is initialized in three phases: * - Add: Loads the plugin from a remote source and parses it. @@ -115,13 +133,10 @@ type AddPluginArgs = AddPluginByFetchingArgs | AddPluginDirectlyArgs; * - Start: Initializes the plugin in its SES realm with the authorized permissions. */ -export class PluginController extends EventEmitter { - public store: ObservableStore; - - public memStore: ObservableStore; - - private workerController: WorkerController; - +export class PluginController extends BaseController< + string, + PluginControllerState +> { private _removeAllPermissionsFor: RemoveAllPermissionsFunction; private _pluginRpcHooks: Map; @@ -134,40 +149,56 @@ export class PluginController extends EventEmitter { private _hasPermission: HasPermissionFunction; + private _terminateWorkerOf: TerminateWorkerOf; + + private _command: Command; + + private _terminateAll: TerminateAll; + + private _createPluginWorker: CreatePluginWorker; + + private _startPlugin: StartPlugin; + private _pluginsBeingAdded: Map>; constructor({ - initState, - setupWorkerPluginProvider, removeAllPermissionsFor, closeAllConnections, requestPermissions, getPermissions, + terminateWorkerOf, + terminateAll, hasPermission, - workerUrl, + createPluginWorker, + startPlugin, + command, + messenger, + state, }: PluginControllerArgs) { - super(); - const _initState: PluginControllerState = { - plugins: {}, - pluginStates: {}, - ...initState, - }; - - this.store = new ObservableStore({ - plugins: {}, - pluginStates: {}, - }); - - this.memStore = new ObservableStore({ - inlinePluginIsRunning: false, - plugins: {}, - pluginStates: {}, + super({ + messenger, + metadata: { + inlinePluginIsRunning: { + persist: false, + anonymous: false, + }, + pluginStates: { + persist: true, + anonymous: false, + }, + plugins: { + persist: true, + anonymous: false, + }, + }, + name, + state: { ...defaultState, ...state }, }); - this.updateState(_initState); - this.workerController = new WorkerController({ - setupWorkerConnection: setupWorkerPluginProvider, - workerUrl, + this.update((_state: any) => { + _state.inlinePluginIsRunning = state.inlinePluginIsRunning; + _state.plugins = state.plugins; + _state.pluginStates = state.pluginStates; }); this._removeAllPermissionsFor = removeAllPermissionsFor; @@ -176,50 +207,22 @@ export class PluginController extends EventEmitter { this._getPermissions = getPermissions; this._hasPermission = hasPermission; + this._terminateWorkerOf = terminateWorkerOf; + this._terminateAll = terminateAll; + this._createPluginWorker = createPluginWorker; + this._startPlugin = startPlugin; + this._command = command; + this._pluginRpcHooks = new Map(); this._pluginsBeingAdded = new Map(); } - /** - * Updates the state of this controller. - */ - updateState(newState: Partial) { - this.store.updateState(newState); - this.memStore.updateState(this._filterMemStoreState(newState)); - } - - /** - * Takes in a full state object and filters out the parts that we don't want - * to keep in memory. Currently just the sourceCode property of any plugins. - */ - private _filterMemStoreState( - newState: Partial, - ): Partial { - const memState: Partial = { - ...newState, - }; - - if (newState.plugins) { - // Copy existing plugins to the new memState - memState.plugins = this.memStore.getState().plugins || {}; - - // Remove sourceCode from updated memState plugin objects - Object.keys(newState.plugins).forEach((name) => { - const plugin = { ...(newState as PluginControllerState).plugins[name] }; - delete (plugin as Partial).sourceCode; - (memState as PluginControllerMemState).plugins[name] = plugin; - }); - } - - return memState; - } - /** * Runs existing (installed) plugins. * Deletes any plugins that cannot be started. */ async runExistingPlugins(): Promise { - const { plugins } = this.store.getState(); + const { plugins } = this.state; if (Object.keys(plugins).length > 0) { console.log('Starting existing plugins...', plugins); @@ -295,7 +298,7 @@ export class PluginController extends EventEmitter { private _stopPlugin(pluginName: string, setNotRunning = true): void { this._removePluginHooks(pluginName); this._closeAllConnections(pluginName); - this.workerController.terminateWorkerOf(pluginName); + this._terminateWorkerOf(pluginName); if (setNotRunning) { this._setPluginToNotRunning(pluginName); } @@ -322,7 +325,7 @@ export class PluginController extends EventEmitter { * @param pluginName - The name of the plugin to check for. */ has(pluginName: string): boolean { - return pluginName in this.store.getState().plugins; + return pluginName in this.state.plugins; } /** @@ -333,7 +336,7 @@ export class PluginController extends EventEmitter { * @param pluginName - The name of the plugin to get. */ get(pluginName: string) { - return this.store.getState().plugins[pluginName]; + return this.state.plugins[pluginName]; } /** @@ -366,16 +369,10 @@ export class PluginController extends EventEmitter { */ async updatePluginState( pluginName: string, - newPluginState: unknown, + newPluginState: Json, ): Promise { - const state = this.store.getState(); - const newPluginStates = { - ...state.pluginStates, - [pluginName]: newPluginState, - }; - - this.updateState({ - pluginStates: newPluginStates, + this.update((state: any) => { + state[pluginName] = newPluginState; }); } @@ -386,7 +383,7 @@ export class PluginController extends EventEmitter { * @param pluginName - The name of the plugin whose state to get. */ async getPluginState(pluginName: string): Promise { - return this.store.getState().pluginStates[pluginName]; + return this.state.pluginStates[pluginName]; } /** @@ -395,18 +392,16 @@ export class PluginController extends EventEmitter { */ clearState() { this._pluginRpcHooks.clear(); - const pluginNames = Object.keys(this.store.getState().plugins); - this.updateState({ - plugins: {}, - pluginStates: {}, + const pluginNames = Object.keys(this.state.plugins); + pluginNames.forEach((pluginName) => { + this._closeAllConnections(pluginName); }); - pluginNames.forEach((name) => { - this._closeAllConnections(name); - }); - this.workerController.terminateAll(); + this._terminateAll(); this._removeAllPermissionsFor(pluginNames); - this.memStore.updateState({ - inlinePluginIsRunning: false, + this.update((state: any) => { + state.inlinePluginIsRunning = false; + state.plugins = {}; + state.pluginStates = {}; }); } @@ -431,21 +426,15 @@ export class PluginController extends EventEmitter { throw new Error('Expected array of plugin names.'); } - const state = this.store.getState(); - const newPlugins = { ...state.plugins }; - const newPluginStates = { ...state.pluginStates }; - - pluginNames.forEach((name) => { - this._stopPlugin(name, false); - delete newPlugins[name]; - delete newPluginStates[name]; + this.update((state: any) => { + pluginNames.forEach((pluginName) => { + this._stopPlugin(pluginName, false); + delete state.plugins[pluginName]; + delete state.pluginStates[pluginName]; + }); }); - this._removeAllPermissionsFor(pluginNames); - this.updateState({ - plugins: newPlugins, - pluginStates: newPluginStates, - }); + this._removeAllPermissionsFor(pluginNames); } /** @@ -483,7 +472,7 @@ export class PluginController extends EventEmitter { */ async installPlugins( origin: string, - requestedPlugins: IRequestedPermissions, + requestedPlugins: RequestedPluginPermissions, ): Promise { const result: InstallPluginsResult = {}; @@ -619,7 +608,7 @@ export class PluginController extends EventEmitter { version: manifest.version, }; - const pluginsState = this.store.getState().plugins; + const pluginsState = this.state.plugins; // restore relevant plugin state if it exists if (pluginsState[pluginName]) { @@ -627,11 +616,8 @@ export class PluginController extends EventEmitter { } // store the plugin back in state - this.updateState({ - plugins: { - ...pluginsState, - [pluginName]: plugin, - }, + this.update((state: any) => { + state.plugins[pluginName] = plugin; }); return plugin; @@ -644,7 +630,7 @@ export class PluginController extends EventEmitter { * @param manifestUrl - The URL of the plugin's manifest file. */ private async _fetchPlugin( - name: string, + pluginName: string, manifestUrl: string, ): Promise<[PluginManifest, string]> { try { @@ -663,7 +649,9 @@ export class PluginController extends EventEmitter { return [manifest, sourceCode]; } catch (err) { - throw new Error(`Problem fetching plugin "${name}": ${err.message}`); + throw new Error( + `Problem fetching plugin "${pluginName}": ${err.message}`, + ); } } @@ -676,7 +664,7 @@ export class PluginController extends EventEmitter { */ async authorize(pluginName: string): Promise { console.log(`Authorizing plugin: ${pluginName}`); - const pluginsState = this.store.getState().plugins; + const pluginsState = this.state.plugins; const plugin = pluginsState[pluginName]; const { initialPermissions } = plugin; @@ -684,6 +672,9 @@ export class PluginController extends EventEmitter { if (Object.keys(initialPermissions).length === 0) { return []; } + if (initialPermissions === null) { + return []; + } try { const approvedPermissions = await this._requestPermissions( @@ -701,8 +692,8 @@ export class PluginController extends EventEmitter { */ runInlinePlugin(inlinePluginName: keyof typeof INLINE_PLUGINS = 'IDLE') { this._startPluginInWorker('inlinePlugin', INLINE_PLUGINS[inlinePluginName]); - this.memStore.updateState({ - inlinePluginIsRunning: true, + this.update((state: any) => { + state.inlinePluginIsRunning = true; }); } @@ -710,18 +701,18 @@ export class PluginController extends EventEmitter { * Test method. */ removeInlinePlugin() { - this.memStore.updateState({ - inlinePluginIsRunning: false, + this.update((state: any) => { + state.inlinePluginIsRunning = false; }); this.removePlugin('inlinePlugin'); } private async _startPluginInWorker(pluginName: string, sourceCode: string) { - const workerId = await this.workerController.createPluginWorker({ + const workerId = await this._createPluginWorker({ hostname: pluginName, }); this._createPluginHooks(pluginName, workerId); - await this.workerController.startPlugin(workerId, { + await this._startPlugin(workerId, { pluginName, sourceCode, }); @@ -742,7 +733,7 @@ export class PluginController extends EventEmitter { origin: string, request: Record, ) => { - return await this.workerController.command(workerId, { + return await this._command(workerId, { id: nanoid(), jsonrpc: '2.0', method: 'pluginRpc', @@ -774,12 +765,12 @@ export class PluginController extends EventEmitter { property: keyof Plugin, value: unknown, ) { - const { plugins } = this.store.getState(); + const { plugins } = this.state; const plugin = plugins[pluginName]; const newPlugin = { ...plugin, [property]: value }; const newPlugins = { ...plugins, [pluginName]: newPlugin }; - this.updateState({ - plugins: newPlugins, + this.update((state: any) => { + state.plugins = newPlugins; }); } } diff --git a/packages/controllers/src/workers/WorkerController.ts b/packages/controllers/src/workers/WorkerController.ts index 05366530cc..0adaef0837 100644 --- a/packages/controllers/src/workers/WorkerController.ts +++ b/packages/controllers/src/workers/WorkerController.ts @@ -16,7 +16,7 @@ import { export type SetupWorkerConnection = (metadata: any, stream: Duplex) => void; -interface PluginWorkerMetadata { +export interface PluginWorkerMetadata { hostname: string; } interface WorkerControllerArgs { diff --git a/yarn.lock b/yarn.lock index 310abf54a5..387e564378 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1550,6 +1550,11 @@ resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.22.0.tgz#55cc84756c703c433176b484b1d34f0e03d16d1e" integrity sha512-t4ijbU+4OH9UAlrPkfLPFo6KmkRTRZJHB+Vly4ajF8oZMnota5YjVVl/SmltsoRC9xvJtRn9DUVf3YMHMIdofw== +"@metamask/contract-metadata@^1.25.0": + version "1.25.0" + resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.25.0.tgz#442ace91fb40165310764b68d8096d0017bb0492" + integrity sha512-yhmYB9CQPv0dckNcPoWDcgtrdUp0OgK0uvkRE5QIBv4b3qENI1/03BztvK2ijbTuMlORUpjPq7/1MQDUPoRPVw== + "@metamask/controllers@^5.0.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-5.1.0.tgz#02c1957295bcb6db1655a716d165665d170e7f34" @@ -1578,6 +1583,39 @@ web3 "^0.20.7" web3-provider-engine "^16.0.1" +"@metamask/controllers@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-9.1.0.tgz#4434f22eba2522889224b35aa08bc7b67d7248b7" + integrity sha512-jn/F0BNbaPsgEevHaPqk0lGAONKom4re1a4yBC67h7Vu6yu26CRi30SJl4xIh3IW4+ySbPhVLaiXFiXr3fESRQ== + dependencies: + "@metamask/contract-metadata" "^1.25.0" + "@types/uuid" "^8.3.0" + async-mutex "^0.2.6" + babel-runtime "^6.26.0" + eth-ens-namehash "^2.0.8" + eth-json-rpc-infura "^5.1.0" + eth-keyring-controller "^6.2.1" + eth-method-registry "1.1.0" + eth-phishing-detect "^1.1.14" + eth-query "^2.1.2" + eth-rpc-errors "^4.0.0" + eth-sig-util "^3.0.0" + ethereumjs-tx "^1.3.7" + ethereumjs-util "^6.1.0" + ethereumjs-wallet "^1.0.1" + ethjs-util "^0.1.6" + human-standard-collectible-abi "^1.0.2" + human-standard-token-abi "^2.0.0" + immer "^8.0.1" + isomorphic-fetch "^3.0.0" + jsonschema "^1.2.4" + nanoid "^3.1.12" + punycode "^2.1.1" + single-call-balance-checker-abi "^1.0.0" + uuid "^8.3.2" + web3 "^0.20.7" + web3-provider-engine "^16.0.1" + "@metamask/eslint-config-nodejs@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@metamask/eslint-config-nodejs/-/eslint-config-nodejs-6.0.0.tgz#df77bb35b91556030f1b23ad4ff51c1caf033339" @@ -1757,6 +1795,13 @@ dependencies: "@types/node" "*" +"@types/bn.js@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" + integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + dependencies: + "@types/node" "*" + "@types/graceful-fs@^4.1.2": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -1873,6 +1918,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== +"@types/uuid@^8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f" + integrity sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ== + "@types/yargs-parser@*": version "20.2.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" @@ -2597,6 +2647,11 @@ bn.js@^5.0.0, bn.js@^5.1.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== +bn.js@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + boolean@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.4.tgz#aa1df8749af41d7211b66b4eee584722ff428c27" @@ -4295,6 +4350,17 @@ eth-hd-keyring@^3.5.0: events "^1.1.1" xtend "^4.0.1" +eth-hd-keyring@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-3.6.0.tgz#6835d30aa411b8d3ef098e82f6427b5325082abb" + integrity sha512-n2CwE9VNXsxLrXQa6suv0Umt4NT6+HtoahKgWx3YviXx4rQFwVT5nDwZfjhwrT31ESuoXYNIeJgz5hKLD96QeQ== + dependencies: + bip39 "^2.2.0" + eth-sig-util "^3.0.1" + eth-simple-keyring "^4.2.0" + ethereumjs-util "^7.0.9" + ethereumjs-wallet "^1.0.1" + eth-json-rpc-filters@^4.2.1: version "4.2.2" resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.2.2.tgz#eb35e1dfe9357ace8a8908e7daee80b2cd60a10d" @@ -4349,6 +4415,21 @@ eth-keyring-controller@^6.1.0: loglevel "^1.5.0" obs-store "^4.0.3" +eth-keyring-controller@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.2.1.tgz#61901071fc74059ed37cb5ae93870fdcae6e3781" + integrity sha512-x2gTM1iHp2Kbvdtd9Eslysw0qzVZiqOzpVB3AU/ni2Xiit+rlcv2H80zYKjrEwlfWFDj4YILD3bOqlnEMmRJOA== + dependencies: + bip39 "^2.4.0" + bluebird "^3.5.0" + browser-passworder "^2.0.3" + eth-hd-keyring "^3.6.0" + eth-sig-util "^3.0.1" + eth-simple-keyring "^4.2.0" + ethereumjs-util "^7.0.9" + loglevel "^1.5.0" + obs-store "^4.0.3" + eth-method-registry@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eth-method-registry/-/eth-method-registry-1.1.0.tgz#3cc01bd23dcf513428d14a0bb19910652cc5cac0" @@ -4356,7 +4437,7 @@ eth-method-registry@1.1.0: dependencies: ethjs "^0.3.0" -eth-phishing-detect@^1.1.13: +eth-phishing-detect@^1.1.13, eth-phishing-detect@^1.1.14: version "1.1.14" resolved "https://registry.yarnpkg.com/eth-phishing-detect/-/eth-phishing-detect-1.1.14.tgz#64dcd35dd3a7a95266d875cbc5280842cda133d7" integrity sha512-nMQmzrgYabZ52YpuKZ38lStJy9Lozww2WBhyFbu/oepjsZzPvnl2KwJ6TJ78kk14USdl8Htt+eEMk2WAdAjlWg== @@ -4403,7 +4484,7 @@ eth-sig-util@^2.4.4, eth-sig-util@^2.5.0: tweetnacl "^1.0.3" tweetnacl-util "^0.15.0" -eth-sig-util@^3.0.0: +eth-sig-util@^3.0.0, eth-sig-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.1.tgz#8753297c83a3f58346bd13547b59c4b2cd110c96" integrity sha512-0Us50HiGGvZgjtWTyAI/+qTzYPMLy5Q451D0Xy68bxq1QMWdoOddDwGvsqcFT27uohKgalM9z/yxplyt+mY2iQ== @@ -4425,6 +4506,16 @@ eth-simple-keyring@^3.5.0: events "^1.1.1" xtend "^4.0.1" +eth-simple-keyring@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eth-simple-keyring/-/eth-simple-keyring-4.2.0.tgz#c197a4bd4cce7d701b5f3607d0b843112ddb17e3" + integrity sha512-lBxFObXJTBjktDkQszXrqoB317wghEUYATQ3W19vLAjaznrmbdy1lccPhXIRMT9bHIUgNKOJQkLohNZiT9tO8Q== + dependencies: + eth-sig-util "^3.0.1" + ethereumjs-util "^7.0.9" + ethereumjs-wallet "^1.0.1" + events "^1.1.1" + ethereum-common@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" @@ -4507,7 +4598,7 @@ ethereumjs-common@^1.1.0, ethereumjs-common@^1.5.0: resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== -ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2: +ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== @@ -4549,6 +4640,18 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0: ethjs-util "0.1.6" rlp "^2.2.3" +ethereumjs-util@^7.0.2, ethereumjs-util@^7.0.9: + version "7.0.10" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz#5fb7b69fa1fda0acc59634cf39d6b0291180fc1f" + integrity sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.4" + ethereumjs-vm@^2.3.4: version "2.6.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" @@ -4581,6 +4684,20 @@ ethereumjs-wallet@^0.6.0, ethereumjs-wallet@^0.6.4: utf8 "^3.0.0" uuid "^3.3.2" +ethereumjs-wallet@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.1.tgz#664a4bcacfc1291ca2703de066df1178938dba1c" + integrity sha512-3Z5g1hG1das0JWU6cQ9HWWTY2nt9nXCcwj7eXVNAHKbo00XAZO8+NHlwdgXDWrL0SXVQMvTWN8Q/82DRH/JhPw== + dependencies: + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^7.0.2" + randombytes "^2.0.6" + scrypt-js "^3.0.1" + utf8 "^3.0.0" + uuid "^3.3.2" + ethjs-abi@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.2.0.tgz#d3e2c221011520fc499b71682036c14fcc2f5b25" @@ -4680,7 +4797,7 @@ ethjs-util@0.1.3: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" -ethjs-util@0.1.6, ethjs-util@^0.1.3: +ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== @@ -5534,6 +5651,11 @@ immediate@^3.2.3: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== +immer@^8.0.1: + version "8.0.4" + resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.4.tgz#3a21605a4e2dded852fb2afd208ad50969737b7a" + integrity sha512-jMfL18P+/6P6epANRvRk6q8t+3gGhqsJ9EuJ25AXE+9bNTYtssvzeYbEd0mXRYWCmmXSIbnlpz6vd6iJlmGGGQ== + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -8627,7 +8749,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.3: +rlp@^2.0.0, rlp@^2.2.3, rlp@^2.2.4: version "2.2.6" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c" integrity sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg== @@ -8744,7 +8866,7 @@ scope-analyzer@^2.0.0: estree-is-function "^1.0.0" get-assigned-identifiers "^1.1.0" -scrypt-js@^3.0.0: +scrypt-js@^3.0.0, scrypt-js@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== @@ -9931,7 +10053,7 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.0: +uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==