From dd3766242dcdfd334f79367793d2b27bfcc36eb6 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 19:52:27 -0700 Subject: Adjust dimensions of popup.html and app bar to match --- app/notification.html | 2 +- app/popup.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/notification.html b/app/notification.html index cc485da7f..be38f4aa3 100644 --- a/app/notification.html +++ b/app/notification.html @@ -9,7 +9,7 @@ } - +
diff --git a/app/popup.html b/app/popup.html index d09b09315..471468b13 100644 --- a/app/popup.html +++ b/app/popup.html @@ -5,7 +5,7 @@ MetaMask Plugin - +
-- cgit From 7ea38523ea8231fa75916f48803abb0eb593f9a2 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Sun, 30 Jul 2017 19:56:11 -0700 Subject: Set font-size on body of popup.html, for responsiveness --- app/popup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/popup.html b/app/popup.html index 471468b13..a742686c5 100644 --- a/app/popup.html +++ b/app/popup.html @@ -5,7 +5,7 @@ MetaMask Plugin - +
-- cgit From 3797b9921fc227c1bcf9681cffa73588cc7afb44 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 20:22:15 -0700 Subject: Adjust popup size to 545x450; refactor wallet view to fit --- app/popup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/popup.html b/app/popup.html index a742686c5..de0e100a5 100644 --- a/app/popup.html +++ b/app/popup.html @@ -5,7 +5,7 @@ MetaMask Plugin - +
-- cgit From fce6041dbeb3384badef50467912ab47e51053ff Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 20:44:32 -0700 Subject: Add new fonts from @cjeria: DIN Next and DIN OT --- app/fonts/DIN Next/DIN Next W01 Bold.otf | Bin 0 -> 106032 bytes app/fonts/DIN Next/DIN Next W01 Regular.otf | Bin 0 -> 106580 bytes app/fonts/DIN Next/DIN Next W10 Black.otf | Bin 0 -> 105972 bytes app/fonts/DIN Next/DIN Next W10 Italic.otf | Bin 0 -> 115984 bytes app/fonts/DIN Next/DIN Next W10 Light.otf | Bin 0 -> 108672 bytes app/fonts/DIN Next/DIN Next W10 Medium.otf | Bin 0 -> 105684 bytes app/fonts/DIN_OT/DINOT-2.otf | Bin 0 -> 44144 bytes app/fonts/DIN_OT/DINOT-Bold 2.otf | Bin 0 -> 45564 bytes app/fonts/DIN_OT/DINOT-BoldItalic.otf | Bin 0 -> 49684 bytes app/fonts/DIN_OT/DINOT-Italic 2.otf | Bin 0 -> 47956 bytes app/fonts/DIN_OT/DINOT-Medium 2.otf | Bin 0 -> 44652 bytes app/fonts/DIN_OT/DINOT-MediumItalic 2.otf | Bin 0 -> 47732 bytes 12 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/fonts/DIN Next/DIN Next W01 Bold.otf create mode 100644 app/fonts/DIN Next/DIN Next W01 Regular.otf create mode 100644 app/fonts/DIN Next/DIN Next W10 Black.otf create mode 100644 app/fonts/DIN Next/DIN Next W10 Italic.otf create mode 100644 app/fonts/DIN Next/DIN Next W10 Light.otf create mode 100644 app/fonts/DIN Next/DIN Next W10 Medium.otf create mode 100644 app/fonts/DIN_OT/DINOT-2.otf create mode 100644 app/fonts/DIN_OT/DINOT-Bold 2.otf create mode 100644 app/fonts/DIN_OT/DINOT-BoldItalic.otf create mode 100644 app/fonts/DIN_OT/DINOT-Italic 2.otf create mode 100644 app/fonts/DIN_OT/DINOT-Medium 2.otf create mode 100644 app/fonts/DIN_OT/DINOT-MediumItalic 2.otf (limited to 'app') diff --git a/app/fonts/DIN Next/DIN Next W01 Bold.otf b/app/fonts/DIN Next/DIN Next W01 Bold.otf new file mode 100644 index 000000000..2b78d1ff4 Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W01 Bold.otf differ diff --git a/app/fonts/DIN Next/DIN Next W01 Regular.otf b/app/fonts/DIN Next/DIN Next W01 Regular.otf new file mode 100644 index 000000000..09f6ee297 Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W01 Regular.otf differ diff --git a/app/fonts/DIN Next/DIN Next W10 Black.otf b/app/fonts/DIN Next/DIN Next W10 Black.otf new file mode 100644 index 000000000..08eb73373 Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W10 Black.otf differ diff --git a/app/fonts/DIN Next/DIN Next W10 Italic.otf b/app/fonts/DIN Next/DIN Next W10 Italic.otf new file mode 100644 index 000000000..73f2b9e8c Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W10 Italic.otf differ diff --git a/app/fonts/DIN Next/DIN Next W10 Light.otf b/app/fonts/DIN Next/DIN Next W10 Light.otf new file mode 100644 index 000000000..700450e49 Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W10 Light.otf differ diff --git a/app/fonts/DIN Next/DIN Next W10 Medium.otf b/app/fonts/DIN Next/DIN Next W10 Medium.otf new file mode 100644 index 000000000..b73f2e43f Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W10 Medium.otf differ diff --git a/app/fonts/DIN_OT/DINOT-2.otf b/app/fonts/DIN_OT/DINOT-2.otf new file mode 100644 index 000000000..4a5e13127 Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-2.otf differ diff --git a/app/fonts/DIN_OT/DINOT-Bold 2.otf b/app/fonts/DIN_OT/DINOT-Bold 2.otf new file mode 100644 index 000000000..6ed5b6c3d Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-Bold 2.otf differ diff --git a/app/fonts/DIN_OT/DINOT-BoldItalic.otf b/app/fonts/DIN_OT/DINOT-BoldItalic.otf new file mode 100644 index 000000000..148c90588 Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-BoldItalic.otf differ diff --git a/app/fonts/DIN_OT/DINOT-Italic 2.otf b/app/fonts/DIN_OT/DINOT-Italic 2.otf new file mode 100644 index 000000000..e365e77ab Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-Italic 2.otf differ diff --git a/app/fonts/DIN_OT/DINOT-Medium 2.otf b/app/fonts/DIN_OT/DINOT-Medium 2.otf new file mode 100644 index 000000000..a87a2df37 Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-Medium 2.otf differ diff --git a/app/fonts/DIN_OT/DINOT-MediumItalic 2.otf b/app/fonts/DIN_OT/DINOT-MediumItalic 2.otf new file mode 100644 index 000000000..14eddfc76 Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-MediumItalic 2.otf differ -- cgit From 9cc461a6c2348ffd1a884e0ca92d74294cce6b4e Mon Sep 17 00:00:00 2001 From: sdtsui Date: Mon, 31 Jul 2017 23:07:25 -0700 Subject: Reset popup to 350x500, old form factor as advised by @Zanibas --- app/popup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/popup.html b/app/popup.html index de0e100a5..fddf01841 100644 --- a/app/popup.html +++ b/app/popup.html @@ -5,7 +5,7 @@ MetaMask Plugin - +
-- cgit From 46da924d485cf10be2965f4126609aa55707bfb5 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 18:24:30 -0700 Subject: Add Ethereum Logo --- app/images/eth_logo.svg | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 app/images/eth_logo.svg (limited to 'app') diff --git a/app/images/eth_logo.svg b/app/images/eth_logo.svg new file mode 100644 index 000000000..894bd70dd --- /dev/null +++ b/app/images/eth_logo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file -- cgit From 61b4b1f947230a8d5157fab27ee8ec82e0826e02 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 19:13:17 -0700 Subject: Ensure app-header is rendered in responsive layout --- app/scripts/lib/is-popup-or-notification.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/is-popup-or-notification.js b/app/scripts/lib/is-popup-or-notification.js index 693fa8751..73a812d5f 100644 --- a/app/scripts/lib/is-popup-or-notification.js +++ b/app/scripts/lib/is-popup-or-notification.js @@ -1,6 +1,6 @@ module.exports = function isPopupOrNotification () { const url = window.location.href - if (url.match(/popup.html$/)) { + if (url.match(/popup.html$/) || url.match(/home.html$/)) { return 'popup' } else { return 'notification' -- cgit From dd4586ee84ea0e6a74ad4cd6b6f058169ddd9129 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Wed, 2 Aug 2017 19:26:46 -0700 Subject: Adjust sidebar transition using @cjeria\'s feedback --- app/scripts/lib/environment-type.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 app/scripts/lib/environment-type.js (limited to 'app') diff --git a/app/scripts/lib/environment-type.js b/app/scripts/lib/environment-type.js new file mode 100644 index 000000000..7966926eb --- /dev/null +++ b/app/scripts/lib/environment-type.js @@ -0,0 +1,10 @@ +module.exports = function environmentType () { + const url = window.location.href + if (url.match(/popup.html$/)) { + return 'popup' + } else if (url.match(/home.html$/)) { + return 'responsive' + } else { + return 'notification' + } +} -- cgit From f7f9f87ef7850ae94595a5366d269d169139c127 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Fri, 4 Aug 2017 10:11:18 -0700 Subject: Add Roboto without hooking it up via import --- app/fonts/Roboto/Roboto-Black.ttf | Bin 0 -> 142472 bytes app/fonts/Roboto/Roboto-BlackItalic.ttf | Bin 0 -> 149644 bytes app/fonts/Roboto/Roboto-Bold.ttf | Bin 0 -> 135820 bytes app/fonts/Roboto/Roboto-BoldItalic.ttf | Bin 0 -> 144700 bytes app/fonts/Roboto/Roboto-Italic.ttf | Bin 0 -> 148540 bytes app/fonts/Roboto/Roboto-Light.ttf | Bin 0 -> 140276 bytes app/fonts/Roboto/Roboto-LightItalic.ttf | Bin 0 -> 145932 bytes app/fonts/Roboto/Roboto-Medium.ttf | Bin 0 -> 137308 bytes app/fonts/Roboto/Roboto-MediumItalic.ttf | Bin 0 -> 147876 bytes app/fonts/Roboto/Roboto-Regular.ttf | Bin 0 -> 145348 bytes app/fonts/Roboto/Roboto-Thin.ttf | Bin 0 -> 130044 bytes app/fonts/Roboto/Roboto-ThinItalic.ttf | Bin 0 -> 132376 bytes app/fonts/Roboto/RobotoCondensed-Bold.ttf | Bin 0 -> 141796 bytes app/fonts/Roboto/RobotoCondensed-BoldItalic.ttf | Bin 0 -> 145256 bytes app/fonts/Roboto/RobotoCondensed-Italic.ttf | Bin 0 -> 144404 bytes app/fonts/Roboto/RobotoCondensed-Light.ttf | Bin 0 -> 141384 bytes app/fonts/Roboto/RobotoCondensed-LightItalic.ttf | Bin 0 -> 145104 bytes app/fonts/Roboto/RobotoCondensed-Regular.ttf | Bin 0 -> 140396 bytes 18 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/fonts/Roboto/Roboto-Black.ttf create mode 100644 app/fonts/Roboto/Roboto-BlackItalic.ttf create mode 100644 app/fonts/Roboto/Roboto-Bold.ttf create mode 100644 app/fonts/Roboto/Roboto-BoldItalic.ttf create mode 100644 app/fonts/Roboto/Roboto-Italic.ttf create mode 100644 app/fonts/Roboto/Roboto-Light.ttf create mode 100644 app/fonts/Roboto/Roboto-LightItalic.ttf create mode 100644 app/fonts/Roboto/Roboto-Medium.ttf create mode 100644 app/fonts/Roboto/Roboto-MediumItalic.ttf create mode 100644 app/fonts/Roboto/Roboto-Regular.ttf create mode 100644 app/fonts/Roboto/Roboto-Thin.ttf create mode 100644 app/fonts/Roboto/Roboto-ThinItalic.ttf create mode 100644 app/fonts/Roboto/RobotoCondensed-Bold.ttf create mode 100644 app/fonts/Roboto/RobotoCondensed-BoldItalic.ttf create mode 100644 app/fonts/Roboto/RobotoCondensed-Italic.ttf create mode 100644 app/fonts/Roboto/RobotoCondensed-Light.ttf create mode 100644 app/fonts/Roboto/RobotoCondensed-LightItalic.ttf create mode 100644 app/fonts/Roboto/RobotoCondensed-Regular.ttf (limited to 'app') diff --git a/app/fonts/Roboto/Roboto-Black.ttf b/app/fonts/Roboto/Roboto-Black.ttf new file mode 100644 index 000000000..71f01ac2b Binary files /dev/null and b/app/fonts/Roboto/Roboto-Black.ttf differ diff --git a/app/fonts/Roboto/Roboto-BlackItalic.ttf b/app/fonts/Roboto/Roboto-BlackItalic.ttf new file mode 100644 index 000000000..ec309c785 Binary files /dev/null and b/app/fonts/Roboto/Roboto-BlackItalic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Bold.ttf b/app/fonts/Roboto/Roboto-Bold.ttf new file mode 100644 index 000000000..aaf374d2c Binary files /dev/null and b/app/fonts/Roboto/Roboto-Bold.ttf differ diff --git a/app/fonts/Roboto/Roboto-BoldItalic.ttf b/app/fonts/Roboto/Roboto-BoldItalic.ttf new file mode 100644 index 000000000..dcd0f8007 Binary files /dev/null and b/app/fonts/Roboto/Roboto-BoldItalic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Italic.ttf b/app/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 000000000..f382c6874 Binary files /dev/null and b/app/fonts/Roboto/Roboto-Italic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Light.ttf b/app/fonts/Roboto/Roboto-Light.ttf new file mode 100644 index 000000000..664e1b2f9 Binary files /dev/null and b/app/fonts/Roboto/Roboto-Light.ttf differ diff --git a/app/fonts/Roboto/Roboto-LightItalic.ttf b/app/fonts/Roboto/Roboto-LightItalic.ttf new file mode 100644 index 000000000..b8f529637 Binary files /dev/null and b/app/fonts/Roboto/Roboto-LightItalic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Medium.ttf b/app/fonts/Roboto/Roboto-Medium.ttf new file mode 100644 index 000000000..aa00de0ef Binary files /dev/null and b/app/fonts/Roboto/Roboto-Medium.ttf differ diff --git a/app/fonts/Roboto/Roboto-MediumItalic.ttf b/app/fonts/Roboto/Roboto-MediumItalic.ttf new file mode 100644 index 000000000..67e25f019 Binary files /dev/null and b/app/fonts/Roboto/Roboto-MediumItalic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Regular.ttf b/app/fonts/Roboto/Roboto-Regular.ttf new file mode 100644 index 000000000..3e6e2e761 Binary files /dev/null and b/app/fonts/Roboto/Roboto-Regular.ttf differ diff --git a/app/fonts/Roboto/Roboto-Thin.ttf b/app/fonts/Roboto/Roboto-Thin.ttf new file mode 100644 index 000000000..d262d1446 Binary files /dev/null and b/app/fonts/Roboto/Roboto-Thin.ttf differ diff --git a/app/fonts/Roboto/Roboto-ThinItalic.ttf b/app/fonts/Roboto/Roboto-ThinItalic.ttf new file mode 100644 index 000000000..63e9f9718 Binary files /dev/null and b/app/fonts/Roboto/Roboto-ThinItalic.ttf differ diff --git a/app/fonts/Roboto/RobotoCondensed-Bold.ttf b/app/fonts/Roboto/RobotoCondensed-Bold.ttf new file mode 100644 index 000000000..48dd63534 Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-Bold.ttf differ diff --git a/app/fonts/Roboto/RobotoCondensed-BoldItalic.ttf b/app/fonts/Roboto/RobotoCondensed-BoldItalic.ttf new file mode 100644 index 000000000..ad728646a Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-BoldItalic.ttf differ diff --git a/app/fonts/Roboto/RobotoCondensed-Italic.ttf b/app/fonts/Roboto/RobotoCondensed-Italic.ttf new file mode 100644 index 000000000..a232513d5 Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-Italic.ttf differ diff --git a/app/fonts/Roboto/RobotoCondensed-Light.ttf b/app/fonts/Roboto/RobotoCondensed-Light.ttf new file mode 100644 index 000000000..a6e368d40 Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-Light.ttf differ diff --git a/app/fonts/Roboto/RobotoCondensed-LightItalic.ttf b/app/fonts/Roboto/RobotoCondensed-LightItalic.ttf new file mode 100644 index 000000000..5b2b6ae08 Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-LightItalic.ttf differ diff --git a/app/fonts/Roboto/RobotoCondensed-Regular.ttf b/app/fonts/Roboto/RobotoCondensed-Regular.ttf new file mode 100644 index 000000000..65bf32a19 Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-Regular.ttf differ -- cgit From 65d27623466527edfa42e29807e658c073eebcc2 Mon Sep 17 00:00:00 2001 From: sdtsui Date: Tue, 22 Aug 2017 12:47:33 -0700 Subject: Add bolt and info icon vector images --- app/images/mm-bolt.svg | 11 +++++++++++ app/images/mm-info-icon.svg | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 app/images/mm-bolt.svg create mode 100644 app/images/mm-info-icon.svg (limited to 'app') diff --git a/app/images/mm-bolt.svg b/app/images/mm-bolt.svg new file mode 100644 index 000000000..bbf0abcc7 --- /dev/null +++ b/app/images/mm-bolt.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/app/images/mm-info-icon.svg b/app/images/mm-info-icon.svg new file mode 100644 index 000000000..825f0f200 --- /dev/null +++ b/app/images/mm-info-icon.svg @@ -0,0 +1,11 @@ + + + + + + + -- cgit From 5facba89ca8a106e7ae964f351ab532d9029e0f5 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 29 Aug 2017 14:11:11 -0230 Subject: Replace Avenir Next with alternative. --- app/fonts/Lato/Lato-Black.ttf | Bin 0 -> 114588 bytes app/fonts/Lato/Lato-BlackItalic.ttf | Bin 0 -> 111616 bytes app/fonts/Lato/Lato-Bold.ttf | Bin 0 -> 121788 bytes app/fonts/Lato/Lato-BoldItalic.ttf | Bin 0 -> 120312 bytes app/fonts/Lato/Lato-Hairline.ttf | Bin 0 -> 115316 bytes app/fonts/Lato/Lato-HairlineItalic.ttf | Bin 0 -> 91460 bytes app/fonts/Lato/Lato-Italic.ttf | Bin 0 -> 118352 bytes app/fonts/Lato/Lato-Light.ttf | Bin 0 -> 122524 bytes app/fonts/Lato/Lato-LightItalic.ttf | Bin 0 -> 91600 bytes app/fonts/Lato/Lato-Regular.ttf | Bin 0 -> 120196 bytes app/fonts/Lato/OFL.txt | 93 +++++++++++++++++++++++++++++++++ 11 files changed, 93 insertions(+) create mode 100755 app/fonts/Lato/Lato-Black.ttf create mode 100755 app/fonts/Lato/Lato-BlackItalic.ttf create mode 100755 app/fonts/Lato/Lato-Bold.ttf create mode 100755 app/fonts/Lato/Lato-BoldItalic.ttf create mode 100755 app/fonts/Lato/Lato-Hairline.ttf create mode 100755 app/fonts/Lato/Lato-HairlineItalic.ttf create mode 100755 app/fonts/Lato/Lato-Italic.ttf create mode 100755 app/fonts/Lato/Lato-Light.ttf create mode 100755 app/fonts/Lato/Lato-LightItalic.ttf create mode 100755 app/fonts/Lato/Lato-Regular.ttf create mode 100755 app/fonts/Lato/OFL.txt (limited to 'app') diff --git a/app/fonts/Lato/Lato-Black.ttf b/app/fonts/Lato/Lato-Black.ttf new file mode 100755 index 000000000..6848db0d1 Binary files /dev/null and b/app/fonts/Lato/Lato-Black.ttf differ diff --git a/app/fonts/Lato/Lato-BlackItalic.ttf b/app/fonts/Lato/Lato-BlackItalic.ttf new file mode 100755 index 000000000..5decf1297 Binary files /dev/null and b/app/fonts/Lato/Lato-BlackItalic.ttf differ diff --git a/app/fonts/Lato/Lato-Bold.ttf b/app/fonts/Lato/Lato-Bold.ttf new file mode 100755 index 000000000..74343694e Binary files /dev/null and b/app/fonts/Lato/Lato-Bold.ttf differ diff --git a/app/fonts/Lato/Lato-BoldItalic.ttf b/app/fonts/Lato/Lato-BoldItalic.ttf new file mode 100755 index 000000000..684aacf5b Binary files /dev/null and b/app/fonts/Lato/Lato-BoldItalic.ttf differ diff --git a/app/fonts/Lato/Lato-Hairline.ttf b/app/fonts/Lato/Lato-Hairline.ttf new file mode 100755 index 000000000..288be2955 Binary files /dev/null and b/app/fonts/Lato/Lato-Hairline.ttf differ diff --git a/app/fonts/Lato/Lato-HairlineItalic.ttf b/app/fonts/Lato/Lato-HairlineItalic.ttf new file mode 100755 index 000000000..c2bfd3353 Binary files /dev/null and b/app/fonts/Lato/Lato-HairlineItalic.ttf differ diff --git a/app/fonts/Lato/Lato-Italic.ttf b/app/fonts/Lato/Lato-Italic.ttf new file mode 100755 index 000000000..3d3b7a298 Binary files /dev/null and b/app/fonts/Lato/Lato-Italic.ttf differ diff --git a/app/fonts/Lato/Lato-Light.ttf b/app/fonts/Lato/Lato-Light.ttf new file mode 100755 index 000000000..a958067a8 Binary files /dev/null and b/app/fonts/Lato/Lato-Light.ttf differ diff --git a/app/fonts/Lato/Lato-LightItalic.ttf b/app/fonts/Lato/Lato-LightItalic.ttf new file mode 100755 index 000000000..5e45ad9a6 Binary files /dev/null and b/app/fonts/Lato/Lato-LightItalic.ttf differ diff --git a/app/fonts/Lato/Lato-Regular.ttf b/app/fonts/Lato/Lato-Regular.ttf new file mode 100755 index 000000000..04ea8efb1 Binary files /dev/null and b/app/fonts/Lato/Lato-Regular.ttf differ diff --git a/app/fonts/Lato/OFL.txt b/app/fonts/Lato/OFL.txt new file mode 100755 index 000000000..dfca0da4b --- /dev/null +++ b/app/fonts/Lato/OFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2010-2014 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato" + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. -- cgit From bffdde2082a64a78228b58b45778fd7886a0eceb Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 5 Sep 2017 23:33:41 -0700 Subject: Fix html height --- app/popup.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/popup.html b/app/popup.html index fddf01841..c4e5188e5 100644 --- a/app/popup.html +++ b/app/popup.html @@ -1,11 +1,11 @@ - + MetaMask Plugin - +
-- cgit From 7eb6dae4185d083ebb967256fdd09203b5092480 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 12 Sep 2017 02:22:23 -0700 Subject: Added signTokenTx; Adding token confirmation screen --- app/scripts/popup-core.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index f1eb394d7..94ba141bc 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -1,6 +1,7 @@ const EventEmitter = require('events').EventEmitter const async = require('async') const Dnode = require('dnode') +const Eth = require('ethjs') const EthQuery = require('eth-query') const launchMetamaskUi = require('../../ui') const StreamProvider = require('web3-stream-provider') @@ -34,6 +35,7 @@ function setupWeb3Connection (connectionStream) { providerStream.on('error', console.error.bind(console)) global.ethereumProvider = providerStream global.ethQuery = new EthQuery(providerStream) + global.eth = new Eth(providerStream) } function setupControllerConnection (connectionStream, cb) { @@ -47,6 +49,7 @@ function setupControllerConnection (connectionStream, cb) { }) connectionStream.pipe(accountManagerDnode).pipe(connectionStream) accountManagerDnode.once('remote', function (accountManager) { + console.log({ accountManager }) // setup push events accountManager.on = eventEmitter.on.bind(eventEmitter) cb(null, accountManager) -- cgit From 8b5f2a95df45c24061c13c51ca874e933e743381 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 12 Sep 2017 23:02:51 -0700 Subject: Improve styling in Confirmation Screen; Show decoded send token data --- app/scripts/popup-core.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 94ba141bc..2e4334bb1 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -49,7 +49,6 @@ function setupControllerConnection (connectionStream, cb) { }) connectionStream.pipe(accountManagerDnode).pipe(connectionStream) accountManagerDnode.once('remote', function (accountManager) { - console.log({ accountManager }) // setup push events accountManager.on = eventEmitter.on.bind(eventEmitter) cb(null, accountManager) -- cgit From ac4868170f4c61d13291389d01bf1002fe240ed4 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 3 Oct 2017 14:55:52 -0230 Subject: Enables remove token and ensures add/remove update the list without need for refresh. --- app/scripts/controllers/preferences.js | 13 ++++++++++++- app/scripts/metamask-controller.js | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index bc4848421..ecac40481 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -42,7 +42,18 @@ class PreferencesController { } this.store.updateState({ tokens }) - return Promise.resolve() + return Promise.resolve(tokens) + } + + removeToken (rawAddress) { + const address = normalizeAddress(rawAddress) + + const tokens = this.store.getState().tokens + + const updatedTokens = tokens.filter(token => token.address !== rawAddress) + + this.store.updateState({ tokens: updatedTokens }) + return Promise.resolve(updatedTokens) } getTokens () { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 5b3161bc6..b5c81c348 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -327,6 +327,7 @@ module.exports = class MetamaskController extends EventEmitter { // PreferencesController setSelectedAddress: nodeify(preferencesController.setSelectedAddress, preferencesController), addToken: nodeify(preferencesController.addToken, preferencesController), + removeToken: nodeify(preferencesController.removeToken, preferencesController), setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab, preferencesController), setDefaultRpc: nodeify(this.setDefaultRpc, this), setCustomRpc: nodeify(this.setCustomRpc, this), -- cgit From 147b81068a643074a1fd7aa3e0488263a64961ad Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 4 Oct 2017 09:56:18 -0700 Subject: Include OS version --- app/scripts/platforms/extension.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 0afe04b74..83c77a77f 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -17,6 +17,10 @@ class ExtensionPlatform { return extension.runtime.getManifest().version } + getPlatformInfo () { + return extension.runtime.getPlatformInfo() + } + } module.exports = ExtensionPlatform -- cgit From 3d80565339f02e1fa3e4bc0f8aaedbeea663a712 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 4 Oct 2017 10:55:10 -0700 Subject: Configured for callback-required function.' --- app/scripts/platforms/extension.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 83c77a77f..5ed2fdc4f 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -17,8 +17,8 @@ class ExtensionPlatform { return extension.runtime.getManifest().version } - getPlatformInfo () { - return extension.runtime.getPlatformInfo() + getPlatformInfo (cb) { + return extension.runtime.getPlatformInfo(cb) } } -- cgit From 15809894ff42bacc3babfb9aaba48389417907c0 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 5 Oct 2017 09:58:04 -0700 Subject: Add indicator for specified gas price --- app/scripts/controllers/transactions.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 94e04c429..481dd62a5 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -169,6 +169,7 @@ module.exports = class TransactionController extends EventEmitter { async addTxDefaults (txMeta) { const txParams = txMeta.txParams // ensure value + txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) const gasPrice = txParams.gasPrice || await this.query.gasPrice() txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' -- cgit From 106af9ec5b5671ec312117b1e2bd0ba5350d2085 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 5 Oct 2017 17:13:58 -0700 Subject: Catch an error if this is not defined. --- app/scripts/platforms/extension.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 5ed2fdc4f..f9e1d84b7 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -18,7 +18,14 @@ class ExtensionPlatform { } getPlatformInfo (cb) { - return extension.runtime.getPlatformInfo(cb) + var info + try { + info = extension.runtime.getPlatformInfo(cb) + } catch (e) { + log.debug(e) + info = undefined + } + return info } } -- cgit From f6821781d2ee3b1562008f47d9581ed21efee3ef Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 5 Oct 2017 17:17:34 -0700 Subject: Simplify try catch --- app/scripts/platforms/extension.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index f9e1d84b7..61d67e1b4 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -18,14 +18,12 @@ class ExtensionPlatform { } getPlatformInfo (cb) { - var info try { - info = extension.runtime.getPlatformInfo(cb) + return extension.runtime.getPlatformInfo(cb) } catch (e) { log.debug(e) - info = undefined + return undefined } - return info } } -- cgit From bbe893a0d8d759ba750ba78ff8aed0f0876a43ff Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 5 Oct 2017 13:14:45 -0230 Subject: UI for send screen container without form rows. --- app/scripts/lib/is-popup-or-notification.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/is-popup-or-notification.js b/app/scripts/lib/is-popup-or-notification.js index 73a812d5f..e2999411f 100644 --- a/app/scripts/lib/is-popup-or-notification.js +++ b/app/scripts/lib/is-popup-or-notification.js @@ -1,6 +1,9 @@ module.exports = function isPopupOrNotification () { const url = window.location.href - if (url.match(/popup.html$/) || url.match(/home.html$/)) { + // if (url.match(/popup.html$/) || url.match(/home.html$/)) { + // Below regexes needed for feature toggles (e.g. see line ~340 in ui/app/app.js) + // Revert below regexes to above commented out regexes before merge to master + if (url.match(/popup.html(?:\?.+)*$/) || url.match(/home.html(?:\?.+)*$/)) { return 'popup' } else { return 'notification' -- cgit From 24a55cf7770a6154fe723cf13cdc9998e1759f3b Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 10 Oct 2017 08:36:15 -0700 Subject: Make the function callback friendly. --- app/scripts/platforms/extension.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 61d67e1b4..2f47512eb 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -19,13 +19,13 @@ class ExtensionPlatform { getPlatformInfo (cb) { try { - return extension.runtime.getPlatformInfo(cb) + extension.runtime.getPlatformInfo((platform) => { + cb(null, platform) + }) } catch (e) { - log.debug(e) - return undefined + cb(e) } } - } module.exports = ExtensionPlatform -- cgit From 81f62a7443d47461b5f9b20f442392562458c79a Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Fri, 13 Oct 2017 02:10:58 -0400 Subject: Adding Account Dropdown V2 --- app/images/.DS_Store | Bin 6148 -> 0 bytes app/images/import-account.svg | 18 +++++++++++++++++ app/images/plus-btn-white.svg | 17 ++++++++++++++++ app/images/settings.svg | 46 ++++++++++++++++++++---------------------- 4 files changed, 57 insertions(+), 24 deletions(-) delete mode 100644 app/images/.DS_Store create mode 100644 app/images/import-account.svg create mode 100644 app/images/plus-btn-white.svg (limited to 'app') diff --git a/app/images/.DS_Store b/app/images/.DS_Store deleted file mode 100644 index d28ef2089..000000000 Binary files a/app/images/.DS_Store and /dev/null differ diff --git a/app/images/import-account.svg b/app/images/import-account.svg new file mode 100644 index 000000000..d6a81b70c --- /dev/null +++ b/app/images/import-account.svg @@ -0,0 +1,18 @@ + + + + import-account + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/images/plus-btn-white.svg b/app/images/plus-btn-white.svg new file mode 100644 index 000000000..2672d39dd --- /dev/null +++ b/app/images/plus-btn-white.svg @@ -0,0 +1,17 @@ + + + + plus-btn-white + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/app/images/settings.svg b/app/images/settings.svg index fe61320a5..cf9b298dd 100644 --- a/app/images/settings.svg +++ b/app/images/settings.svg @@ -1,24 +1,22 @@ - - - - - - + + + + settings + Created with Sketch. + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit From ab31eb6a17f5ab230fe47df66344cbce59223306 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 17 Oct 2017 13:09:41 -0700 Subject: Select first account on new vault creation --- app/scripts/metamask-controller.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a742f3cba..2a45e413b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -336,7 +336,7 @@ module.exports = class MetamaskController extends EventEmitter { // KeyringController setLocked: nodeify(keyringController.setLocked, keyringController), - createNewVaultAndKeychain: nodeify(keyringController.createNewVaultAndKeychain, keyringController), + createNewVaultAndKeychain: this.createNewVaultAndKeychain.bind(this), createNewVaultAndRestore: nodeify(keyringController.createNewVaultAndRestore, keyringController), addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController), saveAccountLabel: nodeify(keyringController.saveAccountLabel, keyringController), @@ -458,6 +458,17 @@ module.exports = class MetamaskController extends EventEmitter { // Vault Management // + createNewVaultAndKeychain (password, cb) { + this.keyringController.createNewVaultAndKeychain(password) + .then((vault) => { + const { identities } = vault + const address = Object.keys(identities)[0] + this.preferencesController.setSelectedAddress(address) + cb(null, vault) + }) + .catch(reason => cb(reason)) + } + submitPassword (password, cb) { return this.keyringController.submitPassword(password) .then((newState) => { cb(null, newState) }) -- cgit From d7f384485d2af15ec694208b9ef068c18c7dc91d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 17 Oct 2017 13:19:57 -0700 Subject: Select first account when restoring seed Fixes #2348 --- app/scripts/metamask-controller.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 2a45e413b..8a51fdd8d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -337,7 +337,7 @@ module.exports = class MetamaskController extends EventEmitter { // KeyringController setLocked: nodeify(keyringController.setLocked, keyringController), createNewVaultAndKeychain: this.createNewVaultAndKeychain.bind(this), - createNewVaultAndRestore: nodeify(keyringController.createNewVaultAndRestore, keyringController), + createNewVaultAndRestore: this.createNewVaultAndRestore.bind(this), addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController), saveAccountLabel: nodeify(keyringController.saveAccountLabel, keyringController), exportAccount: nodeify(keyringController.exportAccount, keyringController), @@ -461,14 +461,28 @@ module.exports = class MetamaskController extends EventEmitter { createNewVaultAndKeychain (password, cb) { this.keyringController.createNewVaultAndKeychain(password) .then((vault) => { - const { identities } = vault - const address = Object.keys(identities)[0] + this.selectFirstIdentity(vault) this.preferencesController.setSelectedAddress(address) cb(null, vault) }) .catch(reason => cb(reason)) } + createNewVaultAndRestore (password, seed, cb) { + this.keyringController.createNewVaultAndRestore(password, seed) + .then((vault) => { + this.selectFirstIdentity(vault) + cb(null, vault) + }) + .catch(reason => cb(reason)) + } + + selectFirstIdentity (vault) { + const { identities } = vault + const address = Object.keys(identities)[0] + this.preferencesController.setSelectedAddress(address) + } + submitPassword (password, cb) { return this.keyringController.submitPassword(password) .then((newState) => { cb(null, newState) }) -- cgit From 50e8599988c54bbf9ee0e9f324f79f5835fa6727 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 17 Oct 2017 13:25:27 -0700 Subject: Promisify metamask-controller vault creating methods --- app/scripts/metamask-controller.js | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 8a51fdd8d..4b11f6024 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -336,8 +336,8 @@ module.exports = class MetamaskController extends EventEmitter { // KeyringController setLocked: nodeify(keyringController.setLocked, keyringController), - createNewVaultAndKeychain: this.createNewVaultAndKeychain.bind(this), - createNewVaultAndRestore: this.createNewVaultAndRestore.bind(this), + createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this), + createNewVaultAndRestore: nodeify(this.createNewVaultAndRestore, this), addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController), saveAccountLabel: nodeify(keyringController.saveAccountLabel, keyringController), exportAccount: nodeify(keyringController.exportAccount, keyringController), @@ -458,23 +458,16 @@ module.exports = class MetamaskController extends EventEmitter { // Vault Management // - createNewVaultAndKeychain (password, cb) { - this.keyringController.createNewVaultAndKeychain(password) - .then((vault) => { - this.selectFirstIdentity(vault) - this.preferencesController.setSelectedAddress(address) - cb(null, vault) - }) - .catch(reason => cb(reason)) + async createNewVaultAndKeychain (password, cb) { + const vault = await this.keyringController.createNewVaultAndKeychain(password) + this.selectFirstIdentity(vault) + return vault } - createNewVaultAndRestore (password, seed, cb) { - this.keyringController.createNewVaultAndRestore(password, seed) - .then((vault) => { - this.selectFirstIdentity(vault) - cb(null, vault) - }) - .catch(reason => cb(reason)) + async createNewVaultAndRestore (password, seed, cb) { + const vault = await this.keyringController.createNewVaultAndRestore(password, seed) + this.selectFirstIdentity(vault) + return vault } selectFirstIdentity (vault) { -- cgit From 7032edf32b43e94a7f58c7bcb068da63fa6bda1b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 18 Oct 2017 11:13:14 -0700 Subject: Stop tracking old account balances after restore vault Per @kgserrano note --- app/scripts/metamask-controller.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4b11f6024..b6a3749e4 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -459,17 +459,30 @@ module.exports = class MetamaskController extends EventEmitter { // async createNewVaultAndKeychain (password, cb) { + this.forgetOldAccounts() const vault = await this.keyringController.createNewVaultAndKeychain(password) this.selectFirstIdentity(vault) return vault } async createNewVaultAndRestore (password, seed, cb) { + this.forgetOldAccounts() const vault = await this.keyringController.createNewVaultAndRestore(password, seed) this.selectFirstIdentity(vault) return vault } + forgetOldAccounts () { + const { accountTracker } = this + let oldAccounts = [] + try { + oldAccounts = Object.keys(accountTracker.store.getState().accounts) + } catch (e) { + log.warn('Could not load old accounts to forget', e) + } + oldAccounts.forEach(addr => accountTracker.removeAccount(addr)) + } + selectFirstIdentity (vault) { const { identities } = vault const address = Object.keys(identities)[0] -- cgit From ea79eca8eb19cf7ce375e03ad8cbde010299936c Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 18 Oct 2017 12:21:22 -0700 Subject: Add validation to balance constructor --- app/scripts/controllers/balance.js | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/balance.js b/app/scripts/controllers/balance.js index 4fa4c78fe..f83f294cc 100644 --- a/app/scripts/controllers/balance.js +++ b/app/scripts/controllers/balance.js @@ -5,7 +5,9 @@ const BN = require('ethereumjs-util').BN class BalanceController { constructor (opts = {}) { + this._validateParams(opts) const { address, accountTracker, txController, blockTracker } = opts + this.address = address this.accountTracker = accountTracker this.txController = txController @@ -65,6 +67,14 @@ class BalanceController { return pending } + _validateParams (opts) { + const { address, accountTracker, txController, blockTracker } = opts + if (!address || !accountTracker || !txController || !blockTracker) { + const error = 'Cannot construct a balance checker without address, accountTracker, txController, and blockTracker.' + throw new Error(error) + } + } + } module.exports = BalanceController -- cgit From 9cc1e8a6d867b7f0663c55b017b471132f6a719e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 18 Oct 2017 14:22:04 -0700 Subject: Refresh computed balances controller when restoring vault --- app/scripts/controllers/computed-balances.js | 4 ++++ app/scripts/metamask-controller.js | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/computed-balances.js b/app/scripts/controllers/computed-balances.js index 2479e1b3a..3479eae2b 100644 --- a/app/scripts/controllers/computed-balances.js +++ b/app/scripts/controllers/computed-balances.js @@ -25,6 +25,10 @@ class ComputedbalancesController { } } + forgetAllBalances () { + this.balances = {} + } + _initBalanceUpdating () { const store = this.accountTracker.store.getState() this.addAnyAccountsFromStore(store) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b6a3749e4..b312106dd 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -473,7 +473,7 @@ module.exports = class MetamaskController extends EventEmitter { } forgetOldAccounts () { - const { accountTracker } = this + const { accountTracker, balancesController } = this let oldAccounts = [] try { oldAccounts = Object.keys(accountTracker.store.getState().accounts) @@ -481,6 +481,7 @@ module.exports = class MetamaskController extends EventEmitter { log.warn('Could not load old accounts to forget', e) } oldAccounts.forEach(addr => accountTracker.removeAccount(addr)) + balancesController.forgetAllBalances() } selectFirstIdentity (vault) { -- cgit From 75177ce34cac589be26fb8089aac04feccdbae81 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 18 Oct 2017 15:08:34 -0700 Subject: Make account tracking more reactive We were doing a lot of conditional observation & updating. Pulled out a bunch of that for generic observer/syncers. --- app/scripts/controllers/computed-balances.js | 22 ++++++++++++++-------- app/scripts/lib/account-tracker.js | 18 ++++++++++++++++++ app/scripts/metamask-controller.js | 22 +--------------------- 3 files changed, 33 insertions(+), 29 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/computed-balances.js b/app/scripts/controllers/computed-balances.js index 3479eae2b..009405d29 100644 --- a/app/scripts/controllers/computed-balances.js +++ b/app/scripts/controllers/computed-balances.js @@ -25,22 +25,28 @@ class ComputedbalancesController { } } - forgetAllBalances () { - this.balances = {} - } - _initBalanceUpdating () { const store = this.accountTracker.store.getState() - this.addAnyAccountsFromStore(store) - this.accountTracker.store.subscribe(this.addAnyAccountsFromStore.bind(this)) + this.syncAllAccountsFromStore(store) + this.accountTracker.store.subscribe(this.syncAllAccountsFromStore.bind(this)) } - addAnyAccountsFromStore(store) { - const balances = store.accounts + syncAllAccountsFromStore(store) { + const upstream = Object.keys(store.accounts) + const balances = Object.keys(this.balances) + .map(address => this.balances[address]) + // Follow new addresses for (let address in balances) { this.trackAddressIfNotAlready(address) } + + // Unfollow old ones + balances.forEach(({ address }) => { + if (!upstream.includes(address)) { + delete this.balances[address] + } + }) } trackAddressIfNotAlready (address) { diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index cdc21282d..13dea918f 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -38,6 +38,24 @@ class AccountTracker extends EventEmitter { // public // + syncWithAddresses (addresses) { + const accounts = this.store.getState().accounts + const locals = Object.keys(accounts) + .map(account => accounts[account.address]) + + addresses.forEach((upstream) => { + if (!locals.includes(upstream)) { + this.addAccount(upstream) + } + }) + + locals.forEach((local) => { + if (!addresses.includes(local)) { + this.removeAccount(local) + } + }) + } + addAccount (address) { const accounts = this.store.getState().accounts accounts[address] = {} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b312106dd..eae4478b5 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -123,13 +123,7 @@ module.exports = class MetamaskController extends EventEmitter { const address = addresses[0] this.preferencesController.setSelectedAddress(address) } - }) - this.keyringController.on('newAccount', (address) => { - this.preferencesController.setSelectedAddress(address) - this.accountTracker.addAccount(address) - }) - this.keyringController.on('removedAccount', (address) => { - this.accountTracker.removeAccount(address) + this.accountTracker.syncWithAddresses(addresses) }) // address book controller @@ -459,31 +453,17 @@ module.exports = class MetamaskController extends EventEmitter { // async createNewVaultAndKeychain (password, cb) { - this.forgetOldAccounts() const vault = await this.keyringController.createNewVaultAndKeychain(password) this.selectFirstIdentity(vault) return vault } async createNewVaultAndRestore (password, seed, cb) { - this.forgetOldAccounts() const vault = await this.keyringController.createNewVaultAndRestore(password, seed) this.selectFirstIdentity(vault) return vault } - forgetOldAccounts () { - const { accountTracker, balancesController } = this - let oldAccounts = [] - try { - oldAccounts = Object.keys(accountTracker.store.getState().accounts) - } catch (e) { - log.warn('Could not load old accounts to forget', e) - } - oldAccounts.forEach(addr => accountTracker.removeAccount(addr)) - balancesController.forgetAllBalances() - } - selectFirstIdentity (vault) { const { identities } = vault const address = Object.keys(identities)[0] -- cgit From d89394a7c9a5139ed5708ce7022fbbe2809e612a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 18 Oct 2017 17:07:22 -0700 Subject: Make account tracking much more reactive --- app/scripts/lib/account-tracker.js | 11 ++++++++--- app/scripts/metamask-controller.js | 14 +++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 13dea918f..b9959dc25 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -41,19 +41,24 @@ class AccountTracker extends EventEmitter { syncWithAddresses (addresses) { const accounts = this.store.getState().accounts const locals = Object.keys(accounts) - .map(account => accounts[account.address]) + const toAdd = [] addresses.forEach((upstream) => { if (!locals.includes(upstream)) { - this.addAccount(upstream) + toAdd.push(upstream) } }) + const toRemove = [] locals.forEach((local) => { if (!addresses.includes(local)) { - this.removeAccount(local) + toRemove.push(local) } }) + + toAdd.forEach(upstream => this.addAccount(upstream)) + toRemove.forEach(local=> this.removeAccount(local)) + this._updateAccounts() } addAccount (address) { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index eae4478b5..11a26df64 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -117,8 +117,10 @@ module.exports = class MetamaskController extends EventEmitter { }) // If only one account exists, make sure it is selected. - this.keyringController.store.subscribe((state) => { - const addresses = Object.keys(state.walletNicknames || {}) + this.keyringController.memStore.subscribe((state) => { + const addresses = state.keyrings.reduce((res, keyring) => { + return res.concat(keyring.accounts) + }, []) if (addresses.length === 1) { const address = addresses[0] this.preferencesController.setSelectedAddress(address) @@ -314,7 +316,7 @@ module.exports = class MetamaskController extends EventEmitter { importAccountWithStrategy: this.importAccountWithStrategy.bind(this), // vault management - submitPassword: this.submitPassword.bind(this), + submitPassword: nodeify(keyringController.submitPassword, keyringController), // network management setProviderType: nodeify(networkController.setProviderType, networkController), @@ -470,12 +472,6 @@ module.exports = class MetamaskController extends EventEmitter { this.preferencesController.setSelectedAddress(address) } - submitPassword (password, cb) { - return this.keyringController.submitPassword(password) - .then((newState) => { cb(null, newState) }) - .catch((reason) => { cb(reason) }) - } - // // Opinionated Keyring Management // -- cgit From 21bde66e16c3a41a1cb8fca5e9e9e3e97875d23b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 18 Oct 2017 17:14:26 -0700 Subject: Remove account-tracker from keyringController --- app/scripts/metamask-controller.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index dd34cec97..366bb6d98 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -96,7 +96,6 @@ module.exports = class MetamaskController extends EventEmitter { // key mgmt this.keyringController = new KeyringController({ initState: initState.KeyringController, - accountTracker: this.accountTracker, getNetwork: this.networkController.getNetworkState.bind(this.networkController), encryptor: opts.encryptor || undefined, }) -- cgit From 0ae406e489a635ea094913ee5c20d1e8f2165db5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 19 Oct 2017 09:59:57 -0700 Subject: Allow computed balances to enumerate its own view --- app/scripts/controllers/computed-balances.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/computed-balances.js b/app/scripts/controllers/computed-balances.js index 009405d29..9855f715e 100644 --- a/app/scripts/controllers/computed-balances.js +++ b/app/scripts/controllers/computed-balances.js @@ -20,9 +20,10 @@ class ComputedbalancesController { } updateAllBalances () { - for (let address in this.accountTracker.store.getState().accounts) { + Object.keys(this.balances).forEach((balance) => { + const address = balance.address this.balances[address].updateBalance() - } + }) } _initBalanceUpdating () { -- cgit From 3b4c679ffcd76279221bb7cb6b83c53f0468ee65 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 19 Oct 2017 12:15:26 -0700 Subject: Fix bug where new account was not immediately selected --- app/scripts/metamask-controller.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 366bb6d98..457d38e26 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -324,7 +324,7 @@ module.exports = class MetamaskController extends EventEmitter { createShapeShiftTx: this.createShapeShiftTx.bind(this), // primary HD keyring management - addNewAccount: this.addNewAccount.bind(this), + addNewAccount: nodeify(this.addNewAccount, this), placeSeedWords: this.placeSeedWords.bind(this), clearSeedWordCache: this.clearSeedWordCache.bind(this), importAccountWithStrategy: this.importAccountWithStrategy.bind(this), @@ -490,10 +490,21 @@ module.exports = class MetamaskController extends EventEmitter { // Opinionated Keyring Management // - addNewAccount (cb) { + async addNewAccount (cb) { const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found')) - promiseToCallback(this.keyringController.addNewAccount(primaryKeyring))(cb) + const keyringController = this.keyringController + const oldAccounts = await keyringController.getAccounts() + const keyState = await keyringController.addNewAccount(primaryKeyring) + const newAccounts = await keyringController.getAccounts() + + newAccounts.forEach((address) => { + if (!oldAccounts.includes(address)) { + this.preferencesController.setSelectedAddress(address) + } + }) + + return keyState } // Adds the current vault's seed words to the UI's state tree. -- cgit From a10a600cced6273047f224c5e19d186de091efe0 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 19 Oct 2017 12:33:43 -0700 Subject: Linted --- app/scripts/lib/account-tracker.js | 2 +- app/scripts/metamask-controller.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index b9959dc25..ce6642150 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -57,7 +57,7 @@ class AccountTracker extends EventEmitter { }) toAdd.forEach(upstream => this.addAccount(upstream)) - toRemove.forEach(local=> this.removeAccount(local)) + toRemove.forEach(local => this.removeAccount(local)) this._updateAccounts() } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 457d38e26..ad42a39fb 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1,6 +1,5 @@ const EventEmitter = require('events') const extend = require('xtend') -const promiseToCallback = require('promise-to-callback') const pump = require('pump') const Dnode = require('dnode') const ObservableStore = require('obs-store') -- cgit From 48f348e7296dd323c1cfd6194a88a26b3339042b Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 20 Oct 2017 11:30:56 -0700 Subject: 4.0.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a0f449c68..e88d8dc11 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.11.0", + "version": "4.0.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 56dcf7c011f48c5f49e5339c9d36527d1f68cf93 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 20 Oct 2017 14:07:54 -0700 Subject: Version 3.11.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a0f449c68..c30d90dfa 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.11.0", + "version": "3.11.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From a9a841ba01f6bffa29a3e0491e3a88f6aff72ac7 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 20 Oct 2017 19:33:15 -0700 Subject: 4.0.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index e88d8dc11..33b1ac6e3 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.1", + "version": "4.0.2", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 5aaa2d679b00a7a78338b9b72fa72397ad945b35 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Sun, 24 Sep 2017 23:27:08 -0700 Subject: Add ShapeShift UI --- app/images/caret-right.svg | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 app/images/caret-right.svg (limited to 'app') diff --git a/app/images/caret-right.svg b/app/images/caret-right.svg new file mode 100644 index 000000000..8981ac254 --- /dev/null +++ b/app/images/caret-right.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit From 43b1cb9100e74ab32efe1a59b3320d0aeadedcdf Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Sat, 21 Oct 2017 21:06:39 +0200 Subject: Fix lint warnings Fixed warnings: ```md app/scripts/controllers/computed-balances.js + 35:27 warning Missing space before function parentheses space-before-function-paren + 41:14 warning 'address' is never reassigned. Use 'const' instead prefer-const + 61:9 warning 'updater' is never reassigned. Use 'const' instead prefer-const + 68:11 warning 'newState' is never reassigned. Use 'const' instead prefer-const app/scripts/controllers/network.js + 104:29 warning Missing space before function parentheses space-before-function-paren app/scripts/lib/createLoggerMiddleware.js + 4:32 warning Missing space before function parentheses space-before-function-paren + 15:2 warning Newline required at end of file but not found eol-last app/scripts/lib/createOriginMiddleware.js + 4:32 warning Missing space before function parentheses space-before-function-paren + 9:2 warning Newline required at end of file but not found eol-last app/scripts/lib/createProviderMiddleware.js + 5:34 warning Missing space before function parentheses space-before-function-paren + 13:2 warning Newline required at end of file but not found eol-last app/scripts/lib/events-proxy.js + 1:50 warning Missing space before function parentheses space-before-function-paren + 31:2 warning Newline required at end of file but not found eol-last app/scripts/lib/nodeify.js + 2:22 warning Missing space before function parentheses space-before-function-paren + 2:24 warning Missing space before opening brace space-before-blocks + 5:18 warning Missing space before function parentheses space-before-function-paren + 5:20 warning Missing space before opening brace space-before-blocks app/scripts/lib/pending-balance-calculator.js + 16:19 warning Missing space before function parentheses space-before-function-paren app/scripts/lib/pending-tx-tracker.js + 85:11 warning '||' should be placed at the end of the line operator-linebreak + 87:11 warning '||' should be placed at the end of the line operator-linebreak + 88:11 warning '||' should be placed at the end of the line operator-linebreak + 90:11 warning '||' should be placed at the end of the line operator-linebreak + 91:11 warning '||' should be placed at the end of the line operator-linebreak app/scripts/lib/port-stream.js + 3:22 warning Missing space before function parentheses space-before-function-paren + 3:24 warning Missing space before opening brace space-before-blocks app/scripts/lib/tx-gas-utils.js + 84:2 warning Newline required at end of file but not found eol-last app/scripts/lib/tx-state-history-helper.js + 12:37 warning Missing space before function parentheses space-before-function-paren + 23:30 warning Missing space before function parentheses space-before-function-paren + 30:23 warning Missing space before function parentheses space-before-function-paren + 35:28 warning Missing space before function parentheses space-before-function-paren + 41:2 warning Newline required at end of file but not found eol-last app/scripts/lib/tx-state-manager.js + 94:13 warning 'value' is never reassigned. Use 'const' instead prefer-const ui/app/reducers.js + 45:7 warning 'state' is never reassigned. Use 'const' instead prefer-const + 53:7 warning 'stateString' is never reassigned. Use 'const' instead prefer-const ui/lib/tx-helper.js + 27:2 warning Newline required at end of file but not found eol-last ui/app/components/account-dropdowns.js + 163:1 warning More than 2 blank lines not allowed no-multiple-empty-lines ui/app/components/menu-droppo.js + 22:7 warning 'style' is never reassigned. Use 'const' instead prefer-const ui/app/components/shapeshift-form.js + 135:11 warning '&&' should be placed at the end of the line operator-linebreak ui/app/components/typed-message-renderer.js + 35:25 warning Missing space before function parentheses space-before-function-paren + 42:2 warning Newline required at end of file but not found eol-last mascara/server/index.js + 11:42 warning Use path.join() or path.resolve() instead of + to create paths no-path-concat + 12:36 warning Use path.join() or path.resolve() instead of + to create paths no-path-concat + 13:33 warning Use path.join() or path.resolve() instead of + to create paths no-path-concat + 14:40 warning Use path.join() or path.resolve() instead of + to create paths no-path-concat + 20:29 warning Use path.join() or path.resolve() instead of + to create paths no-path-concat + 21:29 warning Use path.join() or path.resolve() instead of + to create paths no-path-concat + 26:40 warning Use path.join() or path.resolve() instead of + to create paths no-path-concat ``` --- app/scripts/controllers/computed-balances.js | 8 ++++---- app/scripts/controllers/network.js | 2 +- app/scripts/lib/createLoggerMiddleware.js | 4 ++-- app/scripts/lib/createOriginMiddleware.js | 4 ++-- app/scripts/lib/createProviderMiddleware.js | 5 ++--- app/scripts/lib/events-proxy.js | 4 ++-- app/scripts/lib/nodeify.js | 4 ++-- app/scripts/lib/pending-balance-calculator.js | 2 +- app/scripts/lib/pending-tx-tracker.js | 12 ++++++------ app/scripts/lib/port-stream.js | 2 +- app/scripts/lib/tx-gas-utils.js | 2 +- app/scripts/lib/tx-state-history-helper.js | 10 +++++----- app/scripts/lib/tx-state-manager.js | 2 +- 13 files changed, 30 insertions(+), 31 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/computed-balances.js b/app/scripts/controllers/computed-balances.js index 9855f715e..907b087cf 100644 --- a/app/scripts/controllers/computed-balances.js +++ b/app/scripts/controllers/computed-balances.js @@ -32,13 +32,13 @@ class ComputedbalancesController { this.accountTracker.store.subscribe(this.syncAllAccountsFromStore.bind(this)) } - syncAllAccountsFromStore(store) { + syncAllAccountsFromStore (store) { const upstream = Object.keys(store.accounts) const balances = Object.keys(this.balances) .map(address => this.balances[address]) // Follow new addresses - for (let address in balances) { + for (const address in balances) { this.trackAddressIfNotAlready(address) } @@ -58,14 +58,14 @@ class ComputedbalancesController { } trackAddress (address) { - let updater = new BalanceController({ + const updater = new BalanceController({ address, accountTracker: this.accountTracker, txController: this.txController, blockTracker: this.blockTracker, }) updater.store.subscribe((accountBalance) => { - let newState = this.store.getState() + const newState = this.store.getState() newState.computedBalances[address] = accountBalance this.store.updateState(newState) }) diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 0f9db4d53..66cebb842 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -101,7 +101,7 @@ module.exports = class NetworkController extends EventEmitter { this.emit('networkDidChange') } - _configureStandardProvider(_providerParams) { + _configureStandardProvider (_providerParams) { const providerParams = extend(this._baseProviderParams, _providerParams) const provider = createMetamaskProvider(providerParams) this._setProvider(provider) diff --git a/app/scripts/lib/createLoggerMiddleware.js b/app/scripts/lib/createLoggerMiddleware.js index b92a965de..2707cbd9e 100644 --- a/app/scripts/lib/createLoggerMiddleware.js +++ b/app/scripts/lib/createLoggerMiddleware.js @@ -1,7 +1,7 @@ // log rpc activity module.exports = createLoggerMiddleware -function createLoggerMiddleware({ origin }) { +function createLoggerMiddleware ({ origin }) { return function loggerMiddleware (req, res, next, end) { next((cb) => { if (res.error) { @@ -12,4 +12,4 @@ function createLoggerMiddleware({ origin }) { cb() }) } -} \ No newline at end of file +} diff --git a/app/scripts/lib/createOriginMiddleware.js b/app/scripts/lib/createOriginMiddleware.js index e1e097cc4..f8bdb2dc2 100644 --- a/app/scripts/lib/createOriginMiddleware.js +++ b/app/scripts/lib/createOriginMiddleware.js @@ -1,9 +1,9 @@ // append dapp origin domain to request module.exports = createOriginMiddleware -function createOriginMiddleware({ origin }) { +function createOriginMiddleware ({ origin }) { return function originMiddleware (req, res, next, end) { req.origin = origin next() } -} \ No newline at end of file +} diff --git a/app/scripts/lib/createProviderMiddleware.js b/app/scripts/lib/createProviderMiddleware.js index 6dd192411..4e667bac2 100644 --- a/app/scripts/lib/createProviderMiddleware.js +++ b/app/scripts/lib/createProviderMiddleware.js @@ -1,8 +1,7 @@ - module.exports = createProviderMiddleware // forward requests to provider -function createProviderMiddleware({ provider }) { +function createProviderMiddleware ({ provider }) { return (req, res, next, end) => { provider.sendAsync(req, (err, _res) => { if (err) return end(err) @@ -10,4 +9,4 @@ function createProviderMiddleware({ provider }) { end() }) } -} \ No newline at end of file +} diff --git a/app/scripts/lib/events-proxy.js b/app/scripts/lib/events-proxy.js index d1199a278..c0a490b05 100644 --- a/app/scripts/lib/events-proxy.js +++ b/app/scripts/lib/events-proxy.js @@ -1,4 +1,4 @@ -module.exports = function createEventEmitterProxy(eventEmitter, listeners) { +module.exports = function createEventEmitterProxy (eventEmitter, listeners) { let target = eventEmitter const eventHandlers = listeners || {} const proxy = new Proxy({}, { @@ -28,4 +28,4 @@ module.exports = function createEventEmitterProxy(eventEmitter, listeners) { } if (listeners) proxy.setTarget(eventEmitter) return proxy -} \ No newline at end of file +} diff --git a/app/scripts/lib/nodeify.js b/app/scripts/lib/nodeify.js index d24e92206..9b595d93c 100644 --- a/app/scripts/lib/nodeify.js +++ b/app/scripts/lib/nodeify.js @@ -1,8 +1,8 @@ const promiseToCallback = require('promise-to-callback') -const noop = function(){} +const noop = function () {} module.exports = function nodeify (fn, context) { - return function(){ + return function () { const args = [].slice.call(arguments) const lastArg = args[args.length - 1] const lastArgIsCallback = typeof lastArg === 'function' diff --git a/app/scripts/lib/pending-balance-calculator.js b/app/scripts/lib/pending-balance-calculator.js index cea642f1a..6ae526463 100644 --- a/app/scripts/lib/pending-balance-calculator.js +++ b/app/scripts/lib/pending-balance-calculator.js @@ -13,7 +13,7 @@ class PendingBalanceCalculator { this.getNetworkBalance = getBalance } - async getBalance() { + async getBalance () { const results = await Promise.all([ this.getNetworkBalance(), this.getPendingTransactions(), diff --git a/app/scripts/lib/pending-tx-tracker.js b/app/scripts/lib/pending-tx-tracker.js index df504c126..0d7c6a92c 100644 --- a/app/scripts/lib/pending-tx-tracker.js +++ b/app/scripts/lib/pending-tx-tracker.js @@ -81,14 +81,14 @@ module.exports = class PendingTransactionTracker extends EventEmitter { const errorMessage = err.message.toLowerCase() const isKnownTx = ( // geth - errorMessage.includes('replacement transaction underpriced') - || errorMessage.includes('known transaction') + errorMessage.includes('replacement transaction underpriced') || + errorMessage.includes('known transaction') || // parity - || errorMessage.includes('gas price too low to replace') - || errorMessage.includes('transaction with the same hash was already imported') + errorMessage.includes('gas price too low to replace') || + errorMessage.includes('transaction with the same hash was already imported') || // other - || errorMessage.includes('gateway timeout') - || errorMessage.includes('nonce too low') + errorMessage.includes('gateway timeout') || + errorMessage.includes('nonce too low') ) // ignore resubmit warnings, return early if (isKnownTx) return diff --git a/app/scripts/lib/port-stream.js b/app/scripts/lib/port-stream.js index 648d88087..a9716fb00 100644 --- a/app/scripts/lib/port-stream.js +++ b/app/scripts/lib/port-stream.js @@ -1,6 +1,6 @@ const Duplex = require('readable-stream').Duplex const inherits = require('util').inherits -const noop = function(){} +const noop = function () {} module.exports = PortDuplexStream diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 41f67e230..7e72ea71d 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -81,4 +81,4 @@ module.exports = class txProvideUtil { throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`) } } -} \ No newline at end of file +} diff --git a/app/scripts/lib/tx-state-history-helper.js b/app/scripts/lib/tx-state-history-helper.js index db6e3bc9f..94c7b6792 100644 --- a/app/scripts/lib/tx-state-history-helper.js +++ b/app/scripts/lib/tx-state-history-helper.js @@ -9,7 +9,7 @@ module.exports = { } -function migrateFromSnapshotsToDiffs(longHistory) { +function migrateFromSnapshotsToDiffs (longHistory) { return ( longHistory // convert non-initial history entries into diffs @@ -20,22 +20,22 @@ function migrateFromSnapshotsToDiffs(longHistory) { ) } -function generateHistoryEntry(previousState, newState, note) { +function generateHistoryEntry (previousState, newState, note) { const entry = jsonDiffer.compare(previousState, newState) // Add a note to the first op, since it breaks if we append it to the entry if (note && entry[0]) entry[0].note = note return entry } -function replayHistory(_shortHistory) { +function replayHistory (_shortHistory) { const shortHistory = clone(_shortHistory) return shortHistory.reduce((val, entry) => jsonDiffer.applyPatch(val, entry).newDocument) } -function snapshotFromTxMeta(txMeta) { +function snapshotFromTxMeta (txMeta) { // create txMeta snapshot for history const snapshot = clone(txMeta) // dont include previous history in this snapshot delete snapshot.history return snapshot -} \ No newline at end of file +} diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 2250403f6..0fd6bed4b 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -91,7 +91,7 @@ module.exports = class TransactionStateManger extends EventEmitter { updateTx (txMeta, note) { if (txMeta.txParams) { Object.keys(txMeta.txParams).forEach((key) => { - let value = txMeta.txParams[key] + const value = txMeta.txParams[key] if (typeof value !== 'string') console.error(`${key}: ${value} in txParams is not a string`) if (!ethUtil.isHexPrefixed(value)) console.error('is not hex prefixed, anything on txParams must be hex prefixed') }) -- cgit From e564ed8d4cfeceb2caf769302a3c34d4b11c7485 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sat, 21 Oct 2017 15:40:57 -0700 Subject: Version 3.11.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index c30d90dfa..eb499390a 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.11.1", + "version": "3.11.2", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 6d052384691b6336df0a60b47f3283ee2bb06ada Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sun, 22 Oct 2017 22:24:50 -0700 Subject: Try to fix intermittent test failure in NonceTracker tests --- app/scripts/controllers/network.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 0f9db4d53..7f0cbd379 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -51,6 +51,10 @@ module.exports = class NetworkController extends EventEmitter { } lookupNetwork () { + // Prevent firing when provider is not defined. + if (!this.ethQuery || !this.ethQuery.sendAsync) { + return + } this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { if (err) return this.setNetworkState('loading') log.info('web3.getNetwork returned ' + network) -- cgit From b17a799de6b04e6971eb3a33e7baa76f8236cad9 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 23 Oct 2017 12:10:49 -0700 Subject: Update network.js --- app/scripts/controllers/network.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 7f0cbd379..2259efaeb 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -53,7 +53,7 @@ module.exports = class NetworkController extends EventEmitter { lookupNetwork () { // Prevent firing when provider is not defined. if (!this.ethQuery || !this.ethQuery.sendAsync) { - return + return console.warn('NetworkController - lookupNetwork aborted due to missing ethQuery') } this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { if (err) return this.setNetworkState('loading') -- cgit From 4401800a42eccbd77f11b332e1052431328401bb Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 24 Oct 2017 00:13:49 -0700 Subject: Account menu white check mark --- app/images/check-white.svg | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 app/images/check-white.svg (limited to 'app') diff --git a/app/images/check-white.svg b/app/images/check-white.svg new file mode 100644 index 000000000..0f15667da --- /dev/null +++ b/app/images/check-white.svg @@ -0,0 +1,14 @@ + + + + check-white + Created with Sketch. + + + + + + + + + \ No newline at end of file -- cgit From 311ca1f3ca52ca4a4f45098ba3a0a5750ae9d3c6 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 25 Oct 2017 00:10:09 -0700 Subject: Fix styling on notification view --- app/notification.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/notification.html b/app/notification.html index be38f4aa3..f10cbbf41 100644 --- a/app/notification.html +++ b/app/notification.html @@ -1,5 +1,5 @@ - + MetaMask Notification @@ -9,7 +9,7 @@ } - +
-- cgit From 3d8182f5d54730d3908a210c3deb71b49dd08100 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 25 Oct 2017 09:26:05 -0700 Subject: Add Info section --- app/images/info-logo.png | Bin 0 -> 32567 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/images/info-logo.png (limited to 'app') diff --git a/app/images/info-logo.png b/app/images/info-logo.png new file mode 100644 index 000000000..f654ed5b1 Binary files /dev/null and b/app/images/info-logo.png differ -- cgit From b9bbf8f3290a9b469f4b9f6ee8becad2c76e7044 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 25 Oct 2017 15:45:26 -0700 Subject: Resolving that ugly merge. --- app/scripts/inpage.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 9e98c044b..b6889b00f 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -1,6 +1,7 @@ /*global Web3*/ cleanContextForImports() require('web3/dist/web3.min.js') +const log = require('loglevel') const LocalMessageDuplexStream = require('post-message-stream') // const PingStream = require('ping-pong-stream/ping') // const endOfStream = require('end-of-stream') @@ -8,6 +9,10 @@ const setupDappAutoReload = require('./lib/auto-reload.js') const MetamaskInpageProvider = require('./lib/inpage-provider.js') restoreContextAfterImports() +const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +window.log = log +log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn') + // // setup plugin communication @@ -28,9 +33,9 @@ var inpageProvider = new MetamaskInpageProvider(metamaskStream) var web3 = new Web3(inpageProvider) web3.setProvider = function () { - console.log('MetaMask - overrode web3.setProvider') + log.debug('MetaMask - overrode web3.setProvider') } -console.log('MetaMask - injected web3') +log.debug('MetaMask - injected web3') // export global web3, with usage-detection setupDappAutoReload(web3, inpageProvider.publicConfigStore) @@ -65,4 +70,3 @@ function restoreContextAfterImports () { console.warn('MetaMask - global.define could not be overwritten.') } } - -- cgit From ddf11011c9467209e6b9810dff2df84ea9e4a040 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 25 Oct 2017 21:58:56 -0230 Subject: Signature request fixes. --- app/scripts/lib/notification-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index 7846ef7f0..98cd3f760 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -1,5 +1,5 @@ const extension = require('extensionizer') -const height = 520 +const height = 610 const width = 360 -- cgit From fa95303e1efef03db6c44878b89ccca680639598 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 25 Oct 2017 18:05:52 -0700 Subject: Sign Typed Request styling fixes --- app/scripts/lib/notification-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index 98cd3f760..adaf60c65 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -1,5 +1,5 @@ const extension = require('extensionizer') -const height = 610 +const height = 620 const width = 360 -- cgit From a7424f0c0d134b730e7e5209612a3b26f990f75f Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 25 Oct 2017 20:06:26 -0700 Subject: 3.12.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index eb499390a..b6ff3d1cb 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.11.2", + "version": "3.12.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From c1d2a1226c5ba4e5cfe1eeae2f52a86b67fc7404 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 25 Oct 2017 20:13:05 -0700 Subject: 4.0.3 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 33b1ac6e3..65d7a4811 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.2", + "version": "4.0.3", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 5ce94e69b311428d9d2f9b5502c02d3b960e380e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 31 Oct 2017 09:59:26 -0700 Subject: Add useful error when duplicate web3 is detected. Fixes #2507 --- app/scripts/inpage.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'app') diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index b6889b00f..9261e7d64 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -31,6 +31,13 @@ var inpageProvider = new MetamaskInpageProvider(metamaskStream) // setup web3 // +if (typeof window.web3 !== 'undefined') { + throw new Error(`MetaMask detected another web3. + MetaMask will not work reliably with another web3 extension. + This usually happens if you have two MetaMasks installed, + or MetaMask and another web3 extension. Please remove one + and try again.`) +} var web3 = new Web3(inpageProvider) web3.setProvider = function () { log.debug('MetaMask - overrode web3.setProvider') -- cgit From 5a94775b3fa22517a71232ebe229ee83e9debcf1 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 2 Nov 2017 00:00:33 -0230 Subject: Lint fixes for NewUI-flat. --- app/scripts/controllers/preferences.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index ecac40481..10004caad 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -46,8 +46,6 @@ class PreferencesController { } removeToken (rawAddress) { - const address = normalizeAddress(rawAddress) - const tokens = this.store.getState().tokens const updatedTokens = tokens.filter(token => token.address !== rawAddress) -- cgit From 41fea44af3105313b33d9882859935019b6a2410 Mon Sep 17 00:00:00 2001 From: "Dora E. Mondrian" Date: Mon, 6 Nov 2017 04:35:51 -0800 Subject: newUnaprovedTx => newUnapprovedTx This typo tripped me up when I was reading through the code and trying to understand what's going on. --- app/scripts/controllers/transactions.js | 2 +- app/scripts/metamask-controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index d5fde033b..a861c0342 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -133,7 +133,7 @@ module.exports = class TransactionController extends EventEmitter { async newUnapprovedTransaction (txParams) { log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) const txMeta = await this.addUnapprovedTransaction(txParams) - this.emit('newUnaprovedTx', txMeta) + this.emit('newUnapprovedTx', txMeta) // listen for tx completion (success, fail) return new Promise((resolve, reject) => { this.txStateManager.once(`${txMeta.id}:finished`, (completedTx) => { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index ad42a39fb..968589f6e 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -128,7 +128,7 @@ module.exports = class MetamaskController extends EventEmitter { blockTracker: this.blockTracker, ethQuery: this.ethQuery, }) - this.txController.on('newUnaprovedTx', opts.showUnapprovedTx.bind(opts)) + this.txController.on('newUnapprovedTx', opts.showUnapprovedTx.bind(opts)) // computed balances (accounting for pending transactions) this.balancesController = new BalancesController({ -- cgit From 03968ffafe27e64dcdf58764057cee1d67aa4168 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 15 Nov 2017 12:23:39 -0800 Subject: Version Bump --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 65d7a4811..ff595c717 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.3", + "version": "4.0.4", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From c0aa7ce8574c6a88c348d86c71678fcd24ac168d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 20 Nov 2017 13:27:29 -0800 Subject: Add reproduction and mutex code --- app/scripts/metamask-controller.js | 39 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 968589f6e..69cf65554 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -31,6 +31,7 @@ const ConfigManager = require('./lib/config-manager') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') const getBuyEthUrl = require('./lib/buy-eth-url') +const Mutex = require('await-semaphore').Mutex const version = require('../manifest.json').version module.exports = class MetamaskController extends EventEmitter { @@ -38,6 +39,10 @@ module.exports = class MetamaskController extends EventEmitter { constructor (opts) { super() + this.createVaultRequestStart = [] + this.createVaultRequestEnd = [] + this.createVaultMutex = new Mutex() + this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) this.opts = opts @@ -467,15 +472,45 @@ module.exports = class MetamaskController extends EventEmitter { // Vault Management // - async createNewVaultAndKeychain (password, cb) { + async createNewVaultAndKeychain (password) { + const release = await this.createVaultMutex.acquire() + this.createVaultRequestStart.push(performance.now()) + this.createVaultRequestEnd.push(0); + const idx = this.createVaultRequestStart.length - 1; + if(idx === 1) { + await this.sleep(8000) + } const vault = await this.keyringController.createNewVaultAndKeychain(password) + if(idx === 0) { + //await this.sleep(3000) + } + console.log({ + "idx": idx, + "when": "before", + "obj": vault + }); this.selectFirstIdentity(vault) + console.log({ + "idx": idx, + "when": "after", + "obj": vault + }); + this.createVaultRequestEnd[idx] = performance.now() + console.log(this.createVaultRequestStart) + console.log(this.createVaultRequestEnd) + release() return vault } - async createNewVaultAndRestore (password, seed, cb) { + sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + async createNewVaultAndRestore (password, seed) { + const release = await this.createVaultMutex.acquire() const vault = await this.keyringController.createNewVaultAndRestore(password, seed) this.selectFirstIdentity(vault) + release() return vault } -- cgit From 65cb9704872fe7730285f4185ea6bc1a2d28c149 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 20 Nov 2017 13:47:35 -0800 Subject: Prevent creation of multiple vaults Fixes #2577 by ensuring only one seed phrase can be set for a new vault. Also cleans up logs and reproduction logic. --- app/scripts/metamask-controller.js | 51 +++++++++++++++----------------------- 1 file changed, 20 insertions(+), 31 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 69cf65554..a4c77e468 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -39,9 +39,6 @@ module.exports = class MetamaskController extends EventEmitter { constructor (opts) { super() - this.createVaultRequestStart = [] - this.createVaultRequestEnd = [] - this.createVaultMutex = new Mutex() this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) @@ -54,6 +51,9 @@ module.exports = class MetamaskController extends EventEmitter { // observable state store this.store = new ObservableStore(initState) + // lock to ensure only one vault created at once + this.createVaultMutex = new Mutex() + // network store this.networkController = new NetworkController(initState.NetworkController) @@ -474,36 +474,25 @@ module.exports = class MetamaskController extends EventEmitter { async createNewVaultAndKeychain (password) { const release = await this.createVaultMutex.acquire() - this.createVaultRequestStart.push(performance.now()) - this.createVaultRequestEnd.push(0); - const idx = this.createVaultRequestStart.length - 1; - if(idx === 1) { - await this.sleep(8000) - } - const vault = await this.keyringController.createNewVaultAndKeychain(password) - if(idx === 0) { - //await this.sleep(3000) + let vault + + try { + const accounts = await this.keyringController.getAccounts() + + if (accounts.length > 0) { + vault = await this.keyringController.fullUpdate() + + } else { + let vault = await this.keyringController.createNewVaultAndKeychain(password) + this.selectFirstIdentity(vault) + } + release() + } catch (err) { + release() + throw err } - console.log({ - "idx": idx, - "when": "before", - "obj": vault - }); - this.selectFirstIdentity(vault) - console.log({ - "idx": idx, - "when": "after", - "obj": vault - }); - this.createVaultRequestEnd[idx] = performance.now() - console.log(this.createVaultRequestStart) - console.log(this.createVaultRequestEnd) - release() - return vault - } - sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return vault } async createNewVaultAndRestore (password, seed) { -- cgit From 90fc4812bc75857581e56eb6d63484dbc5c48cb1 Mon Sep 17 00:00:00 2001 From: "Clark, Jason (Contractor)" Date: Thu, 23 Nov 2017 18:33:44 -0700 Subject: incremental commit --- app/scripts/controllers/preferences.js | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 10004caad..c0454f77b 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -14,6 +14,14 @@ class PreferencesController { } // PUBLIC METHODS + toggleUseBlockie () { + this.store.updateState({ useBlockie: !this.useBlockie() }) + } + + getUseBlockie () { + return this.store.getState().useBlockie + } + setSelectedAddress (_address) { return new Promise((resolve, reject) => { const address = normalizeAddress(_address) -- cgit From fc46a16a329df296cb565e3a0b04f268d2aeceb5 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Fri, 24 Nov 2017 10:35:17 -0700 Subject: toggle wired up to preferences property store --- app/scripts/controllers/preferences.js | 4 ++-- app/scripts/metamask-controller.js | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index c0454f77b..7ccb0e730 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -14,8 +14,8 @@ class PreferencesController { } // PUBLIC METHODS - toggleUseBlockie () { - this.store.updateState({ useBlockie: !this.useBlockie() }) + setUseBlockie (val) { + this.store.updateState({ useBlockie: val }) } getUseBlockie () { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index bd71da8e0..3a935d895 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -315,6 +315,7 @@ module.exports = class MetamaskController extends EventEmitter { // etc getState: (cb) => cb(null, this.getState()), setCurrentCurrency: this.setCurrentCurrency.bind(this), + setUseBlockie: this.setUseBlockie.bind(this), markAccountsFound: this.markAccountsFound.bind(this), // coinbase @@ -774,4 +775,13 @@ module.exports = class MetamaskController extends EventEmitter { return rpcTarget } + setUseBlockie(val, cb) { + try { + this.preferencesController.setUseBlockie(val) + cb(null) + } catch (err) { + cb(err) + } + } + } -- cgit From abefcc9612d75067474e521486d62684dfeae9c7 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Sat, 25 Nov 2017 15:57:54 -0700 Subject: more eslint fixes --- app/scripts/metamask-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 3a935d895..4dce89e3a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -775,7 +775,7 @@ module.exports = class MetamaskController extends EventEmitter { return rpcTarget } - setUseBlockie(val, cb) { + setUseBlockie (val, cb) { try { this.preferencesController.setUseBlockie(val) cb(null) -- cgit From a34362b7765f48d24375c9953fa7c49cf3306491 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Mon, 27 Nov 2017 08:11:48 -0700 Subject: Fixes changes requested in pullrequestreview-79088534 --- app/scripts/controllers/preferences.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 7ccb0e730..0aed4dbdf 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -9,6 +9,7 @@ class PreferencesController { frequentRpcList: [], currentAccountTab: 'history', tokens: [], + useBlockie: false, }, opts.initState) this.store = new ObservableStore(initState) } -- cgit From 634102df6331161c21593c0f8cab91a2093209e1 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 27 Nov 2017 13:59:32 -1000 Subject: network controller - warn via log.warn --- app/scripts/controllers/network.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 2259efaeb..f3349d9a0 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -53,7 +53,7 @@ module.exports = class NetworkController extends EventEmitter { lookupNetwork () { // Prevent firing when provider is not defined. if (!this.ethQuery || !this.ethQuery.sendAsync) { - return console.warn('NetworkController - lookupNetwork aborted due to missing ethQuery') + return log.warn('NetworkController - lookupNetwork aborted due to missing ethQuery') } this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { if (err) return this.setNetworkState('loading') -- cgit From e89f82399f1c732c40dc644c496795833691cff0 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 28 Nov 2017 11:14:57 -0800 Subject: Add optional version field to notices Allows notices to only show to users who are on a certain version. --- app/scripts/metamask-controller.js | 11 +++++++++++ app/scripts/notice-controller.js | 10 +++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a4c77e468..c1b63449a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -44,6 +44,7 @@ module.exports = class MetamaskController extends EventEmitter { this.opts = opts const initState = opts.initState || {} + this.recordFirstTimeInfo(initState) // platform-specific api this.platform = opts.platform @@ -149,6 +150,7 @@ module.exports = class MetamaskController extends EventEmitter { // notices this.noticeController = new NoticeController({ initState: initState.NoticeController, + version, }) this.noticeController.updateNoticesList() // to be uncommented when retrieving notices from a remote server. @@ -797,4 +799,13 @@ module.exports = class MetamaskController extends EventEmitter { return rpcTarget } + recordFirstTimeInfo (initState) { + if (!('firstTimeInfo' in initState)) { + initState.firstTimeInfo = { + version, + date: Date.now(), + } + } + } + } diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index 57aad40c5..bc545127e 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -1,4 +1,5 @@ const EventEmitter = require('events').EventEmitter +const semver = require('semver') const extend = require('xtend') const ObservableStore = require('obs-store') const hardCodedNotices = require('../../notices/notices.json') @@ -8,6 +9,7 @@ module.exports = class NoticeController extends EventEmitter { constructor (opts) { super() this.noticePoller = null + this.version = opts.version const initState = extend({ noticesList: [], }, opts.initState) @@ -51,7 +53,13 @@ module.exports = class NoticeController extends EventEmitter { } updateNoticesList () { - return this._retrieveNoticeData().then((newNotices) => { + return this._retrieveNoticeData().then((hardNotices) => { + const newNotices = hardNotices.filter((newNotice) => { + if ('version' in newNotice) { + return semver.satisfies(this.version, newNotice.version) + } + return true + }) var oldNotices = this.getNoticesList() var combinedNotices = this._mergeNotices(oldNotices, newNotices) return Promise.resolve(this.setNoticesList(combinedNotices)) -- cgit From ec4b7de962d0c4913f8f65a21a6cbef9f2ebc261 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 28 Nov 2017 11:22:09 -0800 Subject: Add firstVersion field to notices selector --- app/scripts/metamask-controller.js | 1 + app/scripts/notice-controller.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c1b63449a..0c759010b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -151,6 +151,7 @@ module.exports = class MetamaskController extends EventEmitter { this.noticeController = new NoticeController({ initState: initState.NoticeController, version, + firstVersion: initState.firstTimeInfo.version, }) this.noticeController.updateNoticesList() // to be uncommented when retrieving notices from a remote server. diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index bc545127e..457161ccb 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -9,7 +9,7 @@ module.exports = class NoticeController extends EventEmitter { constructor (opts) { super() this.noticePoller = null - this.version = opts.version + this.firstVersion = opts.firstVersion const initState = extend({ noticesList: [], }, opts.initState) @@ -58,6 +58,9 @@ module.exports = class NoticeController extends EventEmitter { if ('version' in newNotice) { return semver.satisfies(this.version, newNotice.version) } + if ('firstVersion' in newNotice) { + return semver.satisfies(this.firstVersion, newNotice.firstVersion) + } return true }) var oldNotices = this.getNoticesList() -- cgit From f64bc3c01afa688ee4eb4ea681bca0d9a95f0300 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 28 Nov 2017 11:09:18 -1000 Subject: deps - obs-store@3 + migrate stream plumbing --- app/scripts/background.js | 9 +++++---- app/scripts/lib/inpage-provider.js | 4 +++- app/scripts/metamask-controller.js | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 3e560d302..da022c490 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -1,10 +1,11 @@ const urlUtil = require('url') const endOfStream = require('end-of-stream') -const pipe = require('pump') +const pump = require('pump') const log = require('loglevel') const extension = require('extensionizer') const LocalStorageStore = require('obs-store/lib/localStorage') const storeTransform = require('obs-store/lib/transform') +const asStream = require('obs-store/lib/asStream') const ExtensionPlatform = require('./platforms/extension') const Migrator = require('./lib/migrator/') const migrations = require('./migrations/') @@ -72,10 +73,10 @@ function setupController (initState) { global.metamaskController = controller // setup state persistence - pipe( - controller.store, + pump( + asStream(controller.store), storeTransform(versionifyData), - diskStore + asStream(diskStore) ) function versionifyData (state) { diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index da75c4be2..99cc5d2cf 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -3,6 +3,7 @@ const RpcEngine = require('json-rpc-engine') const createIdRemapMiddleware = require('json-rpc-engine/src/idRemapMiddleware') const createStreamMiddleware = require('json-rpc-middleware-stream') const LocalStorageStore = require('obs-store') +const asStream = require('obs-store/lib/asStream') const ObjectMultiplex = require('obj-multiplex') module.exports = MetamaskInpageProvider @@ -21,9 +22,10 @@ function MetamaskInpageProvider (connectionStream) { // subscribe to metamask public config (one-way) self.publicConfigStore = new LocalStorageStore({ storageKey: 'MetaMask-Config' }) + pump( mux.createStream('publicConfig'), - self.publicConfigStore, + asStream(self.publicConfigStore), (err) => logStreamDisconnectWarning('MetaMask PublicConfigStore', err) ) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a4c77e468..f9b7b4182 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3,6 +3,7 @@ const extend = require('xtend') const pump = require('pump') const Dnode = require('dnode') const ObservableStore = require('obs-store') +const asStream = require('obs-store/lib/asStream') const AccountTracker = require('./lib/account-tracker') const EthQuery = require('eth-query') const RpcEngine = require('json-rpc-engine') @@ -456,7 +457,7 @@ module.exports = class MetamaskController extends EventEmitter { setupPublicConfig (outStream) { pump( - this.publicConfigStore, + asStream(this.publicConfigStore), outStream, (err) => { if (err) log.error(err) -- cgit From f0f6bb28e0e721c0f802354b72f02ed83afbb3b5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 28 Nov 2017 15:16:04 -0800 Subject: Get notice version filtering working nicely --- app/scripts/metamask-controller.js | 1 + app/scripts/notice-controller.js | 51 ++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 24 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0c759010b..c9eb27fbf 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -45,6 +45,7 @@ module.exports = class MetamaskController extends EventEmitter { this.opts = opts const initState = opts.initState || {} this.recordFirstTimeInfo(initState) + opts.initState.firstTimeInfo.version = '4.5.0' // platform-specific api this.platform = opts.platform diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index 457161ccb..efad3e516 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -3,6 +3,7 @@ const semver = require('semver') const extend = require('xtend') const ObservableStore = require('obs-store') const hardCodedNotices = require('../../notices/notices.json') +const uniqBy = require('lodash.uniqby') module.exports = class NoticeController extends EventEmitter { @@ -10,6 +11,7 @@ module.exports = class NoticeController extends EventEmitter { super() this.noticePoller = null this.firstVersion = opts.firstVersion + this.version = opts.version const initState = extend({ noticesList: [], }, opts.initState) @@ -32,9 +34,9 @@ module.exports = class NoticeController extends EventEmitter { return unreadNotices[unreadNotices.length - 1] } - setNoticesList (noticesList) { + async setNoticesList (noticesList) { this.store.updateState({ noticesList }) - return Promise.resolve(true) + return true } markNoticeRead (noticeToMark, cb) { @@ -52,21 +54,14 @@ module.exports = class NoticeController extends EventEmitter { } } - updateNoticesList () { - return this._retrieveNoticeData().then((hardNotices) => { - const newNotices = hardNotices.filter((newNotice) => { - if ('version' in newNotice) { - return semver.satisfies(this.version, newNotice.version) - } - if ('firstVersion' in newNotice) { - return semver.satisfies(this.firstVersion, newNotice.firstVersion) - } - return true - }) - var oldNotices = this.getNoticesList() - var combinedNotices = this._mergeNotices(oldNotices, newNotices) - return Promise.resolve(this.setNoticesList(combinedNotices)) - }) + async updateNoticesList () { + const newNotices = await this._retrieveNoticeData() + const oldNotices = this.getNoticesList() + const combinedNotices = this._mergeNotices(oldNotices, newNotices) + const filteredNotices = this._filterNotices(combinedNotices) + const result = this.setNoticesList(filteredNotices) + this._updateMemstore() + return result } startPolling () { @@ -79,22 +74,30 @@ module.exports = class NoticeController extends EventEmitter { } _mergeNotices (oldNotices, newNotices) { - var noticeMap = this._mapNoticeIds(oldNotices) - newNotices.forEach((notice) => { - if (noticeMap.indexOf(notice.id) === -1) { - oldNotices.push(notice) + return uniqBy(oldNotices.concat(newNotices), 'id') + } + + _filterNotices( notices ) { + return notices.filter((newNotice) => { + if ('version' in newNotice) { + const satisfied = semver.satisfies(this.version, newNotice.version) + return satisfied + } + if ('firstVersion' in newNotice) { + const satisfied = semver.satisfies(this.firstVersion, newNotice.firstVersion) + return satisfied } + return true }) - return oldNotices } _mapNoticeIds (notices) { return notices.map((notice) => notice.id) } - _retrieveNoticeData () { + async _retrieveNoticeData () { // Placeholder for the API. - return Promise.resolve(hardCodedNotices) + return hardCodedNotices } _updateMemstore () { -- cgit From 049ec52a95d0323c2b79cbd785582c5d6a90cb52 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 28 Nov 2017 15:29:56 -0800 Subject: Add seed phrase bounty award notice Only shows to people who installed before or equal to MetaMask 3.12.1 --- app/scripts/metamask-controller.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c9eb27fbf..0c759010b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -45,7 +45,6 @@ module.exports = class MetamaskController extends EventEmitter { this.opts = opts const initState = opts.initState || {} this.recordFirstTimeInfo(initState) - opts.initState.firstTimeInfo.version = '4.5.0' // platform-specific api this.platform = opts.platform -- cgit From bd82b173106d8b6d4c7b47a4f6c30d59b76bf8c5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 28 Nov 2017 15:35:20 -0800 Subject: Linted --- app/scripts/metamask-controller.js | 2 +- app/scripts/notice-controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0c759010b..94831e8ef 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -486,7 +486,7 @@ module.exports = class MetamaskController extends EventEmitter { vault = await this.keyringController.fullUpdate() } else { - let vault = await this.keyringController.createNewVaultAndKeychain(password) + vault = await this.keyringController.createNewVaultAndKeychain(password) this.selectFirstIdentity(vault) } release() diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index efad3e516..db2b8c4f4 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -77,7 +77,7 @@ module.exports = class NoticeController extends EventEmitter { return uniqBy(oldNotices.concat(newNotices), 'id') } - _filterNotices( notices ) { + _filterNotices(notices) { return notices.filter((newNotice) => { if ('version' in newNotice) { const satisfied = semver.satisfies(this.version, newNotice.version) -- cgit From ab35a76a240dc0139761678028aa8c187345ab49 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 28 Nov 2017 16:56:45 -0800 Subject: Migrate old data to include firstVersion info --- app/scripts/migrations/020.js | 40 ++++++++++++++++++++++++++++++++++++++++ app/scripts/migrations/index.js | 1 + 2 files changed, 41 insertions(+) create mode 100644 app/scripts/migrations/020.js (limited to 'app') diff --git a/app/scripts/migrations/020.js b/app/scripts/migrations/020.js new file mode 100644 index 000000000..59b9be7b3 --- /dev/null +++ b/app/scripts/migrations/020.js @@ -0,0 +1,40 @@ +const version = 20 + +/* + +This migration sets transactions as failed +whos nonce is too high + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + if ('metamask' in newState && + !('firstTimeInfo' in newState.metamask)) { + newState.metamask.firstTimeInfo = { + version: '3.12.0', + date: Date.now(), + } + } + return newState +} + diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index e9cbd7b98..9d0631042 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -30,4 +30,5 @@ module.exports = [ require('./017'), require('./018'), require('./019'), + require('./020'), ] -- cgit From 8192c0b58ccdb7b045093656cfbd53b0a7cffae9 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 29 Nov 2017 11:51:27 -0800 Subject: Fix migration comment --- app/scripts/migrations/020.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/migrations/020.js b/app/scripts/migrations/020.js index 59b9be7b3..8159b3e70 100644 --- a/app/scripts/migrations/020.js +++ b/app/scripts/migrations/020.js @@ -2,8 +2,9 @@ const version = 20 /* -This migration sets transactions as failed -whos nonce is too high +This migration ensures previous installations +get a `firstTimeInfo` key on the metamask state, +so that we can version notices in the future. */ -- cgit From 9ca6f93ecae53d59e61c4dd777558ebde24a49ee Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 29 Nov 2017 12:50:12 -0800 Subject: Bump version to 3.12.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index b6ff3d1cb..4219f3298 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.12.0", + "version": "3.12.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 7f795240706c013dc4a9ece0e9c9e33897c7fc71 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 14 Nov 2017 12:34:55 -0330 Subject: Add UI selection --- app/scripts/controllers/preferences.js | 17 +++++++++++++++++ app/scripts/metamask-controller.js | 1 + app/scripts/popup.js | 1 + 3 files changed, 19 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 0aed4dbdf..0dd9eae1b 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -10,6 +10,7 @@ class PreferencesController { currentAccountTab: 'history', tokens: [], useBlockie: false, + featureFlags: {}, }, opts.initState) this.store = new ObservableStore(initState) } @@ -100,6 +101,22 @@ class PreferencesController { getFrequentRpcList () { return this.store.getState().frequentRpcList } + + setFeatureFlag (feature, activated) { + const currentFeatureFlags = this.store.getState().featureFlags + const updatedFeatureFlags = { + ...currentFeatureFlags, + [feature]: activated, + } + + this.store.updateState({ featureFlags: updatedFeatureFlags }) + console.log(`!!! updatedFeatureFlags`, updatedFeatureFlags); + return Promise.resolve(updatedFeatureFlags) + } + + getFeatureFlags () { + return this.store.getState().featureFlags + } // // PRIVATE METHODS // diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4dce89e3a..8966ba393 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -341,6 +341,7 @@ module.exports = class MetamaskController extends EventEmitter { addToken: nodeify(preferencesController.addToken, preferencesController), removeToken: nodeify(preferencesController.removeToken, preferencesController), setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab, preferencesController), + setFeatureFlag: nodeify(preferencesController.setFeatureFlag, preferencesController), // AddressController setAddressBook: nodeify(addressBookController.setAddressBook, addressBookController), diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 5f17f0651..8cef06931 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -12,6 +12,7 @@ const notificationManager = new NotificationManager() global.platform = new ExtensionPlatform() // inject css +console.log(`MetaMaskUiCss`, MetaMaskUiCss); const css = MetaMaskUiCss() injectCss(css) -- cgit From db06e7e649c5bdc98063bfeb7d7cbff999543c32 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 15 Nov 2017 14:09:54 -0330 Subject: Css selected in background based on betaUI state. --- app/scripts/popup.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 8cef06931..d0952af6a 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -1,5 +1,6 @@ const injectCss = require('inject-css') -const MetaMaskUiCss = require('../../ui/css') +const OldMetaMaskUiCss = require('../../old-ui/css') +const NewMetaMaskUiCss = require('../../ui/css') const startPopup = require('./popup-core') const PortStream = require('./lib/port-stream.js') const isPopupOrNotification = require('./lib/is-popup-or-notification') @@ -11,11 +12,6 @@ const notificationManager = new NotificationManager() // create platform global global.platform = new ExtensionPlatform() -// inject css -console.log(`MetaMaskUiCss`, MetaMaskUiCss); -const css = MetaMaskUiCss() -injectCss(css) - // identify window type (popup, notification) const windowType = isPopupOrNotification() global.METAMASK_UI_TYPE = windowType @@ -29,8 +25,21 @@ const connectionStream = new PortStream(extensionPort) const container = document.getElementById('app-content') startPopup({ container, connectionStream }, (err, store) => { if (err) return displayCriticalError(err) + + let betaUIState = store.getState().metamask.featureFlags.betaUI + let css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss() + let deleteInjectedCss = injectCss(css) + let newBetaUIState + store.subscribe(() => { const state = store.getState() + newBetaUIState = state.metamask.featureFlags.betaUI + if (newBetaUIState !== betaUIState) { + deleteInjectedCss() + betaUIState = newBetaUIState + css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss() + deleteInjectedCss = injectCss(css) + } if (state.appState.shouldClose) notificationManager.closePopup() }) }) -- cgit From 84321b2d9b08a2b0f3e773cfb6f6d11dff9f7d4c Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 16 Nov 2017 15:58:59 -0330 Subject: Lint fix --- app/scripts/controllers/preferences.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 0dd9eae1b..de9006044 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -110,7 +110,7 @@ class PreferencesController { } this.store.updateState({ featureFlags: updatedFeatureFlags }) - console.log(`!!! updatedFeatureFlags`, updatedFeatureFlags); + return Promise.resolve(updatedFeatureFlags) } -- cgit From 03f86acd60655cf73a8f52dbe503df71e9d2b718 Mon Sep 17 00:00:00 2001 From: William Chong Date: Tue, 5 Dec 2017 19:25:35 +0800 Subject: fix #1398, prevent injecting xml without xml suffix --- app/scripts/contentscript.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index ffbbc73cc..2ed7c87b6 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -96,7 +96,7 @@ function logStreamDisconnectWarning (remoteLabel, err) { } function shouldInjectWeb3 () { - return doctypeCheck() || suffixCheck() + return doctypeCheck() && suffixCheck() && documentElementCheck() } function doctypeCheck () { @@ -104,7 +104,7 @@ function doctypeCheck () { if (doctype) { return doctype.name === 'html' } else { - return false + return true } } @@ -121,6 +121,14 @@ function suffixCheck () { return true } +function documentElementCheck () { + var documentElement = document.documentElement.nodeName + if (documentElement) { + return documentElement.toLowerCase() === 'html' + } + return true +} + function redirectToPhishingWarning () { console.log('MetaMask - redirecting to phishing warning') window.location.href = 'https://metamask.io/phishing.html' -- cgit From ae2a4d78e8c7733da1963965e38e154351d54a20 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 5 Dec 2017 17:21:14 -0330 Subject: Exponentional backoff on transaction retry in pending-tx-tracker --- app/scripts/controllers/transactions.js | 6 ++++++ app/scripts/lib/pending-tx-tracker.js | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index a861c0342..063ba8f65 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -72,6 +72,12 @@ module.exports = class TransactionController extends EventEmitter { }) this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) this.pendingTxTracker.on('tx:confirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) + this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => { + if (!txMeta.firstRetryBlockNumber) { + txMeta.firstRetryBlockNumber = latestBlockNumber + this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry') + } + }) this.pendingTxTracker.on('tx:retry', (txMeta) => { if (!('retryCount' in txMeta)) txMeta.retryCount = 0 txMeta.retryCount++ diff --git a/app/scripts/lib/pending-tx-tracker.js b/app/scripts/lib/pending-tx-tracker.js index 0d7c6a92c..60c837040 100644 --- a/app/scripts/lib/pending-tx-tracker.js +++ b/app/scripts/lib/pending-tx-tracker.js @@ -65,7 +65,7 @@ module.exports = class PendingTransactionTracker extends EventEmitter { } - resubmitPendingTxs () { + resubmitPendingTxs (block) { const pending = this.getPendingTransactions() // only try resubmitting if their are transactions to resubmit if (!pending.length) return @@ -101,13 +101,25 @@ module.exports = class PendingTransactionTracker extends EventEmitter { })) } - async _resubmitTx (txMeta) { + async _resubmitTx (txMeta, latestBlockNumber) { + if (!txMeta.firstRetryBlockNumber) { + this.emit('tx:block-update', txMeta, latestBlockNumber) + } + if (Date.now() > txMeta.time + this.retryTimePeriod) { const hours = (this.retryTimePeriod / 3.6e+6).toFixed(1) const err = new Error(`Gave up submitting after ${hours} hours.`) return this.emit('tx:failed', txMeta.id, err) } + const firstRetryBlockNumber = txMeta.firstRetryBlockNumber + const txBlockDistance = Number.parseInt(latestBlockNumber, 16) - Number.parseInt(firstRetryBlockNumber, 16) + + const retryCount = txMeta.retryCount || 0 + + // Exponential backoff to limit retries at publishing + if (txBlockDistance <= Math.pow(2, retryCount) - 1) return + // Only auto-submit already-signed txs: if (!('rawTx' in txMeta)) return -- cgit From 871d9fd9fb8417a2dd47abafe68ae07e4903ba6e Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Dec 2017 13:02:38 -0330 Subject: Fix undefined latestBlockNumber in _resubmitTx --- app/scripts/lib/pending-tx-tracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/pending-tx-tracker.js b/app/scripts/lib/pending-tx-tracker.js index 60c837040..62d621ac1 100644 --- a/app/scripts/lib/pending-tx-tracker.js +++ b/app/scripts/lib/pending-tx-tracker.js @@ -69,7 +69,7 @@ module.exports = class PendingTransactionTracker extends EventEmitter { const pending = this.getPendingTransactions() // only try resubmitting if their are transactions to resubmit if (!pending.length) return - pending.forEach((txMeta) => this._resubmitTx(txMeta).catch((err) => { + pending.forEach((txMeta) => this._resubmitTx(txMeta, block.number).catch((err) => { /* Dont marked as failed if the error is a "known" transaction warning "there is already a transaction with the same sender-nonce -- cgit From ea23da9e75c92cbf82d0daa19847d2035361a656 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Dec 2017 13:07:31 -0330 Subject: Correct note for updateTx after block-update event in transaction.js --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 063ba8f65..ce709bd28 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -75,7 +75,7 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => { if (!txMeta.firstRetryBlockNumber) { txMeta.firstRetryBlockNumber = latestBlockNumber - this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry') + this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:block-update') } }) this.pendingTxTracker.on('tx:retry', (txMeta) => { -- cgit From f58aae3f2ba3d8a129b2c09dc3b45369c488fd04 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Dec 2017 13:21:09 -0330 Subject: firstRetryBlockNumber defaults to latestBlockNumber if undefined on txMeta in _resubmitTx --- app/scripts/lib/pending-tx-tracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/pending-tx-tracker.js b/app/scripts/lib/pending-tx-tracker.js index 62d621ac1..dc6e526fd 100644 --- a/app/scripts/lib/pending-tx-tracker.js +++ b/app/scripts/lib/pending-tx-tracker.js @@ -112,7 +112,7 @@ module.exports = class PendingTransactionTracker extends EventEmitter { return this.emit('tx:failed', txMeta.id, err) } - const firstRetryBlockNumber = txMeta.firstRetryBlockNumber + const firstRetryBlockNumber = txMeta.firstRetryBlockNumber || latestBlockNumber const txBlockDistance = Number.parseInt(latestBlockNumber, 16) - Number.parseInt(firstRetryBlockNumber, 16) const retryCount = txMeta.retryCount || 0 -- cgit From 7854321faeeb8184b3171e3b214f57d6e61c0814 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Wed, 6 Dec 2017 22:49:24 +0100 Subject: Fix for #2644 - Specified Nonce isn't used Added nonceSpecified. And a check if nonce was specified - then we should use the specified nonce instead of generating a new one. --- app/scripts/controllers/transactions.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ce709bd28..060484b87 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -177,6 +177,7 @@ module.exports = class TransactionController extends EventEmitter { const txParams = txMeta.txParams // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) + txMeta.nonceSpecified = Boolean(txParams.nonce) const gasPrice = txParams.gasPrice || await this.query.gasPrice() txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' @@ -200,7 +201,11 @@ module.exports = class TransactionController extends EventEmitter { // wait for a nonce nonceLock = await this.nonceTracker.getNonceLock(fromAddress) // add nonce to txParams - txMeta.txParams.nonce = ethUtil.addHexPrefix(nonceLock.nextNonce.toString(16)) + if (txMeta.nonceSpecified) { + txMeta.txParams.nonce = ethUtil.addHexPrefix(txMeta.txParams.nonce.toString(16)) + } else { + txMeta.txParams.nonce = ethUtil.addHexPrefix(nonceLock.nextNonce.toString(16)) + } // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction') -- cgit From 6ff580584a74c6d85f54ce7cfc500db822904957 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 22:20:11 -0500 Subject: Add retry background method and action --- app/scripts/controllers/transactions.js | 4 ++++ app/scripts/lib/tx-state-manager.js | 4 ++++ app/scripts/metamask-controller.js | 1 + 3 files changed, 9 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ce709bd28..67043b401 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -184,6 +184,10 @@ module.exports = class TransactionController extends EventEmitter { return await this.txGasUtil.analyzeGasUsage(txMeta) } + async retryTransaction (txId) { + return this.txStateManager.setTxStatusUnapproved(txId) + } + async updateAndApproveTransaction (txMeta) { this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction') await this.approveTransaction(txMeta.id) diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 0fd6bed4b..cc441c584 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -187,6 +187,10 @@ module.exports = class TransactionStateManger extends EventEmitter { this._setTxStatus(txId, 'rejected') } + // should update the status of the tx to 'unapproved'. + setTxStatusUnapproved (txId) { + this._setTxStatus(txId, 'unapproved') + } // should update the status of the tx to 'approved'. setTxStatusApproved (txId) { this._setTxStatus(txId, 'approved') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 130ad1471..3a8100d12 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -363,6 +363,7 @@ module.exports = class MetamaskController extends EventEmitter { // txController cancelTransaction: nodeify(txController.cancelTransaction, txController), updateAndApproveTransaction: nodeify(txController.updateAndApproveTransaction, txController), + retryTransaction: nodeify(txController.retryTransaction, txController), // messageManager signMessage: nodeify(this.signMessage, this), -- cgit From 31564e0a86072ae2b49923dcf28983075308c432 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 23:20:15 -0500 Subject: Fix retry action --- app/scripts/metamask-controller.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 3a8100d12..9d126b416 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -363,7 +363,7 @@ module.exports = class MetamaskController extends EventEmitter { // txController cancelTransaction: nodeify(txController.cancelTransaction, txController), updateAndApproveTransaction: nodeify(txController.updateAndApproveTransaction, txController), - retryTransaction: nodeify(txController.retryTransaction, txController), + retryTransaction: nodeify(this.retryTransaction, this), // messageManager signMessage: nodeify(this.signMessage, this), @@ -574,6 +574,14 @@ module.exports = class MetamaskController extends EventEmitter { // // Identity Management // + // + + async retryTransaction (txId, cb) { + await this.txController.retryTransaction(txId) + const state = await this.getState() + return state + } + newUnsignedMessage (msgParams, cb) { const msgId = this.messageManager.addUnapprovedMessage(msgParams) -- cgit From 0e25129028dd45d717d27dfe0c06db8a4052bd4e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 23:42:47 -0500 Subject: Enforce retry tx at minimum gas of previous tx --- app/scripts/controllers/transactions.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 67043b401..685db6269 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -185,7 +185,10 @@ module.exports = class TransactionController extends EventEmitter { } async retryTransaction (txId) { - return this.txStateManager.setTxStatusUnapproved(txId) + this.txStateManager.setTxStatusUnapproved(txId) + const txMeta = this.txStateManager.getTx(txId) + txMeta.lastGasPrice = txMeta.txParams.gasPrice + this.txStateManager.updateTx(txMeta, 'retryTransaction: manual retry') } async updateAndApproveTransaction (txMeta) { -- cgit From ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 5 Dec 2017 13:11:59 -0330 Subject: Merge branch 'master' into NewUI-flat-merge-with-master --- app/scripts/background.js | 9 ++++---- app/scripts/controllers/network.js | 2 +- app/scripts/inpage.js | 7 ++++++ app/scripts/lib/inpage-provider.js | 4 +++- app/scripts/metamask-controller.js | 47 ++++++++++++++++++++++++++++++++++---- app/scripts/migrations/020.js | 41 +++++++++++++++++++++++++++++++++ app/scripts/migrations/index.js | 1 + app/scripts/notice-controller.js | 44 +++++++++++++++++++++++------------ 8 files changed, 129 insertions(+), 26 deletions(-) create mode 100644 app/scripts/migrations/020.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 3e560d302..da022c490 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -1,10 +1,11 @@ const urlUtil = require('url') const endOfStream = require('end-of-stream') -const pipe = require('pump') +const pump = require('pump') const log = require('loglevel') const extension = require('extensionizer') const LocalStorageStore = require('obs-store/lib/localStorage') const storeTransform = require('obs-store/lib/transform') +const asStream = require('obs-store/lib/asStream') const ExtensionPlatform = require('./platforms/extension') const Migrator = require('./lib/migrator/') const migrations = require('./migrations/') @@ -72,10 +73,10 @@ function setupController (initState) { global.metamaskController = controller // setup state persistence - pipe( - controller.store, + pump( + asStream(controller.store), storeTransform(versionifyData), - diskStore + asStream(diskStore) ) function versionifyData (state) { diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 23afdc12b..045bfcc5d 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -53,7 +53,7 @@ module.exports = class NetworkController extends EventEmitter { lookupNetwork () { // Prevent firing when provider is not defined. if (!this.ethQuery || !this.ethQuery.sendAsync) { - return + return log.warn('NetworkController - lookupNetwork aborted due to missing ethQuery') } this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { if (err) return this.setNetworkState('loading') diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index b6889b00f..9261e7d64 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -31,6 +31,13 @@ var inpageProvider = new MetamaskInpageProvider(metamaskStream) // setup web3 // +if (typeof window.web3 !== 'undefined') { + throw new Error(`MetaMask detected another web3. + MetaMask will not work reliably with another web3 extension. + This usually happens if you have two MetaMasks installed, + or MetaMask and another web3 extension. Please remove one + and try again.`) +} var web3 = new Web3(inpageProvider) web3.setProvider = function () { log.debug('MetaMask - overrode web3.setProvider') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index da75c4be2..99cc5d2cf 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -3,6 +3,7 @@ const RpcEngine = require('json-rpc-engine') const createIdRemapMiddleware = require('json-rpc-engine/src/idRemapMiddleware') const createStreamMiddleware = require('json-rpc-middleware-stream') const LocalStorageStore = require('obs-store') +const asStream = require('obs-store/lib/asStream') const ObjectMultiplex = require('obj-multiplex') module.exports = MetamaskInpageProvider @@ -21,9 +22,10 @@ function MetamaskInpageProvider (connectionStream) { // subscribe to metamask public config (one-way) self.publicConfigStore = new LocalStorageStore({ storageKey: 'MetaMask-Config' }) + pump( mux.createStream('publicConfig'), - self.publicConfigStore, + asStream(self.publicConfigStore), (err) => logStreamDisconnectWarning('MetaMask PublicConfigStore', err) ) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4dce89e3a..a96d20d3b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3,6 +3,7 @@ const extend = require('xtend') const pump = require('pump') const Dnode = require('dnode') const ObservableStore = require('obs-store') +const asStream = require('obs-store/lib/asStream') const AccountTracker = require('./lib/account-tracker') const EthQuery = require('eth-query') const RpcEngine = require('json-rpc-engine') @@ -31,6 +32,7 @@ const ConfigManager = require('./lib/config-manager') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') const getBuyEthUrl = require('./lib/buy-eth-url') +const Mutex = require('await-semaphore').Mutex const version = require('../manifest.json').version module.exports = class MetamaskController extends EventEmitter { @@ -38,10 +40,12 @@ module.exports = class MetamaskController extends EventEmitter { constructor (opts) { super() + this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) this.opts = opts const initState = opts.initState || {} + this.recordFirstTimeInfo(initState) // platform-specific api this.platform = opts.platform @@ -49,6 +53,9 @@ module.exports = class MetamaskController extends EventEmitter { // observable state store this.store = new ObservableStore(initState) + // lock to ensure only one vault created at once + this.createVaultMutex = new Mutex() + // network store this.networkController = new NetworkController(initState.NetworkController) @@ -144,6 +151,8 @@ module.exports = class MetamaskController extends EventEmitter { // notices this.noticeController = new NoticeController({ initState: initState.NoticeController, + version, + firstVersion: initState.firstTimeInfo.version, }) this.noticeController.updateNoticesList() // to be uncommented when retrieving notices from a remote server. @@ -453,7 +462,7 @@ module.exports = class MetamaskController extends EventEmitter { setupPublicConfig (outStream) { pump( - this.publicConfigStore, + asStream(this.publicConfigStore), outStream, (err) => { if (err) log.error(err) @@ -469,15 +478,34 @@ module.exports = class MetamaskController extends EventEmitter { // Vault Management // - async createNewVaultAndKeychain (password, cb) { - const vault = await this.keyringController.createNewVaultAndKeychain(password) - this.selectFirstIdentity(vault) + async createNewVaultAndKeychain (password) { + const release = await this.createVaultMutex.acquire() + let vault + + try { + const accounts = await this.keyringController.getAccounts() + + if (accounts.length > 0) { + vault = await this.keyringController.fullUpdate() + + } else { + vault = await this.keyringController.createNewVaultAndKeychain(password) + this.selectFirstIdentity(vault) + } + release() + } catch (err) { + release() + throw err + } + return vault } - async createNewVaultAndRestore (password, seed, cb) { + async createNewVaultAndRestore (password, seed) { + const release = await this.createVaultMutex.acquire() const vault = await this.keyringController.createNewVaultAndRestore(password, seed) this.selectFirstIdentity(vault) + release() return vault } @@ -784,4 +812,13 @@ module.exports = class MetamaskController extends EventEmitter { } } + recordFirstTimeInfo (initState) { + if (!('firstTimeInfo' in initState)) { + initState.firstTimeInfo = { + version, + date: Date.now(), + } + } + } + } diff --git a/app/scripts/migrations/020.js b/app/scripts/migrations/020.js new file mode 100644 index 000000000..8159b3e70 --- /dev/null +++ b/app/scripts/migrations/020.js @@ -0,0 +1,41 @@ +const version = 20 + +/* + +This migration ensures previous installations +get a `firstTimeInfo` key on the metamask state, +so that we can version notices in the future. + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + if ('metamask' in newState && + !('firstTimeInfo' in newState.metamask)) { + newState.metamask.firstTimeInfo = { + version: '3.12.0', + date: Date.now(), + } + } + return newState +} + diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index e9cbd7b98..9d0631042 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -30,4 +30,5 @@ module.exports = [ require('./017'), require('./018'), require('./019'), + require('./020'), ] diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index 57aad40c5..db2b8c4f4 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -1,13 +1,17 @@ const EventEmitter = require('events').EventEmitter +const semver = require('semver') const extend = require('xtend') const ObservableStore = require('obs-store') const hardCodedNotices = require('../../notices/notices.json') +const uniqBy = require('lodash.uniqby') module.exports = class NoticeController extends EventEmitter { constructor (opts) { super() this.noticePoller = null + this.firstVersion = opts.firstVersion + this.version = opts.version const initState = extend({ noticesList: [], }, opts.initState) @@ -30,9 +34,9 @@ module.exports = class NoticeController extends EventEmitter { return unreadNotices[unreadNotices.length - 1] } - setNoticesList (noticesList) { + async setNoticesList (noticesList) { this.store.updateState({ noticesList }) - return Promise.resolve(true) + return true } markNoticeRead (noticeToMark, cb) { @@ -50,12 +54,14 @@ module.exports = class NoticeController extends EventEmitter { } } - updateNoticesList () { - return this._retrieveNoticeData().then((newNotices) => { - var oldNotices = this.getNoticesList() - var combinedNotices = this._mergeNotices(oldNotices, newNotices) - return Promise.resolve(this.setNoticesList(combinedNotices)) - }) + async updateNoticesList () { + const newNotices = await this._retrieveNoticeData() + const oldNotices = this.getNoticesList() + const combinedNotices = this._mergeNotices(oldNotices, newNotices) + const filteredNotices = this._filterNotices(combinedNotices) + const result = this.setNoticesList(filteredNotices) + this._updateMemstore() + return result } startPolling () { @@ -68,22 +74,30 @@ module.exports = class NoticeController extends EventEmitter { } _mergeNotices (oldNotices, newNotices) { - var noticeMap = this._mapNoticeIds(oldNotices) - newNotices.forEach((notice) => { - if (noticeMap.indexOf(notice.id) === -1) { - oldNotices.push(notice) + return uniqBy(oldNotices.concat(newNotices), 'id') + } + + _filterNotices(notices) { + return notices.filter((newNotice) => { + if ('version' in newNotice) { + const satisfied = semver.satisfies(this.version, newNotice.version) + return satisfied + } + if ('firstVersion' in newNotice) { + const satisfied = semver.satisfies(this.firstVersion, newNotice.firstVersion) + return satisfied } + return true }) - return oldNotices } _mapNoticeIds (notices) { return notices.map((notice) => notice.id) } - _retrieveNoticeData () { + async _retrieveNoticeData () { // Placeholder for the API. - return Promise.resolve(hardCodedNotices) + return hardCodedNotices } _updateMemstore () { -- cgit From c391b25015b391d2818de067fa17ad3d9a3a9b30 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 7 Dec 2017 03:01:46 -0500 Subject: Version 3.13.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 4219f3298..aa23f85ff 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.12.1", + "version": "3.13.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 553d713636d317b74d819d62b5b931bdf2d112d8 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Thu, 7 Dec 2017 15:30:05 +0100 Subject: A more expressive way replaced ifs with ? : --- app/scripts/controllers/transactions.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 060484b87..6bdbd2cfc 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -201,11 +201,8 @@ module.exports = class TransactionController extends EventEmitter { // wait for a nonce nonceLock = await this.nonceTracker.getNonceLock(fromAddress) // add nonce to txParams - if (txMeta.nonceSpecified) { - txMeta.txParams.nonce = ethUtil.addHexPrefix(txMeta.txParams.nonce.toString(16)) - } else { - txMeta.txParams.nonce = ethUtil.addHexPrefix(nonceLock.nextNonce.toString(16)) - } + const nonce = txMeta.nonceSpecified ? txMeta.txParams.nonce : nonceLock.nextNonce + txMeta.txParams.nonce = ethUtil.addHexPrefix(nonce.toString(16)) // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction') -- cgit From 950ec9596c931055c3e0f2212f2733c9ca07739d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 7 Dec 2017 16:13:38 -0500 Subject: Do not allow nonces larger than the next valid nonce To avoid situations where a user signs a transaction that will become surprisingly valid in the future. --- app/scripts/controllers/transactions.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index bb408d445..6110b9c75 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -209,6 +209,10 @@ module.exports = class TransactionController extends EventEmitter { nonceLock = await this.nonceTracker.getNonceLock(fromAddress) // add nonce to txParams const nonce = txMeta.nonceSpecified ? txMeta.txParams.nonce : nonceLock.nextNonce + if (nonce > nonceLock.nextNonce) { + const message = `Specified nonce may not be larger than account's next valid nonce.` + throw new Error(message) + } txMeta.txParams.nonce = ethUtil.addHexPrefix(nonce.toString(16)) // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails -- cgit From dc4e3ef24185f3f4dae1fedc5840e36b703617d2 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 7 Dec 2017 16:17:33 -0500 Subject: Version 3.13.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index aa23f85ff..e95e75f6d 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.13.0", + "version": "3.13.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From a91200fd08b429c81d4096de17cdd9066a632ade Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 7 Dec 2017 18:04:14 -0500 Subject: tx-controller - failed state is a finished state --- app/scripts/controllers/transactions.js | 14 ++++++++------ app/scripts/lib/tx-state-manager.js | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 6110b9c75..f95b5e39a 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -138,18 +138,20 @@ module.exports = class TransactionController extends EventEmitter { async newUnapprovedTransaction (txParams) { log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) - const txMeta = await this.addUnapprovedTransaction(txParams) - this.emit('newUnapprovedTx', txMeta) + const initialTxMeta = await this.addUnapprovedTransaction(txParams) + this.emit('newUnapprovedTx', initialTxMeta) // listen for tx completion (success, fail) return new Promise((resolve, reject) => { - this.txStateManager.once(`${txMeta.id}:finished`, (completedTx) => { - switch (completedTx.status) { + this.txStateManager.once(`${initialTxMeta.id}:finished`, (finishedTxMeta) => { + switch (finishedTxMeta.status) { case 'submitted': - return resolve(completedTx.hash) + return resolve(finishedTxMeta.hash) case 'rejected': return reject(new Error('MetaMask Tx Signature: User denied transaction signature.')) + case 'failed': + return reject(new Error(finishedTxMeta.err.message)) default: - return reject(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(completedTx.txParams)}`)) + return reject(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finishedTxMeta.txParams)}`)) } }) }) diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index cc441c584..a8ef39891 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -240,7 +240,7 @@ module.exports = class TransactionStateManger extends EventEmitter { txMeta.status = status this.emit(`${txMeta.id}:${status}`, txId) this.emit(`tx:status-update`, txId, status) - if (status === 'submitted' || status === 'rejected') { + if (['submitted', 'rejected', 'failed'].includes(status)) { this.emit(`${txMeta.id}:finished`, txMeta) } this.updateTx(txMeta, `txStateManager: setting status to ${status}`) -- cgit From 542e0035dd99d07f8a6613d231a36005c5b39825 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sat, 9 Dec 2017 19:58:09 -0500 Subject: Pass polling interval to zero client provider --- app/scripts/controllers/network.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 045bfcc5d..cee918796 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -106,7 +106,11 @@ module.exports = class NetworkController extends EventEmitter { } _configureStandardProvider (_providerParams) { - const providerParams = extend(this._baseProviderParams, _providerParams) + const providerParams = extend(this._baseProviderParams, _providerParams, { + engineParams: { + pollingInterval: 8000, + }, + }) const provider = createMetamaskProvider(providerParams) this._setProvider(provider) } -- cgit From 1ebd5140aaa3dfe98668fad3893834653c5f7109 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sat, 9 Dec 2017 20:00:54 -0500 Subject: Version 3.13.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index e95e75f6d..a5645bb7c 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.13.1", + "version": "3.13.2", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 05c6789030791bd1b46434cf89c1817db37e8f38 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 8 Dec 2017 21:18:08 -0330 Subject: Adds button for opening app in main browser window in extension. --- app/images/open.svg | 15 +++++++++++++++ app/scripts/platforms/extension.js | 5 +++++ 2 files changed, 20 insertions(+) create mode 100644 app/images/open.svg (limited to 'app') diff --git a/app/images/open.svg b/app/images/open.svg new file mode 100644 index 000000000..2957ce43d --- /dev/null +++ b/app/images/open.svg @@ -0,0 +1,15 @@ + + + + open + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 2f47512eb..f5cc255d1 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -17,6 +17,11 @@ class ExtensionPlatform { return extension.runtime.getManifest().version } + openExtensionInBrowser () { + const extensionURL = extension.runtime.getURL('home.html') + this.openWindow({ url: extensionURL }) + } + getPlatformInfo (cb) { try { extension.runtime.getPlatformInfo((platform) => { -- cgit From da209a9cfda60b3acd567ac1c0b3bb535cc6e2e8 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 13 Dec 2017 11:18:43 -0800 Subject: dont aggresively query account data --- app/scripts/lib/account-tracker.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index ce6642150..8c3dd8c71 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -117,8 +117,6 @@ class AccountTracker extends EventEmitter { const query = this._query async.parallel({ balance: query.getBalance.bind(query, address), - nonce: query.getTransactionCount.bind(query, address), - code: query.getCode.bind(query, address), }, cb) } -- cgit From 33e6befdaa1c3f969581117b3ad6136ee263e353 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 13 Dec 2017 13:51:36 -0800 Subject: network - for infura networks use the infura block tracker provider --- app/scripts/controllers/network.js | 57 +++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index cee918796..65d58008a 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -1,6 +1,7 @@ const assert = require('assert') const EventEmitter = require('events') const createMetamaskProvider = require('web3-provider-engine/zero.js') +const createInfuraProvider = require('eth-json-rpc-infura/src/createProvider') const ObservableStore = require('obs-store') const ComposedStore = require('obs-store/lib/composed') const extend = require('xtend') @@ -8,6 +9,7 @@ const EthQuery = require('eth-query') const createEventEmitterProxy = require('../lib/events-proxy.js') const RPC_ADDRESS_LIST = require('../config.js').network const DEFAULT_RPC = RPC_ADDRESS_LIST['rinkeby'] +const INFURA_PROVIDER_TYPES = ['ropsten', 'rinkeby', 'kovan', 'mainnet'] module.exports = class NetworkController extends EventEmitter { @@ -24,8 +26,13 @@ module.exports = class NetworkController extends EventEmitter { initializeProvider (_providerParams) { this._baseProviderParams = _providerParams - const rpcUrl = this.getCurrentRpcAddress() - this._configureStandardProvider({ rpcUrl }) + const { type, rpcTarget } = this.providerStore.getState() + // map rpcTarget to rpcUrl + const opts = { + type, + rpcUrl: rpcTarget, + } + this._configureProvider(opts) this._proxy.on('block', this._logBlock.bind(this)) this._proxy.on('error', this.verifyNetwork.bind(this)) this.ethQuery = new EthQuery(this._proxy) @@ -83,7 +90,7 @@ module.exports = class NetworkController extends EventEmitter { const rpcTarget = this.getRpcAddressForType(type) assert(rpcTarget, `NetworkController - unknown rpc address for type "${type}"`) this.providerStore.updateState({ type, rpcTarget }) - this._switchNetwork({ rpcUrl: rpcTarget }) + this._switchNetwork({ type }) } getProviderConfig () { @@ -99,14 +106,50 @@ module.exports = class NetworkController extends EventEmitter { // Private // - _switchNetwork (providerParams) { + _switchNetwork (opts) { this.setNetworkState('loading') - this._configureStandardProvider(providerParams) + this._configureProvider(opts) this.emit('networkDidChange') } - _configureStandardProvider (_providerParams) { - const providerParams = extend(this._baseProviderParams, _providerParams, { + _configureProvider (opts) { + // type-based rpc endpoints + const { type } = opts + if (type) { + // type-based infura rpc endpoints + const isInfura = INFURA_PROVIDER_TYPES.includes(type) + opts.rpcUrl = this.getRpcAddressForType(type) + if (isInfura) { + this._configureInfuraProvider(opts) + // other type-based rpc endpoints + } else { + this._configureStandardProvider(opts) + } + // url-based rpc endpoints + } else { + this._configureStandardProvider(opts) + } + } + + _configureInfuraProvider (opts) { + console.log('_configureInfuraProvider', opts) + const blockTrackerProvider = createInfuraProvider({ + network: opts.type, + }) + const providerParams = extend(this._baseProviderParams, { + rpcUrl: opts.rpcUrl, + engineParams: { + pollingInterval: 8000, + blockTrackerProvider, + }, + }) + const provider = createMetamaskProvider(providerParams) + this._setProvider(provider) + } + + _configureStandardProvider ({ rpcUrl }) { + const providerParams = extend(this._baseProviderParams, { + rpcUrl, engineParams: { pollingInterval: 8000, }, -- cgit From 5df7dcd758c5a16b503a5ee237970c05c7e990c9 Mon Sep 17 00:00:00 2001 From: Frankie Date: Wed, 13 Dec 2017 17:46:56 -0800 Subject: Revert "network - for infura networks use the infura block tracker provider" --- app/scripts/controllers/network.js | 57 +++++--------------------------------- 1 file changed, 7 insertions(+), 50 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 65d58008a..cee918796 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -1,7 +1,6 @@ const assert = require('assert') const EventEmitter = require('events') const createMetamaskProvider = require('web3-provider-engine/zero.js') -const createInfuraProvider = require('eth-json-rpc-infura/src/createProvider') const ObservableStore = require('obs-store') const ComposedStore = require('obs-store/lib/composed') const extend = require('xtend') @@ -9,7 +8,6 @@ const EthQuery = require('eth-query') const createEventEmitterProxy = require('../lib/events-proxy.js') const RPC_ADDRESS_LIST = require('../config.js').network const DEFAULT_RPC = RPC_ADDRESS_LIST['rinkeby'] -const INFURA_PROVIDER_TYPES = ['ropsten', 'rinkeby', 'kovan', 'mainnet'] module.exports = class NetworkController extends EventEmitter { @@ -26,13 +24,8 @@ module.exports = class NetworkController extends EventEmitter { initializeProvider (_providerParams) { this._baseProviderParams = _providerParams - const { type, rpcTarget } = this.providerStore.getState() - // map rpcTarget to rpcUrl - const opts = { - type, - rpcUrl: rpcTarget, - } - this._configureProvider(opts) + const rpcUrl = this.getCurrentRpcAddress() + this._configureStandardProvider({ rpcUrl }) this._proxy.on('block', this._logBlock.bind(this)) this._proxy.on('error', this.verifyNetwork.bind(this)) this.ethQuery = new EthQuery(this._proxy) @@ -90,7 +83,7 @@ module.exports = class NetworkController extends EventEmitter { const rpcTarget = this.getRpcAddressForType(type) assert(rpcTarget, `NetworkController - unknown rpc address for type "${type}"`) this.providerStore.updateState({ type, rpcTarget }) - this._switchNetwork({ type }) + this._switchNetwork({ rpcUrl: rpcTarget }) } getProviderConfig () { @@ -106,50 +99,14 @@ module.exports = class NetworkController extends EventEmitter { // Private // - _switchNetwork (opts) { + _switchNetwork (providerParams) { this.setNetworkState('loading') - this._configureProvider(opts) + this._configureStandardProvider(providerParams) this.emit('networkDidChange') } - _configureProvider (opts) { - // type-based rpc endpoints - const { type } = opts - if (type) { - // type-based infura rpc endpoints - const isInfura = INFURA_PROVIDER_TYPES.includes(type) - opts.rpcUrl = this.getRpcAddressForType(type) - if (isInfura) { - this._configureInfuraProvider(opts) - // other type-based rpc endpoints - } else { - this._configureStandardProvider(opts) - } - // url-based rpc endpoints - } else { - this._configureStandardProvider(opts) - } - } - - _configureInfuraProvider (opts) { - console.log('_configureInfuraProvider', opts) - const blockTrackerProvider = createInfuraProvider({ - network: opts.type, - }) - const providerParams = extend(this._baseProviderParams, { - rpcUrl: opts.rpcUrl, - engineParams: { - pollingInterval: 8000, - blockTrackerProvider, - }, - }) - const provider = createMetamaskProvider(providerParams) - this._setProvider(provider) - } - - _configureStandardProvider ({ rpcUrl }) { - const providerParams = extend(this._baseProviderParams, { - rpcUrl, + _configureStandardProvider (_providerParams) { + const providerParams = extend(this._baseProviderParams, _providerParams, { engineParams: { pollingInterval: 8000, }, -- cgit From 161aa66cb4c6791659a48738578aac1f8c0c1376 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 13 Dec 2017 18:57:27 -0800 Subject: Revert "Revert "network - for infura networks use the infura block tracker provider"" This reverts commit 5df7dcd758c5a16b503a5ee237970c05c7e990c9. --- app/scripts/controllers/network.js | 57 +++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index cee918796..65d58008a 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -1,6 +1,7 @@ const assert = require('assert') const EventEmitter = require('events') const createMetamaskProvider = require('web3-provider-engine/zero.js') +const createInfuraProvider = require('eth-json-rpc-infura/src/createProvider') const ObservableStore = require('obs-store') const ComposedStore = require('obs-store/lib/composed') const extend = require('xtend') @@ -8,6 +9,7 @@ const EthQuery = require('eth-query') const createEventEmitterProxy = require('../lib/events-proxy.js') const RPC_ADDRESS_LIST = require('../config.js').network const DEFAULT_RPC = RPC_ADDRESS_LIST['rinkeby'] +const INFURA_PROVIDER_TYPES = ['ropsten', 'rinkeby', 'kovan', 'mainnet'] module.exports = class NetworkController extends EventEmitter { @@ -24,8 +26,13 @@ module.exports = class NetworkController extends EventEmitter { initializeProvider (_providerParams) { this._baseProviderParams = _providerParams - const rpcUrl = this.getCurrentRpcAddress() - this._configureStandardProvider({ rpcUrl }) + const { type, rpcTarget } = this.providerStore.getState() + // map rpcTarget to rpcUrl + const opts = { + type, + rpcUrl: rpcTarget, + } + this._configureProvider(opts) this._proxy.on('block', this._logBlock.bind(this)) this._proxy.on('error', this.verifyNetwork.bind(this)) this.ethQuery = new EthQuery(this._proxy) @@ -83,7 +90,7 @@ module.exports = class NetworkController extends EventEmitter { const rpcTarget = this.getRpcAddressForType(type) assert(rpcTarget, `NetworkController - unknown rpc address for type "${type}"`) this.providerStore.updateState({ type, rpcTarget }) - this._switchNetwork({ rpcUrl: rpcTarget }) + this._switchNetwork({ type }) } getProviderConfig () { @@ -99,14 +106,50 @@ module.exports = class NetworkController extends EventEmitter { // Private // - _switchNetwork (providerParams) { + _switchNetwork (opts) { this.setNetworkState('loading') - this._configureStandardProvider(providerParams) + this._configureProvider(opts) this.emit('networkDidChange') } - _configureStandardProvider (_providerParams) { - const providerParams = extend(this._baseProviderParams, _providerParams, { + _configureProvider (opts) { + // type-based rpc endpoints + const { type } = opts + if (type) { + // type-based infura rpc endpoints + const isInfura = INFURA_PROVIDER_TYPES.includes(type) + opts.rpcUrl = this.getRpcAddressForType(type) + if (isInfura) { + this._configureInfuraProvider(opts) + // other type-based rpc endpoints + } else { + this._configureStandardProvider(opts) + } + // url-based rpc endpoints + } else { + this._configureStandardProvider(opts) + } + } + + _configureInfuraProvider (opts) { + console.log('_configureInfuraProvider', opts) + const blockTrackerProvider = createInfuraProvider({ + network: opts.type, + }) + const providerParams = extend(this._baseProviderParams, { + rpcUrl: opts.rpcUrl, + engineParams: { + pollingInterval: 8000, + blockTrackerProvider, + }, + }) + const provider = createMetamaskProvider(providerParams) + this._setProvider(provider) + } + + _configureStandardProvider ({ rpcUrl }) { + const providerParams = extend(this._baseProviderParams, { + rpcUrl, engineParams: { pollingInterval: 8000, }, -- cgit From 622a1f7f4a972b7ea665de941d61bedb5ff03331 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 14 Dec 2017 11:45:51 -0800 Subject: Version 3.13.3 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a5645bb7c..d6c57d681 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.13.2", + "version": "3.13.3", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 828734b977f7c26c249c81af73fc8eef0b66e416 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 14 Dec 2017 18:15:38 -0800 Subject: transactions:gas-utils - handle new type of estimateGas error --- app/scripts/lib/tx-gas-utils.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 7e72ea71d..56bee19f7 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -22,7 +22,11 @@ module.exports = class txProvideUtil { try { estimatedGasHex = await this.estimateTxGas(txMeta, block.gasLimit) } catch (err) { - if (err.message.includes('Transaction execution error.')) { + const simulationFailed = ( + err.message.includes('Transaction execution error.') || + err.message.includes('gas required exceeds allowance or always failing transaction') + ) + if ( simulationFailed ) { txMeta.simulationFails = true return txMeta } -- cgit From fb8744771a78eabe98b5be7fb32af19666b107bd Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Fri, 15 Dec 2017 14:43:55 -0600 Subject: Change console.log for opts in _configureInfuraProvider --- app/scripts/controllers/network.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 65d58008a..377ba6eca 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -132,7 +132,7 @@ module.exports = class NetworkController extends EventEmitter { } _configureInfuraProvider (opts) { - console.log('_configureInfuraProvider', opts) + log.info('_configureInfuraProvider', opts) const blockTrackerProvider = createInfuraProvider({ network: opts.type, }) -- cgit From 10ff77477cf3163eaea5ac9485977d91bcc102c0 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sun, 17 Dec 2017 16:36:03 -0800 Subject: Add Recent Blocks controller Tracks recent blocks, useful for estimating recent successful gas prices. --- app/scripts/controllers/recent-blocks.js | 37 ++++++++++++++++++++++++++++++ app/scripts/metamask-controller.js | 39 ++++++++++++++++++++------------ 2 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 app/scripts/controllers/recent-blocks.js (limited to 'app') diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js new file mode 100644 index 000000000..27f9013ff --- /dev/null +++ b/app/scripts/controllers/recent-blocks.js @@ -0,0 +1,37 @@ +const ObservableStore = require('obs-store') +const extend = require('xtend') + +class RecentBlocksController { + + constructor (opts = {}) { + const { blockTracker } = opts + this.blockTracker = blockTracker + this.historyLength = opts.historyLength || 40 + + const initState = extend({ + recentBlocks: [], + }, opts.initState) + this.store = new ObservableStore(initState) + + this.blockTracker.on('block', this.processBlock.bind(this)) + } + + resetState () { + this.store.updateState({ + recentBlocks: [], + }) + } + + processBlock (newBlock) { + const state = this.store.getState() + state.recentBlocks.push(newBlock) + + while (state.recentBlocks.length > this.historyLength) { + state.recentBlocks.shift() + } + + this.store.updateState(state) + } +} + +module.exports = RecentBlocksController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 9d126b416..23f2a1598 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -23,6 +23,7 @@ const ShapeShiftController = require('./controllers/shapeshift') const AddressBookController = require('./controllers/address-book') const InfuraController = require('./controllers/infura') const BlacklistController = require('./controllers/blacklist') +const RecentBlocksController = require('./controllers/recent-blocks') const MessageManager = require('./lib/message-manager') const PersonalMessageManager = require('./lib/personal-message-manager') const TypedMessageManager = require('./lib/typed-message-manager') @@ -91,6 +92,10 @@ module.exports = class MetamaskController extends EventEmitter { this.provider = this.initializeProvider() this.blockTracker = this.provider._blockTracker + this.recentBlocksController = new RecentBlocksController({ + blockTracker: this.blockTracker, + }) + // eth data query tools this.ethQuery = new EthQuery(this.provider) // account tracker watches balances, nonces, and any code at their address. @@ -196,25 +201,30 @@ module.exports = class MetamaskController extends EventEmitter { this.blacklistController.store.subscribe((state) => { this.store.updateState({ BlacklistController: state }) }) + this.recentBlocksController.store.subscribe((state) => { + this.store.updateState({ RecentBlocks: state }) + }) this.infuraController.store.subscribe((state) => { this.store.updateState({ InfuraController: state }) }) // manual mem state subscriptions - this.networkController.store.subscribe(this.sendUpdate.bind(this)) - this.accountTracker.store.subscribe(this.sendUpdate.bind(this)) - this.txController.memStore.subscribe(this.sendUpdate.bind(this)) - this.balancesController.store.subscribe(this.sendUpdate.bind(this)) - this.messageManager.memStore.subscribe(this.sendUpdate.bind(this)) - this.personalMessageManager.memStore.subscribe(this.sendUpdate.bind(this)) - this.typedMessageManager.memStore.subscribe(this.sendUpdate.bind(this)) - this.keyringController.memStore.subscribe(this.sendUpdate.bind(this)) - this.preferencesController.store.subscribe(this.sendUpdate.bind(this)) - this.addressBookController.store.subscribe(this.sendUpdate.bind(this)) - this.currencyController.store.subscribe(this.sendUpdate.bind(this)) - this.noticeController.memStore.subscribe(this.sendUpdate.bind(this)) - this.shapeshiftController.store.subscribe(this.sendUpdate.bind(this)) - this.infuraController.store.subscribe(this.sendUpdate.bind(this)) + const sendUpdate = this.sendUpdate.bind(this) + this.networkController.store.subscribe(sendUpdate) + this.accountTracker.store.subscribe(sendUpdate) + this.txController.memStore.subscribe(sendUpdate) + this.balancesController.store.subscribe(sendUpdate) + this.messageManager.memStore.subscribe(sendUpdate) + this.personalMessageManager.memStore.subscribe(sendUpdate) + this.typedMessageManager.memStore.subscribe(sendUpdate) + this.keyringController.memStore.subscribe(sendUpdate) + this.preferencesController.store.subscribe(sendUpdate) + this.recentBlocksController.store.subscribe(sendUpdate) + this.addressBookController.store.subscribe(sendUpdate) + this.currencyController.store.subscribe(sendUpdate) + this.noticeController.memStore.subscribe(sendUpdate) + this.shapeshiftController.store.subscribe(sendUpdate) + this.infuraController.store.subscribe(sendUpdate) } // @@ -298,6 +308,7 @@ module.exports = class MetamaskController extends EventEmitter { this.currencyController.store.getState(), this.noticeController.memStore.getState(), this.infuraController.store.getState(), + this.recentBlocksController.store.getState(), // config manager this.configManager.getConfig(), this.shapeshiftController.store.getState(), -- cgit From 975f7279c713d88bb59205073540b2185f3a812f Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 18 Dec 2017 15:57:04 -0800 Subject: Allow updating token details Fixes #2173 --- app/scripts/controllers/preferences.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index bc4848421..c42f47037 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -26,23 +26,23 @@ class PreferencesController { return this.store.getState().selectedAddress } - addToken (rawAddress, symbol, decimals) { + async addToken (rawAddress, symbol, decimals) { const address = normalizeAddress(rawAddress) const newEntry = { address, symbol, decimals } const tokens = this.store.getState().tokens - const previousIndex = tokens.find((token, index) => { + const previousEntry = tokens.find((token, index) => { return token.address === address }) + const previousIndex = tokens.indexOf(previousEntry) - if (previousIndex) { + if (previousEntry) { tokens[previousIndex] = newEntry } else { tokens.push(newEntry) } this.store.updateState({ tokens }) - return Promise.resolve() } getTokens () { -- cgit From 30b45c8a385e9ae4c6b78d0a7ec6929f7bad4d9a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 19 Dec 2017 12:22:48 -0800 Subject: Do not log whole txs in recent block controller. Only record gas prices, because that has a current use. --- app/scripts/controllers/recent-blocks.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js index 27f9013ff..4a906261e 100644 --- a/app/scripts/controllers/recent-blocks.js +++ b/app/scripts/controllers/recent-blocks.js @@ -23,8 +23,15 @@ class RecentBlocksController { } processBlock (newBlock) { + const block = extend(newBlock, { + gasPrices: newBlock.transactions.map((tx) => { + return tx.gasPrice + }), + }) + delete block.transactions + const state = this.store.getState() - state.recentBlocks.push(newBlock) + state.recentBlocks.push(block) while (state.recentBlocks.length > this.historyLength) { state.recentBlocks.shift() -- cgit From f47e81e4937871a7a690e357443a728b9049b8f0 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 19 Dec 2017 14:28:02 -0800 Subject: transactions - throw error if dapp provides txParams whos value has a decimal --- app/scripts/lib/tx-gas-utils.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 56bee19f7..c00323a64 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -81,8 +81,15 @@ module.exports = class txProvideUtil { } async validateTxParams (txParams) { - if (('value' in txParams) && txParams.value.indexOf('-') === 0) { - throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`) + if ('value' in txParams) { + const value = txParams.value.toString() + if (value.indexOf('-') === 0) { + throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`) + } + + if (value.indexOf('.') >= 0) { + throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`) + } } } } -- cgit From 1f1fc2c49ecbb5c6a0a1d925d5c02cf48f795b2f Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 19 Dec 2017 11:16:11 -0330 Subject: Canceled, edited transactions show edited amount. --- app/scripts/controllers/transactions.js | 5 +++++ app/scripts/metamask-controller.js | 1 + 2 files changed, 6 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ce709bd28..0d6b97d51 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -189,6 +189,11 @@ module.exports = class TransactionController extends EventEmitter { await this.approveTransaction(txMeta.id) } + async updateAndCancelTransaction (txMeta) { + this.txStateManager.updateTx(txMeta, 'confTx: user rejected transaction') + await this.cancelTransaction(txMeta.id) + } + async approveTransaction (txId) { let nonceLock try { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 018eb2c76..935a3e76e 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -366,6 +366,7 @@ module.exports = class MetamaskController extends EventEmitter { // txController cancelTransaction: nodeify(txController.cancelTransaction, txController), updateAndApproveTransaction: nodeify(txController.updateAndApproveTransaction, txController), + updateAndCancelTransaction: nodeify(txController.updateAndCancelTransaction, txController), // messageManager signMessage: nodeify(this.signMessage, this), -- cgit From bf4043c59bb67ea93599207d91cb7a4f4426e75f Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 13:47:16 -0330 Subject: Adds updateTransaction to background and used it to update after editing in send-v2. --- app/scripts/controllers/transactions.js | 9 ++++----- app/scripts/metamask-controller.js | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 0d6b97d51..5b687f67a 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -184,16 +184,15 @@ module.exports = class TransactionController extends EventEmitter { return await this.txGasUtil.analyzeGasUsage(txMeta) } + async updateTransaction (txMeta) { + this.txStateManager.updateTx(txMeta, 'confTx: user updated transaction') + } + async updateAndApproveTransaction (txMeta) { this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction') await this.approveTransaction(txMeta.id) } - async updateAndCancelTransaction (txMeta) { - this.txStateManager.updateTx(txMeta, 'confTx: user rejected transaction') - await this.cancelTransaction(txMeta.id) - } - async approveTransaction (txId) { let nonceLock try { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 935a3e76e..a2d584cf9 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -365,8 +365,8 @@ module.exports = class MetamaskController extends EventEmitter { // txController cancelTransaction: nodeify(txController.cancelTransaction, txController), + updateTransaction: nodeify(txController.updateTransaction, txController), updateAndApproveTransaction: nodeify(txController.updateAndApproveTransaction, txController), - updateAndCancelTransaction: nodeify(txController.updateAndCancelTransaction, txController), // messageManager signMessage: nodeify(this.signMessage, this), -- cgit From 75b8baafb6f2e9a38a52d46c71c6dcca03635886 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 21 Dec 2017 13:40:04 -0800 Subject: Stop failing pending transactions after any period of time --- app/scripts/lib/pending-tx-tracker.js | 7 ------- 1 file changed, 7 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/pending-tx-tracker.js b/app/scripts/lib/pending-tx-tracker.js index dc6e526fd..7956a3329 100644 --- a/app/scripts/lib/pending-tx-tracker.js +++ b/app/scripts/lib/pending-tx-tracker.js @@ -23,7 +23,6 @@ module.exports = class PendingTransactionTracker extends EventEmitter { this.query = new EthQuery(config.provider) this.nonceTracker = config.nonceTracker // default is one day - this.retryTimePeriod = config.retryTimePeriod || 86400000 this.getPendingTransactions = config.getPendingTransactions this.getCompletedTransactions = config.getCompletedTransactions this.publishTransaction = config.publishTransaction @@ -106,12 +105,6 @@ module.exports = class PendingTransactionTracker extends EventEmitter { this.emit('tx:block-update', txMeta, latestBlockNumber) } - if (Date.now() > txMeta.time + this.retryTimePeriod) { - const hours = (this.retryTimePeriod / 3.6e+6).toFixed(1) - const err = new Error(`Gave up submitting after ${hours} hours.`) - return this.emit('tx:failed', txMeta.id, err) - } - const firstRetryBlockNumber = txMeta.firstRetryBlockNumber || latestBlockNumber const txBlockDistance = Number.parseInt(latestBlockNumber, 16) - Number.parseInt(firstRetryBlockNumber, 16) -- cgit From 33dbee3db9f6d66777039579789f36618c95c5fe Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 21 Dec 2017 14:15:17 -0800 Subject: Remove retryTimePeriod from tx controller --- app/scripts/controllers/transactions.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index f95b5e39a..7c7efb84d 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -59,7 +59,6 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker = new PendingTransactionTracker({ provider: this.provider, nonceTracker: this.nonceTracker, - retryTimePeriod: 86400000, // Retry 3500 blocks, or about 1 day. publishTransaction: (rawTx) => this.query.sendRawTransaction(rawTx), getPendingTransactions: this.txStateManager.getPendingTransactions.bind(this.txStateManager), getCompletedTransactions: this.txStateManager.getConfirmedTransactions.bind(this.txStateManager), -- cgit From a218008adf85dfb5fa8ca93c789e14d9f2090813 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 22 Dec 2017 10:43:02 -0800 Subject: Track usage of old and new UI (#2794) [NewUI] Track usage of old and new UI --- app/scripts/config.js | 22 +++++++++++++++++++++ app/scripts/controllers/network.js | 40 ++++++++++++++++++++++++++++++++------ app/scripts/metamask-controller.js | 1 + 3 files changed, 57 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/scripts/config.js b/app/scripts/config.js index 1d4ff7c0d..74c5b576e 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -4,6 +4,15 @@ const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask' const RINKEBY_RPC_URL = 'https://rinkeby.infura.io/metamask' const LOCALHOST_RPC_URL = 'http://localhost:8545' +const MAINET_RPC_URL_BETA = 'https://mainnet.infura.io/metamask2' +const ROPSTEN_RPC_URL_BETA = 'https://ropsten.infura.io/metamask2' +const KOVAN_RPC_URL_BETA = 'https://kovan.infura.io/metamask2' +const RINKEBY_RPC_URL_BETA = 'https://rinkeby.infura.io/metamask2' + +const DEFAULT_RPC = 'rinkeby' +const OLD_UI_NETWORK_TYPE = 'network' +const BETA_UI_NETWORK_TYPE = 'networkBeta' + global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' module.exports = { @@ -14,9 +23,22 @@ module.exports = { kovan: KOVAN_RPC_URL, rinkeby: RINKEBY_RPC_URL, }, + // Used for beta UI + networkBeta: { + localhost: LOCALHOST_RPC_URL, + mainnet: MAINET_RPC_URL_BETA, + ropsten: ROPSTEN_RPC_URL_BETA, + kovan: KOVAN_RPC_URL_BETA, + rinkeby: RINKEBY_RPC_URL_BETA, + }, networkNames: { 3: 'Ropsten', 4: 'Rinkeby', 42: 'Kovan', }, + enums: { + DEFAULT_RPC, + OLD_UI_NETWORK_TYPE, + BETA_UI_NETWORK_TYPE, + }, } diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 377ba6eca..db1a5b374 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -7,14 +7,19 @@ const ComposedStore = require('obs-store/lib/composed') const extend = require('xtend') const EthQuery = require('eth-query') const createEventEmitterProxy = require('../lib/events-proxy.js') -const RPC_ADDRESS_LIST = require('../config.js').network -const DEFAULT_RPC = RPC_ADDRESS_LIST['rinkeby'] +const networkConfig = require('../config.js') +const { OLD_UI_NETWORK_TYPE, DEFAULT_RPC } = networkConfig.enums const INFURA_PROVIDER_TYPES = ['ropsten', 'rinkeby', 'kovan', 'mainnet'] module.exports = class NetworkController extends EventEmitter { constructor (config) { super() + + this._networkEndpointVersion = OLD_UI_NETWORK_TYPE + this._networkEndpoints = this.getNetworkEndpoints(OLD_UI_NETWORK_TYPE) + this._defaultRpc = this._networkEndpoints[DEFAULT_RPC] + config.provider.rpcTarget = this.getRpcAddressForType(config.provider.type, config.provider) this.networkStore = new ObservableStore('loading') this.providerStore = new ObservableStore(config.provider) @@ -24,6 +29,23 @@ module.exports = class NetworkController extends EventEmitter { this.on('networkDidChange', this.lookupNetwork) } + async setNetworkEndpoints (version) { + if (version === this._networkEndpointVersion) { + return + } + + this._networkEndpointVersion = version + this._networkEndpoints = this.getNetworkEndpoints(version) + this._defaultRpc = this._networkEndpoints[DEFAULT_RPC] + const { type } = this.getProviderConfig() + + return this.setProviderType(type, true) + } + + getNetworkEndpoints (version = OLD_UI_NETWORK_TYPE) { + return networkConfig[version] + } + initializeProvider (_providerParams) { this._baseProviderParams = _providerParams const { type, rpcTarget } = this.providerStore.getState() @@ -83,10 +105,13 @@ module.exports = class NetworkController extends EventEmitter { return this.getRpcAddressForType(provider.type) } - async setProviderType (type) { + async setProviderType (type, forceUpdate = false) { assert(type !== 'rpc', `NetworkController.setProviderType - cannot connect by type "rpc"`) // skip if type already matches - if (type === this.getProviderConfig().type) return + if (type === this.getProviderConfig().type && !forceUpdate) { + return + } + const rpcTarget = this.getRpcAddressForType(type) assert(rpcTarget, `NetworkController - unknown rpc address for type "${type}"`) this.providerStore.updateState({ type, rpcTarget }) @@ -98,8 +123,11 @@ module.exports = class NetworkController extends EventEmitter { } getRpcAddressForType (type, provider = this.getProviderConfig()) { - if (RPC_ADDRESS_LIST[type]) return RPC_ADDRESS_LIST[type] - return provider && provider.rpcTarget ? provider.rpcTarget : DEFAULT_RPC + if (this._networkEndpoints[type]) { + return this._networkEndpoints[type] + } + + return provider && provider.rpcTarget ? provider.rpcTarget : this._defaultRpc } // diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index e2a911598..b50a04703 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -353,6 +353,7 @@ module.exports = class MetamaskController extends EventEmitter { submitPassword: nodeify(keyringController.submitPassword, keyringController), // network management + setNetworkEndpoints: nodeify(networkController.setNetworkEndpoints, networkController), setProviderType: nodeify(networkController.setProviderType, networkController), setCustomRpc: nodeify(this.setCustomRpc, this), -- cgit From 8f6c322e0121ff1dd086086e5599c2ce8eadfe05 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 22 Dec 2017 10:56:31 -0800 Subject: Update manifest.json version from 4.0.4 to 4.0.5 (#2797) --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index ff595c717..8ae27fe8b 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.4", + "version": "4.0.5", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From a76324f6d397c3e746ba501cfd858c4869cb0af7 Mon Sep 17 00:00:00 2001 From: Ellie Day Date: Sat, 23 Dec 2017 08:23:34 -0600 Subject: Add ExtensionStore and add basic store instance syncing to main controller --- app/scripts/background.js | 12 ++++++++++++ app/scripts/lib/extension-store.js | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 app/scripts/lib/extension-store.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index da022c490..45da2f6d0 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -4,6 +4,7 @@ const pump = require('pump') const log = require('loglevel') const extension = require('extensionizer') const LocalStorageStore = require('obs-store/lib/localStorage') +const ExtensionStore = require('./lib/extension-store') const storeTransform = require('obs-store/lib/transform') const asStream = require('obs-store/lib/asStream') const ExtensionPlatform = require('./platforms/extension') @@ -28,6 +29,7 @@ let popupIsOpen = false // state persistence const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) +const extensionStore = new ExtensionStore() // initialization flow initialize().catch(log.error) @@ -45,8 +47,12 @@ async function initialize () { async function loadStateFromPersistence () { // migrations const migrator = new Migrator({ migrations }) + // fetch from extension store + const extensionData = await extensionStore.fetch() // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) // read from disk let versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) + // merge extension and versioned data + versionedData = { ...versionedData, ...extensionData } // migrate data versionedData = await migrator.migrateData(versionedData) // write to disk @@ -76,6 +82,7 @@ function setupController (initState) { pump( asStream(controller.store), storeTransform(versionifyData), + storeTransform(syncDataWithExtension), asStream(diskStore) ) @@ -85,6 +92,11 @@ function setupController (initState) { return versionedData } + function syncDataWithExtension(state) { + extensionStore.sync(state) // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) + return state + } + // // connect to other contexts // diff --git a/app/scripts/lib/extension-store.js b/app/scripts/lib/extension-store.js new file mode 100644 index 000000000..a8b730a65 --- /dev/null +++ b/app/scripts/lib/extension-store.js @@ -0,0 +1,20 @@ +const extension = require('extensionizer') + +const KEYS_TO_SYNC = ['KeyringController', 'PreferencesController'] + +module.exports = class ExtensionStore { + async fetch() { + return new Promise((resolve) => { + extension.storage.sync.get(KEYS_TO_SYNC, data => resolve(data)) + }) + } + async sync(state) { + const dataToSync = KEYS_TO_SYNC.reduce((result, key) => { + result[key] = state.data[key] + return result + }, {}) + return new Promise((resolve) => { + extension.storage.sync.set(dataToSync, () => resolve()) + }) + } +} -- cgit From 5efb0044d8e334d6c4ec2b5d68e830932eb96ed7 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 27 Dec 2017 16:50:15 -0800 Subject: transactions:pending - only check nonces of transactions who's from adress match the txMeta --- app/scripts/lib/pending-tx-tracker.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/pending-tx-tracker.js b/app/scripts/lib/pending-tx-tracker.js index 7956a3329..e8869e6b8 100644 --- a/app/scripts/lib/pending-tx-tracker.js +++ b/app/scripts/lib/pending-tx-tracker.js @@ -178,7 +178,8 @@ module.exports = class PendingTransactionTracker extends EventEmitter { } async _checkIfNonceIsTaken (txMeta) { - const completed = this.getCompletedTransactions() + const address = txMeta.txParams.from + const completed = this.getCompletedTransactions(address) const sameNonce = completed.filter((otherMeta) => { return otherMeta.txParams.nonce === txMeta.txParams.nonce }) -- cgit From 414f89668eb554e82ab22d3b3080322057388266 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 27 Dec 2017 17:27:48 -0800 Subject: Fix some silly linting issues. --- app/scripts/lib/tx-gas-utils.js | 2 +- app/scripts/notice-controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 56bee19f7..247b34e47 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -26,7 +26,7 @@ module.exports = class txProvideUtil { err.message.includes('Transaction execution error.') || err.message.includes('gas required exceeds allowance or always failing transaction') ) - if ( simulationFailed ) { + if (simulationFailed) { txMeta.simulationFails = true return txMeta } diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index db2b8c4f4..14a63eae7 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -77,7 +77,7 @@ module.exports = class NoticeController extends EventEmitter { return uniqBy(oldNotices.concat(newNotices), 'id') } - _filterNotices(notices) { + _filterNotices (notices) { return notices.filter((newNotice) => { if ('version' in newNotice) { const satisfied = semver.satisfies(this.version, newNotice.version) -- cgit From 3f6cef0b3f56edc8cc0b66403f23ae216de7bcfa Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 2 Jan 2018 14:22:44 -0800 Subject: tx-gas-utils - tx-param-validation - use more intuitive check --- app/scripts/lib/tx-gas-utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index c00323a64..bc891fc07 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -83,11 +83,11 @@ module.exports = class txProvideUtil { async validateTxParams (txParams) { if ('value' in txParams) { const value = txParams.value.toString() - if (value.indexOf('-') === 0) { + if (value.includes('-')) { throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`) } - if (value.indexOf('.') >= 0) { + if (value.includes('.')) { throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`) } } -- cgit From 7184db7632ef79d4bde0e643fdc1a4ee910c77fb Mon Sep 17 00:00:00 2001 From: Ellie Day Date: Tue, 2 Jan 2018 21:31:17 -0800 Subject: handle situation where storage.sync is disabled in certain versions of firefox --- app/scripts/background.js | 5 ++--- app/scripts/lib/extension-store.js | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 45da2f6d0..732f47590 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -47,11 +47,10 @@ async function initialize () { async function loadStateFromPersistence () { // migrations const migrator = new Migrator({ migrations }) - // fetch from extension store - const extensionData = await extensionStore.fetch() // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) // read from disk let versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) - // merge extension and versioned data + // fetch from extension store and merge in data + const extensionData = await extensionStore.fetch() // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) versionedData = { ...versionedData, ...extensionData } // migrate data versionedData = await migrator.migrateData(versionedData) diff --git a/app/scripts/lib/extension-store.js b/app/scripts/lib/extension-store.js index a8b730a65..dd0f82f36 100644 --- a/app/scripts/lib/extension-store.js +++ b/app/scripts/lib/extension-store.js @@ -1,11 +1,24 @@ const extension = require('extensionizer') const KEYS_TO_SYNC = ['KeyringController', 'PreferencesController'] +const FIREFOX_SYNC_DISABLED_MESSAGE = 'Please set webextensions.storage.sync.enabled to true in about:config' + +const handleDisabledSyncAndResolve = (resolve, toResolve) => { + // Firefox 52 has sync available on extension.storage, but it is disabled by default + const lastError = extension.runtime.lastError + if (lastError && lastError.message.includes(FIREFOX_SYNC_DISABLED_MESSAGE)) { + resolve({}) + } else { + resolve(toResolve) + } +} module.exports = class ExtensionStore { async fetch() { return new Promise((resolve) => { - extension.storage.sync.get(KEYS_TO_SYNC, data => resolve(data)) + extension.storage.sync.get(KEYS_TO_SYNC, (data) => { + handleDisabledSyncAndResolve(resolve, data) + }) }) } async sync(state) { @@ -14,7 +27,9 @@ module.exports = class ExtensionStore { return result }, {}) return new Promise((resolve) => { - extension.storage.sync.set(dataToSync, () => resolve()) + extension.storage.sync.set(dataToSync, () => { + handleDisabledSyncAndResolve(resolve) + }) }) } } -- cgit From 3c6a5b16ad37c83f548028d5b6fa3d0f75293ca5 Mon Sep 17 00:00:00 2001 From: Ellie Day Date: Tue, 2 Jan 2018 21:53:11 -0800 Subject: conditionally use extension store if supported or enabled --- app/scripts/background.js | 12 +++++++++--- app/scripts/lib/extension-store.js | 4 ++++ 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 732f47590..d9a2b0a6e 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -50,8 +50,12 @@ async function loadStateFromPersistence () { // read from disk let versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) // fetch from extension store and merge in data - const extensionData = await extensionStore.fetch() // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) - versionedData = { ...versionedData, ...extensionData } + + if (extensionStore.isSupported && extensionStore.isEnabled) { + const extensionData = await extensionStore.fetch() // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) + versionedData = { ...versionedData, ...extensionData } + } + // migrate data versionedData = await migrator.migrateData(versionedData) // write to disk @@ -92,7 +96,9 @@ function setupController (initState) { } function syncDataWithExtension(state) { - extensionStore.sync(state) // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) + if (extensionStore.isSupported && extensionStore.isEnabled) { + extensionStore.sync(state) // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) + } return state } diff --git a/app/scripts/lib/extension-store.js b/app/scripts/lib/extension-store.js index dd0f82f36..67ee71f16 100644 --- a/app/scripts/lib/extension-store.js +++ b/app/scripts/lib/extension-store.js @@ -14,6 +14,10 @@ const handleDisabledSyncAndResolve = (resolve, toResolve) => { } module.exports = class ExtensionStore { + constructor() { + this.isSupported = !!(extension.storage.sync) + this.isEnabled = true // TODO: get value from user settings + } async fetch() { return new Promise((resolve) => { extension.storage.sync.get(KEYS_TO_SYNC, (data) => { -- cgit From 20aa135ad87231694ead2fe65a3124b719b8fc4d Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 3 Jan 2018 16:06:46 -0800 Subject: Add fix for infinite spinner for incorrect seed phrase. --- app/scripts/metamask-controller.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 23f2a1598..8d8c1d094 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -513,10 +513,15 @@ module.exports = class MetamaskController extends EventEmitter { async createNewVaultAndRestore (password, seed) { const release = await this.createVaultMutex.acquire() - const vault = await this.keyringController.createNewVaultAndRestore(password, seed) - this.selectFirstIdentity(vault) - release() - return vault + try { + const vault = await this.keyringController.createNewVaultAndRestore(password, seed) + this.selectFirstIdentity(vault) + release() + return vault + } catch (err) { + release() + throw err + } } selectFirstIdentity (vault) { -- cgit From 4bca98d588869fb58796a6b2f29dca48605ceeba Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 5 Jan 2018 21:24:20 -0800 Subject: Derive gas price estimate from previous transactions Return the 50th percentile lowest gas price of the previous 20 blocks. --- app/scripts/controllers/blacklist.js | 1 + app/scripts/controllers/transactions.js | 3 ++- app/scripts/metamask-controller.js | 21 ++++++++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js index dd671943f..33c31dab9 100644 --- a/app/scripts/controllers/blacklist.js +++ b/app/scripts/controllers/blacklist.js @@ -57,3 +57,4 @@ class BlacklistController { } module.exports = BlacklistController + diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 7c7efb84d..be7e7221f 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -32,6 +32,7 @@ module.exports = class TransactionController extends EventEmitter { this.provider = opts.provider this.blockTracker = opts.blockTracker this.signEthTx = opts.signTransaction + this.getGasPrice = opts.getGasPrice this.memStore = new ObservableStore({}) this.query = new EthQuery(this.provider) @@ -179,7 +180,7 @@ module.exports = class TransactionController extends EventEmitter { // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) txMeta.nonceSpecified = Boolean(txParams.nonce) - const gasPrice = txParams.gasPrice || await this.query.gasPrice() + const gasPrice = txParams.gasPrice || this.getGasPrice() txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' // set gasLimit diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 23f2a1598..7ffa653e4 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -35,13 +35,15 @@ const accountImporter = require('./account-import-strategies') const getBuyEthUrl = require('./lib/buy-eth-url') const Mutex = require('await-semaphore').Mutex const version = require('../manifest.json').version +const BN = require('ethereumjs-util').BN +const GWEI_BN = new BN('1000000000') +const percentile = require('percentile') module.exports = class MetamaskController extends EventEmitter { constructor (opts) { super() - this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) this.opts = opts @@ -139,6 +141,7 @@ module.exports = class MetamaskController extends EventEmitter { provider: this.provider, blockTracker: this.blockTracker, ethQuery: this.ethQuery, + getGasPrice: this.getGasPrice.bind(this), }) this.txController.on('newUnapprovedTx', opts.showUnapprovedTx.bind(opts)) @@ -484,6 +487,22 @@ module.exports = class MetamaskController extends EventEmitter { this.emit('update', this.getState()) } + getGasPrice () { + const { recentBlocksController } = this + console.dir(recentBlocksController) + const { recentBlocks } = recentBlocksController.store.getState() + console.dir(recentBlocks) + const lowestPrices = recentBlocks.map((block) => { + return block.transactions + .sort((a, b) => { + return a.gt(b) ? 1 : -1 + })[0] + }) + .map(number => number.div(GWEI_BN).toNumber()) + console.dir({ lowestPrices }) + return percentile(50, lowestPrices) + } + // // Vault Management // -- cgit From 447682d1fbb07309c696217fba3839455721d003 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 5 Jan 2018 21:34:35 -0800 Subject: Linted --- app/scripts/metamask-controller.js | 3 --- 1 file changed, 3 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 7ffa653e4..79ad2ff05 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -489,9 +489,7 @@ module.exports = class MetamaskController extends EventEmitter { getGasPrice () { const { recentBlocksController } = this - console.dir(recentBlocksController) const { recentBlocks } = recentBlocksController.store.getState() - console.dir(recentBlocks) const lowestPrices = recentBlocks.map((block) => { return block.transactions .sort((a, b) => { @@ -499,7 +497,6 @@ module.exports = class MetamaskController extends EventEmitter { })[0] }) .map(number => number.div(GWEI_BN).toNumber()) - console.dir({ lowestPrices }) return percentile(50, lowestPrices) } -- cgit From aec24ec81e4785ceea93375d562458f62be69266 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 5 Jan 2018 22:08:03 -0800 Subject: Fix feature to work --- app/scripts/controllers/transactions.js | 3 ++- app/scripts/metamask-controller.js | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index be7e7221f..469deb670 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -180,7 +180,8 @@ module.exports = class TransactionController extends EventEmitter { // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) txMeta.nonceSpecified = Boolean(txParams.nonce) - const gasPrice = txParams.gasPrice || this.getGasPrice() + const gasPrice = txParams.gasPrice || this.getGasPrice ? this.getGasPrice() + : await this.query.gasPrice() txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' // set gasLimit diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 79ad2ff05..1b13f6567 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -491,13 +491,20 @@ module.exports = class MetamaskController extends EventEmitter { const { recentBlocksController } = this const { recentBlocks } = recentBlocksController.store.getState() const lowestPrices = recentBlocks.map((block) => { - return block.transactions + if (!block.gasPrices) { + return new BN(0) + } + return block.gasPrices + .map(hexPrefix => hexPrefix.substr(2)) + .map(hex => new BN(hex, 16)) .sort((a, b) => { return a.gt(b) ? 1 : -1 })[0] }) .map(number => number.div(GWEI_BN).toNumber()) - return percentile(50, lowestPrices) + const percentileNum = percentile(50, lowestPrices) + const percentileNumBn = new BN(percentileNum) + return '0x' + percentileNumBn.mul(GWEI_BN).toString(16) } // -- cgit From 39b700bf87f213d2fb06dcde85f4e6173a6ce70c Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 8 Jan 2018 03:16:20 -0800 Subject: Account for 0x/empty string address and contract creation --- app/scripts/lib/tx-gas-utils.js | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index ccf8bb1b1..5e49fdb22 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -81,6 +81,7 @@ module.exports = class txProvideUtil { } async validateTxParams (txParams) { + this.validateRecipient(txParams) if ('value' in txParams) { const value = txParams.value.toString() if (value.includes('-')) { @@ -92,4 +93,14 @@ module.exports = class txProvideUtil { } } } + validateRecipient (txParams) { + if (txParams.to === '0x') { + if (txParams.data) { + delete txParams.to + } else { + throw new Error('Invalid recipient address') + } + } + return txParams + } } -- cgit From 3b2a519d46b44b819c799741d44bc94022f4b6ed Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 8 Jan 2018 09:47:51 -0800 Subject: 4.0.9 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 8ae27fe8b..d65374330 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.5", + "version": "4.0.9", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 9a8670309d2791b212d04ee795f70040cc5f40fc Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 8 Jan 2018 13:19:18 -0800 Subject: bugfix - transactions controller - breakout logic and fix order of operations bug --- app/scripts/controllers/transactions.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 469deb670..ded9739a8 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -180,8 +180,10 @@ module.exports = class TransactionController extends EventEmitter { // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) txMeta.nonceSpecified = Boolean(txParams.nonce) - const gasPrice = txParams.gasPrice || this.getGasPrice ? this.getGasPrice() - : await this.query.gasPrice() + let gasPrice = txParams.gasPrice + if (!gasPrice) { + gasPrice = this.getGasPrice ? this.getGasPrice() : await this.query.gasPrice() + } txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' // set gasLimit -- cgit From 63ae7fb589b43d2af87f31d51f5b5f96669dabe0 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 8 Jan 2018 13:19:18 -0800 Subject: bugfix - transactions controller - breakout logic and fix order of operations bug --- app/scripts/controllers/transactions.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 469deb670..ded9739a8 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -180,8 +180,10 @@ module.exports = class TransactionController extends EventEmitter { // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) txMeta.nonceSpecified = Boolean(txParams.nonce) - const gasPrice = txParams.gasPrice || this.getGasPrice ? this.getGasPrice() - : await this.query.gasPrice() + let gasPrice = txParams.gasPrice + if (!gasPrice) { + gasPrice = this.getGasPrice ? this.getGasPrice() : await this.query.gasPrice() + } txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' // set gasLimit -- cgit From ab7701efb35f39e73fcccc2110a754384e23d695 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 8 Jan 2018 14:57:57 -0800 Subject: provider - infura - use infura REST api --- app/scripts/controllers/network.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 377ba6eca..a1db8946a 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -1,6 +1,7 @@ const assert = require('assert') const EventEmitter = require('events') const createMetamaskProvider = require('web3-provider-engine/zero.js') +const SubproviderFromProvider = require('web3-provider-engine/subproviders/web3.js') const createInfuraProvider = require('eth-json-rpc-infura/src/createProvider') const ObservableStore = require('obs-store') const ComposedStore = require('obs-store/lib/composed') @@ -133,15 +134,17 @@ module.exports = class NetworkController extends EventEmitter { _configureInfuraProvider (opts) { log.info('_configureInfuraProvider', opts) - const blockTrackerProvider = createInfuraProvider({ + const infuraProvider = createInfuraProvider({ network: opts.type, }) + const infuraSubprovider = new SubproviderFromProvider(infuraProvider) const providerParams = extend(this._baseProviderParams, { rpcUrl: opts.rpcUrl, engineParams: { pollingInterval: 8000, - blockTrackerProvider, + blockTrackerProvider: infuraProvider, }, + dataSubprovider: infuraSubprovider, }) const provider = createMetamaskProvider(providerParams) this._setProvider(provider) -- cgit From 0275231e13d49a9b71b85af389d2a9850229eacb Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 8 Jan 2018 15:08:05 -0800 Subject: Default gas estimate to 1 gwei for networks with no block activity --- app/scripts/metamask-controller.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 66738db51..9462af494 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -490,6 +490,12 @@ module.exports = class MetamaskController extends EventEmitter { getGasPrice () { const { recentBlocksController } = this const { recentBlocks } = recentBlocksController.store.getState() + + // Return 1 gwei if no blocks have been observed: + if (recentBlocks.length === 0) { + return '0x' + GWEI_BN.toString(16) + } + const lowestPrices = recentBlocks.map((block) => { if (!block.gasPrices) { return new BN(0) -- cgit From d829fb91b889f35a3e1043dec56d8f0ff6faa09d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 8 Jan 2018 15:41:57 -0800 Subject: Default to 1 gwei for empty blocks --- app/scripts/metamask-controller.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 9462af494..f62b5e5cd 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -497,8 +497,8 @@ module.exports = class MetamaskController extends EventEmitter { } const lowestPrices = recentBlocks.map((block) => { - if (!block.gasPrices) { - return new BN(0) + if (!block.gasPrices || block.gasPrices.length < 1) { + return GWEI_BN } return block.gasPrices .map(hexPrefix => hexPrefix.substr(2)) @@ -508,6 +508,7 @@ module.exports = class MetamaskController extends EventEmitter { })[0] }) .map(number => number.div(GWEI_BN).toNumber()) + const percentileNum = percentile(50, lowestPrices) const percentileNumBn = new BN(percentileNum) return '0x' + percentileNumBn.mul(GWEI_BN).toString(16) -- cgit From 330ae020287f4178b493619ede17ee0b1b67b7af Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 9 Jan 2018 10:13:25 -0800 Subject: Version 3.13.4 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index d6c57d681..df7b1f1aa 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.13.3", + "version": "3.13.4", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 9c42216c4e6059af131820fbd12e3b2df2d8edec Mon Sep 17 00:00:00 2001 From: x86kernel Date: Wed, 10 Jan 2018 21:06:20 +0900 Subject: ci(ko/messages.json): add korean localization file --- app/_locales/ko/messages.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 app/_locales/ko/messages.json (limited to 'app') diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json new file mode 100644 index 000000000..c58af4b80 --- /dev/null +++ b/app/_locales/ko/messages.json @@ -0,0 +1,10 @@ +{ + "appName": { + "message": "MetaMask", + "description": "The name of the application" + }, + "appDescription": { + "message": "이더리움 계좌 관리", + "description": "The description of the application" + } +} -- cgit From 208e94d3bfdaf5ab6f279fb2000f1a3d14920b1b Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 10 Jan 2018 21:09:09 -0800 Subject: Update main view styling --- app/images/metamask-fox.svg | 128 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 app/images/metamask-fox.svg (limited to 'app') diff --git a/app/images/metamask-fox.svg b/app/images/metamask-fox.svg new file mode 100644 index 000000000..f3c24f79e --- /dev/null +++ b/app/images/metamask-fox.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit From 4a9dad7c40b97f1e625931d6b57fc9d7fdc5080d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 11 Jan 2018 15:00:48 -0800 Subject: Improve gas price estimation by backfilling recent-blocks When first initializing, recent-block controller now back-fills up to its desired history length. This makes estimated gas prices reflect a longer recent history, even when first switching to a new network. Fixes #2925 --- app/scripts/controllers/recent-blocks.js | 79 +++++++++++++++++++++++++++++--- app/scripts/metamask-controller.js | 6 ++- 2 files changed, 76 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js index 4a906261e..c65c2b1c4 100644 --- a/app/scripts/controllers/recent-blocks.js +++ b/app/scripts/controllers/recent-blocks.js @@ -1,11 +1,13 @@ const ObservableStore = require('obs-store') const extend = require('xtend') +const BN = require('ethereumjs-util').BN class RecentBlocksController { constructor (opts = {}) { - const { blockTracker } = opts + const { blockTracker, ethQuery } = opts this.blockTracker = blockTracker + this.ethQuery = ethQuery this.historyLength = opts.historyLength || 40 const initState = extend({ @@ -14,6 +16,7 @@ class RecentBlocksController { this.store = new ObservableStore(initState) this.blockTracker.on('block', this.processBlock.bind(this)) + this.backfill() } resetState () { @@ -23,12 +26,7 @@ class RecentBlocksController { } processBlock (newBlock) { - const block = extend(newBlock, { - gasPrices: newBlock.transactions.map((tx) => { - return tx.gasPrice - }), - }) - delete block.transactions + const block = this.mapTransactionsToPrices(newBlock) const state = this.store.getState() state.recentBlocks.push(block) @@ -39,6 +37,73 @@ class RecentBlocksController { this.store.updateState(state) } + + backfillBlock (newBlock) { + const block = this.mapTransactionsToPrices(newBlock) + + const state = this.store.getState() + + if (state.recentBlocks.length < this.historyLength) { + state.recentBlocks.unshift(block) + } + + this.store.updateState(state) + } + + mapTransactionsToPrices (newBlock) { + const block = extend(newBlock, { + gasPrices: newBlock.transactions.map((tx) => { + return tx.gasPrice + }), + }) + delete block.transactions + return block + } + + async backfill() { + this.blockTracker.once('block', async (block) => { + let blockNum = block.number + let recentBlocks + let state = this.store.getState() + recentBlocks = state.recentBlocks + + while (recentBlocks.length < this.historyLength) { + try { + let blockNumBn = new BN(blockNum.substr(2), 16) + const newNum = blockNumBn.subn(1).toString(10) + const newBlock = await this.getBlockByNumber(newNum) + + if (newBlock) { + this.backfillBlock(newBlock) + blockNum = newBlock.number + } + + state = this.store.getState() + recentBlocks = state.recentBlocks + } catch (e) { + log.error(e) + } + await this.wait() + } + }) + } + + async wait () { + return new Promise((resolve) => { + setTimeout(resolve, 100) + }) + } + + async getBlockByNumber (number) { + const bn = new BN(number) + return new Promise((resolve, reject) => { + this.ethQuery.getBlockByNumber('0x' + bn.toString(16), true, (err, block) => { + if (err) reject(err) + resolve(block) + }) + }) + } + } module.exports = RecentBlocksController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index f62b5e5cd..81d70797a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -94,12 +94,14 @@ module.exports = class MetamaskController extends EventEmitter { this.provider = this.initializeProvider() this.blockTracker = this.provider._blockTracker + // eth data query tools + this.ethQuery = new EthQuery(this.provider) + this.recentBlocksController = new RecentBlocksController({ blockTracker: this.blockTracker, + ethQuery: this.ethQuery, }) - // eth data query tools - this.ethQuery = new EthQuery(this.provider) // account tracker watches balances, nonces, and any code at their address. this.accountTracker = new AccountTracker({ provider: this.provider, -- cgit From 7cb66ce4cba446f8149c4a8872dbdfbc53f72f7c Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 12 Jan 2018 10:25:36 -0800 Subject: Prefer passing a provider over an ethQuery instance --- app/scripts/controllers/recent-blocks.js | 5 +++-- app/scripts/metamask-controller.js | 7 +------ 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js index c65c2b1c4..4ae3810eb 100644 --- a/app/scripts/controllers/recent-blocks.js +++ b/app/scripts/controllers/recent-blocks.js @@ -1,13 +1,14 @@ const ObservableStore = require('obs-store') const extend = require('xtend') const BN = require('ethereumjs-util').BN +const EthQuery = require('eth-query') class RecentBlocksController { constructor (opts = {}) { - const { blockTracker, ethQuery } = opts + const { blockTracker, provider } = opts this.blockTracker = blockTracker - this.ethQuery = ethQuery + this.ethQuery = new EthQuery(provider) this.historyLength = opts.historyLength || 40 const initState = extend({ diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 81d70797a..000e17b9e 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -5,7 +5,6 @@ const Dnode = require('dnode') const ObservableStore = require('obs-store') const asStream = require('obs-store/lib/asStream') const AccountTracker = require('./lib/account-tracker') -const EthQuery = require('eth-query') const RpcEngine = require('json-rpc-engine') const debounce = require('debounce') const createEngineStream = require('json-rpc-middleware-stream/engineStream') @@ -94,12 +93,9 @@ module.exports = class MetamaskController extends EventEmitter { this.provider = this.initializeProvider() this.blockTracker = this.provider._blockTracker - // eth data query tools - this.ethQuery = new EthQuery(this.provider) - this.recentBlocksController = new RecentBlocksController({ blockTracker: this.blockTracker, - ethQuery: this.ethQuery, + provider: this.provider, }) // account tracker watches balances, nonces, and any code at their address. @@ -142,7 +138,6 @@ module.exports = class MetamaskController extends EventEmitter { signTransaction: this.keyringController.signTransaction.bind(this.keyringController), provider: this.provider, blockTracker: this.blockTracker, - ethQuery: this.ethQuery, getGasPrice: this.getGasPrice.bind(this), }) this.txController.on('newUnapprovedTx', opts.showUnapprovedTx.bind(opts)) -- cgit From 5c1dcf3e9bdb317dd8b42aadb18657eb4bfa2e0f Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 12 Jan 2018 16:18:18 -0330 Subject: [NewUI-flat] New deposit ether modal UI. (#2642) * New deposit ether modal. * New deposit modal full screen on mobile, and other style fixes. * Hide shapeshift option from deposit modal for now. * Add shapeshift form to new deposit modal. * Store recipient address for shapeshift tx in background. * Use Simpledropdown to achieve desired styling in coin selector. * Lint fix * Fix typos and remove dead code. * Remove storage of shapeshift receiving address from background. * Fix typos --- app/images/coinbase logo.png | Bin 0 -> 9775 bytes app/images/shapeshift logo.png | Bin 0 -> 17537 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/images/coinbase logo.png create mode 100644 app/images/shapeshift logo.png (limited to 'app') diff --git a/app/images/coinbase logo.png b/app/images/coinbase logo.png new file mode 100644 index 000000000..a23d7926d Binary files /dev/null and b/app/images/coinbase logo.png differ diff --git a/app/images/shapeshift logo.png b/app/images/shapeshift logo.png new file mode 100644 index 000000000..ac8faba5b Binary files /dev/null and b/app/images/shapeshift logo.png differ -- cgit From bdcee058dc278c46c828f376476f121417481385 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Tue, 9 Jan 2018 16:45:39 -0800 Subject: Fix styling in initialization --- app/scripts/popup.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/popup.js b/app/scripts/popup.js index d0952af6a..97a29fb1a 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -26,8 +26,13 @@ const container = document.getElementById('app-content') startPopup({ container, connectionStream }, (err, store) => { if (err) return displayCriticalError(err) - let betaUIState = store.getState().metamask.featureFlags.betaUI - let css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss() + const { isMascara, identities = {}, featureFlags = {} } = store.getState().metamask + const firstTime = Object.keys(identities).length === 0 + let betaUIState = featureFlags.betaUI + + const useBetaCss = isMascara || firstTime || betaUIState + + let css = useBetaCss ? NewMetaMaskUiCss() : OldMetaMaskUiCss() let deleteInjectedCss = injectCss(css) let newBetaUIState -- cgit From f0dd4f19238d63875fbdfa3a9b31fa7b9d8925ed Mon Sep 17 00:00:00 2001 From: frankiebee Date: Sun, 14 Jan 2018 14:00:17 -0800 Subject: transactions - emit 'newUnapprovedTx' before estimateGas finishes --- app/scripts/controllers/transactions.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ded9739a8..bb9253175 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -139,7 +139,6 @@ module.exports = class TransactionController extends EventEmitter { async newUnapprovedTransaction (txParams) { log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) const initialTxMeta = await this.addUnapprovedTransaction(txParams) - this.emit('newUnapprovedTx', initialTxMeta) // listen for tx completion (success, fail) return new Promise((resolve, reject) => { this.txStateManager.once(`${initialTxMeta.id}:finished`, (finishedTxMeta) => { @@ -167,11 +166,16 @@ module.exports = class TransactionController extends EventEmitter { status: 'unapproved', metamaskNetworkId: this.getNetwork(), txParams: txParams, + loadingDefaults: true, } + this.addTx(txMeta) + this.emit('newUnapprovedTx', txMeta) // add default tx params await this.addTxDefaults(txMeta) + + txMeta.loadingDefaults = false // save txMeta - this.addTx(txMeta) + this.txStateManager.updateTx(txMeta) return txMeta } -- cgit From aa833a09281960bfc0af5032034021c25c26a7fd Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Mon, 15 Jan 2018 17:53:44 -0330 Subject: [NewUI] Place all users of extension into old UI (disable auto adding). (#2946) * Place all users of extension into old UI (disable auto adding). * Fix lint errors. --- app/scripts/popup.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 97a29fb1a..1a2e425dc 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -26,11 +26,15 @@ const container = document.getElementById('app-content') startPopup({ container, connectionStream }, (err, store) => { if (err) return displayCriticalError(err) - const { isMascara, identities = {}, featureFlags = {} } = store.getState().metamask - const firstTime = Object.keys(identities).length === 0 + // Code commented out until we begin auto adding users to NewUI + // const { isMascara, identities = {}, featureFlags = {} } = store.getState().metamask + // const firstTime = Object.keys(identities).length === 0 + const { isMascara, featureFlags = {} } = store.getState().metamask let betaUIState = featureFlags.betaUI - const useBetaCss = isMascara || firstTime || betaUIState + // Code commented out until we begin auto adding users to NewUI + // const useBetaCss = isMascara || firstTime || betaUIState + const useBetaCss = isMascara || betaUIState let css = useBetaCss ? NewMetaMaskUiCss() : OldMetaMaskUiCss() let deleteInjectedCss = injectCss(css) -- cgit From cd7eaaa735aa084cec0c4a647edf89bc5e4b2ec7 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 15 Jan 2018 15:08:07 -0800 Subject: Set gas limit to 21k for recipients with no code Fixes #2907 --- app/scripts/lib/tx-gas-utils.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 5e49fdb22..d57c70b10 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -4,6 +4,7 @@ const { BnMultiplyByFraction, bnToHex, } = require('./util') +const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. /* tx-utils are utility methods for Transaction manager @@ -37,14 +38,30 @@ module.exports = class txProvideUtil { async estimateTxGas (txMeta, blockGasLimitHex) { const txParams = txMeta.txParams + // check if gasLimit is already specified txMeta.gasLimitSpecified = Boolean(txParams.gas) - // if not, fallback to block gasLimit - if (!txMeta.gasLimitSpecified) { - const blockGasLimitBN = hexToBn(blockGasLimitHex) - const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20) - txParams.gas = bnToHex(saferGasLimitBN) + + // if it is, use that value + if (txMeta.gasLimitSpecified) { + return txParams.gas } + + // if recipient has no code, gas is 21k max: + const recipient = txParams.to + const hasRecipient = Boolean(recipient) + const code = await this.query.getCode(recipient) + if (hasRecipient && (!code || code === '0x')) { + txParams.gas = SIMPLE_GAS_COST + txMeta.gasLimitSpecified = true // Prevents buffer addition + return SIMPLE_GAS_COST + } + + // if not, fall back to block gasLimit + const blockGasLimitBN = hexToBn(blockGasLimitHex) + const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20) + txParams.gas = bnToHex(saferGasLimitBN) + // run tx return await this.query.estimateGas(txParams) } -- cgit From 8fb62b97c5b0901c7e4402d49538db87396c8579 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 Jan 2018 11:05:11 -0800 Subject: Create new flag for simple sends to avoid overloading other flag --- app/scripts/lib/tx-gas-utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index d57c70b10..e80e0467e 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -53,7 +53,7 @@ module.exports = class txProvideUtil { const code = await this.query.getCode(recipient) if (hasRecipient && (!code || code === '0x')) { txParams.gas = SIMPLE_GAS_COST - txMeta.gasLimitSpecified = true // Prevents buffer addition + txMeta.simpleSend = true // Prevents buffer addition return SIMPLE_GAS_COST } @@ -72,7 +72,7 @@ module.exports = class txProvideUtil { // if gasLimit was specified and doesnt OOG, // use original specified amount - if (txMeta.gasLimitSpecified) { + if (txMeta.gasLimitSpecified || txMeta.simpleSend) { txMeta.estimatedGas = txParams.gas return } -- cgit From 41fdff41cd83f9c954be0f8b8bd66586a8b8a968 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 Jan 2018 12:20:15 -0800 Subject: Version 3.13.5 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index df7b1f1aa..3b6fc6b20 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.13.4", + "version": "3.13.5", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 7d1554b1c14a04077285bec20ebad0f2f9381164 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 17 Jan 2018 14:04:37 -0800 Subject: sentry - add raven + sentry reporting config --- app/scripts/background.js | 5 +++++ app/scripts/raven.min.js | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 app/scripts/raven.min.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index da022c490..9d9fbf892 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -14,6 +14,11 @@ const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') const firstTimeState = require('./first-time-state') +// raven / sentry error catching START +const Raven = require('./raven.min.js') +Raven.config('https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496').install() +// raven / sentry error catching END + const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' diff --git a/app/scripts/raven.min.js b/app/scripts/raven.min.js new file mode 100644 index 000000000..b6094a65f --- /dev/null +++ b/app/scripts/raven.min.js @@ -0,0 +1,3 @@ +/*! Raven.js 3.19.1 (aa94a44) | github.com/getsentry/raven-js */ +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;gthis.k.maxBreadcrumbs&&this.t.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.q.push([a,b]),this.m&&this.C(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.Q("extra",a),this},setTagsContext:function(a){return this.Q("tags",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(h(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=e(b,a),this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=e(b,a),this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=e(b,a),this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.y("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var a=H.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(I){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new i("Missing eventId");var c=a.dsn||this.E;if(!c)throw new i("Missing DSN");var d=encodeURIComponent,e="";e+="?eventId="+d(b),e+="&dsn="+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+="&name="+d(f.name)),f.email&&(e+="&email="+d(f.email)));var g=this.G(this.D(c)),h=I.createElement("script");h.async=!0,h.src=g+"/api/embed/error-page/"+e,(I.head||I.body).appendChild(h)}},I:function(){var a=this;this.l+=1,setTimeout(function(){a.l-=1})},R:function(a,b){var c,d;if(this.b){b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),I.createEvent?(c=I.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=I.createEventObject(),c.eventType=a);for(d in b)v(b,d)&&(c[d]=b[d]);if(I.createEvent)I.dispatchEvent(c);else try{I.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}},S:function(a){var b=this;return function(c){if(b.T=null,b.u!==c){b.u=c;var d;try{d=z(c.target)}catch(e){d=""}b.captureBreadcrumb({category:"ui."+a,message:d})}}},U:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&("INPUT"===f||"TEXTAREA"===f||d.isContentEditable)){var g=a.T;g||a.S("input")(c),clearTimeout(g),a.T=setTimeout(function(){a.T=null},b)}}},V:function(a,b){var c=C(this.v.href),d=C(b),e=C(a);this.w=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:"navigation",data:{to:b,from:a}})},A:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f2?arguments[2]:void 0;return c&&b.V(b.w,c+""),a.apply(this,arguments)}};D(history,"pushState",j,d),D(history,"replaceState",j,d)}if(c.console&&"console"in H&&console.log){var k=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:"console"})};r(["debug","info","warn","error","log"],function(a,b){E(console,b,k)})}},M:function(){for(var a;this.s.length;){a=this.s.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},C:function(){var a=this;r(this.q,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},D:function(a){var b=G.exec(a),c={},d=7;try{for(;d--;)c[F[d]]=b[d]||""}catch(e){throw new i("Invalid DSN: "+a)}if(c.pass&&!this.k.allowSecretKey)throw new i("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return c},G:function(a){var b="//"+a.host+(a.port?":"+a.port:"");return a.protocol&&(b=a.protocol+":"+b),b},z:function(){this.l||this.N.apply(this,arguments)},N:function(a,b){var c=this.O(a,b);this.R("handle",{stackInfo:a,options:b}),this.X(a.name,a.message,a.url,a.lineno,c,b)},O:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(r(a.stack,function(b,e){var f=c.Y(e,a.url);f&&d.push(f)}),b&&b.trimHeadFrames))for(var e=0;e0&&(a.breadcrumbs={values:[].slice.call(this.t,0)}),q(a.tags)&&delete a.tags,this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),o(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!q(a)&&(!o(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ca()?void this.y("warn","Raven dropped error due to backoff: ",a):void("number"==typeof b.sampleRate?Math.random() ",i=h.length;a&&f++1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function v(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return"";if(g.push(a.tagName.toLowerCase()),a.id&&g.push("#"+a.id),b=a.className,b&&h(b))for(c=b.split(/\s+/),f=0;f=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,a),o();else if(h&&e.isError(h))l=f.computeStackTrace(h),k(l,!0);else{var m,n={url:b,line:c,column:g},p=void 0,r=a;if("[object String]"==={}.toString.call(a)){var m=a.match(j);m&&(p=m[1],r=m[2])}n.func=i,l={name:p,message:r,url:d(),stack:[n]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if("undefined"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,g=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,h=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,j=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,k=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=a.stack.split("\n"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n eval")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||"undefined"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(","):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),"undefined"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf("{"))}catch(p){}m[""+o]?n=!0:m[""+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){function d(a,b){for(var c=0;c0){var i=d(c,this);~i?c.splice(i+1):c.push(this),~i?e.splice(i,1/0,g):e.push(g),~d(c,h)&&(h=b.call(this,g,h))}else c.push(h);return null==a?h instanceof Error?f(h):h:a.call(this,g,h)}}c=b.exports=e,c.getSerialize=g},{}]},{},[4])(4)}); +//# sourceMappingURL=raven.min.js.map \ No newline at end of file -- cgit From 52a1c954f1aec551571d8167858f7f2857273fc9 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 17 Jan 2018 14:28:37 -0800 Subject: sentry - update raven and add to ui --- app/scripts/background.js | 9 ++++----- app/scripts/popup.js | 4 ++++ app/scripts/raven.min.js | 4 ++-- app/scripts/vendor/raven.min.js | 3 +++ 4 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 app/scripts/vendor/raven.min.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 9d9fbf892..ddd1f5b4f 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -12,12 +12,11 @@ const migrations = require('./migrations/') const PortStream = require('./lib/port-stream.js') const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') -const firstTimeState = require('./first-time-state') +const firstTimeState = require ('./first-time-state') +const Raven = require('./vendor/raven.min.js') -// raven / sentry error catching START -const Raven = require('./raven.min.js') -Raven.config('https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496').install() -// raven / sentry error catching END +// Setup raven / sentry remote error reporting +Raven.config('https://3567c198f8a8412082d32655da2961d0@sentry.io/273505').install() const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 5f17f0651..4d5f40853 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -7,6 +7,10 @@ const extension = require('extensionizer') const ExtensionPlatform = require('./platforms/extension') const NotificationManager = require('./lib/notification-manager') const notificationManager = new NotificationManager() +const Raven = require('./vendor/raven.min.js') + +// Setup raven / sentry remote error reporting +Raven.config('https://3567c198f8a8412082d32655da2961d0@sentry.io/273505').install() // create platform global global.platform = new ExtensionPlatform() diff --git a/app/scripts/raven.min.js b/app/scripts/raven.min.js index b6094a65f..b439aeae6 100644 --- a/app/scripts/raven.min.js +++ b/app/scripts/raven.min.js @@ -1,3 +1,3 @@ -/*! Raven.js 3.19.1 (aa94a44) | github.com/getsentry/raven-js */ -!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;gthis.k.maxBreadcrumbs&&this.t.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.q.push([a,b]),this.m&&this.C(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.Q("extra",a),this},setTagsContext:function(a){return this.Q("tags",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(h(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=e(b,a),this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=e(b,a),this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=e(b,a),this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.y("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var a=H.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(I){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new i("Missing eventId");var c=a.dsn||this.E;if(!c)throw new i("Missing DSN");var d=encodeURIComponent,e="";e+="?eventId="+d(b),e+="&dsn="+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+="&name="+d(f.name)),f.email&&(e+="&email="+d(f.email)));var g=this.G(this.D(c)),h=I.createElement("script");h.async=!0,h.src=g+"/api/embed/error-page/"+e,(I.head||I.body).appendChild(h)}},I:function(){var a=this;this.l+=1,setTimeout(function(){a.l-=1})},R:function(a,b){var c,d;if(this.b){b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),I.createEvent?(c=I.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=I.createEventObject(),c.eventType=a);for(d in b)v(b,d)&&(c[d]=b[d]);if(I.createEvent)I.dispatchEvent(c);else try{I.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}},S:function(a){var b=this;return function(c){if(b.T=null,b.u!==c){b.u=c;var d;try{d=z(c.target)}catch(e){d=""}b.captureBreadcrumb({category:"ui."+a,message:d})}}},U:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&("INPUT"===f||"TEXTAREA"===f||d.isContentEditable)){var g=a.T;g||a.S("input")(c),clearTimeout(g),a.T=setTimeout(function(){a.T=null},b)}}},V:function(a,b){var c=C(this.v.href),d=C(b),e=C(a);this.w=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:"navigation",data:{to:b,from:a}})},A:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f2?arguments[2]:void 0;return c&&b.V(b.w,c+""),a.apply(this,arguments)}};D(history,"pushState",j,d),D(history,"replaceState",j,d)}if(c.console&&"console"in H&&console.log){var k=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:"console"})};r(["debug","info","warn","error","log"],function(a,b){E(console,b,k)})}},M:function(){for(var a;this.s.length;){a=this.s.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},C:function(){var a=this;r(this.q,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},D:function(a){var b=G.exec(a),c={},d=7;try{for(;d--;)c[F[d]]=b[d]||""}catch(e){throw new i("Invalid DSN: "+a)}if(c.pass&&!this.k.allowSecretKey)throw new i("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return c},G:function(a){var b="//"+a.host+(a.port?":"+a.port:"");return a.protocol&&(b=a.protocol+":"+b),b},z:function(){this.l||this.N.apply(this,arguments)},N:function(a,b){var c=this.O(a,b);this.R("handle",{stackInfo:a,options:b}),this.X(a.name,a.message,a.url,a.lineno,c,b)},O:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(r(a.stack,function(b,e){var f=c.Y(e,a.url);f&&d.push(f)}),b&&b.trimHeadFrames))for(var e=0;e0&&(a.breadcrumbs={values:[].slice.call(this.t,0)}),q(a.tags)&&delete a.tags,this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),o(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!q(a)&&(!o(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ca()?void this.y("warn","Raven dropped error due to backoff: ",a):void("number"==typeof b.sampleRate?Math.random() ",i=h.length;a&&f++1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function v(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return"";if(g.push(a.tagName.toLowerCase()),a.id&&g.push("#"+a.id),b=a.className,b&&h(b))for(c=b.split(/\s+/),f=0;f=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,a),o();else if(h&&e.isError(h))l=f.computeStackTrace(h),k(l,!0);else{var m,n={url:b,line:c,column:g},p=void 0,r=a;if("[object String]"==={}.toString.call(a)){var m=a.match(j);m&&(p=m[1],r=m[2])}n.func=i,l={name:p,message:r,url:d(),stack:[n]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if("undefined"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,g=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,h=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,j=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,k=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=a.stack.split("\n"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n eval")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||"undefined"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(","):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),"undefined"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf("{"))}catch(p){}m[""+o]?n=!0:m[""+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){function d(a,b){for(var c=0;c0){var i=d(c,this);~i?c.splice(i+1):c.push(this),~i?e.splice(i,1/0,g):e.push(g),~d(c,h)&&(h=b.call(this,g,h))}else c.push(h);return null==a?h instanceof Error?f(h):h:a.call(this,g,h)}}c=b.exports=e,c.getSerialize=g},{}]},{},[4])(4)}); +/*! Raven.js 3.22.1 (7584197) | github.com/getsentry/raven-js */ +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;gthis.k.maxBreadcrumbs&&this.u.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.r.push([a,b]),this.n&&this.E(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.T("extra",a),this},setTagsContext:function(a){return this.T("tags",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(h(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=e(b,a),this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=e(b,a),this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=e(b,a),this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.z("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var a=J.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(K){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new i("Missing eventId");var c=a.dsn||this.G;if(!c)throw new i("Missing DSN");var d=encodeURIComponent,e="";e+="?eventId="+d(b),e+="&dsn="+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+="&name="+d(f.name)),f.email&&(e+="&email="+d(f.email)));var g=this.I(this.F(c)),h=K.createElement("script");h.async=!0,h.src=g+"/api/embed/error-page/"+e,(K.head||K.body).appendChild(h)}},K:function(){var a=this;this.m+=1,setTimeout(function(){a.m-=1})},U:function(a,b){var c,d;if(this.b){b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),K.createEvent?(c=K.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=K.createEventObject(),c.eventType=a);for(d in b)w(b,d)&&(c[d]=b[d]);if(K.createEvent)K.dispatchEvent(c);else try{K.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}},V:function(a){var b=this;return function(c){if(b.W=null,b.v!==c){b.v=c;var d;try{d=A(c.target)}catch(e){d=""}b.captureBreadcrumb({category:"ui."+a,message:d})}}},X:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&("INPUT"===f||"TEXTAREA"===f||d.isContentEditable)){var g=a.W;g||a.V("input")(c),clearTimeout(g),a.W=setTimeout(function(){a.W=null},b)}}},Y:function(a,b){var c=D(this.w.href),d=D(b),e=D(a);this.x=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:"navigation",data:{to:b,from:a}})},B:function(){var a=this;a.Z=Function.prototype.toString,Function.prototype.toString=function(){return"function"==typeof this&&this.L?a.Z.apply(this.N,arguments):a.Z.apply(this,arguments)}},O:function(){this.Z&&(Function.prototype.toString=this.Z)},C:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f2?arguments[2]:void 0;return c&&b.Y(b.x,c+""),a.apply(this,arguments)}};E(history,"pushState",j,d),E(history,"replaceState",j,d)}if(c.console&&"console"in J&&console.log){var k=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:"console"})};s(["debug","info","warn","error","log"],function(a,b){G(console,b,k)})}},P:function(){for(var a;this.t.length;){a=this.t.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},E:function(){var a=this;s(this.r,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},F:function(a){var b=I.exec(a),c={},d=7;try{for(;d--;)c[H[d]]=b[d]||""}catch(e){throw new i("Invalid DSN: "+a)}if(c.pass&&!this.k.allowSecretKey)throw new i("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return c},I:function(a){var b="//"+a.host+(a.port?":"+a.port:"");return a.protocol&&(b=a.protocol+":"+b),b},A:function(){this.m||this.Q.apply(this,arguments)},Q:function(a,b){var c=this.R(a,b);this.U("handle",{stackInfo:a,options:b}),this._(a.name,a.message,a.url,a.lineno,c,b)},R:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(s(a.stack,function(b,e){var f=c.aa(e,a.url);f&&d.push(f)}),b&&b.trimHeadFrames))for(var e=0;e0&&(a.breadcrumbs={values:[].slice.call(this.u,0)}),this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),Object.keys(a).forEach(function(b){(null==a[b]||""===a[b]||r(a[b]))&&delete a[b]}),o(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!r(a)&&(!o(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ga()?void this.z("warn","Raven dropped error due to backoff: ",a):void("number"==typeof b.sampleRate?Math.random() ",i=h.length;a&&f++1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function y(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return"";if(g.push(a.tagName.toLowerCase()),a.id&&g.push("#"+a.id),b=a.className,b&&i(b))for(c=b.split(/\s+/),f=0;f=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null,m=e.isErrorEvent(h)?h.error:h,n=e.isErrorEvent(a)?a.message:a;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,n),o();else if(m&&e.isError(m))l=f.computeStackTrace(m),k(l,!0);else{var p,r={url:b,line:c,column:g},s=void 0;if("[object String]"==={}.toString.call(n)){var p=n.match(j);p&&(s=p[1],n=p[2])}r.func=i,l={name:s,message:n,url:d(),stack:[r]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if("undefined"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,g=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,h=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,j=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,k=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=a.stack.split("\n"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n eval")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||"undefined"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(","):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),"undefined"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf("{"))}catch(p){}m[""+o]?n=!0:m[""+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){function d(a,b){for(var c=0;c0){var i=d(c,this);~i?c.splice(i+1):c.push(this),~i?e.splice(i,1/0,g):e.push(g),~d(c,h)&&(h=b.call(this,g,h))}else c.push(h);return null==a?h instanceof Error?f(h):h:a.call(this,g,h)}}c=b.exports=e,c.getSerialize=g},{}]},{},[4])(4)}); //# sourceMappingURL=raven.min.js.map \ No newline at end of file diff --git a/app/scripts/vendor/raven.min.js b/app/scripts/vendor/raven.min.js new file mode 100644 index 000000000..b6094a65f --- /dev/null +++ b/app/scripts/vendor/raven.min.js @@ -0,0 +1,3 @@ +/*! Raven.js 3.19.1 (aa94a44) | github.com/getsentry/raven-js */ +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;gthis.k.maxBreadcrumbs&&this.t.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.q.push([a,b]),this.m&&this.C(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.Q("extra",a),this},setTagsContext:function(a){return this.Q("tags",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(h(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=e(b,a),this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=e(b,a),this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=e(b,a),this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.y("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var a=H.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(I){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new i("Missing eventId");var c=a.dsn||this.E;if(!c)throw new i("Missing DSN");var d=encodeURIComponent,e="";e+="?eventId="+d(b),e+="&dsn="+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+="&name="+d(f.name)),f.email&&(e+="&email="+d(f.email)));var g=this.G(this.D(c)),h=I.createElement("script");h.async=!0,h.src=g+"/api/embed/error-page/"+e,(I.head||I.body).appendChild(h)}},I:function(){var a=this;this.l+=1,setTimeout(function(){a.l-=1})},R:function(a,b){var c,d;if(this.b){b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),I.createEvent?(c=I.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=I.createEventObject(),c.eventType=a);for(d in b)v(b,d)&&(c[d]=b[d]);if(I.createEvent)I.dispatchEvent(c);else try{I.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}},S:function(a){var b=this;return function(c){if(b.T=null,b.u!==c){b.u=c;var d;try{d=z(c.target)}catch(e){d=""}b.captureBreadcrumb({category:"ui."+a,message:d})}}},U:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&("INPUT"===f||"TEXTAREA"===f||d.isContentEditable)){var g=a.T;g||a.S("input")(c),clearTimeout(g),a.T=setTimeout(function(){a.T=null},b)}}},V:function(a,b){var c=C(this.v.href),d=C(b),e=C(a);this.w=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:"navigation",data:{to:b,from:a}})},A:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f2?arguments[2]:void 0;return c&&b.V(b.w,c+""),a.apply(this,arguments)}};D(history,"pushState",j,d),D(history,"replaceState",j,d)}if(c.console&&"console"in H&&console.log){var k=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:"console"})};r(["debug","info","warn","error","log"],function(a,b){E(console,b,k)})}},M:function(){for(var a;this.s.length;){a=this.s.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},C:function(){var a=this;r(this.q,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},D:function(a){var b=G.exec(a),c={},d=7;try{for(;d--;)c[F[d]]=b[d]||""}catch(e){throw new i("Invalid DSN: "+a)}if(c.pass&&!this.k.allowSecretKey)throw new i("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return c},G:function(a){var b="//"+a.host+(a.port?":"+a.port:"");return a.protocol&&(b=a.protocol+":"+b),b},z:function(){this.l||this.N.apply(this,arguments)},N:function(a,b){var c=this.O(a,b);this.R("handle",{stackInfo:a,options:b}),this.X(a.name,a.message,a.url,a.lineno,c,b)},O:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(r(a.stack,function(b,e){var f=c.Y(e,a.url);f&&d.push(f)}),b&&b.trimHeadFrames))for(var e=0;e0&&(a.breadcrumbs={values:[].slice.call(this.t,0)}),q(a.tags)&&delete a.tags,this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),o(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!q(a)&&(!o(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ca()?void this.y("warn","Raven dropped error due to backoff: ",a):void("number"==typeof b.sampleRate?Math.random() ",i=h.length;a&&f++1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function v(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return"";if(g.push(a.tagName.toLowerCase()),a.id&&g.push("#"+a.id),b=a.className,b&&h(b))for(c=b.split(/\s+/),f=0;f=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,a),o();else if(h&&e.isError(h))l=f.computeStackTrace(h),k(l,!0);else{var m,n={url:b,line:c,column:g},p=void 0,r=a;if("[object String]"==={}.toString.call(a)){var m=a.match(j);m&&(p=m[1],r=m[2])}n.func=i,l={name:p,message:r,url:d(),stack:[n]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if("undefined"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,g=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,h=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,j=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,k=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=a.stack.split("\n"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n eval")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||"undefined"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(","):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),"undefined"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf("{"))}catch(p){}m[""+o]?n=!0:m[""+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){function d(a,b){for(var c=0;c0){var i=d(c,this);~i?c.splice(i+1):c.push(this),~i?e.splice(i,1/0,g):e.push(g),~d(c,h)&&(h=b.call(this,g,h))}else c.push(h);return null==a?h instanceof Error?f(h):h:a.call(this,g,h)}}c=b.exports=e,c.getSerialize=g},{}]},{},[4])(4)}); +//# sourceMappingURL=raven.min.js.map \ No newline at end of file -- cgit From daa62b507a654f6c913725b3c36fc6122b1c088e Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 17 Jan 2018 14:59:15 -0800 Subject: sentry - breakout raven setup and add release config --- app/scripts/background.js | 11 ++++++----- app/scripts/popup.js | 9 +++++---- app/scripts/setupRaven.js | 24 ++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 app/scripts/setupRaven.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index ddd1f5b4f..8c1252d3e 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -12,11 +12,8 @@ const migrations = require('./migrations/') const PortStream = require('./lib/port-stream.js') const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') -const firstTimeState = require ('./first-time-state') -const Raven = require('./vendor/raven.min.js') - -// Setup raven / sentry remote error reporting -Raven.config('https://3567c198f8a8412082d32655da2961d0@sentry.io/273505').install() +const firstTimeState = require('./first-time-state') +const setupRaven = require('./setupRaven') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -28,6 +25,10 @@ const platform = new ExtensionPlatform() const notificationManager = new NotificationManager() global.METAMASK_NOTIFIER = notificationManager +// setup sentry error reporting +const release = platform.getVersion() +setupRaven({ release }) + let popupIsOpen = false // state persistence diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 4d5f40853..860cc567d 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -7,14 +7,15 @@ const extension = require('extensionizer') const ExtensionPlatform = require('./platforms/extension') const NotificationManager = require('./lib/notification-manager') const notificationManager = new NotificationManager() -const Raven = require('./vendor/raven.min.js') - -// Setup raven / sentry remote error reporting -Raven.config('https://3567c198f8a8412082d32655da2961d0@sentry.io/273505').install() +const setupRaven = require('./setupRaven') // create platform global global.platform = new ExtensionPlatform() +// setup sentry error reporting +const release = global.platform.getVersion() +setupRaven({ release }) + // inject css const css = MetaMaskUiCss() injectCss(css) diff --git a/app/scripts/setupRaven.js b/app/scripts/setupRaven.js new file mode 100644 index 000000000..4888c85fe --- /dev/null +++ b/app/scripts/setupRaven.js @@ -0,0 +1,24 @@ +const Raven = require('./vendor/raven.min.js') +const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' +const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' + +module.exports = setupRaven + +// Setup raven / sentry remote error reporting +function setupRaven(opts) { + const { release } = opts + let ravenTarget + + if (METAMASK_DEBUG) { + console.log('Setting up Sentry Remote Error Reporting: DEV') + ravenTarget = DEV + } else { + console.log('Setting up Sentry Remote Error Reporting: PROD') + ravenTarget = PROD + } + + Raven.config(ravenTarget, { + release, + }).install() +} -- cgit From 1f5325804b7a002bdf0ce1ff68512b58ab9f06a3 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 17 Jan 2018 15:38:25 -0800 Subject: sentry - dedupe raven vendor --- app/scripts/raven.min.js | 3 --- app/scripts/vendor/raven.min.js | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 app/scripts/raven.min.js (limited to 'app') diff --git a/app/scripts/raven.min.js b/app/scripts/raven.min.js deleted file mode 100644 index b439aeae6..000000000 --- a/app/scripts/raven.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! Raven.js 3.22.1 (7584197) | github.com/getsentry/raven-js */ -!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;gthis.k.maxBreadcrumbs&&this.u.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.r.push([a,b]),this.n&&this.E(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.T("extra",a),this},setTagsContext:function(a){return this.T("tags",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(h(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=e(b,a),this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=e(b,a),this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=e(b,a),this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.z("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var a=J.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(K){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new i("Missing eventId");var c=a.dsn||this.G;if(!c)throw new i("Missing DSN");var d=encodeURIComponent,e="";e+="?eventId="+d(b),e+="&dsn="+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+="&name="+d(f.name)),f.email&&(e+="&email="+d(f.email)));var g=this.I(this.F(c)),h=K.createElement("script");h.async=!0,h.src=g+"/api/embed/error-page/"+e,(K.head||K.body).appendChild(h)}},K:function(){var a=this;this.m+=1,setTimeout(function(){a.m-=1})},U:function(a,b){var c,d;if(this.b){b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),K.createEvent?(c=K.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=K.createEventObject(),c.eventType=a);for(d in b)w(b,d)&&(c[d]=b[d]);if(K.createEvent)K.dispatchEvent(c);else try{K.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}},V:function(a){var b=this;return function(c){if(b.W=null,b.v!==c){b.v=c;var d;try{d=A(c.target)}catch(e){d=""}b.captureBreadcrumb({category:"ui."+a,message:d})}}},X:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&("INPUT"===f||"TEXTAREA"===f||d.isContentEditable)){var g=a.W;g||a.V("input")(c),clearTimeout(g),a.W=setTimeout(function(){a.W=null},b)}}},Y:function(a,b){var c=D(this.w.href),d=D(b),e=D(a);this.x=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:"navigation",data:{to:b,from:a}})},B:function(){var a=this;a.Z=Function.prototype.toString,Function.prototype.toString=function(){return"function"==typeof this&&this.L?a.Z.apply(this.N,arguments):a.Z.apply(this,arguments)}},O:function(){this.Z&&(Function.prototype.toString=this.Z)},C:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f2?arguments[2]:void 0;return c&&b.Y(b.x,c+""),a.apply(this,arguments)}};E(history,"pushState",j,d),E(history,"replaceState",j,d)}if(c.console&&"console"in J&&console.log){var k=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:"console"})};s(["debug","info","warn","error","log"],function(a,b){G(console,b,k)})}},P:function(){for(var a;this.t.length;){a=this.t.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},E:function(){var a=this;s(this.r,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},F:function(a){var b=I.exec(a),c={},d=7;try{for(;d--;)c[H[d]]=b[d]||""}catch(e){throw new i("Invalid DSN: "+a)}if(c.pass&&!this.k.allowSecretKey)throw new i("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return c},I:function(a){var b="//"+a.host+(a.port?":"+a.port:"");return a.protocol&&(b=a.protocol+":"+b),b},A:function(){this.m||this.Q.apply(this,arguments)},Q:function(a,b){var c=this.R(a,b);this.U("handle",{stackInfo:a,options:b}),this._(a.name,a.message,a.url,a.lineno,c,b)},R:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(s(a.stack,function(b,e){var f=c.aa(e,a.url);f&&d.push(f)}),b&&b.trimHeadFrames))for(var e=0;e0&&(a.breadcrumbs={values:[].slice.call(this.u,0)}),this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),Object.keys(a).forEach(function(b){(null==a[b]||""===a[b]||r(a[b]))&&delete a[b]}),o(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!r(a)&&(!o(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ga()?void this.z("warn","Raven dropped error due to backoff: ",a):void("number"==typeof b.sampleRate?Math.random() ",i=h.length;a&&f++1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function y(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return"";if(g.push(a.tagName.toLowerCase()),a.id&&g.push("#"+a.id),b=a.className,b&&i(b))for(c=b.split(/\s+/),f=0;f=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null,m=e.isErrorEvent(h)?h.error:h,n=e.isErrorEvent(a)?a.message:a;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,n),o();else if(m&&e.isError(m))l=f.computeStackTrace(m),k(l,!0);else{var p,r={url:b,line:c,column:g},s=void 0;if("[object String]"==={}.toString.call(n)){var p=n.match(j);p&&(s=p[1],n=p[2])}r.func=i,l={name:s,message:n,url:d(),stack:[r]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if("undefined"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,g=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,h=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,j=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,k=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=a.stack.split("\n"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n eval")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||"undefined"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(","):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),"undefined"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf("{"))}catch(p){}m[""+o]?n=!0:m[""+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){function d(a,b){for(var c=0;c0){var i=d(c,this);~i?c.splice(i+1):c.push(this),~i?e.splice(i,1/0,g):e.push(g),~d(c,h)&&(h=b.call(this,g,h))}else c.push(h);return null==a?h instanceof Error?f(h):h:a.call(this,g,h)}}c=b.exports=e,c.getSerialize=g},{}]},{},[4])(4)}); -//# sourceMappingURL=raven.min.js.map \ No newline at end of file diff --git a/app/scripts/vendor/raven.min.js b/app/scripts/vendor/raven.min.js index b6094a65f..b439aeae6 100644 --- a/app/scripts/vendor/raven.min.js +++ b/app/scripts/vendor/raven.min.js @@ -1,3 +1,3 @@ -/*! Raven.js 3.19.1 (aa94a44) | github.com/getsentry/raven-js */ -!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;gthis.k.maxBreadcrumbs&&this.t.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.q.push([a,b]),this.m&&this.C(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.Q("extra",a),this},setTagsContext:function(a){return this.Q("tags",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(h(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=e(b,a),this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=e(b,a),this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=e(b,a),this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.y("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var a=H.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(I){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new i("Missing eventId");var c=a.dsn||this.E;if(!c)throw new i("Missing DSN");var d=encodeURIComponent,e="";e+="?eventId="+d(b),e+="&dsn="+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+="&name="+d(f.name)),f.email&&(e+="&email="+d(f.email)));var g=this.G(this.D(c)),h=I.createElement("script");h.async=!0,h.src=g+"/api/embed/error-page/"+e,(I.head||I.body).appendChild(h)}},I:function(){var a=this;this.l+=1,setTimeout(function(){a.l-=1})},R:function(a,b){var c,d;if(this.b){b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),I.createEvent?(c=I.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=I.createEventObject(),c.eventType=a);for(d in b)v(b,d)&&(c[d]=b[d]);if(I.createEvent)I.dispatchEvent(c);else try{I.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}},S:function(a){var b=this;return function(c){if(b.T=null,b.u!==c){b.u=c;var d;try{d=z(c.target)}catch(e){d=""}b.captureBreadcrumb({category:"ui."+a,message:d})}}},U:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&("INPUT"===f||"TEXTAREA"===f||d.isContentEditable)){var g=a.T;g||a.S("input")(c),clearTimeout(g),a.T=setTimeout(function(){a.T=null},b)}}},V:function(a,b){var c=C(this.v.href),d=C(b),e=C(a);this.w=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:"navigation",data:{to:b,from:a}})},A:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f2?arguments[2]:void 0;return c&&b.V(b.w,c+""),a.apply(this,arguments)}};D(history,"pushState",j,d),D(history,"replaceState",j,d)}if(c.console&&"console"in H&&console.log){var k=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:"console"})};r(["debug","info","warn","error","log"],function(a,b){E(console,b,k)})}},M:function(){for(var a;this.s.length;){a=this.s.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},C:function(){var a=this;r(this.q,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},D:function(a){var b=G.exec(a),c={},d=7;try{for(;d--;)c[F[d]]=b[d]||""}catch(e){throw new i("Invalid DSN: "+a)}if(c.pass&&!this.k.allowSecretKey)throw new i("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return c},G:function(a){var b="//"+a.host+(a.port?":"+a.port:"");return a.protocol&&(b=a.protocol+":"+b),b},z:function(){this.l||this.N.apply(this,arguments)},N:function(a,b){var c=this.O(a,b);this.R("handle",{stackInfo:a,options:b}),this.X(a.name,a.message,a.url,a.lineno,c,b)},O:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(r(a.stack,function(b,e){var f=c.Y(e,a.url);f&&d.push(f)}),b&&b.trimHeadFrames))for(var e=0;e0&&(a.breadcrumbs={values:[].slice.call(this.t,0)}),q(a.tags)&&delete a.tags,this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),o(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!q(a)&&(!o(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ca()?void this.y("warn","Raven dropped error due to backoff: ",a):void("number"==typeof b.sampleRate?Math.random() ",i=h.length;a&&f++1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function v(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return"";if(g.push(a.tagName.toLowerCase()),a.id&&g.push("#"+a.id),b=a.className,b&&h(b))for(c=b.split(/\s+/),f=0;f=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,a),o();else if(h&&e.isError(h))l=f.computeStackTrace(h),k(l,!0);else{var m,n={url:b,line:c,column:g},p=void 0,r=a;if("[object String]"==={}.toString.call(a)){var m=a.match(j);m&&(p=m[1],r=m[2])}n.func=i,l={name:p,message:r,url:d(),stack:[n]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if("undefined"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,g=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,h=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,j=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,k=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=a.stack.split("\n"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n eval")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||"undefined"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(","):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),"undefined"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf("{"))}catch(p){}m[""+o]?n=!0:m[""+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){function d(a,b){for(var c=0;c0){var i=d(c,this);~i?c.splice(i+1):c.push(this),~i?e.splice(i,1/0,g):e.push(g),~d(c,h)&&(h=b.call(this,g,h))}else c.push(h);return null==a?h instanceof Error?f(h):h:a.call(this,g,h)}}c=b.exports=e,c.getSerialize=g},{}]},{},[4])(4)}); +/*! Raven.js 3.22.1 (7584197) | github.com/getsentry/raven-js */ +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;gthis.k.maxBreadcrumbs&&this.u.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.r.push([a,b]),this.n&&this.E(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.T("extra",a),this},setTagsContext:function(a){return this.T("tags",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(h(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=e(b,a),this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=e(b,a),this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=e(b,a),this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.z("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var a=J.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(K){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new i("Missing eventId");var c=a.dsn||this.G;if(!c)throw new i("Missing DSN");var d=encodeURIComponent,e="";e+="?eventId="+d(b),e+="&dsn="+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+="&name="+d(f.name)),f.email&&(e+="&email="+d(f.email)));var g=this.I(this.F(c)),h=K.createElement("script");h.async=!0,h.src=g+"/api/embed/error-page/"+e,(K.head||K.body).appendChild(h)}},K:function(){var a=this;this.m+=1,setTimeout(function(){a.m-=1})},U:function(a,b){var c,d;if(this.b){b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),K.createEvent?(c=K.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=K.createEventObject(),c.eventType=a);for(d in b)w(b,d)&&(c[d]=b[d]);if(K.createEvent)K.dispatchEvent(c);else try{K.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}},V:function(a){var b=this;return function(c){if(b.W=null,b.v!==c){b.v=c;var d;try{d=A(c.target)}catch(e){d=""}b.captureBreadcrumb({category:"ui."+a,message:d})}}},X:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&("INPUT"===f||"TEXTAREA"===f||d.isContentEditable)){var g=a.W;g||a.V("input")(c),clearTimeout(g),a.W=setTimeout(function(){a.W=null},b)}}},Y:function(a,b){var c=D(this.w.href),d=D(b),e=D(a);this.x=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:"navigation",data:{to:b,from:a}})},B:function(){var a=this;a.Z=Function.prototype.toString,Function.prototype.toString=function(){return"function"==typeof this&&this.L?a.Z.apply(this.N,arguments):a.Z.apply(this,arguments)}},O:function(){this.Z&&(Function.prototype.toString=this.Z)},C:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f2?arguments[2]:void 0;return c&&b.Y(b.x,c+""),a.apply(this,arguments)}};E(history,"pushState",j,d),E(history,"replaceState",j,d)}if(c.console&&"console"in J&&console.log){var k=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:"console"})};s(["debug","info","warn","error","log"],function(a,b){G(console,b,k)})}},P:function(){for(var a;this.t.length;){a=this.t.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},E:function(){var a=this;s(this.r,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},F:function(a){var b=I.exec(a),c={},d=7;try{for(;d--;)c[H[d]]=b[d]||""}catch(e){throw new i("Invalid DSN: "+a)}if(c.pass&&!this.k.allowSecretKey)throw new i("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return c},I:function(a){var b="//"+a.host+(a.port?":"+a.port:"");return a.protocol&&(b=a.protocol+":"+b),b},A:function(){this.m||this.Q.apply(this,arguments)},Q:function(a,b){var c=this.R(a,b);this.U("handle",{stackInfo:a,options:b}),this._(a.name,a.message,a.url,a.lineno,c,b)},R:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(s(a.stack,function(b,e){var f=c.aa(e,a.url);f&&d.push(f)}),b&&b.trimHeadFrames))for(var e=0;e0&&(a.breadcrumbs={values:[].slice.call(this.u,0)}),this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),Object.keys(a).forEach(function(b){(null==a[b]||""===a[b]||r(a[b]))&&delete a[b]}),o(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!r(a)&&(!o(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ga()?void this.z("warn","Raven dropped error due to backoff: ",a):void("number"==typeof b.sampleRate?Math.random() ",i=h.length;a&&f++1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function y(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return"";if(g.push(a.tagName.toLowerCase()),a.id&&g.push("#"+a.id),b=a.className,b&&i(b))for(c=b.split(/\s+/),f=0;f=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null,m=e.isErrorEvent(h)?h.error:h,n=e.isErrorEvent(a)?a.message:a;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,n),o();else if(m&&e.isError(m))l=f.computeStackTrace(m),k(l,!0);else{var p,r={url:b,line:c,column:g},s=void 0;if("[object String]"==={}.toString.call(n)){var p=n.match(j);p&&(s=p[1],n=p[2])}r.func=i,l={name:s,message:n,url:d(),stack:[r]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if("undefined"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,g=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,h=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,j=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,k=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=a.stack.split("\n"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n eval")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||"undefined"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(","):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),"undefined"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf("{"))}catch(p){}m[""+o]?n=!0:m[""+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){function d(a,b){for(var c=0;c0){var i=d(c,this);~i?c.splice(i+1):c.push(this),~i?e.splice(i,1/0,g):e.push(g),~d(c,h)&&(h=b.call(this,g,h))}else c.push(h);return null==a?h instanceof Error?f(h):h:a.call(this,g,h)}}c=b.exports=e,c.getSerialize=g},{}]},{},[4])(4)}); //# sourceMappingURL=raven.min.js.map \ No newline at end of file -- cgit From 9f19fea8e08415c670ce3df5d7e363baac366d2c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 17 Jan 2018 15:42:01 -0800 Subject: transactions - wrap addTxDefaults in a try catch and re try addTxDefaults on boot if they did not complete --- app/scripts/controllers/transactions.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index bb9253175..4c9a4cd80 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -43,6 +43,18 @@ module.exports = class TransactionController extends EventEmitter { txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), }) + + this.txStateManager.getFilteredTxList({ + status: 'unapproved', + loadingDefaults: true, + }).forEach((tx) => { + this.addTxDefaults(tx) + .then((txMeta) => { + txMeta.loadingDefaults = false + this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot') + }) + }) + this.store = this.txStateManager.store this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update')) this.nonceTracker = new NonceTracker({ @@ -171,11 +183,17 @@ module.exports = class TransactionController extends EventEmitter { this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) // add default tx params - await this.addTxDefaults(txMeta) - + try { + await this.addTxDefaults(txMeta) + } catch (error) { + console.log(error) + this.txStateManager.setTxStatusFailed(txMeta.id, error) + throw error + } txMeta.loadingDefaults = false // save txMeta this.txStateManager.updateTx(txMeta) + return txMeta } -- cgit From be8d9244326443fb7f54df271d4e2a2abda90f6f Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 17 Jan 2018 15:48:37 -0800 Subject: transactions - fail txs on boot who fail addTxDefaults --- app/scripts/controllers/transactions.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 4c9a4cd80..73aadb292 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -52,6 +52,8 @@ module.exports = class TransactionController extends EventEmitter { .then((txMeta) => { txMeta.loadingDefaults = false this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot') + }).catch((error) => { + this.txStateManager.setTxStatusFailed(tx.id, error) }) }) -- cgit From 234c2417ca2480fc3025030bc19ef007ea8e8d30 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 17 Jan 2018 16:49:38 -0800 Subject: transactions - transtion approved transactions to failed transactions on boot --- app/scripts/controllers/transactions.js | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 73aadb292..c1909d95c 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -57,6 +57,14 @@ module.exports = class TransactionController extends EventEmitter { }) }) + this.txStateManager.getFilteredTxList({ + status: 'approved', + }).forEach((txMeta) => { + const txSignError = new Error('Transaction was interrupted during signing process') + this.txStateManager.setTxStatusFailed(txMeta.id, txSignError) + }) + + this.store = this.txStateManager.store this.txStateManager.on('tx:status-update', this.emit.bind(this, 'tx:status-update')) this.nonceTracker = new NonceTracker({ -- cgit From f8bf8cb527ae0e24ccf9d1c9f2f6baa457f2e659 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 17 Jan 2018 17:37:18 -0800 Subject: Update popout to fullscreen icon --- app/images/popout.svg | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 app/images/popout.svg (limited to 'app') diff --git a/app/images/popout.svg b/app/images/popout.svg new file mode 100644 index 000000000..760fe4379 --- /dev/null +++ b/app/images/popout.svg @@ -0,0 +1,21 @@ + + + + popout + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit From 96fc916024cf16790a19472f31d3861168b8433b Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 17 Jan 2018 17:56:31 -0800 Subject: Update transactions.js --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index c1909d95c..9c3618e60 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -60,7 +60,7 @@ module.exports = class TransactionController extends EventEmitter { this.txStateManager.getFilteredTxList({ status: 'approved', }).forEach((txMeta) => { - const txSignError = new Error('Transaction was interrupted during signing process') + const txSignError = new Error('Transaction found as "approved" during boot - possibly stuck during signing') this.txStateManager.setTxStatusFailed(txMeta.id, txSignError) }) -- cgit From d7c8ec22a45a704036c4969496ef293c524f4542 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 17 Jan 2018 20:09:13 -0800 Subject: test - tx controller - fix txGasUtil reference --- app/scripts/lib/tx-gas-utils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index e80e0467e..f68f3a9e2 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -12,7 +12,8 @@ its passed ethquery and used to do things like calculate gas of a tx. */ -module.exports = class txProvideUtil { +module.exports = class TxGasUtil { + constructor (provider) { this.query = new EthQuery(provider) } -- cgit From 4e63924e607a07f94ff0a741a036ab352b0b7a3f Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 18 Jan 2018 16:02:35 -0800 Subject: 4.0.10 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index d65374330..d906382e9 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.9", + "version": "4.0.10", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From b91e2b5eb1f34e8f835ac4a8a35b7da16fe66c78 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 22 Jan 2018 15:54:26 -0800 Subject: sentry - report failed txs --- app/scripts/background.js | 12 +++++++++++- app/scripts/setupRaven.js | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 8c1252d3e..0471cee3b 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -27,7 +27,7 @@ global.METAMASK_NOTIFIER = notificationManager // setup sentry error reporting const release = platform.getVersion() -setupRaven({ release }) +const raven = setupRaven({ release }) let popupIsOpen = false @@ -77,6 +77,16 @@ function setupController (initState) { }) global.metamaskController = controller + // report failed transactions to Sentry + controller.txController.on(`tx:status-update`, (txId, status) => { + if (status !== 'failed') return + const txMeta = controller.txController.txStateManager.getTx(txId) + raven.captureMessage('Transaction Failed', { + // "extra" key is required by Sentry + extra: txMeta, + }) + }) + // setup state persistence pump( asStream(controller.store), diff --git a/app/scripts/setupRaven.js b/app/scripts/setupRaven.js index 4888c85fe..7beffeff9 100644 --- a/app/scripts/setupRaven.js +++ b/app/scripts/setupRaven.js @@ -21,4 +21,6 @@ function setupRaven(opts) { Raven.config(ravenTarget, { release, }).install() + + return Raven } -- cgit From 5568053cd81d26f1888239d335708cd746f224df Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 22 Jan 2018 15:46:09 -0800 Subject: Version 3.13.7 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 3b6fc6b20..d795a225a 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.13.5", + "version": "3.13.7", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 97ca86733cb49750a9909b57ac1f31bc0f49abc5 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 23 Jan 2018 01:12:50 -0800 Subject: Merge branch 'master' into uat --- app/manifest.json | 2 +- app/scripts/background.js | 12 +++++++++++- app/scripts/setupRaven.js | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index d906382e9..d795a225a 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.10", + "version": "3.13.7", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", diff --git a/app/scripts/background.js b/app/scripts/background.js index 8c1252d3e..0471cee3b 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -27,7 +27,7 @@ global.METAMASK_NOTIFIER = notificationManager // setup sentry error reporting const release = platform.getVersion() -setupRaven({ release }) +const raven = setupRaven({ release }) let popupIsOpen = false @@ -77,6 +77,16 @@ function setupController (initState) { }) global.metamaskController = controller + // report failed transactions to Sentry + controller.txController.on(`tx:status-update`, (txId, status) => { + if (status !== 'failed') return + const txMeta = controller.txController.txStateManager.getTx(txId) + raven.captureMessage('Transaction Failed', { + // "extra" key is required by Sentry + extra: txMeta, + }) + }) + // setup state persistence pump( asStream(controller.store), diff --git a/app/scripts/setupRaven.js b/app/scripts/setupRaven.js index 4888c85fe..7beffeff9 100644 --- a/app/scripts/setupRaven.js +++ b/app/scripts/setupRaven.js @@ -21,4 +21,6 @@ function setupRaven(opts) { Raven.config(ravenTarget, { release, }).install() + + return Raven } -- cgit From bad70eb1b328aa911a2523ccab642d7607161b4b Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Mon, 22 Jan 2018 23:48:03 -1000 Subject: first steps to i18n --- app/_locales/en/messages.json | 167 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 8c28f1c43..6967a44d2 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -6,5 +6,170 @@ "appDescription": { "message": "Ethereum Identity Management", "description": "The description of the application" - } + }, + "encryptNewDen": { + "message": "Encrypt your new DEN" + }, + "denExplainer": { + "message": "Your DEN is your password-encrypted storage within MetaMask." + }, + "importDen": { + "message": "Import Existing DEN" + }, + "createDen": { + "message": "Create" + }, + "newPassword": { + "message": "New Password (min 8 chars)" + }, + "confirmPassword": { + "message": "Confirm Password" + }, + "passwordMismatch": { + "message": "passwords don't match" + }, + "passwordShort": { + "message": "password not long enough" + }, + "myAccounts": { + "message": "My Accounts" + }, + "logout": { + "message": "Log out" + }, + "createAccount": { + "message": "Create Account" + }, + "importAccount": { + "message": "Import Account" + }, + "account": { + "message": "Account:" + }, + "infoHelp": { + "message": "Info & Help" + }, + "settings": { + "message": "Settings" + }, + "importedCaps": { + "message": "IMPORTED" + }, + "saveButton": { + "message": "SAVE" + }, + "cancelButton": { + "message": "CANCEL" + }, + "signButton": { + "message": "SIGN" + }, + "revert": { + "message": "Revert" + }, + "gasLimit": { + "message": "Gas Limit" + }, + "gasLimitCalculation": { + "message": "We calculate the suggested gas limit based on network success rates." + }, + "gasPrice": { + "message": "Gas Price (GWEI)" + }, + "gasPriceCalculation": { + "message": "We calculate the suggested gas prices based on network success rates." + }, + "customGas": { + "message": "Customize Gas" + }, + "balanceIsInsufficientGas": { + "message": "Insufficient balance for current gas total" + }, + "gasLimitTooLow": { + "message": "Gas limit must be at least 21000" + }, + "editButton": { + "message": "Edit" + }, + "looseCaps": { + "message": "LOOSE" + }, + "addToken": "Add Token", + "exportPrivateKey": "Export Private Key", + "copyAddress": "Copy Address to clipboard", + "etherscanView": "View account on Etherscan", + "qrCode": "Show QR Code", + "accDetails": "Account Details", + "networks": "Networks", + "defaultNetwork": "The default network for Ether transactions is Main Net.", + "mainnet": "Main Ethereum Network", + "unknownNetwork": "Unknown Private Network", + "rinkeby": "Rinkeby Test Network", + "kovan": "Kovan Test Network", + "ropsten": "Ropsten Test Network", + "localhost": "Localhost 8545", + "customRPC": "Custom RPC", + "hideToken": "Hide Token", + "copiedClipboard": "Copied to Clipboard", + "detailsCaps": "DETAILS", + "sendButton": "SEND", + "depositButton": "DEPOSIT", + "notStarted": "Not Started", + "noTransactions": "No Transactions", + "contractPublished": "Contract Published", + "noTransactionHistory": "No transaction history.", + "warning": "Warning", + "failed": "Failed", + "rejected": "Rejected", + "sigRequested": "Signature Requested", + "yourSigRequested": "Your signature is being requested", + "balance": "Balance:", + "retryWithMoreGas": "Retry with a higher gas price here", + "takesTooLong": "Taking too long?", + "transactionNumber": "Transaction Number", + "loadingTokens": "Loading Tokens...", + "troubleTokenBalances": "We had trouble loading your token balances. You can view them ", + "here": "here", + "message": "Message", + "signNotice": "Signing this message can have \ndangerous side effects. Only sign messages from \nsites you fully trust with your entire account.\n This dangerous method will be removed in a future version. ", + "youSign": "You are signing:", + "conversionProgress": "Conversion in progress", + "noDeposits": "No deposits received", + "fromShapeShift": "From ShapeShift", + "invalidRequest": "Invalid Request", + "status": "Status", + "limit": "Limit", + "exchangeRate": "Exchange Rate", + "min": "Minimum", + "available": "Available", + "unavailable": "Unavailable", + "depositBTC": "Deposit your BTC to the address below:", + "deposit": "Deposit", + "receive": "Receive", + "refundAddress": "Your Refund Address", + "buyButton": "Buy", + "signMessage": "Sign Message", + "youSignCaps": "YOU ARE SIGNING", + "messageCaps": "MESSAGE", + "readMore": "Read more here.", + "cancel": "Cancel", + "sign": "Sign", + "accept": "Accept", + "attemptingConnect": "Attempting to connect to blockchain.", + "privateNetwork": "Private Network", + "invalidInput": "Invalid input.", + "noAddressForName": "No address has been set for this name.", + "clickCopy": "Click to Copy", + "copyButton": " Copy ", + "copiedButton": "Copied", + "copy": "Copy", + "copiedExclamation": "Copied!", + "continueToCoinbase": "Continue to Coinbase", + "depositEth": "Deposit Eth", + "selectService": "Select Service", + "unknownNetworkId": "Unknown network ID", + "borrowDharma": "Borrow With Dharma (Beta)", + "exportPrivateKeyWarning": "Export private keys at your own risk.", + "confirmPasswordSmall": "confirm password", + "submit": "Submit", } -- cgit From 03c64ba8a646cbc5a62f2b2a8c5881bb4a4bda60 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 Jan 2018 15:45:33 -0800 Subject: Add unlimitedStorage option to manifest --- app/manifest.json | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index d795a225a..13ba074e7 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -60,6 +60,7 @@ "http://localhost:8545/", "https://*.infura.io/" ], + "unlimitedStorage": true, "web_accessible_resources": [ "scripts/inpage.js" ], -- cgit From 456dfdb9fdc0b7b0637d50808beb85ae33602f5b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 Jan 2018 16:26:50 -0800 Subject: Modify @heyellieday's work to use storage.local to replace main storage --- app/scripts/background.js | 15 ++++++++------- app/scripts/lib/local-store.js | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 app/scripts/lib/local-store.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index d9a2b0a6e..9790129aa 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -4,7 +4,7 @@ const pump = require('pump') const log = require('loglevel') const extension = require('extensionizer') const LocalStorageStore = require('obs-store/lib/localStorage') -const ExtensionStore = require('./lib/extension-store') +const LocalStore = require('./lib/local-store') const storeTransform = require('obs-store/lib/transform') const asStream = require('obs-store/lib/asStream') const ExtensionPlatform = require('./platforms/extension') @@ -29,7 +29,7 @@ let popupIsOpen = false // state persistence const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) -const extensionStore = new ExtensionStore() +const localStore = new LocalStore() // initialization flow initialize().catch(log.error) @@ -51,9 +51,10 @@ async function loadStateFromPersistence () { let versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) // fetch from extension store and merge in data - if (extensionStore.isSupported && extensionStore.isEnabled) { - const extensionData = await extensionStore.fetch() // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) - versionedData = { ...versionedData, ...extensionData } + if (localStore.isSupported) { + const localData = await localStore.get() + // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) + versionedData = localData || versionedData } // migrate data @@ -96,8 +97,8 @@ function setupController (initState) { } function syncDataWithExtension(state) { - if (extensionStore.isSupported && extensionStore.isEnabled) { - extensionStore.sync(state) // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) + if (localStore.isSupported) { + localStore.set(state) // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) } return state } diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js new file mode 100644 index 000000000..32faac96b --- /dev/null +++ b/app/scripts/lib/local-store.js @@ -0,0 +1,25 @@ +// We should not rely on local storage in an extension! +// We should use this instead! +// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/local + +const extension = require('extensionizer') +const STORAGE_KEY = 'metamask-config' + +module.exports = class ExtensionStore { + constructor() { + this.isSupported = !!(extension.storage.local) + if (!this.isSupported) { + log.error('Storage local API not available.') + } + } + async get() { + return new Promise((resolve) => { + extension.storage.local.get(STORAGE_KEY, resolve) + }) + } + async set(state) { + return new Promise((resolve) => { + extension.storage.local.set(state, resolve) + }) + } +} -- cgit From 99898ac77594d8fe6d4d2aa5bc3e3ba6492f4a10 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Tue, 23 Jan 2018 22:14:47 -1000 Subject: better organization of locale file; i18n in more view files --- app/_locales/en/messages.json | 631 +++++++++++++++++++++++++++++++++--------- 1 file changed, 506 insertions(+), 125 deletions(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 6967a44d2..54f266318 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1,71 +1,224 @@ { - "appName": { - "message": "MetaMask", - "description": "The name of the application" + "accept": { + "message": "Accept" + }, + "account": { + "message": "Account:" + }, + "accDetails": { + "message": "Account Details" + }, + "accountName": { + "message": "Account Name" + }, + "address": { + "message": "Address" + }, + "addToken": { + "message": "Add Token" + }, + "amountPlusGas": { + "message": "Amount + Gas" }, "appDescription": { "message": "Ethereum Identity Management", "description": "The description of the application" }, - "encryptNewDen": { - "message": "Encrypt your new DEN" + "appName": { + "message": "MetaMask", + "description": "The name of the application" }, - "denExplainer": { - "message": "Your DEN is your password-encrypted storage within MetaMask." + "attemptingConnect": { + "message": "Attempting to connect to blockchain." }, - "importDen": { - "message": "Import Existing DEN" + "available": { + "message": "Available" }, - "createDen": { - "message": "Create" + "back": { + "message": "Back" }, - "newPassword": { - "message": "New Password (min 8 chars)" + "balance": { + "message": "Balance:" + }, + "balanceIsInsufficientGas": { + "message": "Insufficient balance for current gas total" + }, + "borrowDharma": { + "message": "Borrow With Dharma (Beta)" + }, + "buyButton": { + "message": "Buy" + }, + "buyCoinbase": { + "message": "Buy on Coinbase" + }, + "buyCoinbaseExplainer": { + "message": "Coinbase is the world’s most popular way to buy and sell bitcoin, ethereum, and litecoin." + }, + "cancel": { + "message": "Cancel" + }, + "cancelCaps": { + "message": "CANCEL" + }, + "clickCopy": { + "message": "Click to Copy" + }, + "confirm": { + "message": "Confirm" + }, + "confirmCaps": { + "message": "CONFIRM" + }, + "confirmContract": { + "message": "Confirm Contract" }, "confirmPassword": { "message": "Confirm Password" }, - "passwordMismatch": { - "message": "passwords don't match" + "confirmPasswordSmall": { + "message": "confirm password" }, - "passwordShort": { - "message": "password not long enough" + "continueToCoinbase": { + "message": "Continue to Coinbase" }, - "myAccounts": { - "message": "My Accounts" + "contractPublished": { + "message": "Contract Published" }, - "logout": { - "message": "Log out" + "conversionProgress": { + "message": "Conversion in progress" + }, + "copiedButton": { + "message": "Copied" + }, + "copiedClipboard": { + "message": "Copied to Clipboard" + }, + "copiedExclamation": { + "message": "Copied!" + }, + "copy": { + "message": "Copy" + }, + "copyAddress": { + "message": "Copy Address to clipboard" + }, + "copyButton": { + "message": " Copy " + }, + "copyPrivateKey": { + "message": "This is your private key (click to copy)" }, "createAccount": { "message": "Create Account" }, - "importAccount": { - "message": "Import Account" + "createCaps": { + "message": "CREATE" }, - "account": { - "message": "Account:" + "createDen": { + "message": "Create" }, - "infoHelp": { - "message": "Info & Help" + "customGas": { + "message": "Customize Gas" }, - "settings": { - "message": "Settings" + "customize": { + "message": "Customize" }, - "importedCaps": { - "message": "IMPORTED" + "customRPC": { + "message": "Custom RPC" }, - "saveButton": { - "message": "SAVE" + "defaultNetwork": { + "message": "The default network for Ether transactions is Main Net." }, - "cancelButton": { - "message": "CANCEL" + "denExplainer": { + "message": "Your DEN is your password-encrypted storage within MetaMask." }, - "signButton": { - "message": "SIGN" + "deposit": { + "message": "Deposit" }, - "revert": { - "message": "Revert" + "depositBTC": { + "message": "Deposit your BTC to the address below:" + }, + "depositButton": { + "message": "DEPOSIT" + }, + "depositEth": { + "message": "Deposit Eth" + }, + "depositEther": { + "message": "Deposit Ether" + }, + "depositFiat": { + "message": "Deposit with Fiat" + }, + "depositFromAccount": { + "message": "Deposit from another account" + }, + "depositShapeShift": { + "message": "Deposit with ShapeShift" + }, + "depositShapeShiftExplainer": { + "message": "If you own other cryptocurrencies, you can trade and deposit Ether directly into your MetaMask wallet. No Account Needed." + }, + "detailsCaps": { + "message": "DETAILS" + }, + "directDeposit": { + "message": "Direct Deposit" + }, + "directDepositEther": { + "message": "Directly Deposit Ether" + }, + "directDepositEtherExplainer": { + "message": "If you already have some Ether, the quickest way to get Ether in your new wallet by direct deposit." + }, + "done": { + "message": "Done" + }, + "editAccountName": { + "message": "Edit Account Name" + }, + "editCaps": { + "message": "EDIT" + }, + "encryptNewDen": { + "message": "Encrypt your new DEN" + }, + "enterPassword": { + "message": "Enter password" + }, + "etherscanView": { + "message": "View account on Etherscan" + }, + "exchangeRate": { + "message": "Exchange Rate" + }, + "exportPrivateKey": { + "message": "Export Private Key" + }, + "exportPrivateKeyLower": { + "message": "Export private key" + }, + "exportPrivateKeyWarning": { + "message": "Export private keys at your own risk." + }, + "failed": { + "message": "Failed" + }, + "fileImportFail": { + "message": "File import not working? Click here!" + }, + "from": { + "message": "From" + }, + "fromShapeShift": { + "message": "From ShapeShift" + }, + "gasFee": { + "message": "Gas Fee" + }, + "gasFeeSpecific": { + "message": "Gas fee:" }, "gasLimit": { "message": "Gas Limit" @@ -73,103 +226,331 @@ "gasLimitCalculation": { "message": "We calculate the suggested gas limit based on network success rates." }, + "gasLimitRequired": { + "message": "Gas Limit Required" + }, + "gasLimitTooLow": { + "message": "Gas limit must be at least 21000" + }, "gasPrice": { "message": "Gas Price (GWEI)" }, "gasPriceCalculation": { "message": "We calculate the suggested gas prices based on network success rates." }, - "customGas": { - "message": "Customize Gas" + "gasPriceRequired": { + "message": "Gas Price Required" }, - "balanceIsInsufficientGas": { - "message": "Insufficient balance for current gas total" + "getEther": { + "message": "Get Ether" }, - "gasLimitTooLow": { - "message": "Gas limit must be at least 21000" + "here": { + "message": "here" + }, + "hideCaps": { + "message": "HIDE" + }, + "hideToken": { + "message": "Hide Token" + }, + "hideTokenPrompt": { + "message": "Hide Token?" + }, + "howToDeposit": { + "message": "How would you like to deposit Ether?" + }, + "import": { + "message": "Import" }, - "editButton": { - "message": "Edit" + "importAccount": { + "message": "Import Account" + }, + "importAnAccount": { + "message": "Import an account" + }, + "importCaps": { + "message": "IMPORT" + }, + "importDen": { + "message": "Import Existing DEN" + }, + "importedCaps": { + "message": "IMPORTED" + }, + "infoHelp": { + "message": "Info & Help" + }, + "invalidAddress": { + "message": "Invalid address" + }, + "invalidGasParams": { + "message": "Invalid Gas Parameters" + }, + "invalidInput": { + "message": "Invalid input." + }, + "invalidRequest": { + "message": "Invalid Request" + }, + "kovan": { + "message": "Kovan Test Network" + }, + "limit": { + "message": "Limit" + }, + "loading": { + "message": "Loading..." + }, + "loadingTokens": { + "message": "Loading Tokens..." + }, + "localhost": { + "message": "Localhost 8545" + }, + "logout": { + "message": "Log out" }, "looseCaps": { "message": "LOOSE" }, - "addToken": "Add Token", - "exportPrivateKey": "Export Private Key", - "copyAddress": "Copy Address to clipboard", - "etherscanView": "View account on Etherscan", - "qrCode": "Show QR Code", - "accDetails": "Account Details", - "networks": "Networks", - "defaultNetwork": "The default network for Ether transactions is Main Net.", - "mainnet": "Main Ethereum Network", - "unknownNetwork": "Unknown Private Network", - "rinkeby": "Rinkeby Test Network", - "kovan": "Kovan Test Network", - "ropsten": "Ropsten Test Network", - "localhost": "Localhost 8545", - "customRPC": "Custom RPC", - "hideToken": "Hide Token", - "copiedClipboard": "Copied to Clipboard", - "detailsCaps": "DETAILS", - "sendButton": "SEND", - "depositButton": "DEPOSIT", - "notStarted": "Not Started", - "noTransactions": "No Transactions", - "contractPublished": "Contract Published", - "noTransactionHistory": "No transaction history.", - "warning": "Warning", - "failed": "Failed", - "rejected": "Rejected", - "sigRequested": "Signature Requested", - "yourSigRequested": "Your signature is being requested", - "balance": "Balance:", - "retryWithMoreGas": "Retry with a higher gas price here", - "takesTooLong": "Taking too long?", - "transactionNumber": "Transaction Number", - "loadingTokens": "Loading Tokens...", - "troubleTokenBalances": "We had trouble loading your token balances. You can view them ", - "here": "here", - "message": "Message", - "signNotice": "Signing this message can have \ndangerous side effects. Only sign messages from \nsites you fully trust with your entire account.\n This dangerous method will be removed in a future version. ", - "youSign": "You are signing:", - "conversionProgress": "Conversion in progress", - "noDeposits": "No deposits received", - "fromShapeShift": "From ShapeShift", - "invalidRequest": "Invalid Request", - "status": "Status", - "limit": "Limit", - "exchangeRate": "Exchange Rate", - "min": "Minimum", - "available": "Available", - "unavailable": "Unavailable", - "depositBTC": "Deposit your BTC to the address below:", - "deposit": "Deposit", - "receive": "Receive", - "refundAddress": "Your Refund Address", - "buyButton": "Buy", - "signMessage": "Sign Message", - "youSignCaps": "YOU ARE SIGNING", - "messageCaps": "MESSAGE", - "readMore": "Read more here.", - "cancel": "Cancel", - "sign": "Sign", - "accept": "Accept", - "attemptingConnect": "Attempting to connect to blockchain.", - "privateNetwork": "Private Network", - "invalidInput": "Invalid input.", - "noAddressForName": "No address has been set for this name.", - "clickCopy": "Click to Copy", - "copyButton": " Copy ", - "copiedButton": "Copied", - "copy": "Copy", - "copiedExclamation": "Copied!", - "continueToCoinbase": "Continue to Coinbase", - "depositEth": "Deposit Eth", - "selectService": "Select Service", - "unknownNetworkId": "Unknown network ID", - "borrowDharma": "Borrow With Dharma (Beta)", - "exportPrivateKeyWarning": "Export private keys at your own risk.", - "confirmPasswordSmall": "confirm password", - "submit": "Submit", + "mainnet": { + "message": "Main Ethereum Network" + }, + "message": { + "message": "Message" + }, + "messageCaps": { + "message": "MESSAGE" + }, + "min": { + "message": "Minimum" + }, + "myAccounts": { + "message": "My Accounts" + }, + "needEtherInWallet": { + "message": "To interact with decentralized applications using MetaMask, you’ll need Ether in your wallet." + }, + "needImportFile": { + "message": "You must select a file to import." + }, + "needImportPassword": { + "message": "You must enter a password for the selected file." + }, + "networks": { + "message": "Networks" + }, + "newAccount": { + "message": "New Account" + }, + "newContract": { + "message": "New Contract" + }, + "newPassword": { + "message": "New Password (min 8 chars)" + }, + "newRecipient": { + "message": "New Recipient" + }, + "next": { + "message": "Next" + }, + "noAddressForName": { + "message": "No address has been set for this name." + }, + "noDeposits": { + "message": "No deposits received" + }, + "noTransactionHistory": { + "message": "No transaction history." + }, + "noTransactions": { + "message": "No Transactions" + }, + "notStarted": { + "message": "Not Started" + }, + "oldUI": { + "message": "Old UI" + }, + "oldUIMessage": { + "message": "You have returned to the old UI. You can switch back to the New UI through the option in the top right dropdown menu." + }, + "or": { + "message": "or" + }, + "passwordMismatch": { + "message": "passwords don't match" + }, + "passwordShort": { + "message": "password not long enough" + }, + "pastePrivateKey": { + "message": "Paste your private key string here:" + }, + "pasteSeed": { + "message": "Paste your seed phrase here!" + }, + "privateKeyWarning": { + "message": "Warning: Never disclose this key. Anyone with your private keys can take steal any assets held in your account." + }, + "privateNetwork": { + "message": "Private Network" + }, + "qrCode": { + "message": "Show QR Code" + }, + "readdToken": { + "message": "You can add this token back in the future by going go to “Add token” in your accounts options menu." + }, + "readMore": { + "message": "Read more here." + }, + "receive": { + "message": "Receive" + }, + "recipientAddress": { + "message": "Recipient Address" + }, + "refundAddress": { + "message": "Your Refund Address" + }, + "rejected": { + "message": "Rejected" + }, + "required": { + "message": "Required" + }, + "retryWithMoreGas": { + "message": "Retry with a higher gas price here" + }, + "revert": { + "message": "Revert" + }, + "rinkeby": { + "message": "Rinkeby Test Network" + }, + "ropsten": { + "message": "Ropsten Test Network" + }, + "sampleAccountName": { + "message": "E.g. My new account" + }, + "saveCaps": { + "message": "SAVE" + }, + "selectService": { + "message": "Select Service" + }, + "sendButton": { + "message": "SEND" + }, + "sendTokens": { + "message": "Send Tokens" + }, + "sendTokensAnywhere": { + "message": "Send Tokens to anyone with an Ethereum account" + }, + "settings": { + "message": "Settings" + }, + "shapeshiftBuy": { + "message": "Buy with Shapeshift" + }, + "showPrivateKeys": { + "message": "Show Private Keys" + }, + "sign": { + "message": "Sign" + }, + "signCaps": { + "message": "SIGN" + }, + "signMessage": { + "message": "Sign Message" + }, + "signNotice": { + "message": "Signing this message can have \ndangerous side effects. Only sign messages from \nsites you fully trust with your entire account.\n This dangerous method will be removed in a future version. " + }, + "sigRequested": { + "message": "Signature Requested" + }, + "status": { + "message": "Status" + }, + "submit": { + "message": "Submit" + }, + "takesTooLong": { + "message": "Taking too long?" + }, + "testFaucet": { + "message": "Test Faucet" + }, + "to": { + "message": "To" + }, + "tokenBalance": { + "message": "Your Token Balance is:" + }, + "toSpecific": { + "message": "To:" + }, + "total": { + "message": "Total" + }, + "transactionMemo": { + "message": "Transaction memo (optional)" + }, + "transactionNumber": { + "message": "Transaction Number" + }, + "transfers": { + "message": "Transfers" + }, + "troubleTokenBalances": { + "message": "We had trouble loading your token balances. You can view them " + }, + "typePassword": { + "message": "Type Your Password" + }, + "uiWelcome": { + "message": "Welcome to the New UI (Beta)" + }, + "uiWelcomeMessage": { + "message": "You are now using the new Metamask UI. Take a look around, try out new features like sending tokens, and let us know if you have any issues." + }, + "unavailable": { + "message": "Unavailable" + }, + "unknown": { + "message": "Unknown" + }, + "unknownNetwork": { + "message": "Unknown Private Network" + }, + "unknownNetworkId": { + "message": "Unknown network ID" + }, + "usedByClients": { + "message": "Used by a variety of different clients" + }, + "viewAccount": { + "message": "View Account" + }, + "warning": { + "message": "Warning" + }, + "whatsThis": { + "message": "What's this?" + }, + "yourSigRequested": { + "message": "Your signature is being requested" + }, + "youSign": { + "message": "You are signing:" + }, + "youSignCaps": { + "message": "YOU ARE SIGNING" + } } -- cgit From 0164030e56b1db8117a1a0bdff91987321b2cd1a Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 24 Jan 2018 09:41:32 -0330 Subject: Handle errors when getting and setting to localStore. --- app/scripts/background.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 280c28d70..88600bf1e 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -57,7 +57,13 @@ async function loadStateFromPersistence () { // fetch from extension store and merge in data if (localStore.isSupported) { - const localData = await localStore.get() + let localData + try { + localData = await localStore.get() + } catch (err) { + log.error('error fetching state from local store:', err) + } + // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) versionedData = Object.keys(localData).length > 0 ? localData : versionedData } @@ -113,7 +119,11 @@ function setupController (initState) { function syncDataWithExtension(state) { if (localStore.isSupported) { - localStore.set(state) // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) + try { + localStore.set(state) + } catch (err) { + log.error('error setting state in local store:', err) + } } return state } -- cgit From b7ae77f57a0e2bc68e9548364baa120805a1420c Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 24 Jan 2018 09:43:20 -0330 Subject: Check that extension.storage exists before attempting to call methods on it. --- app/scripts/lib/extension-store.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/extension-store.js b/app/scripts/lib/extension-store.js index 67ee71f16..4a970321c 100644 --- a/app/scripts/lib/extension-store.js +++ b/app/scripts/lib/extension-store.js @@ -15,12 +15,12 @@ const handleDisabledSyncAndResolve = (resolve, toResolve) => { module.exports = class ExtensionStore { constructor() { - this.isSupported = !!(extension.storage.sync) + this.isSupported = !!(extension.storage && extension.storage.sync) this.isEnabled = true // TODO: get value from user settings } async fetch() { return new Promise((resolve) => { - extension.storage.sync.get(KEYS_TO_SYNC, (data) => { + extension.storage && extension.storage.sync.get(KEYS_TO_SYNC, (data) => { handleDisabledSyncAndResolve(resolve, data) }) }) @@ -31,7 +31,7 @@ module.exports = class ExtensionStore { return result }, {}) return new Promise((resolve) => { - extension.storage.sync.set(dataToSync, () => { + extension.storage && extension.storage.sync.set(dataToSync, () => { handleDisabledSyncAndResolve(resolve) }) }) -- cgit From dd80bd48babc1bfebf91ac2350491b06971b1fc1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 24 Jan 2018 11:36:15 -0800 Subject: Corrected unlimitedStorage permission --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 13ba074e7..114586d0f 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -56,11 +56,11 @@ ], "permissions": [ "storage", + "unlimitedStorage", "clipboardWrite", "http://localhost:8545/", "https://*.infura.io/" ], - "unlimitedStorage": true, "web_accessible_resources": [ "scripts/inpage.js" ], -- cgit From f09d72fa2aa88f0def76d228cb7d8eab29e3b092 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 24 Jan 2018 11:36:42 -0800 Subject: Remove extension-store since we aren't using it yet --- app/scripts/lib/extension-store.js | 39 -------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 app/scripts/lib/extension-store.js (limited to 'app') diff --git a/app/scripts/lib/extension-store.js b/app/scripts/lib/extension-store.js deleted file mode 100644 index 4a970321c..000000000 --- a/app/scripts/lib/extension-store.js +++ /dev/null @@ -1,39 +0,0 @@ -const extension = require('extensionizer') - -const KEYS_TO_SYNC = ['KeyringController', 'PreferencesController'] -const FIREFOX_SYNC_DISABLED_MESSAGE = 'Please set webextensions.storage.sync.enabled to true in about:config' - -const handleDisabledSyncAndResolve = (resolve, toResolve) => { - // Firefox 52 has sync available on extension.storage, but it is disabled by default - const lastError = extension.runtime.lastError - if (lastError && lastError.message.includes(FIREFOX_SYNC_DISABLED_MESSAGE)) { - resolve({}) - } else { - resolve(toResolve) - } -} - -module.exports = class ExtensionStore { - constructor() { - this.isSupported = !!(extension.storage && extension.storage.sync) - this.isEnabled = true // TODO: get value from user settings - } - async fetch() { - return new Promise((resolve) => { - extension.storage && extension.storage.sync.get(KEYS_TO_SYNC, (data) => { - handleDisabledSyncAndResolve(resolve, data) - }) - }) - } - async sync(state) { - const dataToSync = KEYS_TO_SYNC.reduce((result, key) => { - result[key] = state.data[key] - return result - }, {}) - return new Promise((resolve) => { - extension.storage && extension.storage.sync.set(dataToSync, () => { - handleDisabledSyncAndResolve(resolve) - }) - }) - } -} -- cgit From b281a5275983c4e2d924ba696c4885fd779d2c44 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 24 Jan 2018 16:49:12 -0330 Subject: Remove already handled TODO comment. --- app/scripts/background.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 88600bf1e..3e04a31b3 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -64,7 +64,6 @@ async function loadStateFromPersistence () { log.error('error fetching state from local store:', err) } - // TODO: handle possible exceptions (https://developer.chrome.com/apps/runtime#property-lastError) versionedData = Object.keys(localData).length > 0 ? localData : versionedData } -- cgit From cd5eaa4393a122247295c7627a3fad3e678bea30 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 24 Jan 2018 13:05:13 -0800 Subject: Remove redundant async modifiers --- app/scripts/lib/local-store.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 32faac96b..9114364b6 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -12,12 +12,12 @@ module.exports = class ExtensionStore { log.error('Storage local API not available.') } } - async get() { + get() { return new Promise((resolve) => { extension.storage.local.get(STORAGE_KEY, resolve) }) } - async set(state) { + set(state) { return new Promise((resolve) => { extension.storage.local.set(state, resolve) }) -- cgit From 76521cf7399c1e694a7202dcb9725ed5e1e2a0d7 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 24 Jan 2018 15:03:16 -0800 Subject: Fix retrieval of object --- app/scripts/lib/local-store.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 9114364b6..9e8d8db37 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -3,7 +3,6 @@ // https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/local const extension = require('extensionizer') -const STORAGE_KEY = 'metamask-config' module.exports = class ExtensionStore { constructor() { @@ -14,7 +13,7 @@ module.exports = class ExtensionStore { } get() { return new Promise((resolve) => { - extension.storage.local.get(STORAGE_KEY, resolve) + extension.storage.local.get(null, resolve) }) } set(state) { -- cgit From 2f13790653cb20d9d967700133df6cf31ff02d14 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 24 Jan 2018 15:28:15 -0800 Subject: Remove local storage writes, add log --- app/scripts/background.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 3e04a31b3..a77763c41 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -35,6 +35,7 @@ let popupIsOpen = false // state persistence const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) const localStore = new LocalStore() +let versionedData // initialization flow initialize().catch(log.error) @@ -53,7 +54,7 @@ async function loadStateFromPersistence () { // migrations const migrator = new Migrator({ migrations }) // read from disk - let versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) + versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) // fetch from extension store and merge in data if (localStore.isSupported) { @@ -64,13 +65,24 @@ async function loadStateFromPersistence () { log.error('error fetching state from local store:', err) } - versionedData = Object.keys(localData).length > 0 ? localData : versionedData + console.log('Comparing localdata and versionedData') + console.dir({ localData }) + + if (Object.keys(localData).length > 0) { + console.log('using the local store data') + versionedData = localData + } } // migrate data versionedData = await migrator.migrateData(versionedData) + // write to disk - diskStore.putState(versionedData) + localStore.set(versionedData) + .catch((reason) => { + log.error('Problem saving migrated data', versionedData) + }) + // return just the data return versionedData.data } @@ -107,11 +119,9 @@ function setupController (initState) { asStream(controller.store), storeTransform(versionifyData), storeTransform(syncDataWithExtension), - asStream(diskStore) ) function versionifyData (state) { - const versionedData = diskStore.getState() versionedData.data = state return versionedData } @@ -119,6 +129,7 @@ function setupController (initState) { function syncDataWithExtension(state) { if (localStore.isSupported) { try { + console.log('persisting state', state) localStore.set(state) } catch (err) { log.error('error setting state in local store:', err) -- cgit From 19a379edbafa468c9c3502d2b6d7750ef7ea2238 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 25 Jan 2018 12:28:11 -0800 Subject: Bump limit for event emitter warning. --- app/scripts/metamask-controller.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 000e17b9e..672ec7403 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -43,6 +43,8 @@ module.exports = class MetamaskController extends EventEmitter { constructor (opts) { super() + this.defaultMaxListeners = 20 + this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) this.opts = opts -- cgit From ceebc6caa4f3eab1cf6c9ec8f47dc8bd450ca4a9 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 25 Jan 2018 13:01:03 -0800 Subject: Debounce storage to avoid crashing pump --- app/scripts/background.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index a77763c41..2a8efd844 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -1,6 +1,7 @@ const urlUtil = require('url') const endOfStream = require('end-of-stream') const pump = require('pump') +const debounce = require('debounce-stream') const log = require('loglevel') const extension = require('extensionizer') const LocalStorageStore = require('obs-store/lib/localStorage') @@ -65,11 +66,7 @@ async function loadStateFromPersistence () { log.error('error fetching state from local store:', err) } - console.log('Comparing localdata and versionedData') - console.dir({ localData }) - if (Object.keys(localData).length > 0) { - console.log('using the local store data') versionedData = localData } } @@ -117,8 +114,12 @@ function setupController (initState) { // setup state persistence pump( asStream(controller.store), + debounce(200), storeTransform(versionifyData), storeTransform(syncDataWithExtension), + (error) => { + log.error('pump hit error', error) + } ) function versionifyData (state) { @@ -126,15 +127,14 @@ function setupController (initState) { return versionedData } - function syncDataWithExtension(state) { + async function syncDataWithExtension(state) { if (localStore.isSupported) { try { - console.log('persisting state', state) - localStore.set(state) + await localStore.set(state) } catch (err) { log.error('error setting state in local store:', err) } - } + } else { log.error('local store not supported') } return state } -- cgit From 8ba64c657ff801425c06db166e2c9a06289047de Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 25 Jan 2018 15:38:43 -0800 Subject: Increase storage debounce value --- app/scripts/background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 2a8efd844..07a260a4f 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -114,7 +114,7 @@ function setupController (initState) { // setup state persistence pump( asStream(controller.store), - debounce(200), + debounce(1000), storeTransform(versionifyData), storeTransform(syncDataWithExtension), (error) => { -- cgit From 62b2ce5b69e1ceb638bbed5a860d70362e245999 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 29 Jan 2018 11:38:25 -0800 Subject: Version 3.13.8 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index d795a225a..865c2e301 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.13.7", + "version": "3.13.8", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From abfa74f09a0119345165a32090d88a1d95df6c80 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Mon, 29 Jan 2018 15:29:01 -0500 Subject: complete i18n across new UI --- app/_locales/en/messages.json | 168 +++++++++++++++++++++++++----------------- app/manifest.json | 6 +- 2 files changed, 105 insertions(+), 69 deletions(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 54f266318..a0c9088cb 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -3,9 +3,9 @@ "message": "Accept" }, "account": { - "message": "Account:" + "message": "Account" }, - "accDetails": { + "accountDetails": { "message": "Account Details" }, "accountName": { @@ -17,11 +17,14 @@ "addToken": { "message": "Add Token" }, + "amount": { + "message": "Amount" + }, "amountPlusGas": { "message": "Amount + Gas" }, "appDescription": { - "message": "Ethereum Identity Management", + "message": "Ethereum Browser Extension", "description": "The description of the application" }, "appName": { @@ -43,10 +46,14 @@ "balanceIsInsufficientGas": { "message": "Insufficient balance for current gas total" }, + "betweenMinAndMax": { + "message": "must be greater than or equal to $1 and less than or equal to $2.", + "description": "helper for inputting hex as decimal input" + }, "borrowDharma": { "message": "Borrow With Dharma (Beta)" }, - "buyButton": { + "buy": { "message": "Buy" }, "buyCoinbase": { @@ -58,26 +65,20 @@ "cancel": { "message": "Cancel" }, - "cancelCaps": { - "message": "CANCEL" - }, "clickCopy": { "message": "Click to Copy" }, "confirm": { "message": "Confirm" }, - "confirmCaps": { - "message": "CONFIRM" - }, "confirmContract": { "message": "Confirm Contract" }, "confirmPassword": { "message": "Confirm Password" }, - "confirmPasswordSmall": { - "message": "confirm password" + "confirmTransaction": { + "message": "Confirm Transaction" }, "continueToCoinbase": { "message": "Continue to Coinbase" @@ -109,15 +110,19 @@ "copyPrivateKey": { "message": "This is your private key (click to copy)" }, + "create": { + "message": "Create" + }, "createAccount": { "message": "Create Account" }, - "createCaps": { - "message": "CREATE" - }, "createDen": { "message": "Create" }, + "crypto": { + "message": "Crypto", + "description": "Exchange type (cryptocurrencies)" + }, "customGas": { "message": "Customize Gas" }, @@ -139,9 +144,6 @@ "depositBTC": { "message": "Deposit your BTC to the address below:" }, - "depositButton": { - "message": "DEPOSIT" - }, "depositEth": { "message": "Deposit Eth" }, @@ -160,8 +162,8 @@ "depositShapeShiftExplainer": { "message": "If you own other cryptocurrencies, you can trade and deposit Ether directly into your MetaMask wallet. No Account Needed." }, - "detailsCaps": { - "message": "DETAILS" + "details": { + "message": "Details" }, "directDeposit": { "message": "Direct Deposit" @@ -175,12 +177,12 @@ "done": { "message": "Done" }, + "edit": { + "message": "Edit" + }, "editAccountName": { "message": "Edit Account Name" }, - "editCaps": { - "message": "EDIT" - }, "encryptNewDen": { "message": "Encrypt your new DEN" }, @@ -196,17 +198,19 @@ "exportPrivateKey": { "message": "Export Private Key" }, - "exportPrivateKeyLower": { - "message": "Export private key" - }, "exportPrivateKeyWarning": { "message": "Export private keys at your own risk." }, "failed": { "message": "Failed" }, + "fiat": { + "message": "FIAT", + "description": "Exchange type" + }, "fileImportFail": { - "message": "File import not working? Click here!" + "message": "File import not working? Click here!", + "description": "Helps user import their account from a JSON file" }, "from": { "message": "From" @@ -214,12 +218,13 @@ "fromShapeShift": { "message": "From ShapeShift" }, + "gas": { + "message": "Gas", + "description": "Short indication of gas cost" + }, "gasFee": { "message": "Gas Fee" }, - "gasFeeSpecific": { - "message": "Gas fee:" - }, "gasLimit": { "message": "Gas Limit" }, @@ -244,11 +249,20 @@ "getEther": { "message": "Get Ether" }, + "getEtherFromFaucet": { + "message": "Get Ether from a faucet for the $1", + "description": "Displays network name for Ether faucet" + }, + "greaterThanMin": { + "message": "must be greater than or equal to $1.", + "description": "helper for inputting hex as decimal input" + }, "here": { - "message": "here" + "message": "here", + "description": "as in -click here- for more information (goes with troubleTokenBalances)" }, - "hideCaps": { - "message": "HIDE" + "hide": { + "message": "Hide" }, "hideToken": { "message": "Hide Token" @@ -260,7 +274,8 @@ "message": "How would you like to deposit Ether?" }, "import": { - "message": "Import" + "message": "Import", + "description": "Button to import an account from a selected file" }, "importAccount": { "message": "Import Account" @@ -268,14 +283,12 @@ "importAnAccount": { "message": "Import an account" }, - "importCaps": { - "message": "IMPORT" - }, "importDen": { "message": "Import Existing DEN" }, - "importedCaps": { - "message": "IMPORTED" + "imported": { + "message": "Imported", + "description": "status showing that an account has been fully loaded into the keyring" }, "infoHelp": { "message": "Info & Help" @@ -292,9 +305,17 @@ "invalidRequest": { "message": "Invalid Request" }, + "jsonFile": { + "message": "JSON File", + "description": "format for importing an account" + }, "kovan": { "message": "Kovan Test Network" }, + "lessThanMax": { + "message": "must be less than or equal to $1.", + "description": "helper for inputting hex as decimal input" + }, "limit": { "message": "Limit" }, @@ -310,8 +331,8 @@ "logout": { "message": "Log out" }, - "looseCaps": { - "message": "LOOSE" + "loose": { + "message": "Loose" }, "mainnet": { "message": "Main Ethereum Network" @@ -319,9 +340,6 @@ "message": { "message": "Message" }, - "messageCaps": { - "message": "MESSAGE" - }, "min": { "message": "Minimum" }, @@ -332,10 +350,12 @@ "message": "To interact with decentralized applications using MetaMask, you’ll need Ether in your wallet." }, "needImportFile": { - "message": "You must select a file to import." + "message": "You must select a file to import.", + "description": "User is important an account and needs to add a file to continue" }, "needImportPassword": { - "message": "You must enter a password for the selected file." + "message": "You must enter a password for the selected file.", + "description": "Password and file needed to import an account" }, "networks": { "message": "Networks" @@ -377,20 +397,28 @@ "message": "You have returned to the old UI. You can switch back to the New UI through the option in the top right dropdown menu." }, "or": { - "message": "or" + "message": "or", + "description": "choice between creating or importing a new account" }, "passwordMismatch": { - "message": "passwords don't match" + "message": "passwords don't match", + "description": "in password creation process, the two new password fields did not match" }, "passwordShort": { - "message": "password not long enough" + "message": "password not long enough", + "description": "in password creation process, the password is not long enough to be secure" }, "pastePrivateKey": { - "message": "Paste your private key string here:" + "message": "Paste your private key string here:", + "description": "For importing an account from a private key" }, "pasteSeed": { "message": "Paste your seed phrase here!" }, + "privateKey": { + "message": "Private Key", + "description": "select this type of file to use to import an account" + }, "privateKeyWarning": { "message": "Warning: Never disclose this key. Anyone with your private keys can take steal any assets held in your account." }, @@ -434,16 +462,21 @@ "message": "Ropsten Test Network" }, "sampleAccountName": { - "message": "E.g. My new account" + "message": "E.g. My new account", + "description": "Help user understand concept of adding a human-readable name to their account" + }, + "save": { + "message": "Save" }, - "saveCaps": { - "message": "SAVE" + "saveAsFile": { + "message": "Save as File", + "description": "Account export process" }, "selectService": { "message": "Select Service" }, - "sendButton": { - "message": "SEND" + "send": { + "message": "Send" }, "sendTokens": { "message": "Send Tokens" @@ -460,12 +493,12 @@ "showPrivateKeys": { "message": "Show Private Keys" }, + "showQRCode": { + "message": "Show QR Code" + }, "sign": { "message": "Sign" }, - "signCaps": { - "message": "SIGN" - }, "signMessage": { "message": "Sign Message" }, @@ -490,12 +523,13 @@ "to": { "message": "To" }, + "toETHviaShapeShift": { + "message": "$1 to ETH via ShapeShift", + "description": "system will fill in deposit type in start of message" + }, "tokenBalance": { "message": "Your Token Balance is:" }, - "toSpecific": { - "message": "To:" - }, "total": { "message": "Total" }, @@ -509,7 +543,8 @@ "message": "Transfers" }, "troubleTokenBalances": { - "message": "We had trouble loading your token balances. You can view them " + "message": "We had trouble loading your token balances. You can view them ", + "description": "Followed by a link (here) to view token balances" }, "typePassword": { "message": "Type Your Password" @@ -532,6 +567,10 @@ "unknownNetworkId": { "message": "Unknown network ID" }, + "usaOnly": { + "message": "USA only", + "description": "Using this exchange is limited to people inside the USA" + }, "usedByClients": { "message": "Used by a variety of different clients" }, @@ -548,9 +587,6 @@ "message": "Your signature is being requested" }, "youSign": { - "message": "You are signing:" - }, - "youSignCaps": { - "message": "YOU ARE SIGNING" + "message": "You are signing" } } diff --git a/app/manifest.json b/app/manifest.json index d906382e9..b52d3245d 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,10 +1,10 @@ { - "name": "MetaMask", - "short_name": "Metamask", + "name": "__MSG_appName__", + "short_name": "__MSG_appName__", "version": "4.0.10", "manifest_version": 2, "author": "https://metamask.io", - "description": "Ethereum Browser Extension", + "description": "__MSG_appDescription__", "commands": { "_execute_browser_action": { "suggested_key": { -- cgit From f13ad6bd6a3b57851e20b6abe2715ef3dacc1e66 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 30 Jan 2018 14:01:28 -0800 Subject: remove BlacklistController from disk state --- app/scripts/metamask-controller.js | 7 +------ app/scripts/migrations/index.js | 1 + 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 672ec7403..adc681f6f 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -86,9 +86,7 @@ module.exports = class MetamaskController extends EventEmitter { }) this.infuraController.scheduleInfuraNetworkCheck() - this.blacklistController = new BlacklistController({ - initState: initState.BlacklistController, - }) + this.blacklistController = new BlacklistController() this.blacklistController.scheduleUpdates() // rpc provider @@ -200,9 +198,6 @@ module.exports = class MetamaskController extends EventEmitter { this.networkController.store.subscribe((state) => { this.store.updateState({ NetworkController: state }) }) - this.blacklistController.store.subscribe((state) => { - this.store.updateState({ BlacklistController: state }) - }) this.recentBlocksController.store.subscribe((state) => { this.store.updateState({ RecentBlocks: state }) }) diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 9d0631042..a0cf5f4d4 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -31,4 +31,5 @@ module.exports = [ require('./018'), require('./019'), require('./020'), + require('./021'), ] -- cgit From 28ee0aae9131e4543759e48b8879c364b20a60ac Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 30 Jan 2018 14:02:41 -0800 Subject: creater migration to remove BlacklistController --- app/scripts/migrations/021.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 app/scripts/migrations/021.js (limited to 'app') diff --git a/app/scripts/migrations/021.js b/app/scripts/migrations/021.js new file mode 100644 index 000000000..0d3f35b77 --- /dev/null +++ b/app/scripts/migrations/021.js @@ -0,0 +1,33 @@ +const version = 21 + +/* + +This migration removes the BlackListController from disk state + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + delete newState.BlacklistController + return newState +} + -- cgit From e6fda855a556a6aa0325556b074612ff76925e5d Mon Sep 17 00:00:00 2001 From: Bruno Barbieri Date: Wed, 31 Jan 2018 03:33:15 -0500 Subject: added reset account feature --- app/scripts/controllers/transactions.js | 4 ++++ app/scripts/lib/tx-state-manager.js | 4 ++++ app/scripts/metamask-controller.js | 8 ++++++++ 3 files changed, 16 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 9c3618e60..7ca04caf1 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -152,6 +152,10 @@ module.exports = class TransactionController extends EventEmitter { } } + wipeTransactions(){ + this.txStateManager.wipeTransactions(); + } + // Adds a tx to the txlist addTx (txMeta) { this.txStateManager.addTx(txMeta) diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index a8ef39891..61ce2024a 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -221,6 +221,10 @@ module.exports = class TransactionStateManger extends EventEmitter { this._setTxStatus(txId, 'failed') } + wipeTransactions(){ + this._saveTxList([]); + } + // // PRIVATE METHODS // diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 672ec7403..79e3de4cc 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -348,6 +348,7 @@ module.exports = class MetamaskController extends EventEmitter { addNewAccount: nodeify(this.addNewAccount, this), placeSeedWords: this.placeSeedWords.bind(this), clearSeedWordCache: this.clearSeedWordCache.bind(this), + resetAccount: this.resetAccount.bind(this), importAccountWithStrategy: this.importAccountWithStrategy.bind(this), // vault management @@ -604,6 +605,13 @@ module.exports = class MetamaskController extends EventEmitter { cb(null, this.preferencesController.getSelectedAddress()) } + + resetAccount(cb){ + this.txController.wipeTransactions(); + cb(null, this.preferencesController.getSelectedAddress()) + } + + importAccountWithStrategy (strategy, args, cb) { accountImporter.importAccount(strategy, args) .then((privateKey) => { -- cgit From 5f39844382fb3106b883efb81f55a6e909f28b01 Mon Sep 17 00:00:00 2001 From: Bruno Barbieri Date: Wed, 31 Jan 2018 03:36:04 -0500 Subject: clean up --- app/scripts/lib/tx-state-manager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 61ce2024a..6b4a196f2 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -221,10 +221,10 @@ module.exports = class TransactionStateManger extends EventEmitter { this._setTxStatus(txId, 'failed') } - wipeTransactions(){ - this._saveTxList([]); + wipeTransactions () { + this._saveTxList([]); } - + // // PRIVATE METHODS // -- cgit From 03d17c75ae47806e9afa562cf664819b83a2b926 Mon Sep 17 00:00:00 2001 From: Bruno Barbieri Date: Wed, 31 Jan 2018 04:25:32 -0500 Subject: wipe only transactions for current account --- app/scripts/controllers/transactions.js | 4 ++-- app/scripts/lib/tx-state-manager.js | 12 +++++++++--- app/scripts/metamask-controller.js | 8 ++++---- 3 files changed, 15 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 7ca04caf1..a3670155a 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -152,8 +152,8 @@ module.exports = class TransactionController extends EventEmitter { } } - wipeTransactions(){ - this.txStateManager.wipeTransactions(); + wipeTransactions (address) { + this.txStateManager.wipeTransactions(address) } // Adds a tx to the txlist diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 6b4a196f2..13e645a28 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -221,10 +221,16 @@ module.exports = class TransactionStateManger extends EventEmitter { this._setTxStatus(txId, 'failed') } - wipeTransactions () { - this._saveTxList([]); + wipeTransactions (address) { + // network only tx + const txs = this.getTxList() + + // Filter out the ones from the current account + const otherAccountTxs = txs.filter((txMeta) => txMeta.from !== address) + + // Update state + this._saveTxList(otherAccountTxs) } - // // PRIVATE METHODS // diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 79e3de4cc..14ce9c590 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -605,10 +605,10 @@ module.exports = class MetamaskController extends EventEmitter { cb(null, this.preferencesController.getSelectedAddress()) } - - resetAccount(cb){ - this.txController.wipeTransactions(); - cb(null, this.preferencesController.getSelectedAddress()) + resetAccount (cb) { + const selectedAddress = this.preferencesController.getSelectedAddress() + this.txController.wipeTransactions(selectedAddress) + cb(null, selectedAddress) } -- cgit From 7dc1b09f94003fdac4ed9ea36ecf1c1a14d972a1 Mon Sep 17 00:00:00 2001 From: Bruno Barbieri Date: Wed, 31 Jan 2018 04:40:32 -0500 Subject: use txMeta.txParams --- app/scripts/lib/tx-state-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 13e645a28..f488130a2 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -226,7 +226,7 @@ module.exports = class TransactionStateManger extends EventEmitter { const txs = this.getTxList() // Filter out the ones from the current account - const otherAccountTxs = txs.filter((txMeta) => txMeta.from !== address) + const otherAccountTxs = txs.filter((txMeta) => txMeta.txParams.from !== address) // Update state this._saveTxList(otherAccountTxs) -- cgit From c1b7cfe91d803c0085afe59d058f2422a0e8dc30 Mon Sep 17 00:00:00 2001 From: Bruno Barbieri Date: Wed, 31 Jan 2018 13:29:02 -0500 Subject: preserve other networks TXs --- app/scripts/lib/tx-state-manager.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index f488130a2..051efd247 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -223,10 +223,11 @@ module.exports = class TransactionStateManger extends EventEmitter { wipeTransactions (address) { // network only tx - const txs = this.getTxList() + const txs = this.getFullTxList() + const network = this.getNetwork() - // Filter out the ones from the current account - const otherAccountTxs = txs.filter((txMeta) => txMeta.txParams.from !== address) + // Filter out the ones from the current account and network + const otherAccountTxs = txs.filter((txMeta) => !(txMeta.txParams.from === address && txMeta.metamaskNetworkId === network)) // Update state this._saveTxList(otherAccountTxs) -- cgit From c3adbda5f561c20c011a7b78f1e84513cebba87e Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 31 Jan 2018 10:49:58 -0800 Subject: remove RecentBlocks from disk --- app/scripts/metamask-controller.js | 4 +--- app/scripts/migrations/021.js | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index adc681f6f..15058188d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -198,9 +198,7 @@ module.exports = class MetamaskController extends EventEmitter { this.networkController.store.subscribe((state) => { this.store.updateState({ NetworkController: state }) }) - this.recentBlocksController.store.subscribe((state) => { - this.store.updateState({ RecentBlocks: state }) - }) + this.infuraController.store.subscribe((state) => { this.store.updateState({ InfuraController: state }) }) diff --git a/app/scripts/migrations/021.js b/app/scripts/migrations/021.js index 0d3f35b77..d84e77b50 100644 --- a/app/scripts/migrations/021.js +++ b/app/scripts/migrations/021.js @@ -28,6 +28,7 @@ module.exports = { function transformState (state) { const newState = state delete newState.BlacklistController + delete newState.RecentBlocks return newState } -- cgit From 0608d1579fe4a2ea06605cc005ad805f36b94870 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 1 Feb 2018 12:27:19 -0800 Subject: Version 3.14.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 865c2e301..abbb3c865 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.13.8", + "version": "3.14.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 9f304e30263b215862ce1af09e96440acdbc529d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 1 Feb 2018 15:53:18 -0800 Subject: Version 3.14.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index abbb3c865..a0bb5acf6 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.14.0", + "version": "3.14.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 7f151b861cc3a565d3feefc50b3be25ab4490ac8 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 7 Feb 2018 21:08:55 -0330 Subject: [NewUI] Opens to full screen when restoring from seed. (#3201) * Opens to full screen when restoring from seed. * Remove redundant parameter in actions.markPasswordForgotten call. --- app/scripts/lib/config-manager.js | 11 +++++++++++ app/scripts/metamask-controller.js | 15 +++++++++++++++ 2 files changed, 26 insertions(+) (limited to 'app') diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 9c0dffe9c..34b603b96 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -42,6 +42,17 @@ ConfigManager.prototype.getData = function () { return this.store.getState() } +ConfigManager.prototype.setPasswordForgotten = function (passwordForgottenState) { + const data = this.getData() + data.forgottenPassword = passwordForgottenState + this.setData(data) +} + +ConfigManager.prototype.getPasswordForgotten = function (passwordForgottenState) { + const data = this.getData() + return data.forgottenPassword +} + ConfigManager.prototype.setWallet = function (wallet) { var data = this.getData() data.wallet = wallet diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 962516af6..cb671ec3c 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -315,6 +315,7 @@ module.exports = class MetamaskController extends EventEmitter { { lostAccounts: this.configManager.getLostAccounts(), seedWords: this.configManager.getSeedWords(), + forgottenPassword: this.configManager.getPasswordForgotten(), } ) } @@ -337,6 +338,8 @@ module.exports = class MetamaskController extends EventEmitter { setCurrentCurrency: this.setCurrentCurrency.bind(this), setUseBlockie: this.setUseBlockie.bind(this), markAccountsFound: this.markAccountsFound.bind(this), + markPasswordForgotten: this.markPasswordForgotten.bind(this), + unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this), // coinbase buyEth: this.buyEth.bind(this), @@ -791,6 +794,18 @@ module.exports = class MetamaskController extends EventEmitter { cb(null, this.getState()) } + markPasswordForgotten(cb) { + this.configManager.setPasswordForgotten(true) + this.sendUpdate() + cb() + } + + unMarkPasswordForgotten(cb) { + this.configManager.setPasswordForgotten(false) + this.sendUpdate() + cb() + } + restoreOldVaultAccounts (migratorOutput) { const { serialized } = migratorOutput return this.keyringController.restoreKeyring(serialized) -- cgit From 94cd5b9df480a0c2e2897495c9edddd13461f23a Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2018 19:33:33 +0000 Subject: metamask mesh - inject mesh testing container --- app/scripts/background.js | 4 ++++ app/scripts/lib/setupMetamaskMeshMetrics.js | 9 +++++++++ 2 files changed, 13 insertions(+) create mode 100644 app/scripts/lib/setupMetamaskMeshMetrics.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 0471cee3b..6bf7707e8 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -14,6 +14,7 @@ const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') const firstTimeState = require('./first-time-state') const setupRaven = require('./setupRaven') +const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -37,6 +38,9 @@ const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) // initialization flow initialize().catch(log.error) +// setup metamask mesh testing container +setupMetamaskMeshMetrics() + async function initialize () { const initState = await loadStateFromPersistence() await setupController(initState) diff --git a/app/scripts/lib/setupMetamaskMeshMetrics.js b/app/scripts/lib/setupMetamaskMeshMetrics.js new file mode 100644 index 000000000..40343f017 --- /dev/null +++ b/app/scripts/lib/setupMetamaskMeshMetrics.js @@ -0,0 +1,9 @@ + +module.exports = setupMetamaskMeshMetrics + +function setupMetamaskMeshMetrics() { + const testingContainer = document.createElement('iframe') + testingContainer.src = 'https://metamask.github.io/mesh-testing/' + console.log('Injecting MetaMask Mesh testing client') + document.head.appendChild(testingContainer) +} -- cgit From 58a554b1684fd78775b449b8f2b5d9635d30b69b Mon Sep 17 00:00:00 2001 From: Lazaridis Date: Sun, 11 Feb 2018 05:09:27 +0200 Subject: use the providers initial _blocktracker. fixes #2393 --- app/scripts/metamask-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 63815ab65..428c78e2c 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -444,7 +444,7 @@ module.exports = class MetamaskController extends EventEmitter { // create filter polyfill middleware const filterMiddleware = createFilterMiddleware({ provider: this.provider, - blockTracker: this.blockTracker, + blockTracker: this.provider._blockTracker, }) engine.push(createOriginMiddleware({ origin })) -- cgit From dc3f3e79ca7319b97255456a5225a266d38a4d6f Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 14 Feb 2018 14:37:02 -0800 Subject: fix - hex prefix estimatedGas on txMeta --- app/scripts/lib/tx-gas-utils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index f68f3a9e2..6f6ff7852 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -4,6 +4,7 @@ const { BnMultiplyByFraction, bnToHex, } = require('./util') +const addHexPrefix = require('ethereumjs-util').addHexPrefix const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. /* @@ -13,7 +14,7 @@ and used to do things like calculate gas of a tx. */ module.exports = class TxGasUtil { - + constructor (provider) { this.query = new EthQuery(provider) } @@ -68,7 +69,7 @@ module.exports = class TxGasUtil { } setTxGas (txMeta, blockGasLimitHex, estimatedGasHex) { - txMeta.estimatedGas = estimatedGasHex + txMeta.estimatedGas = addHexPrefix(estimatedGasHex) const txParams = txMeta.txParams // if gasLimit was specified and doesnt OOG, -- cgit From ed33f3160a35e2e765012a4726ff90f9b3608998 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Thu, 15 Feb 2018 12:36:26 -0800 Subject: Make oldui compatible with newUI style changes --- app/popup.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/popup.html b/app/popup.html index c4e5188e5..bf09b97ca 100644 --- a/app/popup.html +++ b/app/popup.html @@ -1,11 +1,11 @@ - + MetaMask Plugin - +
-- cgit From 71be537f1cdfe7df41e350f6720c12f5a7bb9b2d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 15 Feb 2018 14:23:22 -0800 Subject: Version 3.14.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a0bb5acf6..3a80cc4fc 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.14.1", + "version": "3.14.2", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 73e5ae6e29d04481cc3ffdd32d5d096e6a10b3b3 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 15 Feb 2018 15:32:48 -0800 Subject: Fix incorrect promise instantiation --- app/scripts/lib/nonce-tracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 0029ac953..ed9dd3f11 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -56,7 +56,7 @@ class NonceTracker { const blockTracker = this._getBlockTracker() const currentBlock = blockTracker.getCurrentBlock() if (currentBlock) return currentBlock - return await Promise((reject, resolve) => { + return await new Promise((reject, resolve) => { blockTracker.once('latest', resolve) }) } -- cgit From 06838774fa0bfb0ddea4db049211f92781841ff5 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 16 Feb 2018 10:21:06 -0800 Subject: sentry - report failed tx with more specific message --- app/scripts/background.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 6bf7707e8..3e1178457 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -85,7 +85,8 @@ function setupController (initState) { controller.txController.on(`tx:status-update`, (txId, status) => { if (status !== 'failed') return const txMeta = controller.txController.txStateManager.getTx(txId) - raven.captureMessage('Transaction Failed', { + const errorMessage = `Transaction Failed: ${txMeta.err.message}` + raven.captureMessage(errorMessage, { // "extra" key is required by Sentry extra: txMeta, }) -- cgit From 7169cb1eb83ae9a378dad3240527989e6df0f158 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 16 Feb 2018 19:36:17 -0330 Subject: Bump uat version to 4.0.12 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a0bb5acf6..c4e134053 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.14.1", + "version": "4.0.12", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 98d3fba3efaedb65ee0cf60b4cc3f954a1fd9740 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 20 Feb 2018 15:45:48 -0800 Subject: Fix promise construction --- app/scripts/lib/nonce-tracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/nonce-tracker.js b/app/scripts/lib/nonce-tracker.js index 0029ac953..ed9dd3f11 100644 --- a/app/scripts/lib/nonce-tracker.js +++ b/app/scripts/lib/nonce-tracker.js @@ -56,7 +56,7 @@ class NonceTracker { const blockTracker = this._getBlockTracker() const currentBlock = blockTracker.getCurrentBlock() if (currentBlock) return currentBlock - return await Promise((reject, resolve) => { + return await new Promise((reject, resolve) => { blockTracker.once('latest', resolve) }) } -- cgit From a4ed6af2ad9469a29e100f9246e8960b078cff46 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 21 Feb 2018 14:54:00 -0330 Subject: Prevents new transaction from generating popup when metamask is open in an active tab. --- app/scripts/background.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 0471cee3b..816c655a1 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -30,6 +30,7 @@ const release = platform.getVersion() const raven = setupRaven({ release }) let popupIsOpen = false +let openMetamaskTabsIDs = {} // state persistence const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) @@ -113,9 +114,15 @@ function setupController (initState) { popupIsOpen = popupIsOpen || (remotePort.name === 'popup') controller.setupTrustedCommunication(portStream, 'MetaMask') // record popup as closed + if (remotePort.sender.url.match(/home.html$/)) { + openMetamaskTabsIDs[remotePort.sender.tab.id] = true + } if (remotePort.name === 'popup') { endOfStream(portStream, () => { popupIsOpen = false + if (remotePort.sender.url.match(/home.html$/)) { + openMetamaskTabsIDs[remotePort.sender.tab.id] = false + } }) } } else { @@ -158,7 +165,10 @@ function setupController (initState) { // popup trigger function triggerUi () { - if (!popupIsOpen) notificationManager.showPopup() + extension.tabs.query({ active: true }, (tabs) => { + const currentlyActiveMetamaskTab = tabs.find(tab => openMetamaskTabsIDs[tab.id]) + if (!popupIsOpen && !currentlyActiveMetamaskTab) notificationManager.showPopup() + }) } // On first install, open a window to MetaMask website to how-it-works. -- cgit From 5ec311ba3e01bd9b0a9ff447fd7639d22a7b3d9c Mon Sep 17 00:00:00 2001 From: Csaba Solya Date: Thu, 22 Feb 2018 14:39:32 +0100 Subject: add edge support --- app/scripts/background.js | 8 +++++ app/scripts/edge-encryptor.js | 69 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 app/scripts/edge-encryptor.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 6bf7707e8..7bececba1 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -15,6 +15,7 @@ const MetamaskController = require('./metamask-controller') const firstTimeState = require('./first-time-state') const setupRaven = require('./setupRaven') const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') +const EdgeEncryptor = require('./edge-encryptor') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -30,6 +31,12 @@ global.METAMASK_NOTIFIER = notificationManager const release = platform.getVersion() const raven = setupRaven({ release }) +// browser check if it is Edge - https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser +// Internet Explorer 6-11 +const isIE = !!document.documentMode +// Edge 20+ +const isEdge = !isIE && !!window.StyleMedia + let popupIsOpen = false // state persistence @@ -78,6 +85,7 @@ function setupController (initState) { initState, // platform specific api platform, + encryptor: isEdge ? new EdgeEncryptor() : undefined, }) global.metamaskController = controller diff --git a/app/scripts/edge-encryptor.js b/app/scripts/edge-encryptor.js new file mode 100644 index 000000000..9d6ac37b3 --- /dev/null +++ b/app/scripts/edge-encryptor.js @@ -0,0 +1,69 @@ +const asmcrypto = require('asmcrypto.js') +const Unibabel = require('browserify-unibabel') + +class EdgeEncryptor { + + encrypt (password, dataObject) { + + var salt = this._generateSalt() + return this.keyFromPassword(password, salt) + .then(function (key) { + + var data = JSON.stringify(dataObject) + var dataBuffer = Unibabel.utf8ToBuffer(data) + var vector = global.crypto.getRandomValues(new Uint8Array(16)) + var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) + + var buffer = new Uint8Array(resultbuffer) + var vectorStr = Unibabel.bufferToBase64(vector) + var vaultStr = Unibabel.bufferToBase64(buffer) + return JSON.stringify({ + data: vaultStr, + iv: vectorStr, + salt: salt, + }) + }) + } + + decrypt (password, text) { + + const payload = JSON.parse(text) + const salt = payload.salt + return this.keyFromPassword(password, salt) + .then(function (key) { + const encryptedData = Unibabel.base64ToBuffer(payload.data) + const vector = Unibabel.base64ToBuffer(payload.iv) + return new Promise((resolve, reject) => { + var result + try { + result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector) + } catch (err) { + return reject(new Error('Incorrect password')) + } + const decryptedData = new Uint8Array(result) + const decryptedStr = Unibabel.bufferToUtf8(decryptedData) + const decryptedObj = JSON.parse(decryptedStr) + resolve(decryptedObj) + }) + }) + } + + keyFromPassword (password, salt) { + + var passBuffer = Unibabel.utf8ToBuffer(password) + var saltBuffer = Unibabel.base64ToBuffer(salt) + return new Promise((resolve) => { + var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000) + resolve(key) + }) + } + + _generateSalt (byteCount = 32) { + var view = new Uint8Array(byteCount) + global.crypto.getRandomValues(view) + var b64encoded = btoa(String.fromCharCode.apply(null, view)) + return b64encoded + } +} + +module.exports = EdgeEncryptor -- cgit From b45295499e0df87c20e1411b43d6e6ba88e9aeed Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 22 Feb 2018 14:57:24 -0800 Subject: Version 4.0.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index c4e134053..2abe673db 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.12", + "version": "4.0.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 73d9bfc52cfb4b63f0960d80a7b68f2bf6f7d88c Mon Sep 17 00:00:00 2001 From: Csaba Solya Date: Fri, 23 Feb 2018 10:09:16 +0100 Subject: make keyFromPassword private --- app/scripts/edge-encryptor.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/edge-encryptor.js b/app/scripts/edge-encryptor.js index 9d6ac37b3..24c0c93a8 100644 --- a/app/scripts/edge-encryptor.js +++ b/app/scripts/edge-encryptor.js @@ -6,7 +6,7 @@ class EdgeEncryptor { encrypt (password, dataObject) { var salt = this._generateSalt() - return this.keyFromPassword(password, salt) + return this._keyFromPassword(password, salt) .then(function (key) { var data = JSON.stringify(dataObject) @@ -29,7 +29,7 @@ class EdgeEncryptor { const payload = JSON.parse(text) const salt = payload.salt - return this.keyFromPassword(password, salt) + return this._keyFromPassword(password, salt) .then(function (key) { const encryptedData = Unibabel.base64ToBuffer(payload.data) const vector = Unibabel.base64ToBuffer(payload.iv) @@ -48,7 +48,7 @@ class EdgeEncryptor { }) } - keyFromPassword (password, salt) { + _keyFromPassword (password, salt) { var passBuffer = Unibabel.utf8ToBuffer(password) var saltBuffer = Unibabel.base64ToBuffer(salt) -- cgit From d9486a3ce535636f890bee76a635571f2be0ec7c Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 27 Feb 2018 10:35:43 -0800 Subject: Bump Version --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 2abe673db..eab6c7063 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.0.0", + "version": "4.1.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From fca2cbc8ef8e0d8434fd8c437497a7a0792e2caf Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 28 Feb 2018 10:37:53 -0800 Subject: sentry - clean - move setupRaven to lib --- app/scripts/background.js | 2 +- app/scripts/lib/setupRaven.js | 26 ++++++++++++++++++++++++++ app/scripts/popup.js | 2 +- app/scripts/setupRaven.js | 26 -------------------------- 4 files changed, 28 insertions(+), 28 deletions(-) create mode 100644 app/scripts/lib/setupRaven.js delete mode 100644 app/scripts/setupRaven.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 476d073d1..0da079eb6 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -13,7 +13,7 @@ const PortStream = require('./lib/port-stream.js') const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') const firstTimeState = require('./first-time-state') -const setupRaven = require('./setupRaven') +const setupRaven = require('./lib/setupRaven') const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') const STORAGE_KEY = 'metamask-config' diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupRaven.js new file mode 100644 index 000000000..42e48cb90 --- /dev/null +++ b/app/scripts/lib/setupRaven.js @@ -0,0 +1,26 @@ +const Raven = require('../vendor/raven.min.js') +const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' +const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' + +module.exports = setupRaven + +// Setup raven / sentry remote error reporting +function setupRaven(opts) { + const { release } = opts + let ravenTarget + + if (METAMASK_DEBUG) { + console.log('Setting up Sentry Remote Error Reporting: DEV') + ravenTarget = DEV + } else { + console.log('Setting up Sentry Remote Error Reporting: PROD') + ravenTarget = PROD + } + + Raven.config(ravenTarget, { + release, + }).install() + + return Raven +} diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 53ab00e00..11d50ee87 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -8,7 +8,7 @@ const extension = require('extensionizer') const ExtensionPlatform = require('./platforms/extension') const NotificationManager = require('./lib/notification-manager') const notificationManager = new NotificationManager() -const setupRaven = require('./setupRaven') +const setupRaven = require('./lib/setupRaven') // create platform global global.platform = new ExtensionPlatform() diff --git a/app/scripts/setupRaven.js b/app/scripts/setupRaven.js deleted file mode 100644 index 7beffeff9..000000000 --- a/app/scripts/setupRaven.js +++ /dev/null @@ -1,26 +0,0 @@ -const Raven = require('./vendor/raven.min.js') -const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' -const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' -const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' - -module.exports = setupRaven - -// Setup raven / sentry remote error reporting -function setupRaven(opts) { - const { release } = opts - let ravenTarget - - if (METAMASK_DEBUG) { - console.log('Setting up Sentry Remote Error Reporting: DEV') - ravenTarget = DEV - } else { - console.log('Setting up Sentry Remote Error Reporting: PROD') - ravenTarget = PROD - } - - Raven.config(ravenTarget, { - release, - }).install() - - return Raven -} -- cgit From 8e5bcf89359edb70b5d6847a4848c222aa283066 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 28 Feb 2018 10:53:54 -0800 Subject: sentry - failed tx - improve ethjs-rpc error formating --- app/scripts/background.js | 8 +++---- app/scripts/lib/reportFailedTxToSentry.js | 38 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 app/scripts/lib/reportFailedTxToSentry.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 0da079eb6..4487ff318 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -14,8 +14,10 @@ const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') const firstTimeState = require('./first-time-state') const setupRaven = require('./lib/setupRaven') +const reportFailedTxToSentry = require('./lib/reportFailedTxToSentry') const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') + const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -86,11 +88,7 @@ function setupController (initState) { controller.txController.on(`tx:status-update`, (txId, status) => { if (status !== 'failed') return const txMeta = controller.txController.txStateManager.getTx(txId) - const errorMessage = `Transaction Failed: ${txMeta.err.message}` - raven.captureMessage(errorMessage, { - // "extra" key is required by Sentry - extra: txMeta, - }) + reportFailedTxToSentry({ raven, txMeta }) }) // setup state persistence diff --git a/app/scripts/lib/reportFailedTxToSentry.js b/app/scripts/lib/reportFailedTxToSentry.js new file mode 100644 index 000000000..67b0acf43 --- /dev/null +++ b/app/scripts/lib/reportFailedTxToSentry.js @@ -0,0 +1,38 @@ +const ethJsRpcSlug = 'Error: [ethjs-rpc] rpc error with payload ' +const errorLabelPrefix = 'Error: ' + +module.exports = reportFailedTxToSentry + +// +// utility for formatting failed transaction messages +// for sending to sentry +// + +function reportFailedTxToSentry({ raven, txMeta }) { + const errorMessage = extractErrorMessage(txMeta.err.message) + raven.captureMessage(errorMessage, { + // "extra" key is required by Sentry + extra: txMeta, + }) +} + +// +// ethjs-rpc provides overly verbose error messages +// if we detect this type of message, we extract the important part +// Below is an example input and output +// +// Error: [ethjs-rpc] rpc error with payload {"id":3947817945380,"jsonrpc":"2.0","params":["0xf8eb8208708477359400830398539406012c8cf97bead5deae237070f9587f8e7a266d80b8843d7d3f5a0000000000000000000000000000000000000000000000000000000000081d1a000000000000000000000000000000000000000000000000001ff973cafa800000000000000000000000000000000000000000000000000000038d7ea4c68000000000000000000000000000000000000000000000000000000000000003f48025a04c32a9b630e0d9e7ff361562d850c86b7a884908135956a7e4a336fa0300d19ca06830776423f25218e8d19b267161db526e66895567147015b1f3fc47aef9a3c7"],"method":"eth_sendRawTransaction"} Error: replacement transaction underpriced +// +// "Transaction Failed: replacement transaction underpriced" +// + +function extractErrorMessage(errorMessage) { + const isEthjsRpcError = errorMessage.includes(ethJsRpcSlug) + if (isEthjsRpcError) { + const payloadAndError = errorMessage.slice(ethJsRpcSlug.length) + const originalError = payloadAndError.slice(payloadAndError.indexOf(errorLabelPrefix) + errorLabelPrefix.length) + return `Transaction Failed: ${originalError}` + } else { + return `Transaction Failed: ${errorMessage}` + } +} -- cgit From c3bd27c9657d5e0236e2960dedd108ca5e2bb0ec Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 28 Feb 2018 10:57:54 -0800 Subject: sentry - extractErrorMessage - fix comment formatting --- app/scripts/lib/reportFailedTxToSentry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/reportFailedTxToSentry.js b/app/scripts/lib/reportFailedTxToSentry.js index 67b0acf43..ee73f6845 100644 --- a/app/scripts/lib/reportFailedTxToSentry.js +++ b/app/scripts/lib/reportFailedTxToSentry.js @@ -23,7 +23,7 @@ function reportFailedTxToSentry({ raven, txMeta }) { // // Error: [ethjs-rpc] rpc error with payload {"id":3947817945380,"jsonrpc":"2.0","params":["0xf8eb8208708477359400830398539406012c8cf97bead5deae237070f9587f8e7a266d80b8843d7d3f5a0000000000000000000000000000000000000000000000000000000000081d1a000000000000000000000000000000000000000000000000001ff973cafa800000000000000000000000000000000000000000000000000000038d7ea4c68000000000000000000000000000000000000000000000000000000000000003f48025a04c32a9b630e0d9e7ff361562d850c86b7a884908135956a7e4a336fa0300d19ca06830776423f25218e8d19b267161db526e66895567147015b1f3fc47aef9a3c7"],"method":"eth_sendRawTransaction"} Error: replacement transaction underpriced // -// "Transaction Failed: replacement transaction underpriced" +// Transaction Failed: replacement transaction underpriced // function extractErrorMessage(errorMessage) { -- cgit From d45116824c289a12ba43fcff257d282ef7f38902 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 28 Feb 2018 13:03:46 -0800 Subject: Check in all font files locally. --- app/fonts/Font_Awesome/font-awesome.min.css | 4 + app/fonts/fonts/FontAwesome.otf | Bin 0 -> 106260 bytes app/fonts/fonts/fontawesome-webfont.eot | Bin 0 -> 68875 bytes app/fonts/fonts/fontawesome-webfont.svg | 640 ++++++++++++++++++++++++++++ app/fonts/fonts/fontawesome-webfont.ttf | Bin 0 -> 138204 bytes app/fonts/fonts/fontawesome-webfont.woff | Bin 0 -> 81284 bytes app/fonts/fonts/fontawesome-webfont.woff2 | Bin 0 -> 64464 bytes 7 files changed, 644 insertions(+) create mode 100644 app/fonts/Font_Awesome/font-awesome.min.css create mode 100644 app/fonts/fonts/FontAwesome.otf create mode 100644 app/fonts/fonts/fontawesome-webfont.eot create mode 100644 app/fonts/fonts/fontawesome-webfont.svg create mode 100644 app/fonts/fonts/fontawesome-webfont.ttf create mode 100644 app/fonts/fonts/fontawesome-webfont.woff create mode 100644 app/fonts/fonts/fontawesome-webfont.woff2 (limited to 'app') diff --git a/app/fonts/Font_Awesome/font-awesome.min.css b/app/fonts/Font_Awesome/font-awesome.min.css new file mode 100644 index 000000000..ee4e9782b --- /dev/null +++ b/app/fonts/Font_Awesome/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.4.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"} diff --git a/app/fonts/fonts/FontAwesome.otf b/app/fonts/fonts/FontAwesome.otf new file mode 100644 index 000000000..681bdd4d4 Binary files /dev/null and b/app/fonts/fonts/FontAwesome.otf differ diff --git a/app/fonts/fonts/fontawesome-webfont.eot b/app/fonts/fonts/fontawesome-webfont.eot new file mode 100644 index 000000000..a30335d74 Binary files /dev/null and b/app/fonts/fonts/fontawesome-webfont.eot differ diff --git a/app/fonts/fonts/fontawesome-webfont.svg b/app/fonts/fonts/fontawesome-webfont.svg new file mode 100644 index 000000000..6fd19abcb --- /dev/null +++ b/app/fonts/fonts/fontawesome-webfont.svg @@ -0,0 +1,640 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/fonts/fonts/fontawesome-webfont.ttf b/app/fonts/fonts/fontawesome-webfont.ttf new file mode 100644 index 000000000..d7994e130 Binary files /dev/null and b/app/fonts/fonts/fontawesome-webfont.ttf differ diff --git a/app/fonts/fonts/fontawesome-webfont.woff b/app/fonts/fonts/fontawesome-webfont.woff new file mode 100644 index 000000000..6fd4ede0f Binary files /dev/null and b/app/fonts/fonts/fontawesome-webfont.woff differ diff --git a/app/fonts/fonts/fontawesome-webfont.woff2 b/app/fonts/fonts/fontawesome-webfont.woff2 new file mode 100644 index 000000000..5560193cc Binary files /dev/null and b/app/fonts/fonts/fontawesome-webfont.woff2 differ -- cgit From 190389a068b9005b52e9012bce48b93397007e26 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 28 Feb 2018 14:26:14 -0800 Subject: v4.1.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index eab6c7063..80be01759 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.1.0", + "version": "4.1.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 00cd5a340d81da7f3cd6098ca6b16b4400c71efa Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 28 Feb 2018 16:11:58 -0800 Subject: 4.1.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 80be01759..1c9c420f9 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.1.1", + "version": "4.1.2", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 452c5d0513a14419b71ffd92d253fef661b74300 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 2 Mar 2018 12:47:40 -0800 Subject: Version 4.1.3 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 1c9c420f9..2b3acf1b5 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.1.2", + "version": "4.1.3", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 92453f8715b78c0e6e2cdb9b2e1cfe48c0b013ad Mon Sep 17 00:00:00 2001 From: Csaba Solya Date: Sat, 3 Mar 2018 00:32:57 +0100 Subject: seed phrase verifier --- app/scripts/lib/seed-phrase-verifier.js | 43 +++++++++++++++++++++++++++++++++ app/scripts/metamask-controller.js | 20 +++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 app/scripts/lib/seed-phrase-verifier.js (limited to 'app') diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js new file mode 100644 index 000000000..9bea2910e --- /dev/null +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -0,0 +1,43 @@ +const KeyringController = require('eth-keyring-controller') + +const seedPhraseVerifier = { + + verifyAccounts(createdAccounts, seedWords) { + + return new Promise((resolve, reject) => { + + if (!createdAccounts || createdAccounts.length < 1) { + return reject(new Error('No created accounts defined.')) + } + + let keyringController = new KeyringController({}) + let Keyring = keyringController.getKeyringClassForType('HD Key Tree') + let opts = { + mnemonic: seedWords, + numberOfAccounts: createdAccounts.length, + } + + let keyring = new Keyring(opts) + keyring.getAccounts() + .then((restoredAccounts) => { + + log.debug('Created accounts: ' + JSON.stringify(createdAccounts)) + log.debug('Restored accounts: ' + JSON.stringify(restoredAccounts)) + + if (restoredAccounts.length != createdAccounts.length) { + // this should not happen... + return reject(new Error("Wrong number of accounts")) + } + + for (let i = 0; i < restoredAccounts.length; i++) { + if (restoredAccounts[i] !== createdAccounts[i]) { + return reject(new Error('Not identical accounts! Original: ' + createdAccounts[i] + ', Restored: ' + restoredAccounts[i])) + } + } + return resolve() + }) + }) + } +} + +module.exports = seedPhraseVerifier \ No newline at end of file diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index ad4e71792..89bcbd51b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -37,6 +37,7 @@ const version = require('../manifest.json').version const BN = require('ethereumjs-util').BN const GWEI_BN = new BN('1000000000') const percentile = require('percentile') +const seedPhraseVerifier = require('./lib/seed-phrase-verifier') module.exports = class MetamaskController extends EventEmitter { @@ -592,8 +593,23 @@ module.exports = class MetamaskController extends EventEmitter { primaryKeyring.serialize() .then((serialized) => { const seedWords = serialized.mnemonic - this.configManager.setSeedWords(seedWords) - cb(null, seedWords) + + primaryKeyring.getAccounts() + .then((accounts) => { + if (accounts.length < 1) { + return cb(new Error('MetamaskController - No accounts found')) + } + + seedPhraseVerifier.verifyAccounts(accounts, seedWords) + .then(() => { + this.configManager.setSeedWords(seedWords) + cb(null, seedWords) + }) + .catch((err) => { + log.error(err) + cb(err) + }) + }) }) } -- cgit From 4bd7f1a37abcd09dc8816fc5b28ad41bc86b1aea Mon Sep 17 00:00:00 2001 From: Csaba Solya Date: Sat, 3 Mar 2018 00:40:40 +0100 Subject: fix lint issues --- app/scripts/lib/seed-phrase-verifier.js | 18 +++++++++--------- app/scripts/metamask-controller.js | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index 9bea2910e..97a433fd8 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -2,7 +2,7 @@ const KeyringController = require('eth-keyring-controller') const seedPhraseVerifier = { - verifyAccounts(createdAccounts, seedWords) { + verifyAccounts (createdAccounts, seedWords) { return new Promise((resolve, reject) => { @@ -10,23 +10,23 @@ const seedPhraseVerifier = { return reject(new Error('No created accounts defined.')) } - let keyringController = new KeyringController({}) - let Keyring = keyringController.getKeyringClassForType('HD Key Tree') - let opts = { + const keyringController = new KeyringController({}) + const Keyring = keyringController.getKeyringClassForType('HD Key Tree') + const opts = { mnemonic: seedWords, numberOfAccounts: createdAccounts.length, } - let keyring = new Keyring(opts) + const keyring = new Keyring(opts) keyring.getAccounts() .then((restoredAccounts) => { log.debug('Created accounts: ' + JSON.stringify(createdAccounts)) log.debug('Restored accounts: ' + JSON.stringify(restoredAccounts)) - if (restoredAccounts.length != createdAccounts.length) { + if (restoredAccounts.length !== createdAccounts.length) { // this should not happen... - return reject(new Error("Wrong number of accounts")) + return reject(new Error('Wrong number of accounts')) } for (let i = 0; i < restoredAccounts.length; i++) { @@ -37,7 +37,7 @@ const seedPhraseVerifier = { return resolve() }) }) - } + }, } -module.exports = seedPhraseVerifier \ No newline at end of file +module.exports = seedPhraseVerifier diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 89bcbd51b..b9231aa3d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -599,9 +599,9 @@ module.exports = class MetamaskController extends EventEmitter { if (accounts.length < 1) { return cb(new Error('MetamaskController - No accounts found')) } - + seedPhraseVerifier.verifyAccounts(accounts, seedWords) - .then(() => { + .then(() => { this.configManager.setSeedWords(seedWords) cb(null, seedWords) }) -- cgit From 3e05b693dbf55ea7ecb791e8f31b7599a6b89ffd Mon Sep 17 00:00:00 2001 From: Csaba Solya Date: Sat, 3 Mar 2018 14:11:02 +0100 Subject: verify addresses regardless case --- app/scripts/lib/seed-phrase-verifier.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index 97a433fd8..1f35c2c67 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -30,7 +30,7 @@ const seedPhraseVerifier = { } for (let i = 0; i < restoredAccounts.length; i++) { - if (restoredAccounts[i] !== createdAccounts[i]) { + if (restoredAccounts[i].toLowerCase() !== createdAccounts[i].toLowerCase()) { return reject(new Error('Not identical accounts! Original: ' + createdAccounts[i] + ', Restored: ' + restoredAccounts[i])) } } -- cgit From 2b86d65d0c3266e8ddfe814abe1d1755fbf23fda Mon Sep 17 00:00:00 2001 From: Csaba Solya Date: Sat, 3 Mar 2018 22:08:10 +0100 Subject: verify seedwords on log in --- app/scripts/metamask-controller.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b9231aa3d..df9adc248 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -345,6 +345,7 @@ module.exports = class MetamaskController extends EventEmitter { // primary HD keyring management addNewAccount: nodeify(this.addNewAccount, this), placeSeedWords: this.placeSeedWords.bind(this), + verifySeedPhrase: this.verifySeedPhrase.bind(this), clearSeedWordCache: this.clearSeedWordCache.bind(this), resetAccount: this.resetAccount.bind(this), importAccountWithStrategy: this.importAccountWithStrategy.bind(this), @@ -588,6 +589,19 @@ module.exports = class MetamaskController extends EventEmitter { // Used when creating a first vault, to allow confirmation. // Also used when revealing the seed words in the confirmation view. placeSeedWords (cb) { + + this.verifySeedPhrase((err, seedWords) => { + + if (err) { + return cb(err) + } + this.configManager.setSeedWords(seedWords) + return cb(null, seedWords) + }) + } + + verifySeedPhrase (cb) { + const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found')) primaryKeyring.serialize() @@ -602,12 +616,11 @@ module.exports = class MetamaskController extends EventEmitter { seedPhraseVerifier.verifyAccounts(accounts, seedWords) .then(() => { - this.configManager.setSeedWords(seedWords) - cb(null, seedWords) + return cb(null, seedWords) }) .catch((err) => { log.error(err) - cb(err) + return cb(err) }) }) }) -- cgit From f7d4a1080df6d1c8ea5f68f88b01caea065b5e92 Mon Sep 17 00:00:00 2001 From: Csaba Solya Date: Sun, 4 Mar 2018 08:47:46 +0100 Subject: add documentation --- app/scripts/lib/seed-phrase-verifier.js | 5 +++++ app/scripts/metamask-controller.js | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'app') diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index 1f35c2c67..9cea22029 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -2,6 +2,11 @@ const KeyringController = require('eth-keyring-controller') const seedPhraseVerifier = { + // Verifies if the seed words can restore the accounts. + // + // The seed words can recreate the primary keyring and the accounts belonging to it. + // The created accounts in the primary keyring are always the same. + // The keyring always creates the accounts in the same sequence. verifyAccounts (createdAccounts, seedWords) { return new Promise((resolve, reject) => { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index df9adc248..f523e3919 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -600,6 +600,10 @@ module.exports = class MetamaskController extends EventEmitter { }) } + // Verifies the current vault's seed words if they can restore the + // accounts belonging to the current vault. + // + // Called when the first account is created and on unlocking the vault. verifySeedPhrase (cb) { const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] -- cgit From 59007a6c36055f9197ad83ccb1741fa186b85f53 Mon Sep 17 00:00:00 2001 From: Csaba Solya Date: Tue, 6 Mar 2018 15:56:27 +0100 Subject: modify verifySeedPhrase to async and call it from addNewAccount also --- app/scripts/metamask-controller.js | 66 ++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 32 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index f523e3919..0a5c1d36f 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -345,7 +345,7 @@ module.exports = class MetamaskController extends EventEmitter { // primary HD keyring management addNewAccount: nodeify(this.addNewAccount, this), placeSeedWords: this.placeSeedWords.bind(this), - verifySeedPhrase: this.verifySeedPhrase.bind(this), + verifySeedPhrase: nodeify(this.verifySeedPhrase, this), clearSeedWordCache: this.clearSeedWordCache.bind(this), resetAccount: this.resetAccount.bind(this), importAccountWithStrategy: this.importAccountWithStrategy.bind(this), @@ -567,14 +567,18 @@ module.exports = class MetamaskController extends EventEmitter { // Opinionated Keyring Management // - async addNewAccount (cb) { + async addNewAccount () { const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] - if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found')) + if (!primaryKeyring) { + throw new Error('MetamaskController - No HD Key Tree found') + } const keyringController = this.keyringController const oldAccounts = await keyringController.getAccounts() const keyState = await keyringController.addNewAccount(primaryKeyring) const newAccounts = await keyringController.getAccounts() + await this.verifySeedPhrase() + newAccounts.forEach((address) => { if (!oldAccounts.includes(address)) { this.preferencesController.setSelectedAddress(address) @@ -590,44 +594,42 @@ module.exports = class MetamaskController extends EventEmitter { // Also used when revealing the seed words in the confirmation view. placeSeedWords (cb) { - this.verifySeedPhrase((err, seedWords) => { - - if (err) { + this.verifySeedPhrase() + .then((seedWords) => { + this.configManager.setSeedWords(seedWords) + return cb(null, seedWords) + }) + .catch((err) => { return cb(err) - } - this.configManager.setSeedWords(seedWords) - return cb(null, seedWords) - }) + }) } // Verifies the current vault's seed words if they can restore the // accounts belonging to the current vault. // // Called when the first account is created and on unlocking the vault. - verifySeedPhrase (cb) { + async verifySeedPhrase () { const primaryKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] - if (!primaryKeyring) return cb(new Error('MetamaskController - No HD Key Tree found')) - primaryKeyring.serialize() - .then((serialized) => { - const seedWords = serialized.mnemonic - - primaryKeyring.getAccounts() - .then((accounts) => { - if (accounts.length < 1) { - return cb(new Error('MetamaskController - No accounts found')) - } - - seedPhraseVerifier.verifyAccounts(accounts, seedWords) - .then(() => { - return cb(null, seedWords) - }) - .catch((err) => { - log.error(err) - return cb(err) - }) - }) - }) + if (!primaryKeyring) { + throw new Error('MetamaskController - No HD Key Tree found') + } + + const serialized = await primaryKeyring.serialize() + const seedWords = serialized.mnemonic + + const accounts = await primaryKeyring.getAccounts() + if (accounts.length < 1) { + throw new Error('MetamaskController - No accounts found') + } + + try { + await seedPhraseVerifier.verifyAccounts(accounts, seedWords) + return seedWords + } catch (err) { + log.error(err.message) + throw err + } } // ClearSeedWordCache -- cgit From 7c2257e09c2583a4ac24a78e1b3c58a750cb798f Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 6 Mar 2018 21:25:30 -0330 Subject: Missing comma in messages.json --- app/_locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 2884392e8..f4a8fe943 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -373,7 +373,7 @@ "newAccountNumberName": { "message": "Account $1", "description": "Default name of next account to be created on create account screen" - } + }, "newContract": { "message": "New Contract" }, -- cgit From e91a521b1b0cc9262ca31290f3df5778dd1a6919 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 6 Mar 2018 17:30:12 -0800 Subject: Version 4.2.0 --- app/manifest.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 2b3acf1b5..0c89c2b3e 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "4.1.3", + "version": "4.2.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", @@ -59,7 +59,7 @@ "clipboardWrite", "http://localhost:8545/", "https://*.infura.io/" - ], + ], "web_accessible_resources": [ "scripts/inpage.js" ], @@ -68,4 +68,4 @@ "https://metamask.io/*" ] } -} +} \ No newline at end of file -- cgit From 57dc5a6e9b8ecc4414fe72397205d21cec13c5e1 Mon Sep 17 00:00:00 2001 From: Jeffrey Tong Date: Tue, 6 Mar 2018 20:37:26 -0800 Subject: fix typo in transaction.js --- app/scripts/controllers/transactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ef5578d5a..9c2ca0dc8 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -3,7 +3,7 @@ const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const Transaction = require('ethereumjs-tx') const EthQuery = require('ethjs-query') -const TransactionStateManger = require('../lib/tx-state-manager') +const TransactionStateManager = require('../lib/tx-state-manager') const TxGasUtil = require('../lib/tx-gas-utils') const PendingTransactionTracker = require('../lib/pending-tx-tracker') const createId = require('../lib/random-id') @@ -38,7 +38,7 @@ module.exports = class TransactionController extends EventEmitter { this.query = new EthQuery(this.provider) this.txGasUtil = new TxGasUtil(this.provider) - this.txStateManager = new TransactionStateManger({ + this.txStateManager = new TransactionStateManager({ initState: opts.initState, txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), -- cgit From cad5f5f0009713a1101194d964af7a1620ea158c Mon Sep 17 00:00:00 2001 From: Jeffrey Tong Date: Wed, 7 Mar 2018 10:24:36 -0800 Subject: fix typo in tests and tx-state-manager --- app/scripts/lib/tx-state-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 051efd247..2eb006380 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -4,7 +4,7 @@ const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const txStateHistoryHelper = require('./tx-state-history-helper') -module.exports = class TransactionStateManger extends EventEmitter { +module.exports = class TransactionStateManager extends EventEmitter { constructor ({ initState, txHistoryLimit, getNetwork }) { super() -- cgit From ab55c184c7e40e6e46bc4da5d8438a18999a266e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 7 Mar 2018 13:50:22 -0800 Subject: Increase storage debounce to 2s --- app/scripts/background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 464330708..cb6810173 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -126,7 +126,7 @@ function setupController (initState) { // setup state persistence pump( asStream(controller.store), - debounce(1000), + debounce(2000), storeTransform(versionifyData), storeTransform(syncDataWithExtension), (error) => { -- cgit From d58e47edec80180c7dd99effc229e116c63b4f57 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 7 Mar 2018 14:23:31 -0800 Subject: Some fixes for new storage strategy - Don't persist undefined data - Write to new storage strategy without waiting for completion. - Continue writing to localStorage as fallback. --- app/scripts/background.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index cb6810173..b5f7002dc 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -93,6 +93,9 @@ async function loadStateFromPersistence () { .catch((reason) => { log.error('Problem saving migrated data', versionedData) }) + if (versionedData) { + diskStore.putState(versionedData) + } // return just the data return versionedData.data @@ -129,6 +132,7 @@ function setupController (initState) { debounce(2000), storeTransform(versionifyData), storeTransform(syncDataWithExtension), + asStream(diskStore), (error) => { log.error('pump hit error', error) } @@ -139,14 +143,14 @@ function setupController (initState) { return versionedData } - async function syncDataWithExtension(state) { + function syncDataWithExtension(state) { if (localStore.isSupported) { - try { - await localStore.set(state) - } catch (err) { + localStore.set(state) + .catch((err) => { log.error('error setting state in local store:', err) - } + }) } else { log.error('local store not supported') } + return state } -- cgit From b97ac5106fd8479a81dc5c32ede99090427ee1b8 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 7 Mar 2018 14:38:26 -0800 Subject: Add clarifying comment --- app/scripts/background.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index b5f7002dc..55eeed83f 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -80,6 +80,7 @@ async function loadStateFromPersistence () { log.error('error fetching state from local store:', err) } + // If localStore is supported but has not been written to yet, ignore: if (Object.keys(localData).length > 0) { versionedData = localData } -- cgit From 64fcd271028ff57c34dd930b76ce23081eff814a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 7 Mar 2018 14:42:59 -0800 Subject: Tighten up data loading code --- app/scripts/background.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 55eeed83f..e8a7594ac 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -68,10 +68,10 @@ async function initialize () { async function loadStateFromPersistence () { // migrations const migrator = new Migrator({ migrations }) - // read from disk - versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) - // fetch from extension store and merge in data + // read from disk + // first from preferred, async API: + let localStoreData if (localStore.isSupported) { let localData try { @@ -82,10 +82,14 @@ async function loadStateFromPersistence () { // If localStore is supported but has not been written to yet, ignore: if (Object.keys(localData).length > 0) { - versionedData = localData + localStoreData = localData } } + versionedData = localStoreData || + diskStore.getState() || + migrator.generateInitialState(firstTimeState) + // migrate data versionedData = await migrator.migrateData(versionedData) -- cgit From 98efca0a9798db205ef8068c038a225a79c575cd Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 8 Mar 2018 14:10:28 -0800 Subject: background - storage - cleanup storage wiring --- app/scripts/background.js | 34 ++++++++-------------------------- app/scripts/lib/local-store.js | 30 ++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 34 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index e8a7594ac..ef5513ec7 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -71,36 +71,19 @@ async function loadStateFromPersistence () { // read from disk // first from preferred, async API: - let localStoreData - if (localStore.isSupported) { - let localData - try { - localData = await localStore.get() - } catch (err) { - log.error('error fetching state from local store:', err) - } - - // If localStore is supported but has not been written to yet, ignore: - if (Object.keys(localData).length > 0) { - localStoreData = localData - } - } - - versionedData = localStoreData || + versionedData = (await localStore.get()) || diskStore.getState() || migrator.generateInitialState(firstTimeState) // migrate data versionedData = await migrator.migrateData(versionedData) + if (!versionedData) { + throw new Error('MetaMask - migrator returned undefined') + } // write to disk - localStore.set(versionedData) - .catch((reason) => { - log.error('Problem saving migrated data', versionedData) - }) - if (versionedData) { - diskStore.putState(versionedData) - } + if (localStore.isSupported) localStore.set(versionedData) + diskStore.putState(versionedData) // return just the data return versionedData.data @@ -134,7 +117,7 @@ function setupController (initState) { // setup state persistence pump( asStream(controller.store), - debounce(2000), + debounce(1000), storeTransform(versionifyData), storeTransform(syncDataWithExtension), asStream(diskStore), @@ -154,8 +137,7 @@ function setupController (initState) { .catch((err) => { log.error('error setting state in local store:', err) }) - } else { log.error('local store not supported') } - + } return state } diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 9e8d8db37..73482a636 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -3,6 +3,7 @@ // https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/local const extension = require('extensionizer') +const { promisify } = require('util').promisify module.exports = class ExtensionStore { constructor() { @@ -10,15 +11,28 @@ module.exports = class ExtensionStore { if (!this.isSupported) { log.error('Storage local API not available.') } + const local = extension.storage.local + this._get = promisify(local.get).bind(local) + this._set = promisify(local.set).bind(local) } - get() { - return new Promise((resolve) => { - extension.storage.local.get(null, resolve) - }) + + async get() { + if (!this.isSupported) return undefined + const result = await this._get() + // extension.storage.local always returns an obj + // if the object is empty, treat it as undefined + if (isEmpty(result)) { + return undefined + } else { + return result + } } - set(state) { - return new Promise((resolve) => { - extension.storage.local.set(state, resolve) - }) + + async set(state) { + return this._set(state) } } + +function isEmpty(obj) { + return 0 === Object.keys(obj).length +} -- cgit From a88e436b7d45d9a7f9f4d4a4be58aff5e58e9074 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 8 Mar 2018 14:55:35 -0800 Subject: lint fix --- app/scripts/lib/local-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 73482a636..781aea17e 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -34,5 +34,5 @@ module.exports = class ExtensionStore { } function isEmpty(obj) { - return 0 === Object.keys(obj).length + return Object.keys(obj).length === 0 } -- cgit From f7138d81e38661ef9262c6a31b66d962238b5c9c Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 12 Mar 2018 11:41:26 -0700 Subject: Add sigRequest for Signature Request --- app/_locales/en/messages.json | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index f4a8fe943..1ca31427d 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -519,6 +519,9 @@ "signNotice": { "message": "Signing this message can have \ndangerous side effects. Only sign messages from \nsites you fully trust with your entire account.\n This dangerous method will be removed in a future version. " }, + "sigRequest": { + "message": "Signature Request" + }, "sigRequested": { "message": "Signature Requested" }, -- cgit From c15d3e0e237f6b264aab1a7e38fede641d964328 Mon Sep 17 00:00:00 2001 From: Vincent Le Gallic Date: Tue, 13 Mar 2018 22:04:13 +0100 Subject: Add French translation --- app/_locales/fr/messages.json | 609 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 609 insertions(+) create mode 100644 app/_locales/fr/messages.json (limited to 'app') diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json new file mode 100644 index 000000000..6674fb1db --- /dev/null +++ b/app/_locales/fr/messages.json @@ -0,0 +1,609 @@ +{ + "accept": { + "message": "Accepter" + }, + "account": { + "message": "Compte" + }, + "accountDetails": { + "message": "Détails du compte" + }, + "accountName": { + "message": "Nom du compte" + }, + "address": { + "message": "Adresse" + }, + "addToken": { + "message": "Ajouter un jeton" + }, + "amount": { + "message": "Montant" + }, + "amountPlusGas": { + "message": "Montant + Gaz" + }, + "appDescription": { + "message": "Ethereum navigateur extension", + "description": "La description de l'application" + }, + "appName": { + "message": "MetaMask", + "description": "Le nom de l'application" + }, + "attemptingConnect": { + "message": "Tentative de connexion à blockchain." + }, + "available": { + "message": "Disponible" + }, + "back": { + "message": "Retour" + }, + "balance": { + "message": "Balance:" + }, + "balanceIsInsufficientGas": { + "message": "Solde insuffisant pour le total actuel de gaz" + }, + "beta": { + "message": "BETA" + }, + "betweenMinAndMax": { + "message": "doit être supérieur ou égal à 1 $ et inférieur ou égal à 2 $", + "description": "helper pour la saisie hexadécimale en entrée décimale" + }, + "borrowDharma": { + "message": "Emprunter avec Dharma (Bêta)" + }, + "buy": { + "message": "Acheter" + }, + "buyCoinbase": { + "message": "Acheter sur Coinbase" + }, + "buyCoinbaseExplainer": { + "message": "Coinbase est le moyen le plus populaire au monde d'acheter et de vendre du bitcoin, de l'ethereum et du litecoin." + }, + "cancel": { + "message": "Annuler" + }, + "clickCopy": { + "message": "Cliquer pour copier" + }, + "confirm": { + "message": "Confirmer" + }, + "confirmContract": { + "message": "Confirmer le contrat" + }, + "confirmPassword": { + "message": "Confirmer le mot de passe" + }, + "confirmTransaction": { + "message": "Confirmer la transaction" + }, + "continueToCoinbase": { + "message": "Continuer vers Coinbase" + }, + "contractDeployment": { + "message": "Déploiement de contrat" + }, + "conversionProgress": { + "message": "Conversion en cours" + }, + "copiedButton": { + "message": "Copié" + }, + "copiedClipboard": { + "message": "Copié dans le Presse-papiers" + }, + "copiedExclamation": { + "message": "Copié!" + }, + "copy": { + "message": "Copier" + }, + "copyToClipboard": { + "message": "Copier dans le presse-papier" + }, + "copyButton": { + "message": " Copier " + }, + "copyPrivateKey": { + "message": "Ceci est votre clé privée (cliquez pour copier)" + }, + "create": { + "message": "Créer" + }, + "createAccount": { + "message": "Créer un compte" + }, + "createDen": { + "message": "Créer" + }, + "crypto": { + "message": "Crypto", + "description": "Type d'échange (cryptocurrencies)" + }, + "customGas": { + "message": "Personnaliser le Gaz" + }, + "customize": { + "message": "Personnaliser" + }, + "customRPC": { + "message": "RPC personnalisé" + }, + "defaultNetwork": { + "message": "Le réseau par défaut pour les transactions Ether est Main Net." + }, + "denExplainer": { + "message": "Votre DEN est votre stockage crypté par mot de passe dans MetaMask." + }, + "deposit": { + "message": "Dépôt" + }, + "depositBTC": { + "message": "Déposez votre BTC à l'adresse ci-dessous:" + }, + "depositCoin": { + "message": "Déposez votre $1 à l'adresse ci-dessous", + "description": "Indique à l'utilisateur quelle pièce ils ont choisi de déposer avec shapeshift" + }, + "depositEth": { + "message": "Dépôt Eth" + }, + "depositEther": { + "message": "Dépôt Ether" + }, + "depositFiat": { + "message": "Dépôt avec Fiat" + }, + "depositFromAccount": { + "message": "Dépôt d'un autre compte" + }, + "depositShapeShift": { + "message": "Déposez avec ShapeShift" + }, + "depositShapeShiftExplainer": { + "message": "Si vous possédez d'autres crypto-monnaies, vous pouvez échanger et déposer Ether directement dans votre portefeuille MetaMask. Aucun compte requis." + }, + "details": { + "message": "Détails du message" + }, + "directDeposit": { + "message": "Dépôt direct" + }, + "directDepositEther": { + "message": "Dépôt direct d'Ether" + }, + "directDepositEtherExplainer": { + "message": "Si vous avez déjà de l'Ether, le moyen le plus rapide d'obtenir des Ether dans votre nouveau portefeuille par dépôt direct." + }, + "done": { + "message": "Fait" + }, + "edit": { + "message": "Modifier" + }, + "editAccountName": { + "message": "Modifier le nom du compte" + }, + "encryptNewDen": { + "message": "Chiffrer votre nouveau DEN" + }, + "enterPassword": { + "message": "Entrer le mot de passe" + }, + "etherscanView": { + "message": "Afficher le compte sur Etherscan" + }, + "exchangeRate": { + "message": "Taux de change" + }, + "exportPrivateKey": { + "message": "Exporter la clé privée" + }, + "exportPrivateKeyWarning": { + "message": "Exporter les clés privées à vos risques et périls." + }, + "failed": { + "message": "Échec" + }, + "fiat": { + "message": "FIAT", + "description": "Type d'échange" + }, + "fileImportFail": { + "message": "L'importation de fichier ne fonctionne pas? Cliquez ici!", + "description": "Aide l'utilisateur à importer son compte à partir d'un fichier JSON" + }, + "from": { + "message": "message de" + }, + "fromShapeShift": { + "message": "ShapeShift de" + }, + "gas": { + "message": "Gas", + "description": "Indication courte du coût du gaz" + }, + "gasFee": { + "message": "Frais de gaz" + }, + "gasLimit": { + "message": "Limite de gaz" + }, + "gasLimitCalculation": { + "message": "Nous calculons la limite de gaz suggérée en fonction des taux de réussite du réseau." + }, + "gasLimitRequired": { + "message": "Limite de gaz requise" + }, + "gasLimitTooLow": { + "message": "La limite de gaz doit être d'au moins 21000" + }, + "gasPrice": { + "message": "Prix du gaz (GWEI)" + }, + "gasPriceCalculation": { + "message": "Nous calculons les prix du gaz proposés en fonction des taux de réussite du réseau." + }, + "gasPriceRequired": { + "message": "Prix du gaz requis" + }, + "getEther": { + "message": "Obtenir des Ether" + }, + "getEtherFromFaucet": { + "message": "Obtenir de l'Ether d'une faucet pour $1", + "description": "Affiche le nom du réseau pour la faucet d'Ether" + }, + "greaterThanMin": { + "message": "doit être supérieur ou égal à $1.", + "description": "helper pour la saisie hexadécimale en entrée décimale" + }, + "here": { + "message": "ici", + "description": "comme dans -cliquer ici- pour plus d'informations (en rapport avec troubleTokenBalances)" + }, + "hide": { + "message": "Cacher" + }, + "hideToken": { + "message": "Masquer le jeton" + }, + "hideTokenPrompt": { + "message": "Masquer le jeton?" + }, + "howToDeposit": { + "message": "Comment voulez-vous déposer de l'Ether?" + }, + "import": { + "message": "Importer", + "description": "Bouton pour importer un compte à partir d'un fichier sélectionné" + }, + "importAccount": { + "message": "Importer compte" + }, + "importAnAccount": { + "message": "Importer un compte" + }, + "importDen": { + "message": "Importer DEN existant" + }, + "imported": { + "message": "Importé", + "description": "statut indiquant qu'un compte a été entièrement chargé dans le trousseau de clés" + }, + "infoHelp": { + "message": "Info & Aide" + }, + "invalidAddress": { + "message": "Adresse invalide" + }, + "invalidGasParams": { + "message": "Paramètres de gaz invalides" + }, + "invalidInput": { + "message": "Entrée non valide." + }, + "invalidRequest": { + "message": "Requête invalide" + }, + "jsonFile": { + "message": "Fichier JSON", + "description": "format d'importation d'un compte" + }, + "kovan": { + "message": "Réseau de test Kovan" + }, + "lessThanMax": { + "message": "doit être inférieur ou égal à $1.", + "description": "helper pour la saisie hexadécimale en entrée décimale" + }, + "limit": { + "message": "Limite" + }, + "loading": { + "message": "Chargement..." + }, + "loadingTokens": { + "message": "Chargement des jetons..." + }, + "localhost": { + "message": "Localhost 8545" + }, + "logout": { + "message": "Déconnexion" + }, + "loose": { + "message": "Vacant" + }, + "mainnet": { + "message": "Réseau principal Ethereum" + }, + "message": { + "message": "Message" + }, + "min": { + "message": "Minimum" + }, + "myAccounts": { + "message": "Mes comptes" + }, + "needEtherInWallet": { + "message": "Pour interagir avec des applications décentralisées à l'aide de MetaMask, vous aurez besoin d'Ether dans votre portefeuille." + }, + "needImportFile": { + "message": "Vous devez sélectionner un fichier à importer.", + "description": "L'utilisateur doit ajouter un fichier pour continuer" + }, + "needImportPassword": { + "message": "Vous devez entrer un mot de passe pour le fichier sélectionné.", + "description": "Mot de passe et fichier requis pour importer un compte" + }, + "networks": { + "message": "Réseaux" + }, + "newAccount": { + "message": "Nouveau compte" + }, + "newAccountNumberName": { + "message": "Compte $1", + "description": "Nom par défaut du compte suivant à créer sur l'écran de création de compte" + }, + "newContract": { + "message": "Nouveau contrat" + }, + "newPassword": { + "message": "Nouveau mot de passe (min 8 caractères)" + }, + "newRecipient": { + "message": "Nouveau destinataire" + }, + "next": { + "message": "Suivant" + }, + "noAddressForName": { + "message": "Aucune adresse n'a été définie pour ce nom." + }, + "noDeposits": { + "message": "Aucun dépôt reçu" + }, + "noTransactionHistory": { + "message": "Aucun historique de transaction." + }, + "noTransactions": { + "message": "Aucune transaction" + }, + "notStarted": { + "message": "Pas démarré" + }, + "oldUI": { + "message": "Ancienne interface utilisateur" + }, + "oldUIMessage": { + "message": "Vous êtes revenu à l'ancienne interface utilisateur.Vous pouvez revenir à la nouvelle interface via l'option dans le menu déroulant en haut à droite." + }, + "or": { + "message": "ou", + "description": "choix entre la création ou l'importation d'un nouveau compte" + }, + "passwordMismatch": { + "message": "les mots de passe ne correspondent pas", + "description": "dans le processus de création de mot de passe, les deux nouveaux champs de mot de passe ne correspondent pas" + }, + "passwordShort": { + "message": "mot de passe pas assez long", + "description": "dans le processus de création de mot de passe, le mot de passe n'est pas assez long pour être sécurisé" + }, + "pastePrivateKey": { + "message": "Collez votre seed phrase privée ici:", + "description": "Pour l'importation d'un compte à partir d'une clé privée" + }, + "pasteSeed": { + "message": "Collez votre seed phrase ici!" + }, + "pleaseReviewTransaction": { + "message": "Veuillez vérifier votre transaction." + }, + "privateKey": { + "message": "Clé privée", + "description": "sélectionnez ce type de fichier à utiliser pour importer un compte" + }, + "privateKeyWarning": { + "message": "Avertissement: Ne divulguez jamais cette clé, quiconque avec vos clés privées peut voler tous les actifs de votre compte." + }, + "privateNetwork": { + "message": "Réseau privé" + }, + "qrCode": { + "message": "Afficher le QR Code" + }, + "readdToken": { + "message": "Vous pouvez ajouter ce jeton dans le futur en allant sur “Ajouter un jeton” dans le menu des options de votre compte." + }, + "readMore": { + "message": "En savoir plus ici." + }, + "receive": { + "message": "Recevoir" + }, + "recipientAddress": { + "message": "Adresse du destinataire" + }, + "refundAddress": { + "message": "Votre adresse de remboursement" + }, + "rejected": { + "message": "Rejeté" + }, + "required": { + "message": "Obligatoire" + }, + "retryWithMoreGas": { + "message": "Réessayez avec un prix plus élevé du gaz ici" + }, + "revert": { + "message": "Rétablir" + }, + "rinkeby": { + "message": "Réseau de test Rinkeby" + }, + "ropsten": { + "message": "Réseau de test Ropsten" + }, + "sampleAccountName": { + "message": "Par exemple mon nouveau compte", + "description": "Aidez l'utilisateur à comprendre le concept d'ajout d'un nom lisible par un humain à son compte" + }, + "save": { + "message": "Enregistrer" + }, + "saveAsFile": { + "message": "Enregistrer dans un fichier", + "description": "Processus d'exportation de compte" + }, + "selectService": { + "message": "Sélectionner un service" + }, + "send": { + "message": "Envoyé" + }, + "sendTokens": { + "message": "Envoyer des jetons" + }, + "sendTokensAnywhere": { + "message": "Envoyer des jetons à toute personne possédant un compte Ethereum" + }, + "settings": { + "message": "Paramètres" + }, + "shapeshiftBuy": { + "message": "Acheter avec Shapeshift" + }, + "showPrivateKeys": { + "message": "Afficher les clés privées" + }, + "showQRCode": { + "message": "Afficher le QR Code" + }, + "sign": { + "message": "Signer" + }, + "signMessage": { + "message": "Signer le message" + }, + "signNotice": { + "message": "La signature de ce message peut avoir des effets secondaires \ndangereux. Signer uniquement les messages de \nsites auxquels vous faites entièrement confiance avec votre compte.\n Cette méthode dangereuse sera supprimée dans une future version." + }, + "sigRequest": { + "message": "Demande de signature" + }, + "sigRequested": { + "message": "Signature demandée" + }, + "status": { + "message": "Statut" + }, + "submit": { + "message": "Soumettre" + }, + "takesTooLong": { + "message": "Prend trop de temps?" + }, + "testFaucet": { + "message": "Test Faucet" + }, + "to": { + "message": "Destinataire" + }, + "toETHviaShapeShift": { + "message": "$1 à ETH via ShapeShift", + "description": "le système remplira le type de dépôt au début du message" + }, + "tokenBalance": { + "message": "Votre solde de jeton est:" + }, + "total": { + "message": "Total" + }, + "transactionMemo": { + "message": "Mémo de transaction (optionnel)" + }, + "transactionNumber": { + "message": "Numéro de transaction" + }, + "transfers": { + "message": "Transferts" + }, + "troubleTokenBalances": { + "message": "Nous avons eu du mal à charger votre balance de jetons, vous pouvez la consulter ", + "description": "Suivi par un lien (ici) pour voir les soldes des jetons" + }, + "typePassword": { + "message": "Entrez votre mot de passe" + }, + "uiWelcome": { + "message": "Bienvenue dans la nouvelle interface utilisateur (Beta)" + }, + "uiWelcomeMessage": { + "message": "Vous utilisez maintenant la nouvelle interface utilisateur Metamask Jetez un coup d'oeil, essayez de nouvelles fonctionnalités comme l'envoi de jetons, et faites-nous savoir si vous avez des problèmes." + }, + "unavailable": { + "message": "Indisponible" + }, + "unknown": { + "message": "Inconnu" + }, + "unknownNetwork": { + "message": "Réseau privé inconnu" + }, + "unknownNetworkId": { + "message": "ID réseau inconnu" + }, + "usaOnly": { + "message": "Etats-Unis seulement", + "description": "Utiliser cet échange est limité aux personnes à l'intérieur des Etats-Unis" + }, + "usedByClients": { + "message": "Utilisé par une variété de clients différents" + }, + "viewAccount": { + "message": "Afficher le compte" + }, + "warning": { + "message": "Avertissement" + }, + "whatsThis": { + "message": "Qu'est-ce que c'est?" + }, + "yourSigRequested": { + "message": "Votre signature est demandée" + }, + "youSign": { + "message": "Vous signez" + } +} \ No newline at end of file -- cgit From d195cfab50b42d26f3cf9436845838e075e959de Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 13 Mar 2018 15:13:05 -0700 Subject: transactions - insure if a to field in tx params has a truthy valu that it is a valid addres and if it is falsy that it is not null to fix issue #3509 --- app/scripts/lib/tx-gas-utils.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 6f6ff7852..e61db3332 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -4,7 +4,7 @@ const { BnMultiplyByFraction, bnToHex, } = require('./util') -const addHexPrefix = require('ethereumjs-util').addHexPrefix +const {addHexPrefix, isValidAddress} = require('ethereumjs-util') const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. /* @@ -101,6 +101,12 @@ module.exports = class TxGasUtil { async validateTxParams (txParams) { this.validateRecipient(txParams) + if ('to' in txParams) { + if ( txParams.to === null ) delete txParams.to + else if ( txParams.to !== undefined && !isValidAddress(txParams.to) ) { + throw new Error(`Invalid transaction value of ${txParams.to} not a valid to address.`) + } + } if ('value' in txParams) { const value = txParams.value.toString() if (value.includes('-')) { -- cgit From c465d510b100fdf9926413751df04cbd59de68eb Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 13 Mar 2018 15:26:45 -0700 Subject: fix error message --- app/scripts/lib/tx-gas-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index e61db3332..3b0494e04 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -104,7 +104,7 @@ module.exports = class TxGasUtil { if ('to' in txParams) { if ( txParams.to === null ) delete txParams.to else if ( txParams.to !== undefined && !isValidAddress(txParams.to) ) { - throw new Error(`Invalid transaction value of ${txParams.to} not a valid to address.`) + throw new Error(`Invalid recipient address`) } } if ('value' in txParams) { -- cgit From e5a83d3f1a3ebe9115c07e162ee4bca0f157b8b1 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 13 Mar 2018 15:32:03 -0700 Subject: transactions move validation of the to field to validateRecipient --- app/scripts/lib/tx-gas-utils.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 3b0494e04..a8f473a88 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -101,12 +101,6 @@ module.exports = class TxGasUtil { async validateTxParams (txParams) { this.validateRecipient(txParams) - if ('to' in txParams) { - if ( txParams.to === null ) delete txParams.to - else if ( txParams.to !== undefined && !isValidAddress(txParams.to) ) { - throw new Error(`Invalid recipient address`) - } - } if ('value' in txParams) { const value = txParams.value.toString() if (value.includes('-')) { @@ -119,12 +113,14 @@ module.exports = class TxGasUtil { } } validateRecipient (txParams) { - if (txParams.to === '0x') { + if (txParams.to === '0x' || txParams.to === null ) { if (txParams.data) { delete txParams.to } else { throw new Error('Invalid recipient address') } + } else if ( txParams.to !== undefined && !isValidAddress(txParams.to) ) { + throw new Error('Invalid recipient address') } return txParams } -- cgit From 22cd7882038d05e51c5b76f2f4c76c15b2fd89f6 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 13 Mar 2018 15:39:33 -0700 Subject: tx-gas-utils - fix code style --- app/scripts/lib/tx-gas-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index a8f473a88..0fa9dd8d4 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -4,7 +4,7 @@ const { BnMultiplyByFraction, bnToHex, } = require('./util') -const {addHexPrefix, isValidAddress} = require('ethereumjs-util') +const { addHexPrefix, isValidAddress } = require('ethereumjs-util') const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. /* -- cgit From b60992412546b6151d9c992ae2d34bb9e1ebe496 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 14 Mar 2018 08:21:50 -0700 Subject: fix destructuring of variables --- app/scripts/lib/local-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 781aea17e..1cf00dd30 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -3,7 +3,7 @@ // https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/local const extension = require('extensionizer') -const { promisify } = require('util').promisify +const { promisify } = require('util') module.exports = class ExtensionStore { constructor() { -- cgit From 9963bf6429871e85719e06c096ad81bd5d9eda64 Mon Sep 17 00:00:00 2001 From: Vincent Le Gallic Date: Wed, 14 Mar 2018 18:08:14 +0100 Subject: Update messages.json thx to @Senshii --- app/_locales/fr/messages.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 6674fb1db..7edbd41ab 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -24,7 +24,7 @@ "message": "Montant + Gaz" }, "appDescription": { - "message": "Ethereum navigateur extension", + "message": "Extension Ethereum pour navigateur", "description": "La description de l'application" }, "appName": { @@ -50,7 +50,7 @@ "message": "BETA" }, "betweenMinAndMax": { - "message": "doit être supérieur ou égal à 1 $ et inférieur ou égal à 2 $", + "message": "doit être supérieur ou égal à $1 et inférieur ou égal à $2", "description": "helper pour la saisie hexadécimale en entrée décimale" }, "borrowDharma": { @@ -145,11 +145,11 @@ "message": "Dépôt" }, "depositBTC": { - "message": "Déposez votre BTC à l'adresse ci-dessous:" + "message": "Déposez vos BTC à l'adresse ci-dessous:" }, "depositCoin": { "message": "Déposez votre $1 à l'adresse ci-dessous", - "description": "Indique à l'utilisateur quelle pièce ils ont choisi de déposer avec shapeshift" + "description": "Indique à l'utilisateur quelle monnaie ils a choisi de déposer avec shapeshift" }, "depositEth": { "message": "Dépôt Eth" @@ -158,7 +158,7 @@ "message": "Dépôt Ether" }, "depositFiat": { - "message": "Dépôt avec Fiat" + "message": "Dépôt de monnaie-fiat" }, "depositFromAccount": { "message": "Dépôt d'un autre compte" @@ -167,10 +167,10 @@ "message": "Déposez avec ShapeShift" }, "depositShapeShiftExplainer": { - "message": "Si vous possédez d'autres crypto-monnaies, vous pouvez échanger et déposer Ether directement dans votre portefeuille MetaMask. Aucun compte requis." + "message": "Si vous possédez d'autres crypto-monnaies, vous pouvez échanger et déposer de l'Ether directement dans votre portefeuille MetaMask. Aucun compte n'est requis." }, "details": { - "message": "Détails du message" + "message": "Détails" }, "directDeposit": { "message": "Dépôt direct" @@ -179,7 +179,7 @@ "message": "Dépôt direct d'Ether" }, "directDepositEtherExplainer": { - "message": "Si vous avez déjà de l'Ether, le moyen le plus rapide d'obtenir des Ether dans votre nouveau portefeuille par dépôt direct." + "message": "Si vous avez déjà de l'Ether, le moyen le plus rapide d'obtenir des Ether dans votre nouveau portefeuille est par dépôt direct." }, "done": { "message": "Fait" @@ -220,7 +220,7 @@ "description": "Aide l'utilisateur à importer son compte à partir d'un fichier JSON" }, "from": { - "message": "message de" + "message": "de" }, "fromShapeShift": { "message": "ShapeShift de" @@ -420,7 +420,7 @@ "description": "dans le processus de création de mot de passe, le mot de passe n'est pas assez long pour être sécurisé" }, "pastePrivateKey": { - "message": "Collez votre seed phrase privée ici:", + "message": "Collez votre clé privée ici:", "description": "Pour l'importation d'un compte à partir d'une clé privée" }, "pasteSeed": { @@ -570,7 +570,7 @@ "message": "Bienvenue dans la nouvelle interface utilisateur (Beta)" }, "uiWelcomeMessage": { - "message": "Vous utilisez maintenant la nouvelle interface utilisateur Metamask Jetez un coup d'oeil, essayez de nouvelles fonctionnalités comme l'envoi de jetons, et faites-nous savoir si vous avez des problèmes." + "message": "Vous utilisez maintenant la nouvelle interface utilisateur Metamask. Jetez un coup d'oeil, essayez de nouvelles fonctionnalités comme l'envoi de jetons, et faites-nous savoir si vous avez des problèmes." }, "unavailable": { "message": "Indisponible" @@ -606,4 +606,4 @@ "youSign": { "message": "Vous signez" } -} \ No newline at end of file +} -- cgit From 481983aae873d1fb7cceef2cb42ec4fb0580368a Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 14 Mar 2018 10:31:25 -0700 Subject: local-store - fix promisification of methods --- app/scripts/lib/local-store.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 1cf00dd30..2d6155dbf 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -3,7 +3,6 @@ // https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/local const extension = require('extensionizer') -const { promisify } = require('util') module.exports = class ExtensionStore { constructor() { @@ -12,8 +11,8 @@ module.exports = class ExtensionStore { log.error('Storage local API not available.') } const local = extension.storage.local - this._get = promisify(local.get).bind(local) - this._set = promisify(local.set).bind(local) + this._get = function() { return new Promise((resolve) => local.get(resolve)) } + this._set = function(state) { return new Promise((resolve) => local.set(state, resolve)) } } async get() { -- cgit From c4e90c9359de3b4c54622bde3f396bc753c9cffb Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 14 Mar 2018 10:49:54 -0700 Subject: local-store - check for error from extension.runtime --- app/scripts/lib/local-store.js | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 2d6155dbf..175126d86 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -10,9 +10,6 @@ module.exports = class ExtensionStore { if (!this.isSupported) { log.error('Storage local API not available.') } - const local = extension.storage.local - this._get = function() { return new Promise((resolve) => local.get(resolve)) } - this._set = function(state) { return new Promise((resolve) => local.set(state, resolve)) } } async get() { @@ -30,6 +27,34 @@ module.exports = class ExtensionStore { async set(state) { return this._set(state) } + + function _get() { + const local = extension.storage.local + return new Promise((resolve, reject) => { + local.get(null, (result) => { + const err = extension.runtime.lastError + if (err) { + reject(err) + } else { + resolve(result) + } + }) + }) + } + + function _set(obj) { + const local = extension.storage.local + return new Promise((resolve, reject) => { + local.set(obj, () => { + const err = extension.runtime.lastError + if (err) { + reject(err) + } else { + resolve() + } + }) + }) + } } function isEmpty(obj) { -- cgit From 6aef2ed0b26861b3402e13d4e2a7e401ac3e99c8 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 14 Mar 2018 10:59:47 -0700 Subject: local-store - fix class syntax --- app/scripts/lib/local-store.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 175126d86..5b47985f6 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -28,7 +28,7 @@ module.exports = class ExtensionStore { return this._set(state) } - function _get() { + _get() { const local = extension.storage.local return new Promise((resolve, reject) => { local.get(null, (result) => { @@ -42,7 +42,7 @@ module.exports = class ExtensionStore { }) } - function _set(obj) { + _set(obj) { const local = extension.storage.local return new Promise((resolve, reject) => { local.set(obj, () => { -- cgit