diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/extension_description/en.txt | 8 | ||||
-rw-r--r-- | docs/form_persisting_architecture.md | 28 | ||||
-rw-r--r-- | docs/multi_vault_planning.md | 188 |
3 files changed, 224 insertions, 0 deletions
diff --git a/docs/extension_description/en.txt b/docs/extension_description/en.txt new file mode 100644 index 000000000..53bc4780d --- /dev/null +++ b/docs/extension_description/en.txt @@ -0,0 +1,8 @@ +MetaMask is an extension for accessing Ethereum enabled distributed applications, or "Dapps" in your normal browser! + +The extension injects the Ethereum web3 API into every website's javascript context, so that dapps can read from the blockchain. + +MetaMask also lets the user create and manage their own identities, so when a Dapp wants to perform a transaction and write to the blockchain, the user gets a secure interface to review the transaction, before approving or rejecting it. + +Because it adds functionality to the normal browser context, MetaMask requires the permission to read and write to any webpage. You can always "view the source" of MetaMask the way you do any extension, or view the source code on Github: +https://github.com/MetaMask/metamask-plugin
\ No newline at end of file diff --git a/docs/form_persisting_architecture.md b/docs/form_persisting_architecture.md new file mode 100644 index 000000000..e2d766ccc --- /dev/null +++ b/docs/form_persisting_architecture.md @@ -0,0 +1,28 @@ +# Form Persisting Architecture + +Since: + - The popup is torn down completely on every click outside of it. + - We have forms with multiple fields (like passwords & seed phrases) that might encourage a user to leave our panel to refer to a password manager. + + We cause user friction when we lose the contents of certain forms. + + This calls for an architecture of a form component that can completely persist its values to LocalStorage on every relevant change, and restore those values on reopening. + + To achieve this, we have defined a class, a subclass of `React.Component`, called `PersistentForm`, and it's stored at `ui/lib/persistent-form.js`. + +To use this class, simply take your form component (the component that renders `input`, `select`, or `textarea` elements), and make it subclass from `PersistentForm` instead of `React.Component`. + +You can see an example of this in use in `ui/app/first-time/restore-vault.js`. + +Additionally, any field whose value should be persisted, should have a `persistentFormId` attribute, which needs to be assigned under a `dataset` key on the main `attributes` hash. For example: + +```javascript + return h('textarea.twelve-word-phrase.letter-spacey', { + dataset: { + persistentFormId: 'wallet-seed', + }, + }) +``` + +That's it! This field should be persisted to `localStorage` on each `keyUp`, those values should be restored on view load, and the cached values should be cleared when navigating deliberately away from the form. + diff --git a/docs/multi_vault_planning.md b/docs/multi_vault_planning.md new file mode 100644 index 000000000..fdde2bc50 --- /dev/null +++ b/docs/multi_vault_planning.md @@ -0,0 +1,188 @@ +https://hackmd.io/JwIwDMDGKQZgtAFgKZjEgbARhPAhgKxZbwAcA7LAWOQCaKEgFA==?edit + +Subscribablez(initState) + .subscribe() + .emitUpdate(newState) + //.getState() + + +var initState = fromDisk() +ReduxStore(reducer, initState) +.reduce(action) -> .emitUpdate() + +ReduxStore.subscribe(toDisk) + + +### KeyChainManager / idStore 2.0 (maybe just in MetaMaskController) + keychains: [] + getAllAccounts(cb) + getAllKeychainViewStates(cb) -> returns [ KeyChainViewState] + +#### Old idStore external methods, for feature parity: + +- init(configManager) +- setStore(ethStore) +- getState() +- getSelectedAddres() +- setSelectedAddress() +- createNewVault() +- recoverFromSeed() +- submitPassword() +- approveTransaction() +- cancelTransaction() +- addUnconfirmedMessage(msgParams, cb) +- signMessage() +- cancelMessage() +- setLocked() +- clearSeedWordCache() +- exportAccount() +- revealAccount() +- saveAccountLabel() +- tryPassword() +- recoverSeed() +- getNetwork() + +##### Of those methods + +Where they should end up: + +##### MetaMaskController + +- getNetwork() + +##### KeyChainManager + +- init(configManager) +- setStore(ethStore) +- getState() // Deprecate for unidirectional flow +- on('update', cb) +- createNewVault(password) +- getSelectedAddres() +- setSelectedAddress() +- submitPassword() +- tryPassword() +- approveTransaction() +- cancelTransaction() +- signMessage() +- cancelMessage() +- setLocked() +- exportAccount() + +##### Bip44 KeyChain + +- getState() // Deprecate for unidirectional flow +- on('update', cb) + +If we adopt a ReactStore style unidirectional action dispatching data flow, these methods will be unified under a `dispatch` method, and rather than having a cb will emit an update to the UI: + +- createNewKeyChain(entropy) +- recoverFromSeed() +- approveTransaction() +- signMessage() +- clearSeedWordCache() +- exportAccount() +- revealAccount() +- saveAccountLabel() +- recoverSeed() + +Additional methods, new to this: +- serialize() + - Returns pojo with optional `secret` key whose contents will be encrypted with the users' password and salt when written to disk. + - The isolation of secrets is to preserve performance when decrypting user data. +- deserialize(pojo) + +### KeyChain (ReduxStore?) + // attributes + @name + + signTx(txParams, cb) + signMsg(msg, cb) + + getAddressList(cb) + + getViewState(cb) -> returns KeyChainViewState + + serialize(cb) -> obj + deserialize(obj) + + dispatch({ type: <str>, value: <pojo> }) + + +### KeyChainViewState + // The serialized, renderable keychain data + accountList: [], + typeName: 'uPort', + iconAddress: 'uport.gif', + internal: {} // Subclass-defined metadata + +### KeyChainReactComponent + // takes a KeyChainViewState + + // Subclasses of this: + - KeyChainListItemComponent + - KeyChainInitComponent - Maybe part of the List Item + - KeyChainAccountHeaderComponent + - KeyChainConfirmationComponent + // Account list item, tx confirmation extra data (like a QR code), + // Maybe an options screen, init screen, + + how to send actions? + emitAction(keychains.<id>.didInit) + + +gimmeRemoteKeychain((err, remoteKeychain)=> + +) + + + + + +KeyChainReactComponent({ + keychain +}) + +Keychain: + methods:{}, + cachedAccountList: [], + name: '', + + +CoinbaseKeychain + getAccountList + + +CoinbaseKeychainComponent + isLoading = true + keychain.getAccountList(()=>{ + isLoading=false + accountList=accounts + }) + + + + + +KeyChainViewState { + attributes: { + //mandatory: + accountList: [], + typeName: 'uPort', + iconAddress: 'uport.gif', + + internal: { + // keychain-specific metadata + proxyAddresses: { + 0xReal: '0xProxy' + } + }, + }, + methods: { + // arbitrary, internal + } +} + +## A note on the security of arbitrary action dispatchers + +Since keychains will be dispatching actions that are then passed through the background process to be routed, we should not trust or require them to include their own keychain ID as a prefix to their action, but we should tack it on ourselves, so that no action dispatched by a KeyChainComponent ever reaches any KeyChain other than its own. + |