From da84d5a8aec82749de2656762e56281f843e6e02 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 6 Jun 2019 18:13:28 +0200 Subject: [PATCH] Add ExtensionStore (from @polkadot/extension) (#142) * Add ExtensionStore (from @polkadot/extension) * Consistent naming, untested/unused File store * Update File.ts --- package.json | 2 +- packages/ui-keyring/package.json | 3 + packages/ui-keyring/src/Base.ts | 4 +- packages/ui-keyring/src/index.ts | 1 + .../stores/{LocalStorage.ts => Browser.ts} | 2 +- packages/ui-keyring/src/stores/Extension.ts | 58 +++++++++++++++++++ packages/ui-keyring/src/stores/File.ts | 53 +++++++++++++++++ packages/ui-keyring/src/stores/index.ts | 7 +++ yarn.lock | 41 +++++++++++-- 9 files changed, 163 insertions(+), 8 deletions(-) rename packages/ui-keyring/src/stores/{LocalStorage.ts => Browser.ts} (91%) create mode 100644 packages/ui-keyring/src/stores/Extension.ts create mode 100644 packages/ui-keyring/src/stores/File.ts create mode 100644 packages/ui-keyring/src/stores/index.ts diff --git a/package.json b/package.json index f92ab71f..48507ee8 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@babel/core": "^7.4.5", "@babel/runtime": "^7.4.5", "@polkadot/dev-react": "^0.30.0-beta.9", - "@polkadot/ts": "^0.1.58", + "@polkadot/ts": "^0.1.59", "empty": "^0.10.1", "gh-pages": "^2.0.1" } diff --git a/packages/ui-keyring/package.json b/packages/ui-keyring/package.json index c21ee499..7d2fb320 100644 --- a/packages/ui-keyring/package.json +++ b/packages/ui-keyring/package.json @@ -11,7 +11,10 @@ "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.4.5", + "@types/mkdirp": "^0.5.2", "@types/store": "^2.0.2", + "extensionizer": "^1.0.1", + "mkdirp": "^0.5.1", "store": "^2.0.12", "styled-components": "^4.2.0" }, diff --git a/packages/ui-keyring/src/Base.ts b/packages/ui-keyring/src/Base.ts index 0e2a49b5..0b7b17f4 100644 --- a/packages/ui-keyring/src/Base.ts +++ b/packages/ui-keyring/src/Base.ts @@ -14,7 +14,7 @@ import accounts from './observable/accounts'; import addresses from './observable/addresses'; import contracts from './observable/contracts'; import env from './observable/development'; -import LocalStorageStore from './stores/LocalStorage'; +import { BrowserStore } from './stores'; import { MAX_PASS_LEN } from './defaults'; export default class Base { @@ -108,7 +108,7 @@ export default class Base { this._keyring = keyring; this._genesisHash = options.genesisHash && options.genesisHash.toHex(); - this._store = options.store || new LocalStorageStore(); + this._store = options.store || new BrowserStore(); this.addAccountPairs(); } diff --git a/packages/ui-keyring/src/index.ts b/packages/ui-keyring/src/index.ts index 437072ab..1723d642 100644 --- a/packages/ui-keyring/src/index.ts +++ b/packages/ui-keyring/src/index.ts @@ -5,6 +5,7 @@ import { assertSingletonPackage } from '@polkadot/util'; import keyring, { Keyring } from './Keyring'; +export * from './stores'; assertSingletonPackage('@polkadot/ui-keyring'); diff --git a/packages/ui-keyring/src/stores/LocalStorage.ts b/packages/ui-keyring/src/stores/Browser.ts similarity index 91% rename from packages/ui-keyring/src/stores/LocalStorage.ts rename to packages/ui-keyring/src/stores/Browser.ts index 2537b743..f3b0b6d0 100644 --- a/packages/ui-keyring/src/stores/LocalStorage.ts +++ b/packages/ui-keyring/src/stores/Browser.ts @@ -6,7 +6,7 @@ import { KeyringStore } from '../types'; import store from 'store'; -export default class Store implements KeyringStore { +export default class BrowserStore implements KeyringStore { all (cb: (key: string, value: any) => void): void { store.each((value: any, key: string) => cb(key, value) diff --git a/packages/ui-keyring/src/stores/Extension.ts b/packages/ui-keyring/src/stores/Extension.ts new file mode 100644 index 00000000..5254ea81 --- /dev/null +++ b/packages/ui-keyring/src/stores/Extension.ts @@ -0,0 +1,58 @@ +// Copyright 2019 @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 { KeyringStore } from '../types'; + +import extension from 'extensionizer'; + +const lastError = (type: string): void => { + const error = extension.runtime.lastError; + + if (error) { + console.error(`ExtensionStore.${type}:: runtime.lastError:`, error); + } +}; + +export default class ExtensionStore implements KeyringStore { + all (cb: (key: string, value: any) => void): void { + extension.storage.local.get(null, (result: { [index: string]: any }) => { + lastError('all'); + + Object.entries(result).forEach(([key, value]) => + cb(key, value) + ); + }); + } + + get (key: string, cb: (value: any) => void): void { + extension.storage.local.get([key], (result: { [index: string]: any }) => { + lastError('get'); + + cb(result[key]); + }); + } + + remove (key: string, cb?: () => void): void { + extension.storage.local.remove(key, () => { + lastError('remove'); + + cb && cb(); + }); + } + + set (key: string, value: any, cb?: () => void): void { + // shortcut, don't save testing accounts in extension storage + if (key.indexOf('account:') === 0 && value.meta && value.meta.isTesting) { + cb && cb(); + + return; + } + + extension.storage.local.set({ [key]: value }, () => { + lastError('set'); + + cb && cb(); + }); + } +} diff --git a/packages/ui-keyring/src/stores/File.ts b/packages/ui-keyring/src/stores/File.ts new file mode 100644 index 00000000..7d093737 --- /dev/null +++ b/packages/ui-keyring/src/stores/File.ts @@ -0,0 +1,53 @@ +// Copyright 2017-2019 @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 { KeyringStore } from '../types'; + +import fs from 'fs'; +import mkdirp from 'mkdirp'; +import path from 'path'; + +// NOTE untested and unused by any known apps, probably broken in various mysterious ways +export default class FileStore implements KeyringStore { + private _path: string; + + constructor (path: string) { + if (!fs.existsSync(path)) { + mkdirp.sync(path); + } + + this._path = path; + } + + all (cb: (key: string, value: any) => void): void { + fs + .readdirSync(this._path) + .filter((key) => !['.', '..'].includes(key)) + .forEach((key) => cb(key, this._readKey(key))); + } + + get (key: string, cb: (value: any) => void): void { + cb(this._readKey(key)); + } + + remove (key: string, cb?: () => void): void { + fs.unlinkSync(this._getPath(key)); + cb && cb(); + } + + set (key: string, value: any, cb?: () => void): void { + fs.writeFileSync(this._getPath(key), Buffer.from(JSON.stringify(value), 'utf-8')); + cb && cb(); + } + + private _getPath (key: string): string { + return path.join(this._path, key); + } + + private _readKey (key: string): any { + return JSON.parse( + fs.readFileSync(this._getPath(key)).toString('utf-8') + ); + } +} diff --git a/packages/ui-keyring/src/stores/index.ts b/packages/ui-keyring/src/stores/index.ts new file mode 100644 index 00000000..2de43231 --- /dev/null +++ b/packages/ui-keyring/src/stores/index.ts @@ -0,0 +1,7 @@ +// Copyright 2017-2019 @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. + +export { default as BrowserStore } from './Browser'; +export { default as ExtensionStore } from './Extension'; +export { default as FileStore } from './File'; diff --git a/yarn.lock b/yarn.lock index 8726d4c3..288ad60a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1835,10 +1835,12 @@ "@types/bs58" "^4.0.0" bs58 "^4.0.1" -"@polkadot/ts@^0.1.58": - version "0.1.58" - resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.1.58.tgz#bd8883d590fc5be27e1db75c5c629e6bc8c4ce5c" - integrity sha512-+veSrr59SefA43RX034eef1T8qhO15Ye0BQ1+3FxjuFBnlCVmzj6iKGuzCtp4kGp3uFeotQ3m/2xMA+akSwq4Q== +"@polkadot/ts@^0.1.59": + version "0.1.59" + resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.1.59.tgz#e7418db78ad50291a46d61a3ab34ab465c0c3bf0" + integrity sha512-+kiST4RjeuyMWu2HdqIA6Ph2AifjGvlQ5bLDe9mfuApH07h8fgtzu+xVE4FZvMkLtjyKD+FSbB/oVplq2R1WEw== + dependencies: + "@types/chrome" "^0.0.86" "@polkadot/types@^0.80.1": version "0.80.1" @@ -1948,6 +1950,13 @@ dependencies: "@types/base-x" "*" +"@types/chrome@^0.0.86": + version "0.0.86" + resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.86.tgz#1026ef8e76db4fde1859cae858d73236fe670d69" + integrity sha512-7ehebPf/5IR64SYdD2Vig0q0oUCNbWMQ29kASlNJaHVVtA5/J/DnrxnYVPCID70o7LgHdYsav6I4/XdqAxjTLQ== + dependencies: + "@types/filesystem" "*" + "@types/color-convert@*": version "1.9.0" resolved "https://registry.yarnpkg.com/@types/color-convert/-/color-convert-1.9.0.tgz#bfa8203e41e7c65471e9841d7e306a7cd8b5172d" @@ -1977,6 +1986,18 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== +"@types/filesystem@*": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.29.tgz#ee3748eb5be140dcf980c3bd35f11aec5f7a3748" + integrity sha512-85/1KfRedmfPGsbK8YzeaQUyV1FQAvMPMTuWFQ5EkLd2w7szhNO96bk3Rh/SKmOfd9co2rCLf0Voy4o7ECBOvw== + dependencies: + "@types/filewriter" "*" + +"@types/filewriter@*": + version "0.0.28" + resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.28.tgz#c054e8af4d9dd75db4e63abc76f885168714d4b3" + integrity sha1-wFTor02d11205jq8dviFFocU1LM= + "@types/fs-extra@^5.0.3": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1" @@ -2052,6 +2073,13 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + "@types/node@*", "@types/node@^12.0.4": version "12.0.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.5.tgz#ac14404c33d1a789973c45379a67f7f7e58a01b9" @@ -5378,6 +5406,11 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +extensionizer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/extensionizer/-/extensionizer-1.0.1.tgz#504544239a7610ba8404b15c1832091a37768d09" + integrity sha512-UES5CSOYqshNsWFrpORcQR47+ph6UvQK25mguD44IyeMemt40CG+LTZrH1PgpGUHX3w7ACtNQnmM0J+qEe8G0Q== + external-editor@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27"