UNPKG

nano-wallet-js-test-1

Version:

SDK for developers to create and interact with Nanocurrency wallet easily

178 lines (156 loc) 4.71 kB
/* Updated from: https://github.com/MetaMask/controllers/blob/15129ad48fd1390492482c45941bd948ea596e5d/src/BaseController.ts */ /** * State change callbacks */ export type Listener<T> = (state: T, resetting?: boolean) => Promise<void>; /** * @type BaseConfig * * Base controller configuration * @property disabled - Determines if this controller is enabled */ export interface BaseConfig {} /** * @type BaseState * * Base state representation * @property name - Unique name for this controller */ export interface BaseState {} /** * Controller class that provides configuration, state management, and subscriptions */ export default class BaseController<C extends BaseConfig, S extends BaseState> { /** * Default options used to configure this controller */ defaultConfig: C = {} as C; /** * Default state set on this controller */ defaultState: S = {} as S; private readonly initialConfig: C; private readonly initialState: S; private internalConfig: C = this.defaultConfig; private internalState: S = this.defaultState; private internalListeners: Listener<S>[] = []; /** * Creates a BaseController instance. Both initial state and initial * configuration options are merged with defaults upon initialization. * * @param config - Initial options used to configure this controller. * @param state - Initial state to set on this controller. */ constructor(config: Partial<C> = {} as C, state: Partial<S> = {} as S) { // Use assign since generics can't be spread: https://git.io/vpRhY this.initialState = state as S; this.initialConfig = config as C; } /** * Enables the controller. This sets each config option as a member * variable on this instance and triggers any defined setters. This * also sets initial state and triggers any listeners. * * @returns This controller instance. */ protected initialize() { this.internalState = this.defaultState; this.internalConfig = this.defaultConfig; this.configure(this.initialConfig); this.update(this.initialState); return this; } /** * Retrieves current controller configuration options. * * @returns The current configuration. */ get config() { return this.internalConfig; } /** * Retrieves current controller state. * * @returns The current state. */ get state() { return this.internalState; } /** * Updates controller configuration. * * @param config - New configuration options. * @param overwrite - Overwrite config instead of merging. * @param fullUpdate - Boolean that defines if the update is partial or not. */ configure(config: Partial<C>, overwrite = false, fullUpdate = true) { if (fullUpdate) { this.internalConfig = overwrite ? (config as C) : Object.assign(this.internalConfig, config); for (const key in this.internalConfig) { if (typeof this.internalConfig[key] !== 'undefined') { /* eslint-disable-next-line */ (this as any)[key as string] = this.internalConfig[key]; } } } else { for (const key in config) { /* istanbul ignore else */ if (typeof this.internalConfig[key] !== 'undefined') { /* eslint-disable-next-line */ this.internalConfig[key] = config[key] as any; /* eslint-disable-next-line */ (this as any)[key as string] = config[key]; } } } } /** * Notifies all subscribed listeners of current modified state. */ async notify(state: S, resetting = false) { const promises: Promise<void>[] = []; this.internalListeners.forEach(listener => { promises.push(listener(state, resetting)); }); await Promise.all(promises); } /** * Adds new listener to be notified of state changes. * * @param listener - The callback triggered when state changes. */ subscribe(listener: Listener<S>) { this.internalListeners.push(listener); } /** * Removes existing listener from receiving state changes. * * @param listener - The callback to remove. * @returns `true` if a listener is found and unsubscribed. */ unsubscribe(listener: Listener<S>) { const index = this.internalListeners.findIndex(cb => listener === cb); index > -1 && this.internalListeners.splice(index, 1); return index > -1; } /** * Updates controller state. * * @param state - The new state. * @param overwrite - Overwrite state instead of merging. */ async update(state: Partial<S>, overwrite = false, resetting = false) { this.internalState = overwrite ? Object.assign({}, state as S) : Object.assign({}, this.internalState, state); await this.notify(this.internalState, resetting); } /** * Resets controller state to default. */ reset() { this.update(this.defaultState, true, true); } }