diff --git a/.gitignore b/.gitignore
index 9088eeb7e..070f9ccbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,4 +53,4 @@ astar-collator
# Chopstick binaries
db.sqlite*
-.vercel
\ No newline at end of file
+.vercel
diff --git a/package.json b/package.json
index f05d3fc17..dd9ba2767 100644
--- a/package.json
+++ b/package.json
@@ -117,6 +117,7 @@
"@types/validator": "^13.7.11",
"@typescript-eslint/eslint-plugin": "^4.16.1",
"@typescript-eslint/parser": "^4.16.1",
+ "dotenv": "^16.4.7",
"eslint": "^7.14.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-jest": "^25.2.2",
diff --git a/quasar.conf.js b/quasar.conf.js
index 9cbbe728e..5e1996b36 100644
--- a/quasar.conf.js
+++ b/quasar.conf.js
@@ -12,6 +12,8 @@ const { configure } = require('quasar/wrappers');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const path = require('path');
+require('dotenv').config()
+
module.exports = configure(function (ctx) {
return {
@@ -53,7 +55,10 @@ module.exports = configure(function (ctx) {
// Full list of options: https://v2.quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build
build: {
vueRouterMode: 'history', // available values: 'hash', 'history'
-
+ // Memo: Create .env file in root directory to set environment variables
+ // env: {
+ // SONEIUM_CCIP_ROUTER:process.env.SONEIUM_CCIP_ROUTER,
+ // },
// transpile: false,
// Add dependencies for transpiling with Babel (Array of string/regex)
diff --git a/src/assets/img/chain/soneium-white.svg b/src/assets/img/chain/soneium-white.svg
new file mode 100644
index 000000000..1e7334c62
--- /dev/null
+++ b/src/assets/img/chain/soneium-white.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/components/assets/EvmNativeToken.vue b/src/components/assets/EvmNativeToken.vue
index b3410c28f..efab32ca5 100644
--- a/src/components/assets/EvmNativeToken.vue
+++ b/src/components/assets/EvmNativeToken.vue
@@ -45,14 +45,30 @@
-
@@ -144,7 +160,12 @@ import { cbridgeAppLink } from 'src/c-bridge';
import ModalFaucet from 'src/components/assets/modals/ModalFaucet.vue';
import Balloon from 'src/components/common/Balloon.vue';
import { LOCAL_STORAGE } from 'src/config/localStorage';
-import { ccipMinatoBridgeEnabled, layerZeroBridgeEnabled, nativeBridgeEnabled } from 'src/features';
+import {
+ ccipMinatoBridgeEnabled,
+ layerZeroBridgeEnabled,
+ nativeBridgeEnabled,
+ ccipSoneiumBridgeEnabled,
+} from 'src/features';
import { useAccount, useBreakpoints, useFaucet, useNetworkInfo } from 'src/hooks';
import { faucetSethLink } from 'src/links';
import { getTokenImage } from 'src/modules/token';
@@ -156,6 +177,7 @@ import {
} from 'src/router/routes';
import { useStore } from 'src/store';
import { computed, defineComponent, ref, watch, watchEffect } from 'vue';
+
import CustomRouterLink from '../common/CustomRouterLink.vue';
export default defineComponent({
@@ -177,8 +199,9 @@ export default defineComponent({
const isCcipBalloon = ref
(false);
const isBalloonClosing = ref(false);
+ const isSoneiumButtonHover = ref(false);
- const { currentNetworkName, nativeTokenSymbol, isZkEvm, isAstar, isShibuyaEvm } =
+ const { currentNetworkName, nativeTokenSymbol, isZkEvm, isAstar, isShibuyaEvm, isAstarEvm } =
useNetworkInfo();
const closeCcipBalloon = () => {
@@ -229,16 +252,34 @@ export default defineComponent({
const isTruncate = !nativeTokenSymbol.value.toUpperCase().includes('BTC');
+ const isEnableCcipBridge = computed(() => {
+ return (
+ (isShibuyaEvm.value && ccipMinatoBridgeEnabled) ||
+ (isAstarEvm.value && ccipSoneiumBridgeEnabled)
+ );
+ });
+
// Memo: display the balloon animation
watch(
- [isShibuyaEvm],
+ [isShibuyaEvm, isAstarEvm],
async () => {
- const isBallonDisplayed = Boolean(localStorage.getItem(LOCAL_STORAGE.BALLOON_CCIP_SHIBUYA));
- if (isShibuyaEvm.value && !isBallonDisplayed) {
+ const isBallonShibuyaDisplayed = Boolean(
+ localStorage.getItem(LOCAL_STORAGE.BALLOON_CCIP_SHIBUYA)
+ );
+ const isBallonAstarDisplayed = Boolean(
+ localStorage.getItem(LOCAL_STORAGE.BALLOON_CCIP_ASTAR)
+ );
+ if (isShibuyaEvm.value && !isBallonShibuyaDisplayed) {
await wait(1000);
isCcipBalloon.value = true;
localStorage.setItem(LOCAL_STORAGE.BALLOON_CCIP_SHIBUYA, 'true');
}
+
+ if (isAstarEvm.value && !isBallonAstarDisplayed) {
+ await wait(1000);
+ isCcipBalloon.value = true;
+ localStorage.setItem(LOCAL_STORAGE.BALLOON_CCIP_ASTAR, 'true');
+ }
},
{ immediate: true }
);
@@ -261,9 +302,11 @@ export default defineComponent({
nativeBridgeEnabled,
layerZeroBridgeEnabled,
isShibuyaEvm,
- ccipMinatoBridgeEnabled,
+ isEnableCcipBridge,
isCcipBalloon,
isBalloonClosing,
+ isAstarEvm,
+ isSoneiumButtonHover,
closeCcipBalloon,
buildCcipBridgePageLink,
truncate,
diff --git a/src/components/assets/styles/asset-list.scss b/src/components/assets/styles/asset-list.scss
index 554d4e6c7..df54bf82d 100644
--- a/src/components/assets/styles/asset-list.scss
+++ b/src/components/assets/styles/asset-list.scss
@@ -441,6 +441,7 @@
display: block;
text-align: center;
margin-top: 10px;
+ width: 80px;
@media (min-width: $sm) {
display: none;
}
diff --git a/src/components/bridge/BridgeSelection.vue b/src/components/bridge/BridgeSelection.vue
index c5d8a01d4..c518f7842 100644
--- a/src/components/bridge/BridgeSelection.vue
+++ b/src/components/bridge/BridgeSelection.vue
@@ -6,9 +6,9 @@
-
+
@@ -24,20 +24,38 @@
- {{ $t('bridge.ccipMinatoBridge.tag') }}
+ {{
+ $t(
+ isShibuyaEvm
+ ? 'bridge.ccipMinatoBridge.tag'
+ : 'bridge.ccipSoneiumBridge.tag'
+ )
+ }}
-
{{ $t('bridge.ccipMinatoBridge.title') }}
+
{{
+ $t(
+ isShibuyaEvm
+ ? 'bridge.ccipMinatoBridge.title'
+ : 'bridge.ccipSoneiumBridge.title'
+ )
+ }}
- {{ $t('bridge.ccipMinatoBridge.text') }}
+ {{
+ $t(
+ isShibuyaEvm
+ ? 'bridge.ccipMinatoBridge.text'
+ : 'bridge.ccipSoneiumBridge.text'
+ )
+ }}
-
- {{ $t('bridge.ccipMinatoBridge.remark') }}
+
+ {{ $t('bridge.ccipSoneiumBridge.remark') }}
@@ -232,6 +250,7 @@ import {
celerBridgeEnabled,
layerSwapBridgeEnabled,
layerZeroBridgeEnabled,
+ ccipSoneiumBridgeEnabled,
nativeBridgeEnabled,
} from 'src/features';
import { useAccount, useNetworkInfo } from 'src/hooks';
@@ -259,6 +278,7 @@ export default defineComponent({
isAstar,
isH160,
isShibuyaEvm,
+ isAstarEvm,
nativeTokenSymbol,
} = useNetworkInfo();
@@ -280,8 +300,11 @@ export default defineComponent({
return isH160.value && (isAstar.value || isAstarZkEvm.value);
});
- const isEnableMinatoBridge = computed
(() => {
- return isShibuyaEvm.value && ccipMinatoBridgeEnabled;
+ const isEnableCcipBridge = computed(() => {
+ return (
+ (isShibuyaEvm.value && ccipMinatoBridgeEnabled) ||
+ (isAstarEvm.value && ccipSoneiumBridgeEnabled)
+ );
});
return {
@@ -300,8 +323,9 @@ export default defineComponent({
layerSwapBridgeEnabled,
nativeBridgeEnabled,
layerZeroBridgeEnabled,
- isEnableMinatoBridge,
+ isEnableCcipBridge,
isShibuyaEvm,
+ isAstarEvm,
buildEthereumBridgePageLink,
buildLzBridgePageLink,
navigateInNewTab,
diff --git a/src/components/bridge/ccip/CcipBridge.vue b/src/components/bridge/ccip/CcipBridge.vue
index 71bf04d34..1c6d2c616 100644
--- a/src/components/bridge/ccip/CcipBridge.vue
+++ b/src/components/bridge/ccip/CcipBridge.vue
@@ -162,7 +162,7 @@ import { EthBridgeNetworkName } from 'src/modules/zk-evm-bridge';
import { useStore } from 'src/store';
import { PropType, computed, defineComponent, ref, watch } from 'vue';
import Jazzicon from 'vue3-jazzicon/src/components';
-import { ccipMinatoBridgeEnabled } from 'src/features';
+import { ccipMinatoBridgeEnabled, ccipSoneiumBridgeEnabled } from 'src/features';
import {
ccipBridgeIcon,
CCIP_TOKEN,
@@ -255,7 +255,7 @@ export default defineComponent({
},
setup(props) {
const { currentAccount } = useAccount();
- const { nativeTokenSymbol } = useNetworkInfo();
+ const { nativeTokenSymbol, isShibuyaEvm, isAstarEvm } = useNetworkInfo();
const store = useStore();
const isHandling = ref(false);
const isLoading = computed(() => store.getters['general/isLoading']);
@@ -318,9 +318,12 @@ export default defineComponent({
isHandling.value = false;
};
- // Todo: update for Soneium
const ccipBridgeEnabled = computed(() => {
- return ccipMinatoBridgeEnabled;
+ return isShibuyaEvm.value
+ ? ccipMinatoBridgeEnabled
+ : isAstarEvm.value
+ ? ccipSoneiumBridgeEnabled
+ : false;
});
watch(
diff --git a/src/config/localStorage.ts b/src/config/localStorage.ts
index a6cfcf43c..05d1256d6 100644
--- a/src/config/localStorage.ts
+++ b/src/config/localStorage.ts
@@ -18,6 +18,7 @@ export enum LOCAL_STORAGE {
XVM_TX_HISTORIES = 'xvmTxHistories',
BALLOON_NATIVE_TOKEN = 'balloonNativeToken',
BALLOON_CCIP_SHIBUYA = 'balloonCcipShibuya',
+ BALLOON_CCIP_ASTAR = 'balloonCcipAstar',
THEME_COLOR = 'themeColor',
MULTISIG = 'multisig',
CLOSE_DAPP_STAKING_V3_ONBOARDING = 'closeDappStakingV3Onboarding',
diff --git a/src/config/web3/index.ts b/src/config/web3/index.ts
index e39200628..f474b79da 100644
--- a/src/config/web3/index.ts
+++ b/src/config/web3/index.ts
@@ -49,8 +49,7 @@ export enum EVM {
MOONRIVER = 1285,
MOONBEAM = 1284,
SONEIUM_MINATO_TESTNET = 1946,
- // Todo: update
- SONEIUM = 9999,
+ SONEIUM = 1868,
}
export const chainName = {
@@ -166,8 +165,7 @@ export const rpcUrls = {
[EVM.MOONRIVER]: ['https://rpc.api.moonriver.moonbeam.network'],
[EVM.MOONBEAM]: ['https://rpc.api.moonbeam.network'],
[EVM.SONEIUM_MINATO_TESTNET]: ['https://rpc.minato.soneium.org'],
- // Todo: update
- [EVM.SONEIUM]: ['https://rpc.minato.soneium.org'],
+ [EVM.SONEIUM]: ['https://rpc.soneium.org/'],
};
export const blockExplorerUrls = {
@@ -184,8 +182,7 @@ export const blockExplorerUrls = {
[EVM.MOONRIVER]: ['https://moonriver.moonscan.io'],
[EVM.MOONBEAM]: ['https://moonbeam.moonscan.io'],
[EVM.SONEIUM_MINATO_TESTNET]: ['https://soneium-minato.blockscout.com'],
- // Todo: update
- [EVM.SONEIUM]: ['https://soneium-minato.blockscout.com'],
+ [EVM.SONEIUM]: ['https://soneium.blockscout.com'],
};
export const CHAIN_INFORMATION = {
diff --git a/src/features.ts b/src/features.ts
index ff3e7d7f5..7f2fd0568 100644
--- a/src/features.ts
+++ b/src/features.ts
@@ -5,6 +5,7 @@ export const layerSwapBridgeEnabled = false;
export const celerBridgeEnabled = true;
export const omniBridgeEnabled = true;
export const ccipMinatoBridgeEnabled = true;
+export const ccipSoneiumBridgeEnabled = true;
const stargateBridgeEnabled = true;
const stakeStoneBridgeEnabled = true;
const arthSwapBridgeEnabled = true;
diff --git a/src/hooks/bridge/useCcipBridge.ts b/src/hooks/bridge/useCcipBridge.ts
index 903077eea..99c92a1e4 100644
--- a/src/hooks/bridge/useCcipBridge.ts
+++ b/src/hooks/bridge/useCcipBridge.ts
@@ -8,6 +8,7 @@ import {
CCIP_TOKEN,
CCIP_SBY,
ccipBridgeAddress,
+ CCIP_ASTR,
} from 'src/modules/ccip-bridge';
import { showLoading } from 'src/modules/extrinsic/utils';
import { useStore } from 'src/store';
@@ -24,7 +25,7 @@ import { astarNativeTokenErcAddr } from 'src/modules/xcm';
export const useCcipBridge = () => {
const { isShibuya, nativeTokenSymbol } = useNetworkInfo();
- const selectedToken = ref(CCIP_SBY);
+ const selectedToken = ref(isShibuya.value ? CCIP_SBY : CCIP_ASTR);
const bridgeAmt = ref(null);
const toBridgeBalance = ref(0);
const fromBridgeBalance = ref(0);
diff --git a/src/hooks/useNetworkInfo.ts b/src/hooks/useNetworkInfo.ts
index b2a64d339..13e4061bb 100644
--- a/src/hooks/useNetworkInfo.ts
+++ b/src/hooks/useNetworkInfo.ts
@@ -38,6 +38,9 @@ export function useNetworkInfo() {
const isShibuyaEvm = computed(() => {
return isH160.value && isShibuya.value;
});
+ const isAstarEvm = computed(() => {
+ return isH160.value && isAstar.value;
+ });
const currentNetworkChain = computed(() => {
if (isZkEvm.value) {
@@ -133,5 +136,6 @@ export function useNetworkInfo() {
nativeTokenImg,
isShibuya,
isShibuyaEvm,
+ isAstarEvm,
};
}
diff --git a/src/i18n/en-US/index.ts b/src/i18n/en-US/index.ts
index a7e4dc441..55b8eb78e 100644
--- a/src/i18n/en-US/index.ts
+++ b/src/i18n/en-US/index.ts
@@ -494,6 +494,7 @@ export default {
faucet: 'Faucet',
bridge: 'Bridge',
bridgeToSoneium: 'Bridge to Soneium',
+ bridgeToZkEvm: 'Bridge to zkEVM',
swap: 'Swap',
manage: 'Manage',
xcm: 'XCM',
@@ -1092,6 +1093,12 @@ export default {
text: 'Transfer SBY between Soneium Minato and Shibuya EVM. Powered by CCIP.',
remark: 'Available on Shibuya EVM. Switch the network to use it.',
},
+ ccipSoneiumBridge: {
+ title: 'Soneium Bridge',
+ tag: 'ASTR',
+ text: 'Transfer ASTR between Soneium and Astar EVM. Powered by CCIP.',
+ remark: 'Available on Astar EVM. Switch the network to use it.',
+ },
astarBridge: {
title: 'LayerZero',
tag: 'ASTR',
diff --git a/src/modules/ccip-bridge/index.ts b/src/modules/ccip-bridge/index.ts
index 2537d78e7..031fea992 100644
--- a/src/modules/ccip-bridge/index.ts
+++ b/src/modules/ccip-bridge/index.ts
@@ -11,8 +11,7 @@ export enum CcipChainId {
'ShibuyaEvm' = 81,
'AstarEvm' = 592,
'SoneiumMinato' = 1946,
- // Todo: update
- 'Soneium' = 9999,
+ 'Soneium' = 1868,
}
export const ccipChainId = {
@@ -24,25 +23,21 @@ export const ccipChainId = {
export const ccipChainSelector = {
[CcipChainId.ShibuyaEvm]: '6955638871347136141',
- // Todo: update
- [CcipChainId.AstarEvm]: '999999999999999',
+ [CcipChainId.AstarEvm]: '6422105447186081193',
[CcipChainId.SoneiumMinato]: '686603546605904534',
- // Todo: update
- [CcipChainId.Soneium]: '999999999999999',
+ [CcipChainId.Soneium]: '12505351618335765396',
};
const routerSoneiumMinato = '0x443a1bce545d56E2c3f20ED32eA588395FFce0f4';
-const routerSoneium = '0x443a1bce545d56E2c3f20ED32eA588395FFce0f4';
+const routerSoneium = '0x8C8B88d827Fe14Df2bc6392947d513C86afD6977';
const etherSenderReceiverShibuya = '0x89cB78A4A3cAD4cA86D3e3fF565f63B4620CB6ea';
-const etherSenderReceiverAstar = '0x89cB78A4A3cAD4cA86D3e3fF565f63B4620CB6ea';
+const etherSenderReceiverAstar = '0x4036a6Ff8C1a29677108Aef299B560f6E4fA5e71';
export const ccipBridgeAddress = {
[CcipChainId.ShibuyaEvm]: etherSenderReceiverShibuya,
- // Todo: update
[CcipChainId.AstarEvm]: etherSenderReceiverAstar,
[CcipChainId.SoneiumMinato]: routerSoneiumMinato,
- // Todo: update
[CcipChainId.Soneium]: routerSoneium,
};
@@ -50,7 +45,7 @@ export const ccipBridgeIcon = {
[CcipNetworkName.ShibuyaEvm]: require('src/assets/img/chain/astar.png'),
[CcipNetworkName.AstarEvm]: require('src/assets/img/chain/astar.png'),
[CcipNetworkName.SoneiumMinato]: require('src/assets/img/chain/soneium-black.svg'),
- [CcipNetworkName.Soneium]: require('src/assets/img/chain/astar.png'),
+ [CcipNetworkName.Soneium]: require('src/assets/img/chain/soneium-black.svg'),
} as any;
export interface CCIP_TOKEN {
@@ -72,9 +67,20 @@ export const CCIP_SBY: CCIP_TOKEN = {
image: require('/src/assets/img/token/astr.png'),
};
+export const CCIP_ASTR: CCIP_TOKEN = {
+ symbol: 'ASTR',
+ name: 'Astar Token',
+ tokenAddress: {
+ [CcipChainId.AstarEvm]: astarNativeTokenErcAddr,
+ [CcipChainId.Soneium]: '0x2CAE934a1e84F693fbb78CA5ED3B0A6893259441',
+ },
+ decimals: 18,
+ image: require('/src/assets/img/token/astr.png'),
+};
+
export const ccipBridgeTime = {
[CcipNetworkName.ShibuyaEvm]: 3,
[CcipNetworkName.AstarEvm]: 3,
[CcipNetworkName.SoneiumMinato]: 30,
- [CcipNetworkName.Soneium]: 30,
+ [CcipNetworkName.Soneium]: 120,
};
diff --git a/src/modules/information/hot-topics/transfer/index.ts b/src/modules/information/hot-topics/transfer/index.ts
index 5f94844e4..ea1ce22d9 100644
--- a/src/modules/information/hot-topics/transfer/index.ts
+++ b/src/modules/information/hot-topics/transfer/index.ts
@@ -2,6 +2,6 @@ import { Faq } from 'src/modules/information';
export const hotTopics: Faq[] = [
{
title: 'Find latest news here',
- url: 'https://medium.com/astar-network',
+ url: 'https://astar.network/blog',
},
];
diff --git a/src/v2/repositories/implementations/CcipBridgeRepository.ts b/src/v2/repositories/implementations/CcipBridgeRepository.ts
index 61facde0d..eb223a1e8 100644
--- a/src/v2/repositories/implementations/CcipBridgeRepository.ts
+++ b/src/v2/repositories/implementations/CcipBridgeRepository.ts
@@ -86,8 +86,10 @@ export class CcipBridgeRepository implements ICcipBridgeRepository {
const contract = new web3.eth.Contract(abi as AbiItem[], contractAddress);
const { destinationChainSelector, message } = this.getMessageArgs(param);
const fee = await contract.methods.getFee(destinationChainSelector, message).call();
+ // Memo: Add 5% of fee for buffer
+ const feeWithBuffer = ethers.BigNumber.from(fee).mul(105).div(100).toString();
- return fee;
+ return feeWithBuffer;
}
public async getBridgeCcipAssetData({
diff --git a/yarn.lock b/yarn.lock
index 24e4ab79e..3dad0ff07 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6402,7 +6402,7 @@
mini-svg-data-uri "^1.0.3"
traverse "^0.6.6"
-"@tailwindcss/postcss7-compat@^2.0.3":
+"@tailwindcss/postcss7-compat@^2.0.3", "tailwindcss@npm:@tailwindcss/postcss7-compat@^2.0.3":
version "2.2.17"
resolved "https://registry.yarnpkg.com/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.17.tgz#dc78f3880a2af84163150ff426a39e42b9ae8922"
integrity sha512-3h2svqQAqYHxRZ1KjsJjZOVTQ04m29LjfrLjXyZZEJuvUuJN+BCIF9GI8vhE1s0plS0mogd6E6YLg6mu4Wv/Vw==
@@ -10625,6 +10625,11 @@ dot-prop@^5.1.0:
dependencies:
is-obj "^2.0.0"
+dotenv@^16.4.7:
+ version "16.4.7"
+ resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
+ integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
+
duplexer2@~0.1.0:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
@@ -19357,47 +19362,6 @@ tailwindcss-theme-variants@^2.0.0-alpha.2:
lodash "^4.17.21"
postcss-selector-parser "^6.0.6"
-"tailwindcss@npm:@tailwindcss/postcss7-compat@^2.0.3":
- version "2.2.17"
- resolved "https://registry.yarnpkg.com/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.17.tgz#dc78f3880a2af84163150ff426a39e42b9ae8922"
- integrity sha512-3h2svqQAqYHxRZ1KjsJjZOVTQ04m29LjfrLjXyZZEJuvUuJN+BCIF9GI8vhE1s0plS0mogd6E6YLg6mu4Wv/Vw==
- dependencies:
- arg "^5.0.1"
- autoprefixer "^9"
- bytes "^3.0.0"
- chalk "^4.1.2"
- chokidar "^3.5.2"
- color "^4.0.1"
- cosmiconfig "^7.0.1"
- detective "^5.2.0"
- didyoumean "^1.2.2"
- dlv "^1.1.3"
- fast-glob "^3.2.7"
- fs-extra "^10.0.0"
- glob-parent "^6.0.1"
- html-tags "^3.1.0"
- is-color-stop "^1.1.0"
- is-glob "^4.0.1"
- lodash "^4.17.21"
- lodash.topath "^4.5.2"
- modern-normalize "^1.1.0"
- node-emoji "^1.11.0"
- normalize-path "^3.0.0"
- object-hash "^2.2.0"
- postcss "^7"
- postcss-functions "^3"
- postcss-js "^2"
- postcss-load-config "^3.1.0"
- postcss-nested "^4"
- postcss-selector-parser "^6.0.6"
- postcss-value-parser "^4.1.0"
- pretty-hrtime "^1.0.3"
- purgecss "^4.0.3"
- quick-lru "^5.1.1"
- reduce-css-calc "^2.1.8"
- resolve "^1.20.0"
- tmp "^0.2.1"
-
tapable@^1.0.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"