From 3ac4e7d051c43b743ffb3165c28aa22c21d2d9b3 Mon Sep 17 00:00:00 2001 From: MetaMask Bot Date: Tue, 8 Mar 2022 16:34:06 +0000 Subject: [PATCH 1/9] Version v10.11.1 --- CHANGELOG.md | 5 ++++- package.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ffb0292c..64f6c27b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.11.1] + ## [10.11.0] ### Added - Swaps: Add support for Smart Transactions on Mainnet and Rinkeby ([#12676](https://github.com/MetaMask/metamask-extension/pull/12676)) @@ -2764,7 +2766,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Uncategorized - Added the ability to restore accounts from seed words. -[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.11.0...HEAD +[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.11.1...HEAD +[10.11.1]: https://github.com/MetaMask/metamask-extension/compare/v10.11.0...v10.11.1 [10.11.0]: https://github.com/MetaMask/metamask-extension/compare/v10.10.2...v10.11.0 [10.10.2]: https://github.com/MetaMask/metamask-extension/compare/v10.10.1...v10.10.2 [10.10.1]: https://github.com/MetaMask/metamask-extension/compare/v10.10.0...v10.10.1 diff --git a/package.json b/package.json index a5edf84d8..99824e2e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask-crx", - "version": "10.11.0", + "version": "10.11.1", "private": true, "repository": { "type": "git", From 7ec8bd49c76482bcf75c8ca81925ecbb70be52d9 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 7 Mar 2022 09:28:30 -0600 Subject: [PATCH 2/9] [GridPlus] Updates Lattice dependencies (#13834) --- app/manifest/_base.json | 2 +- lavamoat/browserify/beta/policy.json | 2 ++ lavamoat/browserify/flask/policy.json | 2 ++ lavamoat/browserify/main/policy.json | 2 ++ package.json | 2 +- yarn.lock | 39 ++++++++++++++++++--------- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/app/manifest/_base.json b/app/manifest/_base.json index bc63ce27d..c2b20b4db 100644 --- a/app/manifest/_base.json +++ b/app/manifest/_base.json @@ -66,7 +66,7 @@ "clipboardWrite", "http://localhost:8545/", "https://*.infura.io/", - "https://wallet.gridplus.io/*", + "https://lattice.gridplus.io/*", "activeTab", "webRequest", "*://*.eth/", diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index fd9c5466a..bb6798360 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -2337,6 +2337,7 @@ "gridplus-sdk": { "globals": { "console.error": true, + "console.warn": true, "setTimeout": true }, "packages": { @@ -2350,6 +2351,7 @@ "crc-32": true, "elliptic": true, "eth-eip712-util-browser": true, + "hash.js": true, "js-sha3": true, "rlp-browser": true, "secp256k1": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index fc9b78a8e..d3c537308 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -2356,6 +2356,7 @@ "gridplus-sdk": { "globals": { "console.error": true, + "console.warn": true, "setTimeout": true }, "packages": { @@ -2369,6 +2370,7 @@ "crc-32": true, "elliptic": true, "eth-eip712-util-browser": true, + "hash.js": true, "js-sha3": true, "rlp-browser": true, "secp256k1": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index fd9c5466a..bb6798360 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -2337,6 +2337,7 @@ "gridplus-sdk": { "globals": { "console.error": true, + "console.warn": true, "setTimeout": true }, "packages": { @@ -2350,6 +2351,7 @@ "crc-32": true, "elliptic": true, "eth-eip712-util-browser": true, + "hash.js": true, "js-sha3": true, "rlp-browser": true, "secp256k1": true, diff --git a/package.json b/package.json index 99824e2e4..fe00c5d76 100644 --- a/package.json +++ b/package.json @@ -150,7 +150,7 @@ "eth-json-rpc-infura": "^5.1.0", "eth-json-rpc-middleware": "^8.0.0", "eth-keyring-controller": "^6.2.0", - "eth-lattice-keyring": "^0.4.0", + "eth-lattice-keyring": "^0.5.0", "eth-method-registry": "^2.0.0", "eth-query": "^2.1.2", "eth-rpc-errors": "^4.0.2", diff --git a/yarn.lock b/yarn.lock index 561e6bf79..a78c3288e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11084,16 +11084,16 @@ eth-keyring-controller@^6.2.0, eth-keyring-controller@^6.2.1: loglevel "^1.5.0" obs-store "^4.0.3" -eth-lattice-keyring@^0.4.0: - version "0.4.9" - resolved "https://registry.yarnpkg.com/eth-lattice-keyring/-/eth-lattice-keyring-0.4.9.tgz#327a41fa25ef28dfc9fe87f2ce11e95139adfd67" - integrity sha512-ZflOgYrbuGJGPSDWgDA6PndCIlYRS2M+/bxKsJupbPgz/O8XwQdTGttszp0mHwOqPdvUULUmW08QCqd8trnuVg== +eth-lattice-keyring@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/eth-lattice-keyring/-/eth-lattice-keyring-0.5.0.tgz#19dbbc2de31008dfd576531fa44a5d34061e61c8" + integrity sha512-+6iTQqrAqneUDfLR5aLVmYtys++a8C5N6F/9ibEtGT3YNYUE0NLZMI/DvFz/JhjpHhTjSXXtSb3yUajW6liAaQ== dependencies: "@ethereumjs/common" "^2.4.0" "@ethereumjs/tx" "^3.1.1" bignumber.js "^9.0.1" ethereumjs-util "^7.0.10" - gridplus-sdk "^0.9.7" + gridplus-sdk "^1.0.0" eth-lib@0.2.8: version "0.2.8" @@ -11405,10 +11405,10 @@ ethers@^4.0.20, ethers@^4.0.28: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@^5.0.8, ethers@^5.4.0, ethers@^5.4.1, ethers@^5.4.5: - version "5.5.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.1.tgz#d3259a95a42557844aa543906c537106c0406fbf" - integrity sha512-RodEvUFZI+EmFcE6bwkuJqpCYHazdzeR1nMzg+YWQSmQEsNtfl1KHGfp/FWZYl48bI/g7cgBeP2IlPthjiVngw== +ethers@^5.0.8, ethers@^5.4.0, ethers@^5.4.1, ethers@^5.4.5, ethers@^5.5.1: + version "5.5.4" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.4.tgz#e1155b73376a2f5da448e4a33351b57a885f4352" + integrity sha512-N9IAXsF8iKhgHIC6pquzRgPBJEzc9auw3JoRkaKe+y4Wl/LFBtDDunNe7YmdomontECAcC5APaAgWZBiu1kirw== dependencies: "@ethersproject/abi" "5.5.0" "@ethersproject/abstract-provider" "5.5.1" @@ -13456,10 +13456,22 @@ graphql-request@^1.8.2: dependencies: cross-fetch "2.2.2" -gridplus-sdk@^0.9.7: - version "0.9.10" - resolved "https://registry.yarnpkg.com/gridplus-sdk/-/gridplus-sdk-0.9.10.tgz#8835e8bc9a2ca7ae163520ddcc0b313350e67dd2" - integrity sha512-CNvhyaz3F8UvlHqihFJlOt+FenmFkb2dFrbBTyRth/nlzD8Tm0HjW+uyY1W0ekDp45Exz9l0VY0EmdvjphBe1w== +graphql-subscriptions@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-1.2.1.tgz#2142b2d729661ddf967b7388f7cf1dd4cf2e061d" + integrity sha512-95yD/tKi24q8xYa7Q9rhQN16AYj5wPbrb8tmHGM3WRc9EBmWrG/0kkMl+tQG8wcEuE9ibR4zyOM31p5Sdr2v4g== + dependencies: + iterall "^1.3.0" + +"graphql@^14.0.2 || ^15.5": + version "15.8.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" + integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== + +gridplus-sdk@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gridplus-sdk/-/gridplus-sdk-1.0.0.tgz#008a24a8ec5b50a6fdb8005723a77f5d24fc88cd" + integrity sha512-vVyLyAY7Ockkf8hv+em1KkjPwvKkLmb7mYZFY2Vtt60+qpmPut1S2/WjrZGdNGGawWAKAmpw8WKdw5MSg2UkpA== dependencies: aes-js "^3.1.1" bech32 "^2.0.0" @@ -13471,6 +13483,7 @@ gridplus-sdk@^0.9.7: crc-32 "^1.2.0" elliptic "6.5.4" eth-eip712-util-browser "^0.0.3" + hash.js "^1.1.7" js-sha3 "^0.8.0" rlp-browser "^1.0.1" secp256k1 "4.0.2" From c3feabf4de3c978ecb25b5a960cbd2c919d9f20c Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 30 Jul 2021 19:07:40 -0230 Subject: [PATCH 3/9] Update SRP representation An array of integers is now used to represent the SRP in three cases: * In the import wallet flow, the UI uses it to pass the user-provided SRP to the background (which converts the array to a buffer). * In the create wallet flow, the UI uses it to retrieve the generated SRP from the background. * When persisting the wallet to state, the background uses it to serialize the SRP. Co-authored-by: Elliot Winkler --- app/scripts/lib/seed-phrase-verifier.js | 8 +- app/scripts/metamask-controller.js | 18 ++-- lavamoat/browserify/beta/policy.json | 5 ++ lavamoat/browserify/flask/policy.json | 5 ++ lavamoat/browserify/main/policy.json | 5 ++ patches/bip39+2.5.0.patch | 99 ++++++++++++++++++++++ patches/eth-hd-keyring+3.6.0.patch | 43 ++++++++++ patches/eth-keyring-controller+6.2.1.patch | 37 ++++++++ ui/store/actions.js | 65 ++++++++------ ui/store/actions.test.js | 12 ++- 10 files changed, 255 insertions(+), 42 deletions(-) create mode 100644 patches/bip39+2.5.0.patch create mode 100644 patches/eth-hd-keyring+3.6.0.patch create mode 100644 patches/eth-keyring-controller+6.2.1.patch diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index 225a57896..e1c18c1eb 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -11,10 +11,10 @@ const seedPhraseVerifier = { * - The keyring always creates the accounts in the same sequence. * * @param {Array} createdAccounts - The accounts to restore - * @param {string} seedWords - The seed words to verify - * @returns {Promise} Promises undefined + * @param {Buffer} seedPhrase - The seed words to verify, encoded as a Buffer + * @returns {Promise} */ - async verifyAccounts(createdAccounts, seedWords) { + async verifyAccounts(createdAccounts, seedPhrase) { if (!createdAccounts || createdAccounts.length < 1) { throw new Error('No created accounts defined.'); } @@ -22,7 +22,7 @@ const seedPhraseVerifier = { const keyringController = new KeyringController({}); const Keyring = keyringController.getKeyringClassForType('HD Key Tree'); const opts = { - mnemonic: seedWords, + mnemonic: seedPhrase, numberOfAccounts: createdAccounts.length, }; diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c378114a1..30a2bdc0b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1792,13 +1792,16 @@ export default class MetamaskController extends EventEmitter { * Create a new Vault and restore an existent keyring. * * @param {string} password - * @param {string} seed + * @param {number[]} encodedSeedPhrase - The seed phrase, encoded as an array + * of UTF-8 bytes. */ - async createNewVaultAndRestore(password, seed) { + async createNewVaultAndRestore(password, encodedSeedPhrase) { const releaseLock = await this.createVaultMutex.acquire(); try { let accounts, lastBalance; + const seedPhraseAsBuffer = Buffer.from(encodedSeedPhrase); + const { keyringController } = this; // clear known identities @@ -1819,7 +1822,7 @@ export default class MetamaskController extends EventEmitter { // create new vault const vault = await keyringController.createNewVaultAndRestore( password, - seed, + seedPhraseAsBuffer, ); const ethQuery = new EthQuery(this.provider); @@ -2279,7 +2282,8 @@ export default class MetamaskController extends EventEmitter { * * Called when the first account is created and on unlocking the vault. * - * @returns {Promise} Seed phrase to be confirmed by the user. + * @returns {Promise} The seed phrase to be confirmed by the user, + * encoded as an array of UTF-8 bytes. */ async verifySeedPhrase() { const primaryKeyring = this.keyringController.getKeyringsByType( @@ -2290,7 +2294,7 @@ export default class MetamaskController extends EventEmitter { } const serialized = await primaryKeyring.serialize(); - const seedWords = serialized.mnemonic; + const seedPhraseAsBuffer = Buffer.from(serialized.mnemonic); const accounts = await primaryKeyring.getAccounts(); if (accounts.length < 1) { @@ -2298,8 +2302,8 @@ export default class MetamaskController extends EventEmitter { } try { - await seedPhraseVerifier.verifyAccounts(accounts, seedWords); - return seedWords; + await seedPhraseVerifier.verifyAccounts(accounts, seedPhraseAsBuffer); + return Array.from(seedPhraseAsBuffer.values()); } catch (err) { log.error(err.message); throw err; diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index bb6798360..e4d29eb88 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -1175,6 +1175,9 @@ } }, "bip39": { + "globals": { + "console.log": true + }, "packages": { "buffer": true, "create-hash": true, @@ -1889,6 +1892,7 @@ "eth-hd-keyring": { "packages": { "bip39": true, + "buffer": true, "eth-sig-util": true, "eth-simple-keyring": true, "ethereumjs-wallet": true @@ -1947,6 +1951,7 @@ "packages": { "bip39": true, "browser-passworder": true, + "buffer": true, "eth-hd-keyring": true, "eth-sig-util": true, "eth-simple-keyring": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index d3c537308..72fa6de24 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -1194,6 +1194,9 @@ } }, "bip39": { + "globals": { + "console.log": true + }, "packages": { "buffer": true, "create-hash": true, @@ -1908,6 +1911,7 @@ "eth-hd-keyring": { "packages": { "bip39": true, + "buffer": true, "eth-sig-util": true, "eth-simple-keyring": true, "ethereumjs-wallet": true @@ -1966,6 +1970,7 @@ "packages": { "bip39": true, "browser-passworder": true, + "buffer": true, "eth-hd-keyring": true, "eth-sig-util": true, "eth-simple-keyring": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index bb6798360..e4d29eb88 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -1175,6 +1175,9 @@ } }, "bip39": { + "globals": { + "console.log": true + }, "packages": { "buffer": true, "create-hash": true, @@ -1889,6 +1892,7 @@ "eth-hd-keyring": { "packages": { "bip39": true, + "buffer": true, "eth-sig-util": true, "eth-simple-keyring": true, "ethereumjs-wallet": true @@ -1947,6 +1951,7 @@ "packages": { "bip39": true, "browser-passworder": true, + "buffer": true, "eth-hd-keyring": true, "eth-sig-util": true, "eth-simple-keyring": true, diff --git a/patches/bip39+2.5.0.patch b/patches/bip39+2.5.0.patch new file mode 100644 index 000000000..2976f3bb2 --- /dev/null +++ b/patches/bip39+2.5.0.patch @@ -0,0 +1,99 @@ +diff --git a/node_modules/bip39/index.js b/node_modules/bip39/index.js +index aa0f29f..bee8008 100644 +--- a/node_modules/bip39/index.js ++++ b/node_modules/bip39/index.js +@@ -48,7 +48,9 @@ function salt (password) { + } + + function mnemonicToSeed (mnemonic, password) { +- var mnemonicBuffer = Buffer.from(unorm.nfkd(mnemonic), 'utf8') ++ var mnemonicBuffer = typeof mnemonic === 'string' ++ ? Buffer.from(unorm.nfkd(mnemonic), 'utf8') ++ : mnemonic + var saltBuffer = Buffer.from(salt(unorm.nfkd(password)), 'utf8') + + return pbkdf2(mnemonicBuffer, saltBuffer, 2048, 64, 'sha512') +@@ -61,12 +63,28 @@ function mnemonicToSeedHex (mnemonic, password) { + function mnemonicToEntropy (mnemonic, wordlist) { + wordlist = wordlist || DEFAULT_WORDLIST + +- var words = unorm.nfkd(mnemonic).split(' ') ++ var mnemonicAsBuffer = typeof mnemonic === 'string' ++ ? Buffer.from(unorm.nfkd(mnemonic), 'utf8') ++ : mnemonic ++ ++ var words = []; ++ var currentWord = []; ++ for (const byte of mnemonicAsBuffer.values()) { ++ // split at space or \u3000 (ideographic space, for Japanese wordlists) ++ if (byte === 0x20 || byte === 0x3000) { ++ words.push(Buffer.from(currentWord)); ++ currentWord = []; ++ } else { ++ currentWord.push(byte); ++ } ++ } ++ words.push(Buffer.from(currentWord)); ++ + if (words.length % 3 !== 0) throw new Error(INVALID_MNEMONIC) + + // convert word indices to 11 bit binary strings + var bits = words.map(function (word) { +- var index = wordlist.indexOf(word) ++ var index = wordlist.indexOf(word.toString('utf8')) + if (index === -1) throw new Error(INVALID_MNEMONIC) + + return lpad(index.toString(2), '0', 11) +@@ -104,12 +122,41 @@ function entropyToMnemonic (entropy, wordlist) { + + var bits = entropyBits + checksumBits + var chunks = bits.match(/(.{1,11})/g) +- var words = chunks.map(function (binary) { ++ var wordsAsBuffers = chunks.map(function (binary) { + var index = binaryToByte(binary) +- return wordlist[index] ++ return Buffer.from(wordlist[index], 'utf8') + }) + +- return wordlist === JAPANESE_WORDLIST ? words.join('\u3000') : words.join(' ') ++ var bufferSize = wordsAsBuffers.reduce(function (bufferSize, wordAsBuffer, i) { ++ var shouldAddSeparator = i < wordsAsBuffers.length - 1 ++ return ( ++ bufferSize + ++ wordAsBuffer.length + ++ (shouldAddSeparator ? 1 : 0) ++ ) ++ }, 0) ++ var separator = wordlist === JAPANESE_WORDLIST ? '\u3000' : ' ' ++ var result = wordsAsBuffers.reduce(function (result, wordAsBuffer, i) { ++ var shouldAddSeparator = i < wordsAsBuffers.length - 1 ++ result.workingBuffer.set(wordAsBuffer, result.offset) ++ if (shouldAddSeparator) { ++ result.workingBuffer.write( ++ separator, ++ result.offset + wordAsBuffer.length, ++ separator.length, ++ 'utf8' ++ ) ++ } ++ return { ++ workingBuffer: result.workingBuffer, ++ offset: ( ++ result.offset + ++ wordAsBuffer.length + ++ (shouldAddSeparator ? 1 : 0) ++ ) ++ } ++ }, { workingBuffer: Buffer.alloc(bufferSize), offset: 0 }) ++ return result.workingBuffer; + } + + function generateMnemonic (strength, rng, wordlist) { +@@ -124,6 +171,7 @@ function validateMnemonic (mnemonic, wordlist) { + try { + mnemonicToEntropy(mnemonic, wordlist) + } catch (e) { ++ console.log('could not validate mnemonic', e) + return false + } + diff --git a/patches/eth-hd-keyring+3.6.0.patch b/patches/eth-hd-keyring+3.6.0.patch new file mode 100644 index 000000000..211cb89dd --- /dev/null +++ b/patches/eth-hd-keyring+3.6.0.patch @@ -0,0 +1,43 @@ +diff --git a/node_modules/eth-hd-keyring/index.js b/node_modules/eth-hd-keyring/index.js +index 19d1d7f..350d6b8 100644 +--- a/node_modules/eth-hd-keyring/index.js ++++ b/node_modules/eth-hd-keyring/index.js +@@ -17,8 +17,11 @@ class HdKeyring extends SimpleKeyring { + } + + serialize () { ++ const mnemonicAsBuffer = typeof this.mnemonic === 'string' ++ ? Buffer.from(this.mnemonic, 'utf8') ++ : this.mnemonic + return Promise.resolve({ +- mnemonic: this.mnemonic, ++ mnemonic: Array.from(mnemonicAsBuffer.values()), + numberOfAccounts: this.wallets.length, + hdPath: this.hdPath, + }) +@@ -69,9 +72,22 @@ class HdKeyring extends SimpleKeyring { + + /* PRIVATE METHODS */ + +- _initFromMnemonic (mnemonic) { +- this.mnemonic = mnemonic +- const seed = bip39.mnemonicToSeed(mnemonic) ++ /** ++ * Sets appropriate properties for the keyring based on the given ++ * BIP39-compliant mnemonic. ++ * ++ * @param {string|Array|Buffer} mnemonic - A seed phrase represented ++ * as a string, an array of UTF-8 bytes, or a Buffer. ++ */ ++ _initFromMnemonic(mnemonic) { ++ if (typeof mnemonic === 'string') { ++ this.mnemonic = Buffer.from(mnemonic, 'utf8') ++ } else if (Array.isArray(mnemonic)) { ++ this.mnemonic = Buffer.from(mnemonic) ++ } else { ++ this.mnemonic = mnemonic ++ } ++ const seed = bip39.mnemonicToSeed(this.mnemonic) + this.hdWallet = hdkey.fromMasterSeed(seed) + this.root = this.hdWallet.derivePath(this.hdPath) + } diff --git a/patches/eth-keyring-controller+6.2.1.patch b/patches/eth-keyring-controller+6.2.1.patch new file mode 100644 index 000000000..aec0c7168 --- /dev/null +++ b/patches/eth-keyring-controller+6.2.1.patch @@ -0,0 +1,37 @@ +diff --git a/node_modules/eth-keyring-controller/index.js b/node_modules/eth-keyring-controller/index.js +index 250ab98..38615aa 100644 +--- a/node_modules/eth-keyring-controller/index.js ++++ b/node_modules/eth-keyring-controller/index.js +@@ -84,15 +84,20 @@ class KeyringController extends EventEmitter { + * + * @emits KeyringController#unlock + * @param {string} password - The password to encrypt the vault with +- * @param {string} seed - The BIP44-compliant seed phrase. ++ * @param {string|Array} seedPhrase - The BIP39-compliant seed phrase, ++ * either as a string or an array of UTF-8 bytes that represent the string. + * @returns {Promise} A Promise that resolves to the state. + */ +- createNewVaultAndRestore (password, seed) { ++ createNewVaultAndRestore(password, seedPhrase) { ++ const seedPhraseAsBuffer = typeof seedPhrase === 'string' ++ ? Buffer.from(seedPhrase, 'utf8') ++ : Buffer.from(seedPhrase) ++ + if (typeof password !== 'string') { + return Promise.reject(new Error('Password must be text.')) + } + +- if (!bip39.validateMnemonic(seed)) { ++ if (!bip39.validateMnemonic(seedPhraseAsBuffer)) { + return Promise.reject(new Error('Seed phrase is invalid.')) + } + +@@ -101,7 +106,7 @@ class KeyringController extends EventEmitter { + return this.persistAllKeyrings(password) + .then(() => { + return this.addNewKeyring('HD Key Tree', { +- mnemonic: seed, ++ mnemonic: seedPhraseAsBuffer, + numberOfAccounts: 1, + }) + }) diff --git a/ui/store/actions.js b/ui/store/actions.js index 7842b4b5d..71e0bf750 100644 --- a/ui/store/actions.js +++ b/ui/store/actions.js @@ -82,20 +82,39 @@ export function tryUnlockMetamask(password) { }; } -export function createNewVaultAndRestore(password, seed) { +/** + * Adds a new account where all data is encrypted using the given password and + * where all addresses are generated from a given seed phrase. + * + * @param {string} password - The password. + * @param {string} seedPhrase - The seed phrase. + * @returns {Object} The updated state of the keyring controller. + */ +export function createNewVaultAndRestore(password, seedPhrase) { return (dispatch) => { dispatch(showLoadingIndication()); log.debug(`background.createNewVaultAndRestore`); + + // Encode the secret recovery phrase as an array of integers so that it is + // serialized as JSON properly. + const encodedSeedPhrase = Array.from( + Buffer.from(seedPhrase, 'utf8').values(), + ); + let vault; return new Promise((resolve, reject) => { - background.createNewVaultAndRestore(password, seed, (err, _vault) => { - if (err) { - reject(err); - return; - } - vault = _vault; - resolve(); - }); + background.createNewVaultAndRestore( + password, + encodedSeedPhrase, + (err, _vault) => { + if (err) { + reject(err); + return; + } + vault = _vault; + resolve(); + }, + ); }) .then(() => dispatch(unMarkPasswordForgotten())) .then(() => { @@ -117,8 +136,8 @@ export function createNewVaultAndGetSeedPhrase(password) { try { await createNewVault(password); - const seedWords = await verifySeedPhrase(); - return seedWords; + const seedPhrase = await verifySeedPhrase(); + return seedPhrase; } catch (error) { dispatch(displayWarning(error.message)); throw new Error(error.message); @@ -134,9 +153,9 @@ export function unlockAndGetSeedPhrase(password) { try { await submitPassword(password); - const seedWords = await verifySeedPhrase(); + const seedPhrase = await verifySeedPhrase(); await forceUpdateMetamaskState(dispatch); - return seedWords; + return seedPhrase; } catch (error) { dispatch(displayWarning(error.message)); throw new Error(error.message); @@ -185,17 +204,9 @@ export function verifyPassword(password) { }); } -export function verifySeedPhrase() { - return new Promise((resolve, reject) => { - background.verifySeedPhrase((error, seedWords) => { - if (error) { - reject(error); - return; - } - - resolve(seedWords); - }); - }); +export async function verifySeedPhrase() { + const encodedSeedPhrase = await promisifiedBackground.verifySeedPhrase(); + return Buffer.from(encodedSeedPhrase).toString('utf8'); } export function requestRevealSeedWords(password) { @@ -205,11 +216,11 @@ export function requestRevealSeedWords(password) { try { await verifyPassword(password); - const seedWords = await verifySeedPhrase(); - return seedWords; + const seedPhrase = await verifySeedPhrase(); + return seedPhrase; } catch (error) { dispatch(displayWarning(error.message)); - throw new Error(error.message); + throw error; } finally { dispatch(hideLoadingIndication()); } diff --git a/ui/store/actions.test.js b/ui/store/actions.test.js index 0866713b4..727835ecf 100644 --- a/ui/store/actions.test.js +++ b/ui/store/actions.test.js @@ -111,7 +111,9 @@ describe('Actions', () => { actions._setBackgroundConnection(background); - await store.dispatch(actions.createNewVaultAndRestore()); + await store.dispatch( + actions.createNewVaultAndRestore('password', 'test'), + ); expect(createNewVaultAndRestore.callCount).toStrictEqual(1); }); @@ -134,7 +136,9 @@ describe('Actions', () => { { type: 'HIDE_LOADING_INDICATION' }, ]; - await store.dispatch(actions.createNewVaultAndRestore()); + await store.dispatch( + actions.createNewVaultAndRestore('password', 'test'), + ); expect(store.getActions()).toStrictEqual(expectedActions); }); @@ -155,7 +159,7 @@ describe('Actions', () => { ]; await expect( - store.dispatch(actions.createNewVaultAndRestore()), + store.dispatch(actions.createNewVaultAndRestore('password', 'test')), ).rejects.toThrow('error'); expect(store.getActions()).toStrictEqual(expectedActions); @@ -174,7 +178,7 @@ describe('Actions', () => { cb(), ); const verifySeedPhrase = background.verifySeedPhrase.callsFake((cb) => - cb(), + cb(null, Array.from(Buffer.from('test').values())), ); actions._setBackgroundConnection(background); From 3f0fa89d8de5c347f83debfcbb75925c024107a2 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Tue, 22 Feb 2022 12:59:13 -0500 Subject: [PATCH 4/9] Deleting transactions from currentNetworkTxnList based on unique address along with nonce and chainId (#13669) --- app/scripts/controllers/transactions/tx-state-manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 879aac56c..d59b5a058 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -249,9 +249,9 @@ export default class TransactionStateManager extends EventEmitter { const txsToDelete = transactions .reverse() .filter((tx) => { - const { nonce } = tx.txParams; + const { nonce, from } = tx.txParams; const { chainId, metamaskNetworkId, status } = tx; - const key = `${nonce}-${chainId ?? metamaskNetworkId}`; + const key = `${nonce}-${chainId ?? metamaskNetworkId}-${from}`; if (nonceNetworkSet.has(key)) { return false; } else if ( From 8c9efb2a1fe5d20abc2ad9a5e940face2c2cc6cc Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Thu, 24 Feb 2022 11:51:33 -0500 Subject: [PATCH 5/9] Increase the txHistoryLimit in the transaction controller to 60 (#13743) --- app/scripts/metamask-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 30a2bdc0b..a9f549bed 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -671,7 +671,7 @@ export default class MetamaskController extends EventEmitter { this.networkController, ), preferencesStore: this.preferencesController.store, - txHistoryLimit: 40, + txHistoryLimit: 60, signTransaction: this.keyringController.signTransaction.bind( this.keyringController, ), From e7bf63a6d6260552f50968815a55e30bd504f8fb Mon Sep 17 00:00:00 2001 From: Olusegun Akintayo Date: Mon, 7 Mar 2022 19:09:03 +0400 Subject: [PATCH 6/9] Fixes an issue where metamask popup is not loading on eth_accounts (#13840) (first time). Signed-off-by: Akintayo A. Olusegun --- .../lib/rpc-method-middleware/handlers/request-accounts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js b/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js index d9cb68f4b..5e071e9a2 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js @@ -72,7 +72,7 @@ async function requestEthereumAccountsHandler( // lock state when they were received. try { locks.add(origin); - await getUnlockPromise(); + await getUnlockPromise(true); res.result = await getAccounts(); end(); } catch (error) { From b879bf135979c45626f7a3e972eb87b3f945c524 Mon Sep 17 00:00:00 2001 From: Daniel <80175477+dan437@users.noreply.github.com> Date: Thu, 10 Mar 2022 04:17:57 +0100 Subject: [PATCH 7/9] Set up the right gasLimit for STX (#13891) * Set up the right gasLimit for STX * Trigger Build Co-authored-by: Dan J Miller --- ui/ducks/swaps/swaps.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/ducks/swaps/swaps.js b/ui/ducks/swaps/swaps.js index 84d26b2a2..02d442951 100644 --- a/ui/ducks/swaps/swaps.js +++ b/ui/ducks/swaps/swaps.js @@ -915,6 +915,9 @@ export const signAndSendSwapsSmartTransaction = ({ const smartTransactionFees = await dispatch( fetchSwapsSmartTransactionFees(unsignedTransaction), ); + unsignedTransaction.gas = `0x${decimalToHex( + smartTransactionFees?.gasLimit || 0, + )}`; const uuid = await dispatch( signAndSendSmartTransaction({ unsignedTransaction, From 7931e607cbad1ee7451f2309036459fe6f2161d9 Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Thu, 10 Mar 2022 00:00:16 -0330 Subject: [PATCH 8/9] Update changelog for v10.11.1 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64f6c27b4..e8665d9f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ## [10.11.1] +### Changed +- Fixes GridPlus Lattice bugs by upgrading to `gridplus-sdk` v1.0.0, `eth-lattice-keyring` v0.5.0 and to compatibility with v0.14.0 ([#13834](https://github.com/MetaMask/metamask-extension/pull/13834)) +- Increases transaction data in state logs + - Preserves fewer transactions with shared nonces across networks, decreasing number of old transactions that are not deleted ([#13669](https://github.com/MetaMask/metamask-extension/pull/13669)) + - Increase the number of transactions saved in state logs to 60 ([#13743](https://github.com/MetaMask/metamask-extension/pull/13743)) + +### Fixed +- Ensure that MetaMask popup is shown when a user attempts to connect to a dapp they are already connected to ([#13840](https://github.com/MetaMask/metamask-extension/pull/13840)) +- Submit correct gas limit for Swaps Smart Transactions ([#13891](https://github.com/MetaMask/metamask-extension/pull/13891)) ## [10.11.0] ### Added From 0361aa6a9381c943d656fc042fcfb592c0cb51ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ogle?= Date: Thu, 10 Mar 2022 23:42:35 +0200 Subject: [PATCH 9/9] Use pre-wrap instead of pre for signature content (#13828) --- ui/components/app/signature-request-original/index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/components/app/signature-request-original/index.scss b/ui/components/app/signature-request-original/index.scss index e0e650b74..da6d3512e 100644 --- a/ui/components/app/signature-request-original/index.scss +++ b/ui/components/app/signature-request-original/index.scss @@ -222,7 +222,7 @@ overflow-wrap: break-word; border-bottom: 1px solid #d2d8dd; padding: 6px 18px 15px; - white-space: pre; + white-space: pre-wrap; } &__help-link {