diff --git a/app/assets/images/nft.png b/app/assets/images/nft.png new file mode 100644 index 00000000..db3321a5 Binary files /dev/null and b/app/assets/images/nft.png differ diff --git a/app/components/all.scss b/app/components/all.scss index 01b662b8..5bbe2e85 100644 --- a/app/components/all.scss +++ b/app/components/all.scss @@ -50,6 +50,7 @@ @import "./elements/common/DialogManager/index"; @import "./elements/common/TooltipManager/index"; @import "./elements/market/CMCWidget"; +@import "./elements/nft/NFTSmallIcon"; @import "./elements/donate/Donate"; @import "./elements/postEditor/MarkdownEditor/MarkdownEditor"; @import "./elements/postEditor/MarkdownEditorToolbar/index"; diff --git a/app/components/elements/nft/NFTSmallIcon.jsx b/app/components/elements/nft/NFTSmallIcon.jsx new file mode 100644 index 00000000..c3dba897 --- /dev/null +++ b/app/components/elements/nft/NFTSmallIcon.jsx @@ -0,0 +1,12 @@ +import React, { Component, } from 'react' + +class NFTSmallIcon extends Component { + render() { + const { image, ...rest } = this.props + + return + } +} + +export default NFTSmallIcon diff --git a/app/components/elements/nft/NFTSmallIcon.scss b/app/components/elements/nft/NFTSmallIcon.scss new file mode 100644 index 00000000..0ee59410 --- /dev/null +++ b/app/components/elements/nft/NFTSmallIcon.scss @@ -0,0 +1,11 @@ +.NFTSmallIcon { + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + border-radius: 50%; + + width: 3rem; + height: 3rem; + display: inline-block; + vertical-align: top; +} diff --git a/app/components/modules/Donate.jsx b/app/components/modules/Donate.jsx index 7187464a..403211bf 100644 --- a/app/components/modules/Donate.jsx +++ b/app/components/modules/Donate.jsx @@ -110,6 +110,13 @@ class Donate extends React.Component { }) } + showGiftNft = (e) => { + e.preventDefault() + const { opts, } = this.props + const { to, permlink, } = opts + this.props.showGiftNft(to, permlink) + } + render() { const { currentUser, currentAccount, opts, uias, sliderMax } = this.props const { sym } = opts @@ -189,6 +196,9 @@ class Donate extends React.Component { + } { dispatch(user.actions.setDonateDefaults(donateDefaults)) }, + showGiftNft: (author, permlink) => { + dispatch(user.actions.setGiftNftDefaults({ author, permlink })) + dispatch(user.actions.showGiftNft()) + }, dispatchSubmit: async ({ to, amount, memo, isMemoEncrypted, permlink, is_comment, vote, myVote, voteAllowType, currentUser, errorCallback diff --git a/app/components/modules/GiftNFT.jsx b/app/components/modules/GiftNFT.jsx new file mode 100644 index 00000000..3a6d4041 --- /dev/null +++ b/app/components/modules/GiftNFT.jsx @@ -0,0 +1,111 @@ +import React from 'react' +import { connect } from 'react-redux' +import { Map } from 'immutable' +import tt from 'counterpart' +import { Asset } from 'golos-lib-js/lib/utils' + +import NFTSmallIcon from 'app/components/elements/nft/NFTSmallIcon' +import LoadingIndicator from 'app/components/elements/LoadingIndicator' +import g from 'app/redux/GlobalReducer' +import transaction from 'app/redux/Transaction' +import { getAssetMeta } from 'app/utils/market/utils' + +class GiftNFT extends React.Component { + constructor(props) { + super(props) + this.state = { + } + } + + componentDidMount() { + if (!this.props.nft_tokens) { + this.props.fetchNFTTokens(this.props.currentUser) + } + } + + render() { + const { nft_tokens, nft_assets } = this.props + + const tokens = nft_tokens ? nft_tokens.toJS() : [] + const assets = nft_assets ? nft_assets.toJS() : null + + let items = [] + let count = 0 + for (const token of tokens) { + const { json_metadata, image } = token + + let data + if (json_metadata) { + data = JSON.parse(json_metadata) + } + data = data || {} // node allows to use '', null, object, or array + + let last_price + const last_buy_price = Asset(token.last_buy_price) + if (last_buy_price.amount > 0) { + const asset = assets[last_buy_price.symbol] + let imageUrl + if (asset) { + imageUrl = getAssetMeta(asset).image_url + } + last_price = + {imageUrl && {''}} + {last_buy_price.amountFloat} + + } + + items.push( + + + + + {data.title} + + + {last_price} + + ) + + ++count + } + + if (!items.length) { + items = + } else { + items = + {items} +
+ } + + return
+
+

{tt('transfer_jsx.gift_nft')}

+
+ {items} +
+ } +} + +export default connect( + (state, ownProps) => { + const opts = state.user.get('donate_defaults', Map()).toJS() + + const currentUser = state.user.getIn(['current']) + const currentAccount = currentUser && state.global.getIn(['accounts', currentUser.get('username')]) + + + return { ...ownProps, + currentUser, + currentAccount, + nft_tokens: state.global.get('nft_tokens'), + nft_assets: state.global.get('nft_assets'), + } + }, + dispatch => ({ + fetchNFTTokens: (currentUser) => { + if (!currentUser) return + const account = currentUser.get('username') + dispatch(g.actions.fetchNftTokens({ account })) + }, + }) +)(GiftNFT) diff --git a/app/components/modules/Modals.jsx b/app/components/modules/Modals.jsx index de745b5b..980bea7f 100644 --- a/app/components/modules/Modals.jsx +++ b/app/components/modules/Modals.jsx @@ -7,6 +7,7 @@ import Reveal from 'react-foundation-components/lib/global/reveal'; import LoginForm from 'app/components/modules/LoginForm'; import ConfirmTransactionForm from 'app/components/modules/ConfirmTransactionForm'; import Donate from 'app/components/modules/Donate' +import GiftNFT from 'app/components/modules/GiftNFT' import SignUp from 'app/components/modules/SignUp' import ChangeAccount from 'app/components/modules/ChangeAccount' import AddAccount from 'app/components/modules/AddAccount' @@ -22,6 +23,7 @@ class Modals extends React.Component { show_login_modal: PropTypes.bool, show_confirm_modal: PropTypes.bool, show_donate_modal: PropTypes.bool, + show_gift_nft_modal: PropTypes.bool, show_signup_modal: PropTypes.bool, show_promote_post_modal: PropTypes.bool, show_change_account_modal: PropTypes.bool, @@ -53,12 +55,14 @@ class Modals extends React.Component { show_login_modal, show_confirm_modal, show_donate_modal, + show_gift_nft_modal, show_signup_modal, show_change_account_modal, show_add_account_modal, show_app_download_modal, hideLogin, hideDonate, + hideGiftNFT, hideConfirm, hideSignUp, hideChangeAccount, @@ -89,6 +93,10 @@ class Modals extends React.Component { } + {show_gift_nft_modal && + + + } {show_signup_modal && @@ -119,6 +127,7 @@ export default connect( loginUnclosable, show_confirm_modal: state.transaction.get('show_confirm_modal'), show_donate_modal: state.user.get('show_donate_modal'), + show_gift_nft_modal: state.user.get('show_gift_nft_modal'), show_promote_post_modal: state.user.get('show_promote_post_modal'), show_signup_modal: state.user.get('show_signup_modal'), show_change_account_modal: state.user.get('show_change_account_modal'), @@ -140,6 +149,10 @@ export default connect( if (e) e.preventDefault() dispatch(user.actions.hideDonate()) }, + hideGiftNFT: e => { + if (e) e.preventDefault() + dispatch(user.actions.hideGiftNft()) + }, hidePromotePost: e => { if (e) e.preventDefault(); dispatch(user.actions.hidePromotePost()) diff --git a/app/locales/en.json b/app/locales/en.json index 4c73e912..9f61932b 100644 --- a/app/locales/en.json +++ b/app/locales/en.json @@ -909,7 +909,8 @@ "balance": "Balance", "private_key_in_memo": "Do not write your private keys in this field!", "verified_exchange_no_memo": "You must include a memo for your exchange transfer, according to exchanger's rules.", - "verified_exchange_liquid_only": "You may exchange tokens from GOLOS balance only." + "verified_exchange_liquid_only": "You may exchange tokens from GOLOS balance only.", + "gift_nft": "Gift NFT" }, "user_saga_js": { "image_upload": { diff --git a/app/locales/ru-RU.json b/app/locales/ru-RU.json index 52c6bd4f..c363e587 100644 --- a/app/locales/ru-RU.json +++ b/app/locales/ru-RU.json @@ -844,7 +844,8 @@ "can_issue": "Можно выпустить", "private_key_in_memo": "Не пишите в этом поле приватные ключи!", "verified_exchange_no_memo": "Для перевода токенов на этот аккаунт нужно указать заметку/memo.", - "verified_exchange_liquid_only": "Перевод токенов на этот аккаунт с TIP-баланса невозможен, используйте основной баланс." + "verified_exchange_liquid_only": "Перевод токенов на этот аккаунт с TIP-баланса невозможен, используйте основной баланс.", + "gift_nft": "Подарить NFT" }, "user_profile": { "unknown_account": "Неизвестный аккаунт", diff --git a/app/redux/FetchDataSaga.js b/app/redux/FetchDataSaga.js index 60071144..65fb6265 100644 --- a/app/redux/FetchDataSaga.js +++ b/app/redux/FetchDataSaga.js @@ -1,6 +1,7 @@ import { call, put, select, fork, cancelled, takeLatest, takeEvery } from 'redux-saga/effects'; import cookie from "react-cookie"; import {config, api} from 'golos-lib-js'; +import { Asset } from 'golos-lib-js/lib/utils' import { getPinnedPosts, getMutedInNew } from 'app/utils/NormalizeProfile'; import {loadFollows, fetchFollowCount} from 'app/redux/FollowSaga'; @@ -13,6 +14,7 @@ import session from 'app/utils/session' import { getFilterApps, } from 'app/utils/ContentAccess'; import { reveseTag, getFilterTags } from 'app/utils/tags'; import { PUBLIC_API, CATEGORIES, SELECT_TAGS_KEY, DEBT_TOKEN_SHORT, LIQUID_TICKER } from 'app/client_config'; +import { parseNFTImage, NFTImageStub } from 'app/utils/NFTUtils' import { getSubs, notifyGetViews, } from 'app/utils/NotifyApiClient' import { SearchRequest, searchData, stateSetVersion } from 'app/utils/SearchClient' import { hashPermlink, } from 'app/utils/StateFunctions' @@ -27,6 +29,7 @@ export function* fetchDataWatches () { yield fork(watchFetchExchangeRates); yield fork(watchFetchVestingDelegations); yield fork(watchFetchUiaBalances); + yield fork(watchFetchNftTokens) } export function* watchGetContent() { @@ -842,3 +845,43 @@ export function* fetchUiaBalances({ payload: { account } }) { console.error('fetchUiaBalances', err) } } + +export function* watchFetchNftTokens() { + yield takeLatest('global/FETCH_NFT_TOKENS', fetchNftTokens) +} + +export function* fetchNftTokens({ payload: { account } }) { + try { + const nft_tokens = yield call([api, api.getNftTokensAsync], { + owner: account + }) + + const syms = new Set() + + let nft_assets + + try { + for (const no of nft_tokens) { + no.image = parseNFTImage(no.json_metadata) || NFTImageStub() + + const price = Asset(no.last_buy_price) + syms.add(price.symbol) + } + + nft_assets = {} + if (syms.size) { + const assets = yield call([api, api.getAssets], '', [...syms]) + for (const a of assets) { + const supply = Asset(a.supply) + nft_assets[supply.symbol] = a + } + } + } catch (err) { + console.error(err) + } + + yield put(GlobalReducer.actions.receiveNftTokens({nft_tokens, nft_assets})) + } catch (err) { + console.error('fetchNftTokens', err) + } +} diff --git a/app/redux/GlobalReducer.js b/app/redux/GlobalReducer.js index 33ff33c4..1d096331 100644 --- a/app/redux/GlobalReducer.js +++ b/app/redux/GlobalReducer.js @@ -191,6 +191,19 @@ export default createModule({ return state.set('assets', fromJS(assets)) }, }, + { + action: 'FETCH_NFT_TOKENS', + reducer: state => state, + }, + { + action: 'RECEIVE_NFT_TOKENS', + reducer: (state, { payload: { nft_tokens, nft_assets } }) => { + let new_state = state.set('nft_tokens', fromJS(nft_tokens)) + if (nft_assets) + new_state = new_state.set('nft_assets', fromJS(nft_assets)) + return new_state + }, + }, { action: 'LINK_REPLY', reducer: (state, { payload: op }) => { diff --git a/app/redux/User.js b/app/redux/User.js index 24bf2fa9..49c4c5c5 100644 --- a/app/redux/User.js +++ b/app/redux/User.js @@ -8,6 +8,7 @@ const defaultState = fromJS({ show_login_modal: false, show_transfer_modal: false, show_donate_modal: false, + show_nft_gift_modal: false, show_convert_assets_modal: false, show_promote_post_modal: false, show_signup_modal: false, @@ -71,6 +72,9 @@ export default createModule({ { action: 'SHOW_DONATE', reducer: state => state.set('show_donate_modal', true) }, { action: 'HIDE_DONATE', reducer: state => state.set('show_donate_modal', false) }, { action: 'SET_DONATE_DEFAULTS', reducer: (state, {payload}) => state.set('donate_defaults', fromJS(payload)) }, + { action: 'SHOW_GIFT_NFT', reducer: state => state.set('show_gift_nft_modal', true) }, + { action: 'HIDE_GIFT_NFT', reducer: state => state.set('show_gift_nft_modal', false) }, + { action: 'SET_GIFT_NFT_DEFAULTS', reducer: (state, {payload}) => state.set('gift_nft_defaults', fromJS(payload)) }, { action: 'SHOW_CONVERT_ASSETS', reducer: state => state.set('show_convert_assets_modal', true) }, { action: 'HIDE_CONVERT_ASSETS', reducer: state => state.set('show_convert_assets_modal', false) }, { action: 'SET_CONVERT_ASSETS_DEFAULTS', reducer: (state, {payload}) => state.set('convert_assets_defaults', fromJS(payload)) }, diff --git a/app/utils/NFTUtils.js b/app/utils/NFTUtils.js new file mode 100644 index 00000000..d5fb6bc2 --- /dev/null +++ b/app/utils/NFTUtils.js @@ -0,0 +1,12 @@ + +export function parseNFTImage(json_metadata) { + if (json_metadata) { + const meta = JSON.parse(json_metadata) + if (meta) return meta.image + } + return null +} + +export function NFTImageStub() { + return require('app/assets/images/nft.png') +} diff --git a/package.json b/package.json index 13043084..78d75e0e 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "foundation-sites": "^6.4.3", "fs-extra": "^10.0.1", "git-rev-sync": "^3.0.2", - "golos-lib-js": "^0.9.55", + "golos-lib-js": "^0.9.56", "history": "^2.0.0-rc2", "immutable": "^3.8.2", "intl": "^1.2.5", diff --git a/yarn.lock b/yarn.lock index fe9789cb..9a997da2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1879,14 +1879,15 @@ assert@^1.1.1, assert@^1.4.1: util "0.10.3" assert@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" - integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== + version "2.1.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" + integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== dependencies: - es6-object-assign "^1.1.0" - is-nan "^1.2.1" - object-is "^1.0.1" - util "^0.12.0" + call-bind "^1.0.2" + is-nan "^1.3.2" + object-is "^1.1.5" + object.assign "^4.1.4" + util "^0.12.5" assertion-error@^1.0.1: version "1.1.0" @@ -3024,9 +3025,9 @@ core-js@^2.4.0, core-js@^2.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" core-js@^3.17.3: - version "3.32.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.32.0.tgz#7643d353d899747ab1f8b03d2803b0312a0fb3b6" - integrity sha512-rd4rYZNlF3WuoYuRIDEmbR/ga9CeuWX9U05umAvgrrZoHY4Z++cp/xwPQMvUpBB4Ag6J8KfD80G0zwCyaSxDww== + version "3.32.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.32.2.tgz#172fb5949ef468f93b4be7841af6ab1f21992db7" + integrity sha512-pxXSw1mYZPDGvTQqEc5vgIb83jGQKFGYWY76z4a7weZXUolw3G+OvpZqSRcfYOoOVUQJYEPsWeQK8pKEnUtWxQ== core-js@^3.19.0, core-js@^3.19.1: version "3.19.1" @@ -3592,6 +3593,15 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" +define-data-property@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.0.tgz#0db13540704e1d8d479a0656cf781267531b9451" + integrity sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + define-properties@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" @@ -3606,6 +3616,15 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +define-properties@^1.1.4: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -4109,11 +4128,6 @@ es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-object-assign@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw== - es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" @@ -4874,7 +4888,7 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" -get-intrinsic@^1.1.3: +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== @@ -4999,10 +5013,10 @@ globule@^1.0.0: lodash "~4.17.10" minimatch "~3.0.2" -golos-lib-js@^0.9.55: - version "0.9.55" - resolved "https://registry.yarnpkg.com/golos-lib-js/-/golos-lib-js-0.9.55.tgz#e8eafa78d28fb67e3457fe7fa631baa5d036fda0" - integrity sha512-lN+ryXESL04+mw+uREOh8n9k3GLevO0XSgJb9vCsXOXk0/UWD24SFvajxPPPsJmsAUCdwTe7yWLJPYaSxzpuDg== +golos-lib-js@^0.9.56: + version "0.9.56" + resolved "https://registry.yarnpkg.com/golos-lib-js/-/golos-lib-js-0.9.56.tgz#3dfe8c0658fba2f50976ef49103ddc3f34109c19" + integrity sha512-h9ay0q2AuHiYL8aFXsCGoEFe6ojHt67FHMv8W6oWbqayl44JlRuuEysfE1MZQiiLwzBDFOO1SNMAtv5sE0bRcg== dependencies: abort-controller "^3.0.0" assert "^2.0.0" @@ -5115,6 +5129,13 @@ has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + has-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" @@ -5844,7 +5865,7 @@ is-installed-globally@^0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" -is-nan@^1.2.1: +is-nan@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== @@ -7597,7 +7618,7 @@ object-inspect@^1.11.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== -object-is@^1.0.1: +object-is@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== @@ -7639,6 +7660,16 @@ object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" @@ -10994,7 +11025,7 @@ util@^0.11.0: dependencies: inherits "2.0.3" -util@^0.12.0: +util@^0.12.5: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== @@ -11464,9 +11495,9 @@ ws@^8.11.0: integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== ws@^8.2.3: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + version "8.14.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" + integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== x-xss-protection@1.1.0: version "1.1.0"