diff --git a/packages/ui-keyring/src/Base.ts b/packages/ui-keyring/src/Base.ts new file mode 100644 index 00000000..96f34199 --- /dev/null +++ b/packages/ui-keyring/src/Base.ts @@ -0,0 +1,114 @@ +// Copyright 2017-2018 @polkadot/ui-keyring authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { Prefix } from '@polkadot/keyring/address/types'; +import { KeyringInstance, KeyringPair } from '@polkadot/keyring/types'; +import { AddressSubject } from './observable/types'; + +import testKeyring from '@polkadot/keyring/testing'; +import { isString } from '@polkadot/util'; + +import accounts from './observable/accounts'; +import addresses from './observable/addresses'; +import env from './observable/development'; +import { MAX_PASS_LEN } from './defaults'; + +export default class Base { + private _accounts: AddressSubject; + private _addresses: AddressSubject; + private _keyring?: KeyringInstance; + private _prefix: Prefix; + + constructor () { + this._accounts = accounts; + this._addresses = addresses; + this._keyring = undefined; + this._prefix = 42; + } + + get accounts () { + return this._accounts; + } + + get addresses () { + return this._addresses; + } + + get keyring (): KeyringInstance { + if (this._keyring) { + return this._keyring; + } + + throw new Error(`Keyring should be initialised via 'loadAll' before use`); + } + + decodeAddress (key: string | Uint8Array): Uint8Array { + return this.keyring.decodeAddress(key); + } + + encodeAddress (key: string | Uint8Array): string { + return this.keyring.encodeAddress(key); + } + + setAddressPrefix (prefix: number): void { + this._prefix = prefix as Prefix; + } + + setDevMode (isDevelopment: boolean): void { + env.set(isDevelopment); + } + + protected initKeyring (): void { + const keyring = testKeyring(); + + keyring.setAddressPrefix(this._prefix); + + this._keyring = keyring; + + this.addAccountPairs(); + } + + protected addAccountPairs (): void { + this.keyring + .getPairs() + .forEach((pair: KeyringPair) => { + const address = pair.address(); + + this.accounts.add(address, { + address, + meta: pair.getMeta() + }); + }); + } + + protected addTimestamp (pair: KeyringPair): void { + if (!pair.getMeta().whenCreated) { + pair.setMeta({ whenCreated: Date.now() }); + } + } + + isAvailable (_address: Uint8Array | string): boolean { + const accountsValue = this.accounts.subject.getValue(); + const addressesValue = this.addresses.subject.getValue(); + const address = isString(_address) + ? _address + : this.encodeAddress(_address); + + return !accountsValue[address] && !addressesValue[address]; + } + + isPassValid (password: string): boolean { + return password.length > 0 && password.length <= MAX_PASS_LEN; + } + + getPair (address: string | Uint8Array): KeyringPair { + return this.keyring.getPair(address); + } + + getPairs (): Array { + return this.keyring.getPairs().filter((pair: KeyringPair) => + env.isDevelopment() || pair.getMeta().isTesting !== true + ); + } +} diff --git a/packages/ui-keyring/src/index.ts b/packages/ui-keyring/src/index.ts index f28754e2..6d92f6cb 100644 --- a/packages/ui-keyring/src/index.ts +++ b/packages/ui-keyring/src/index.ts @@ -2,89 +2,23 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { Prefix } from '@polkadot/keyring/address/types'; -import { KeyringInstance as BaseKeyringInstance, KeyringPair, KeyringPair$Meta, KeyringPair$Json } from '@polkadot/keyring/types'; -import { AddressSubject, SingleAddress } from './observable/types'; +import { KeyringPair, KeyringPair$Meta, KeyringPair$Json } from '@polkadot/keyring/types'; +import { SingleAddress } from './observable/types'; import { KeyringAddress, KeyringJson, KeyringJson$Meta, KeyringStruct } from './types'; import store from 'store'; import createPair from '@polkadot/keyring/pair'; -import testKeyring from '@polkadot/keyring/testing'; import { hexToU8a, isHex, isString } from '@polkadot/util'; -import accounts from './observable/accounts'; -import addresses from './observable/addresses'; import env from './observable/development'; -import { accountKey, addressKey, accountRegex, addressRegex, MAX_PASS_LEN } from './defaults'; +import Base from './Base'; +import { accountKey, addressKey, accountRegex, addressRegex } from './defaults'; import keyringOption from './options'; // No accounts (or test accounts) should be loaded until after the chain determination. // Chain determination occurs outside of Keyring. Loading `keyring.loadAll()` is triggered // from the API after the chain is received -class Keyring implements KeyringStruct { - private _accounts: AddressSubject; - private _addresses: AddressSubject; - private _keyring?: BaseKeyringInstance; - private _prefix: Prefix; - - constructor () { - this._accounts = accounts; - this._addresses = addresses; - this._keyring = undefined; - this._prefix = 42; - } - - get accounts () { - return this._accounts; - } - - get addresses () { - return this._addresses; - } - - get keyring (): BaseKeyringInstance { - if (this._keyring) { - return this._keyring; - } - - throw new Error(`Keyring should be initialised via 'loadAll' before use`); - } - - decodeAddress (key: string | Uint8Array): Uint8Array { - return this.keyring.decodeAddress(key); - } - - encodeAddress (key: string | Uint8Array): string { - return this.keyring.encodeAddress(key); - } - - setAddressPrefix (prefix: number): void { - this._prefix = prefix as Prefix; - } - - private setKeyring (keyring: BaseKeyringInstance): void { - this._keyring = keyring; - } - - private addAccountPairs (): void { - this.keyring - .getPairs() - .forEach((pair: KeyringPair) => { - const address = pair.address(); - - this.accounts.add(address, { - address, - meta: pair.getMeta() - }); - }); - } - - private addTimestamp (pair: KeyringPair): void { - if (!pair.getMeta().whenCreated) { - pair.setMeta({ whenCreated: Date.now() }); - } - } - +class Keyring extends Base implements KeyringStruct { addAccountPair (pair: KeyringPair, password: string): KeyringPair { this.keyring.addPair(pair); this.saveAccount(pair, password); @@ -178,66 +112,45 @@ class Keyring implements KeyringStruct { .map((address) => this.getAddress(address)); } - getPair (address: string | Uint8Array): KeyringPair { - return this.keyring.getPair(address); + private loadAccount (json: KeyringJson, key: string) { + if (!json.meta.isTesting && (json as KeyringPair$Json).encoded) { + const pair = this.keyring.addFromJson(json as KeyringPair$Json); + + this.accounts.add(pair.address(), json); + } + + const [, hexAddr] = key.split(':'); + + if (hexAddr.substr(0, 2) !== '0x') { + store.remove(key); + store.set(accountKey(hexAddr), json); + } } - getPairs (): Array { - return this.keyring.getPairs().filter((pair: KeyringPair) => - env.isDevelopment() || pair.getMeta().isTesting !== true + private loadAddress (json: KeyringJson, key: string) { + const address = this.encodeAddress( + isHex(json.address) + ? hexToU8a(json.address) + : this.decodeAddress(json.address) ); - } + const [, hexAddr] = key.split(':'); - isAvailable (_address: Uint8Array | string): boolean { - const accountsValue = this.accounts.subject.getValue(); - const addressesValue = this.addresses.subject.getValue(); - const address = isString(_address) - ? _address - : this.encodeAddress(_address); + this.addresses.add(address, json); - return !accountsValue[address] && !addressesValue[address]; - } - - isPassValid (password: string): boolean { - return password.length > 0 && password.length <= MAX_PASS_LEN; + if (hexAddr.substr(0, 2) !== '0x') { + store.remove(key); + store.set(addressKey(hexAddr), json); + } } loadAll (): void { - const keyring = testKeyring(); - - keyring.setAddressPrefix(this._prefix); - - this.setKeyring(keyring); - this.addAccountPairs(); + super.initKeyring(); store.each((json: KeyringJson, key: string) => { if (accountRegex.test(key)) { - if (!json.meta.isTesting && (json as KeyringPair$Json).encoded) { - const pair = keyring.addFromJson(json as KeyringPair$Json); - - this.accounts.add(pair.address(), json); - } - - const [, hexAddr] = key.split(':'); - - if (hexAddr.substr(0, 2) !== '0x') { - store.remove(key); - store.set(accountKey(hexAddr), json); - } + this.loadAccount(json, key); } else if (addressRegex.test(key)) { - const address = this.encodeAddress( - isHex(json.address) - ? hexToU8a(json.address) - : this.decodeAddress(json.address) - ); - const [, hexAddr] = key.split(':'); - - this.addresses.add(address, json); - - if (hexAddr.substr(0, 2) !== '0x') { - store.remove(key); - store.set(addressKey(hexAddr), json); - } + this.loadAddress(json, key); } }); @@ -318,10 +231,6 @@ class Keyring implements KeyringStruct { return this.addresses.subject.getValue()[address]; } - - setDevMode (isDevelopment: boolean): void { - env.set(isDevelopment); - } } const keyringInstance = new Keyring();