aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/_locales/en/messages.json15
-rw-r--r--test/integration/lib/add-token.js17
-rw-r--r--ui/app/add-token.js182
-rw-r--r--ui/app/css/itcss/components/add-token.scss184
-rw-r--r--ui/app/css/itcss/settings/variables.scss1
-rw-r--r--yarn.lock44
6 files changed, 321 insertions, 122 deletions
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index c64b7248b..0bfa992b4 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -171,6 +171,9 @@
"customGas": {
"message": "Customize Gas"
},
+ "customToken": {
+ "message": "Custom Token"
+ },
"customize": {
"message": "Customize"
},
@@ -415,6 +418,9 @@
"message": "JSON File",
"description": "format for importing an account"
},
+ "keepTrackTokens": {
+ "message": "Keep track of the tokens you’ve bought with your MetaMask account."
+ },
"kovan": {
"message": "Kovan Test Network"
},
@@ -424,6 +430,9 @@
"max": {
"message": "Max"
},
+ "learnMore": {
+ "message": "Learn more."
+ },
"lessThanMax": {
"message": "must be less than or equal to $1.",
"description": "helper for inputting hex as decimal input"
@@ -564,6 +573,9 @@
"pleaseReviewTransaction": {
"message": "Please review your transaction."
},
+ "popularTokens": {
+ "message": "Popular Tokens"
+ },
"privacyMsg": {
"message": "Privacy Policy"
},
@@ -702,6 +714,9 @@
"onlySendToEtherAddress": {
"message": "Only send ETH to an Ethereum address."
},
+ "searchTokens": {
+ "message": "Search Tokens"
+ },
"sendTokensAnywhere": {
"message": "Send Tokens to anyone with an Ethereum account"
},
diff --git a/test/integration/lib/add-token.js b/test/integration/lib/add-token.js
index 228192e7b..cc04beb21 100644
--- a/test/integration/lib/add-token.js
+++ b/test/integration/lib/add-token.js
@@ -34,8 +34,8 @@ async function runAddTokenFlowTest (assert, done) {
let addTokenWrapper = await queryAsync($, '.add-token__wrapper')
assert.ok(addTokenWrapper[0], 'add token wrapper renders')
- let addTokenTitle = await queryAsync($, '.add-token__title')
- assert.equal(addTokenTitle[0].textContent, 'Add Token', 'add token title is correct')
+ let addTokenTitle = await queryAsync($, '.add-token__header__title')
+ assert.equal(addTokenTitle[0].textContent, 'Add Tokens', 'add token title is correct')
// Cancel Add Token
const cancelAddTokenButton = await queryAsync($, 'button.btn-secondary--lg.add-token__cancel-button')
@@ -51,9 +51,9 @@ async function runAddTokenFlowTest (assert, done) {
// Verify Add Token Screen
addTokenWrapper = await queryAsync($, '.add-token__wrapper')
- addTokenTitle = await queryAsync($, '.add-token__title')
+ addTokenTitle = await queryAsync($, '.add-token__header__title')
assert.ok(addTokenWrapper[0], 'add token wrapper renders')
- assert.equal(addTokenTitle[0].textContent, 'Add Token', 'add token title is correct')
+ assert.equal(addTokenTitle[0].textContent, 'Add Tokens', 'add token title is correct')
// Search for token
const searchInput = await queryAsync($, 'input.add-token__input')
@@ -91,9 +91,11 @@ async function runAddTokenFlowTest (assert, done) {
assert.ok(addTokenButton[0], 'add token button present')
addTokenButton[0].click()
- const addCustom = await queryAsync($, '.add-token__add-custom')
- assert.ok(addCustom[0], 'add custom token button present')
- addCustom[0].click()
+ const addTokenTabs = await queryAsync($, '.add-token__header__tabs__tab')
+ assert.equal(addTokenTabs.length, 2, 'expected number of tabs')
+ assert.equal(addTokenTabs[1].textContent, 'Custom Token', 'Custom Token tab present')
+ assert.ok(addTokenTabs[1], 'add custom token tab present')
+ addTokenTabs[1].click()
// Input token contract address
const customInput = await queryAsync($, 'input.add-token__add-custom-input')
@@ -108,6 +110,7 @@ async function runAddTokenFlowTest (assert, done) {
// Verify symbol length error since contract address won't return symbol
const errorMessage = await queryAsync($, '.add-token__add-custom-error-message')
assert.ok(errorMessage[0], 'error rendered')
+
$('button.btn-secondary--lg')[0].click()
// // Confirm Add token
diff --git a/ui/app/add-token.js b/ui/app/add-token.js
index edeea11d8..b4ea4a532 100644
--- a/ui/app/add-token.js
+++ b/ui/app/add-token.js
@@ -55,10 +55,10 @@ function AddTokenScreen () {
customSymbol: '',
customDecimals: '',
searchQuery: '',
- isCollapsed: true,
selectedTokens: {},
errors: {},
autoFilled: false,
+ displayedTab: 'SEARCH',
}
this.tokenAddressDidChange = this.tokenAddressDidChange.bind(this)
this.tokenSymbolDidChange = this.tokenSymbolDidChange.bind(this)
@@ -192,7 +192,7 @@ AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address)
AddTokenScreen.prototype.renderCustomForm = function () {
const { autoFilled, customAddress, customSymbol, customDecimals, errors } = this.state
- return !this.state.isCollapsed && (
+ return (
h('div.add-token__add-custom-form', [
h('div', {
className: classnames('add-token__add-custom-field', {
@@ -247,33 +247,36 @@ AddTokenScreen.prototype.renderTokenList = function () {
})
const results = [...addressSearchResult, ...fuseSearchResult]
- return Array(6).fill(undefined)
- .map((_, i) => {
- const { logo, symbol, name, address } = results[i] || {}
- const tokenAlreadyAdded = this.checkExistingAddresses(address)
- return Boolean(logo || symbol || name) && (
- h('div.add-token__token-wrapper', {
- className: classnames({
- 'add-token__token-wrapper--selected': selectedTokens[address],
- 'add-token__token-wrapper--disabled': tokenAlreadyAdded,
- }),
- onClick: () => !tokenAlreadyAdded && this.toggleToken(address, results[i]),
- }, [
- h('div.add-token__token-icon', {
- style: {
- backgroundImage: logo && `url(images/contract/${logo})`,
- },
- }),
- h('div.add-token__token-data', [
- h('div.add-token__token-symbol', symbol),
- h('div.add-token__token-name', name),
- ]),
- // tokenAlreadyAdded && (
- // h('div.add-token__token-message', 'Already added')
- // ),
- ])
- )
- })
+ return h('div', [
+ results.length > 0 && h('div.add-token__token-icons-title', t('popularTokens')),
+ h('div.add-token__token-icons-container', Array(6).fill(undefined)
+ .map((_, i) => {
+ const { logo, symbol, name, address } = results[i] || {}
+ const tokenAlreadyAdded = this.checkExistingAddresses(address)
+ return Boolean(logo || symbol || name) && (
+ h('div.add-token__token-wrapper', {
+ className: classnames({
+ 'add-token__token-wrapper--selected': selectedTokens[address],
+ 'add-token__token-wrapper--disabled': tokenAlreadyAdded,
+ }),
+ onClick: () => !tokenAlreadyAdded && this.toggleToken(address, results[i]),
+ }, [
+ h('div.add-token__token-icon', {
+ style: {
+ backgroundImage: logo && `url(images/contract/${logo})`,
+ },
+ }),
+ h('div.add-token__token-data', [
+ h('div.add-token__token-symbol', symbol),
+ h('div.add-token__token-name', name),
+ ]),
+ // tokenAlreadyAdded && (
+ // h('div.add-token__token-message', 'Already added')
+ // ),
+ ])
+ )
+ })),
+ ])
}
AddTokenScreen.prototype.renderConfirmation = function () {
@@ -300,7 +303,6 @@ AddTokenScreen.prototype.renderConfirmation = function () {
h('div.add-token', [
h('div.add-token__wrapper', [
h('div.add-token__title-container.add-token__confirmation-title', [
- h('div.add-token__title', t('addToken')),
h('div.add-token__description', t('likeToAddTokens')),
]),
h('div.add-token__content-container.add-token__confirmation-content', [
@@ -332,52 +334,86 @@ AddTokenScreen.prototype.renderConfirmation = function () {
)
}
-AddTokenScreen.prototype.render = function () {
- const { isCollapsed, errors, isShowingConfirmation } = this.state
- const { goHome } = this.props
+AddTokenScreen.prototype.displayTab = function (selectedTab) {
+ this.setState({ displayedTab: selectedTab })
+}
- return isShowingConfirmation
- ? this.renderConfirmation()
- : (
- h('div.add-token', [
- h('div.add-token__wrapper', [
- h('div.add-token__title-container', [
- h('div.add-token__title', t('addToken')),
- h('div.add-token__description', t('tokenWarning1')),
- h('div.add-token__description', t('tokenSelection')),
- ]),
- h('div.add-token__content-container', [
- h('div.add-token__input-container', [
- h('input.add-token__input', {
- type: 'text',
- placeholder: t('search'),
- onChange: e => this.setState({ searchQuery: e.target.value }),
- }),
- h('div.add-token__search-input-error-message', errors.tokenSelector),
- ]),
- h(
- 'div.add-token__token-icons-container',
- this.renderTokenList(),
- ),
+AddTokenScreen.prototype.renderTabs = function () {
+ const { displayedTab, errors } = this.state
+
+ return displayedTab === 'CUSTOM_TOKEN'
+ ? this.renderCustomForm()
+ : h('div', [
+ h('div.add-token__wrapper', [
+ h('div.add-token__content-container', [
+ h('div.add-token__info-box', [
+ h('div.add-token__info-box__close'),
+ h('div.add-token__info-box__title', t('whatsThis')),
+ h('div.add-token__info-box__copy', t('keepTrackTokens')),
+ h('div.add-token__info-box__copy--blue', t('learnMore')),
]),
- h('div.add-token__footers', [
- h('div.add-token__add-custom', {
- onClick: () => this.setState({ isCollapsed: !isCollapsed }),
- }, [
- t('addCustomToken'),
- h(`i.fa.fa-angle-${isCollapsed ? 'down' : 'up'}`),
- ]),
- this.renderCustomForm(),
+ h('div.add-token__input-container', [
+ h('input.add-token__input', {
+ type: 'text',
+ placeholder: t('searchTokens'),
+ onChange: e => this.setState({ searchQuery: e.target.value }),
+ }),
+ h('div.add-token__search-input-error-message', errors.tokenSelector),
]),
+ this.renderTokenList(),
]),
- h('div.add-token__buttons', [
- h('button.btn-secondary--lg.add-token__cancel-button', {
- onClick: goHome,
- }, t('cancel')),
- h('button.btn-primary--lg', {
- onClick: this.onNext,
- }, t('next')),
+ ]),
+ ])
+}
+
+AddTokenScreen.prototype.render = function () {
+ const {
+ isShowingConfirmation,
+ displayedTab,
+ } = this.state
+ const { goHome } = this.props
+
+ return h('div.add-token', [
+ h('div.add-token__header', [
+ h('div.add-token__header__cancel', {
+ onClick: () => goHome(),
+ }, [
+ h('i.fa.fa-angle-left.fa-lg'),
+ h('span', t('cancel')),
]),
- ])
- )
+ h('div.add-token__header__title', t('addTokens')),
+ !isShowingConfirmation && h('div.add-token__header__tabs', [
+
+ h('div.add-token__header__tabs__tab', {
+ className: classnames('add-token__header__tabs__tab', {
+ 'add-token__header__tabs__selected': displayedTab === 'SEARCH',
+ 'add-token__header__tabs__unselected cursor-pointer': displayedTab !== 'SEARCH',
+ }),
+ onClick: () => this.displayTab('SEARCH'),
+ }, t('search')),
+
+ h('div.add-token__header__tabs__tab', {
+ className: classnames('add-token__header__tabs__tab', {
+ 'add-token__header__tabs__selected': displayedTab === 'CUSTOM_TOKEN',
+ 'add-token__header__tabs__unselected cursor-pointer': displayedTab !== 'CUSTOM_TOKEN',
+ }),
+ onClick: () => this.displayTab('CUSTOM_TOKEN'),
+ }, t('customToken')),
+
+ ]),
+ ]),
+//
+ isShowingConfirmation
+ ? this.renderConfirmation()
+ : this.renderTabs(),
+
+ !isShowingConfirmation && h('div.add-token__buttons', [
+ h('button.btn-secondary--lg.add-token__cancel-button', {
+ onClick: goHome,
+ }, t('cancel')),
+ h('button.btn-primary--lg.add-token__confirm-button', {
+ onClick: this.onNext,
+ }, t('next')),
+ ]),
+ ])
}
diff --git a/ui/app/css/itcss/components/add-token.scss b/ui/app/css/itcss/components/add-token.scss
index bdf9da385..f5c1de67c 100644
--- a/ui/app/css/itcss/components/add-token.scss
+++ b/ui/app/css/itcss/components/add-token.scss
@@ -1,37 +1,118 @@
.add-token {
width: 498px;
+ max-height: 805px;
display: flex;
flex-flow: column nowrap;
- align-items: center;
position: relative;
z-index: 12;
- font-family: 'DIN Next Light';
+ font-family: 'Roboto';
+ background: white;
+ border-radius: 8px;
&__wrapper {
background-color: $white;
- box-shadow: 0 2px 4px 0 rgba($black, .08);
display: flex;
flex-flow: column nowrap;
align-items: center;
flex: 0 0 auto;
}
- &__title-container {
+ &__header {
display: flex;
flex-flow: column nowrap;
- align-items: center;
- padding: 30px 60px 12px;
- border-bottom: 1px solid $gallery;
+ padding: 16px 16px 0px;
+ border-bottom: 1px solid $geyser;
flex: 0 0 auto;
+
+ &__cancel {
+ color: $dodger-blue;
+ display: flex;
+ align-items: center;
+
+ span {
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 21px;
+ margin-left: 8px;
+ }
+ }
+
+ &__title {
+ color: $tundora;
+ font-size: 32px;
+ font-weight: 500;
+ margin-top: 4px;
+ }
+
+ &__tabs {
+ margin-left: 22px;
+ display: flex;
+
+ &__tab {
+ height: 54px;
+ padding: 15px 10px;
+ color: $dusty-gray;
+ font-family: Roboto;
+ font-size: 18px;
+ line-height: 24px;
+ text-align: center;
+ }
+
+ &__tab:first-of-type {
+ margin-right: 20px;
+ }
+
+ &__unselected:hover {
+ color: $black;
+ border-bottom: none;
+ }
+
+ &__selected {
+ color: $curious-blue;
+ border-bottom: 3px solid $curious-blue;
+ }
+ }
}
- &__title {
- color: $scorpion;
- font-size: 20px;
- line-height: 26px;
- text-align: center;
- font-weight: 600;
- margin-bottom: 12px;
+ &__info-box {
+ height: 96px;
+ margin: 20px 24px 0px;
+ border-radius: 4px;
+ background-color: $alabaster;
+ position: relative;
+ padding-left: 18px;
+ display: flex;
+ flex-flow: column;
+
+ &__close::after {
+ content: '\00D7';
+ font-size: 29px;
+ font-weight: 200;
+ color: $dusty-gray;
+ position: absolute;
+ right: 17px;
+ cursor: pointer;
+ }
+
+ &__title {
+ color: $mid-gray;
+ font-family: Roboto;
+ font-size: 14px;
+ margin-top: 15px;
+ margin-bottom: 9px;
+ }
+
+ &__copy,
+ &__copy--blue {
+ color: $mid-gray;
+ font-family: Roboto;
+ font-size: 12px;
+ line-height: 18px;
+ }
+
+ &__copy--blue {
+ color: $curious-blue;
+ }
}
&__description {
@@ -48,19 +129,17 @@
&__content-container {
width: 100%;
- border-bottom: 1px solid $gallery;
}
&__input-container {
- padding: 11px 0;
- width: 263px;
- margin: 0 auto;
+ display: flex;
position: relative;
}
&__search-input-error-message {
position: absolute;
bottom: -10px;
+ left: 22px;
font-size: 12px;
width: 100%;
text-overflow: ellipsis;
@@ -69,16 +148,24 @@
color: $red;
}
- &__input {
- width: 100%;
- border: 2px solid $gallery;
+ &__input,
+ &__add-custom-input {
+ height: 54px;
+ padding: 21px 6px;
+ border: 1px solid $geyser;
border-radius: 4px;
- padding: 5px 15px;
- font-size: 14px;
- line-height: 19px;
+ margin: 22px 24px;
+ position: relative;
+ flex: 1 0 auto;
+ color: $scorpion;
+ font-family: Roboto;
+ font-size: 16px;
&::placeholder {
- color: $silver;
+ color: $scorpion;
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 21px;
}
}
@@ -115,13 +202,14 @@
&__add-custom-form {
display: flex;
flex-flow: column nowrap;
- margin: 8px 0 51px;
+ margin: 40px 0 30px;
}
&__add-custom-field {
- width: 290px;
- margin: 0 auto;
position: relative;
+ display: flex;
+ flex-flow: column;
+ flex: 1 0 auto;
&--error {
.add-token__add-custom-input {
@@ -132,7 +220,8 @@
&__add-custom-error-message {
position: absolute;
- bottom: -21px;
+ bottom: 1px;
+ left: 22px;
font-size: 12px;
width: 100%;
text-overflow: ellipsis;
@@ -144,38 +233,52 @@
&__add-custom-label {
font-size: 16px;
line-height: 21px;
- margin-bottom: 8px;
+ margin-left: 22px;
+ color: $scorpion;
}
&__add-custom-input {
- width: 100%;
- border: 1px solid $silver;
- padding: 5px 15px;
- font-size: 14px;
- line-height: 19px;
+ margin-top: 6px;
+ font-size: 16px;
&::placeholder {
color: $silver;
+ font-size: 16px;
}
}
&__add-custom-field + &__add-custom-field {
- margin-top: 21px;
+ margin-top: 6px;
}
&__buttons {
display: flex;
flex-flow: row nowrap;
- margin: 30px 0 51px;
flex: 0 0 auto;
align-items: center;
justify-content: center;
+ padding-bottom: 30px;
+ padding-top: 20px;
}
+ &__confirm-button,
&__cancel-button {
+ margin: 0 12px;
+ padding: 10px 13px;
+ height: 54px;
+ width: 133px;
margin-right: 1.2rem;
}
+ &__token-icons-title {
+ color: #5B5D67;
+ font-family: Roboto;
+ font-size: 18px;
+ line-height: 24px;
+ margin-left: 24px;
+ margin-top: 8px;
+ }
+
&__token-icons-container {
display: flex;
flex-flow: row wrap;
@@ -188,7 +291,7 @@
flex: 0 0 42.5%;
align-items: center;
padding: 12px;
- margin: 2.5%;
+ margin: 0% 2.5% 1.5%;
box-sizing: border-box;
border-radius: 10px;
cursor: pointer;
@@ -302,13 +405,14 @@
top: 0;
width: 100%;
overflow: hidden;
- height: 100%;
+ flex: 1 0 auto;
&__wrapper {
box-shadow: none !important;
flex: 1 1 auto;
width: 100%;
- overflow-y: auto;
+ overflow-y: scroll;
+ height: 400px;
}
&__footers {
diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss
index 0031238a8..51548306f 100644
--- a/ui/app/css/itcss/settings/variables.scss
+++ b/ui/app/css/itcss/settings/variables.scss
@@ -51,6 +51,7 @@ $java: #29b6af;
$wild-strawberry: #ff4a8d;
$cornflower-blue: #7057ff;
$saffron: #f6c343;
+$dodger-blue: #3099f2;
$zumthor: #edf7ff;
$ecstasy: #f7861c;
diff --git a/yarn.lock b/yarn.lock
index 7512e10db..8ccdc7efd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -72,6 +72,15 @@
normalize-path "^2.0.1"
through2 "^2.0.3"
+"@sentry/cli@^1.30.3":
+ version "1.30.3"
+ resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.30.3.tgz#02d0f7781c1ee5e1be5a4312a325fbe8b1b37231"
+ dependencies:
+ https-proxy-agent "^2.1.1"
+ node-fetch "^1.7.3"
+ progress "2.0.0"
+ proxy-from-env "^1.0.0"
+
"@types/node@*":
version "8.5.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.5.2.tgz#83b8103fa9a2c2e83d78f701a9aa7c9539739aa5"
@@ -201,6 +210,12 @@ agent-base@2:
extend "~3.0.0"
semver "~5.0.1"
+agent-base@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce"
+ dependencies:
+ es6-promisify "^5.0.0"
+
ajv-keywords@^1.1.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
@@ -3711,6 +3726,16 @@ es6-map@^0.1.3:
es6-symbol "~3.1.1"
event-emitter "~0.3.5"
+es6-promise@^4.0.3:
+ version "4.2.4"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
+
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+ dependencies:
+ es6-promise "^4.0.3"
+
es6-set@~0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
@@ -5919,6 +5944,13 @@ https-proxy-agent@1:
debug "2"
extend "3"
+https-proxy-agent@^2.1.1:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.0.tgz#7fbba856be8cd677986f42ebd3664f6317257887"
+ dependencies:
+ agent-base "^4.1.0"
+ debug "^3.1.0"
+
human-standard-token-abi@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/human-standard-token-abi/-/human-standard-token-abi-1.0.2.tgz#207d7846796ee5bb85fdd336e769cb38045b2ae0"
@@ -7984,7 +8016,7 @@ nock@^9.0.14:
qs "^6.5.1"
semver "^5.3.0"
-node-fetch@^1.0.1, node-fetch@~1.7.1:
+node-fetch@^1.0.1, node-fetch@^1.7.3, node-fetch@~1.7.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
dependencies:
@@ -8991,7 +9023,7 @@ process@~0.5.1:
version "0.5.2"
resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
-progress@^2.0.0:
+progress@2.0.0, progress@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
@@ -9067,6 +9099,10 @@ proxy-agent@~2.0.0:
pac-proxy-agent "1"
socks-proxy-agent "2"
+proxy-from-env@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
+
prr@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
@@ -9245,6 +9281,10 @@ raphael@^2.2.0:
dependencies:
eve-raphael "0.5.0"
+raven-js@^3.24.0:
+ version "3.24.0"
+ resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.24.0.tgz#59464d8bc4b3812ae87a282e9bb98ecad5b4b047"
+
raw-body@2, raw-body@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"