From 61f1335763d1c1c54ae1bf41396bb51a059cde9f Mon Sep 17 00:00:00 2001 From: Inokentii Mazhara Date: Thu, 31 Oct 2024 11:33:13 +0200 Subject: [PATCH 01/16] TW-1571: Update swap to 3Route v4 (#1211) * TW-1566 Update 3route pools types * TW-1571 Migrate to 3Route V4 * TW-1571 Some refactoring * TW-1571 Fix ts error * TW-1571 Some bugfixes and 3route usage improvements * TW-1571 Increase hops limit for SIRS swaps above 10 USD * TW-1571 Apply fixes from TW-1572 * TW-1571 Ignore dependencies issues caused by @types modules * TW-1571 Fix ignoring issues in Github actions * TW-1571 Refactoring according to comments * TW-1571 Remove unnecessary console output * TW-1571 Revert changes to audit script * TW-1571 Fix the crash of 'Swap' section after upgrade * TW-1571 Various bugfixes * TW-1571 Some refactoring * TW-1571 Remove assigning estimations in case of estimation error * TW-1571 Refactoring according to comments * TW-1571 Reduce chances of swap failure * TW-1571 Minor refactoring --- package.json | 37 +- src/app/hooks/use-swap.ts | 6 +- src/app/pages/Staking/MyStake.tsx | 2 +- src/app/store/index.ts | 2 +- src/app/store/migrations.ts | 19 + src/app/store/root-state.reducer.ts | 4 +- src/app/store/swap/reducers.ts | 16 +- src/app/store/swap/selectors.ts | 2 + src/app/store/swap/state.mock.ts | 8 +- src/app/templates/SwapForm/SwapForm.tippy.ts | 4 +- src/app/templates/SwapForm/SwapForm.tsx | 196 ++- .../SwapForm/SwapFormInput/SwapFormInput.tsx | 10 +- .../SwapForm/SwapRoute/SwapRoute.tsx | 136 -- .../SwapRoute/SwapRouteItem/SwapRouteItem.tsx | 42 - .../SwapRoute/SwapRouteItem/hop-item.tsx | 67 - .../SwapRouteItem/swap-route-amounts.tsx | 39 - .../SwapForm/SwapRoute/lb-pool-part.tsx | 62 - src/lib/apis/route3/fetch-route3-dexes.ts | 12 +- .../apis/route3/fetch-route3-swap-params.ts | 128 +- src/lib/apis/route3/route3.api.ts | 4 +- src/lib/assets/known-tokens.ts | 12 +- src/lib/assets/three-route-tokens.ts | 9 + src/lib/constants.ts | 4 + src/lib/fixed-times.ts | 2 +- src/lib/route3/constants.ts | 21 +- src/lib/route3/interfaces/index.ts | 57 +- src/lib/route3/utils/get-dex-name.ts | 19 + src/lib/route3/utils/map-to-route3-hops.ts | 30 +- .../components/DexTypeIcon/DexTypeIcon.tsx | 18 +- .../components/DexTypeIcon/icons/kord.png | Bin 0 -> 1722 bytes .../components/DexTypeIcon/icons/oxtz.svg | 4 + .../components/DexTypeIcon/icons/wtez.svg | 5 + src/lib/swap-router/index.ts | 1 - src/lib/temple/__tests__/helpers.test.ts | 10 +- src/lib/temple/activity-new/fetch.ts | 3 +- src/lib/temple/back/dryrun.ts | 5 +- src/lib/temple/back/vault/index.ts | 2 +- src/lib/temple/front/client.ts | 9 +- src/lib/temple/helpers.ts | 11 +- src/lib/utils/numbers.ts | 4 + src/lib/utils/swap.utils.ts | 186 ++- yarn.lock | 1273 ++++++++++++++--- 42 files changed, 1701 insertions(+), 780 deletions(-) delete mode 100644 src/app/templates/SwapForm/SwapRoute/SwapRoute.tsx delete mode 100644 src/app/templates/SwapForm/SwapRoute/SwapRouteItem/SwapRouteItem.tsx delete mode 100644 src/app/templates/SwapForm/SwapRoute/SwapRouteItem/hop-item.tsx delete mode 100644 src/app/templates/SwapForm/SwapRoute/SwapRouteItem/swap-route-amounts.tsx delete mode 100644 src/app/templates/SwapForm/SwapRoute/lb-pool-part.tsx create mode 100644 src/lib/swap-router/components/DexTypeIcon/icons/kord.png create mode 100644 src/lib/swap-router/components/DexTypeIcon/icons/oxtz.svg create mode 100644 src/lib/swap-router/components/DexTypeIcon/icons/wtez.svg delete mode 100644 src/lib/swap-router/index.ts diff --git a/package.json b/package.json index 0c1d00ffb1..5b3cdaf238 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "audit-deps": "node ./audit-deps.js" }, "engines": { - "node": ">=18" + "node": ">=20" }, "dependencies": { "@apollo/client": "^3.7.2", @@ -60,16 +60,16 @@ "@reduxjs/toolkit": "^1.8.5", "@rnw-community/shared": "^0.48.0", "@svgr/webpack": "6.4.0", - "@taquito/ledger-signer": "20.0.0", - "@taquito/local-forging": "20.0.0", - "@taquito/michel-codec": "20.0.0", - "@taquito/michelson-encoder": "20.0.0", - "@taquito/rpc": "20.0.0", - "@taquito/signer": "20.0.0", - "@taquito/taquito": "20.0.0", - "@taquito/tzip12": "20.0.0", - "@taquito/tzip16": "20.0.0", - "@taquito/utils": "20.0.0", + "@taquito/ledger-signer": "20.1.0", + "@taquito/local-forging": "20.1.0", + "@taquito/michel-codec": "20.1.0", + "@taquito/michelson-encoder": "20.1.0", + "@taquito/rpc": "20.1.0", + "@taquito/signer": "20.1.0", + "@taquito/taquito": "20.1.0", + "@taquito/tzip12": "20.1.0", + "@taquito/tzip16": "20.1.0", + "@taquito/utils": "20.1.0", "@temple-wallet/dapp": "5.0.2", "@temple-wallet/jest-webextension-mock": "^4.1.0", "@temple-wallet/save-remote-file-webpack-plugin": "^1.1.3", @@ -114,7 +114,7 @@ "autoprefixer": "10.4.2", "axios": "^1.7.4", "babel-loader": "8.2.5", - "bignumber.js": "9.1.0", + "bignumber.js": "9.1.2", "bip39": "3.0.4", "bs58check": "2.1.2", "buffer": "5.6.0", @@ -219,12 +219,13 @@ "resolutions": { "tslib": "^2.4.0", "@types/react": "18.0.15", - "@taquito/taquito": "20.0.0", - "@taquito/utils": "20.0.0", - "@taquito/beacon-wallet": "20.0.0", - "@taquito/contracts-library": "20.0.0", - "@taquito/tzip16": "20.0.0", - "bignumber.js": "9.1.0", + "@types/react-dev-utils/@types/webpack-dev-server": "^4", + "@taquito/taquito": "20.1.0", + "@taquito/utils": "20.1.0", + "@taquito/beacon-wallet": "20.1.0", + "@taquito/contracts-library": "20.1.0", + "@taquito/tzip16": "20.1.0", + "bignumber.js": "9.1.2", "eslint-plugin-import": "^2.29.0", "graphql-request": "^6.1.0", "json5": "^2.2.2", diff --git a/src/app/hooks/use-swap.ts b/src/app/hooks/use-swap.ts index fd43f42af4..03c0b3bd73 100644 --- a/src/app/hooks/use-swap.ts +++ b/src/app/hooks/use-swap.ts @@ -3,7 +3,7 @@ import { useCallback } from 'react'; import { BigNumber } from 'bignumber.js'; import { Route3Token } from 'lib/apis/route3/fetch-route3-tokens'; -import { Route3LiquidityBakingChains, Route3SwapChains } from 'lib/route3/interfaces'; +import { Route3SwapHops, Route3LiquidityBakingHops } from 'lib/route3/interfaces'; import { useAccount, useTezos } from 'lib/temple/front'; import { getSwapTransferParams } from 'lib/utils/swap.utils'; @@ -17,14 +17,14 @@ export const useSwap = () => { toRoute3Token: Route3Token, inputAmountAtomic: BigNumber, minimumReceivedAtomic: BigNumber, - chains: Route3SwapChains | Route3LiquidityBakingChains + hops: Route3SwapHops | Route3LiquidityBakingHops ) => getSwapTransferParams( fromRoute3Token, toRoute3Token, inputAmountAtomic, minimumReceivedAtomic, - chains, + hops, tezos, publicKeyHash ), diff --git a/src/app/pages/Staking/MyStake.tsx b/src/app/pages/Staking/MyStake.tsx index b6c730b849..8666393426 100644 --- a/src/app/pages/Staking/MyStake.tsx +++ b/src/app/pages/Staking/MyStake.tsx @@ -182,5 +182,5 @@ export const MyStakeTab = memo(() => { const CYCLES_LOOKUP_URLS: StringRecord = { [ChainIds.MAINNET]: 'https://tzkt.io/cycles', [ChainIds.ITHACANET2]: 'https://ghostnet.tzkt.io/cycles', - [ChainIds.PARISNET]: 'https://parisnet.tzkt.io/cycles' + [ChainIds.PARISCNET]: 'https://parisnet.tzkt.io/cycles' }; diff --git a/src/app/store/index.ts b/src/app/store/index.ts index 4cc72cc80a..152ccb5414 100644 --- a/src/app/store/index.ts +++ b/src/app/store/index.ts @@ -24,7 +24,7 @@ const persistConfigBlacklist: (keyof RootState)[] = SLICES_BLACKLIST; const persistedReducer = persistReducer( { key: 'temple-root', - version: 3, + version: 4, ...storageConfig, stateReconciler: autoMergeLevel2, blacklist: persistConfigBlacklist, diff --git a/src/app/store/migrations.ts b/src/app/store/migrations.ts index e11d699cd6..1fbaf66026 100644 --- a/src/app/store/migrations.ts +++ b/src/app/store/migrations.ts @@ -6,6 +6,7 @@ import { isCollectible } from 'lib/metadata'; import { collectiblesMetadataInitialState } from './collectibles-metadata/state'; import type { RootState } from './root-state.type'; +import { DEFAULT_SWAP_PARAMS } from './swap/state.mock'; import type { SLICES_BLACKLIST } from './index'; @@ -80,6 +81,24 @@ export const MIGRATIONS: MigrationManifest = { } }; + return newState; + }, + + '4': (persistedState: PersistedState) => { + if (!persistedState) return persistedState; + + const typedPersistedState = persistedState as TypedPersistedRootState; + const newState: TypedPersistedRootState = { + ...typedPersistedState, + swap: { + ...typedPersistedState.swap, + swapParams: { + data: DEFAULT_SWAP_PARAMS, + isLoading: false + } + } + }; + return newState; } }; diff --git a/src/app/store/root-state.reducer.ts b/src/app/store/root-state.reducer.ts index 270b9850f4..24f334ebfe 100644 --- a/src/app/store/root-state.reducer.ts +++ b/src/app/store/root-state.reducer.ts @@ -14,7 +14,7 @@ import { dAppsReducer } from './d-apps/reducers'; import { newsletterReducers } from './newsletter/newsletter-reducers'; import { partnersPromotionPersistedReducer } from './partners-promotion/reducers'; import { settingsReducer } from './settings/reducers'; -import { swapReducer } from './swap/reducers'; +import { swapPersistedReducer } from './swap/reducers'; import { tokensMetadataReducer } from './tokens-metadata/reducers'; const rootStateReducersMap = { @@ -23,7 +23,7 @@ const rootStateReducersMap = { currency: currencyReducer, notifications: notificationsReducer, dApps: dAppsReducer, - swap: swapReducer, + swap: swapPersistedReducer, partnersPromotion: partnersPromotionPersistedReducer, balances: balancesReducer, assets: assetsPersistedReducer, diff --git a/src/app/store/swap/reducers.ts b/src/app/store/swap/reducers.ts index 73210979a6..2afd6b3ecf 100644 --- a/src/app/store/swap/reducers.ts +++ b/src/app/store/swap/reducers.ts @@ -1,12 +1,13 @@ import { createReducer } from '@reduxjs/toolkit'; +import { persistReducer } from 'redux-persist'; -import { createEntity } from 'lib/store'; +import { createEntity, storageConfig } from 'lib/store'; import { loadSwapDexesAction, loadSwapParamsAction, loadSwapTokensAction, resetSwapParamsAction } from './actions'; -import { swapInitialState } from './state'; +import { swapInitialState, SwapState } from './state'; import { DEFAULT_SWAP_PARAMS } from './state.mock'; -export const swapReducer = createReducer(swapInitialState, builder => { +const swapReducer = createReducer(swapInitialState, builder => { builder.addCase(loadSwapTokensAction.submit, state => { state.tokens = createEntity([...state.tokens.data], true); }); @@ -38,3 +39,12 @@ export const swapReducer = createReducer(swapInitialState, builder => { state.swapParams = createEntity(DEFAULT_SWAP_PARAMS, false, payload); }); }); + +export const swapPersistedReducer = persistReducer( + { + key: 'root.swap', + ...storageConfig, + blacklist: ['swapParams'] + }, + swapReducer +); diff --git a/src/app/store/swap/selectors.ts b/src/app/store/swap/selectors.ts index 0c2ee2c2e2..827457dd4d 100644 --- a/src/app/store/swap/selectors.ts +++ b/src/app/store/swap/selectors.ts @@ -6,4 +6,6 @@ export const useSwapParamsSelector = () => useSelector(state => state.swap.swapP export const useSwapTokensSelector = () => useSelector(state => state.swap.tokens); export const useSwapTokenSelector = (slug: string) => useSelector(state => getRoute3TokenBySlug(state.swap.tokens.data, slug)); +// TODO: use this selector to display a route +// ts-prune-ignore-next export const useSwapDexesSelector = () => useSelector(state => state.swap.dexes); diff --git a/src/app/store/swap/state.mock.ts b/src/app/store/swap/state.mock.ts index 78a9d0b91f..2bd53eb0c9 100644 --- a/src/app/store/swap/state.mock.ts +++ b/src/app/store/swap/state.mock.ts @@ -1,13 +1,13 @@ import { Route3SwapParamsResponse } from 'lib/route3/interfaces'; -import { createEntity } from 'lib/store'; +import { createEntity, mockPersistedState } from 'lib/store'; import type { SwapState } from './state'; -export const DEFAULT_SWAP_PARAMS: Route3SwapParamsResponse = { input: undefined, output: undefined, chains: [] }; +export const DEFAULT_SWAP_PARAMS: Route3SwapParamsResponse = { input: undefined, output: undefined, hops: [] }; -export const mockSwapState: SwapState = { +export const mockSwapState = mockPersistedState({ swapParams: createEntity(DEFAULT_SWAP_PARAMS), dexes: createEntity([]), tokens: createEntity([]) -}; +}); diff --git a/src/app/templates/SwapForm/SwapForm.tippy.ts b/src/app/templates/SwapForm/SwapForm.tippy.ts index c47ce1153a..c611913250 100644 --- a/src/app/templates/SwapForm/SwapForm.tippy.ts +++ b/src/app/templates/SwapForm/SwapForm.tippy.ts @@ -1,5 +1,5 @@ import { t } from 'lib/i18n'; -import { SWAP_CASHBACK_PERCENT } from 'lib/route3/constants'; +import { SWAP_CASHBACK_RATIO } from 'lib/route3/constants'; export const feeInfoTippyProps = { trigger: 'mouseenter', @@ -11,6 +11,6 @@ export const feeInfoTippyProps = { export const cashbackInfoTippyProps = { trigger: 'mouseenter', hideOnClick: false, - content: t('swapCashbackDescription', [SWAP_CASHBACK_PERCENT]) as string, + content: t('swapCashbackDescription', String(SWAP_CASHBACK_RATIO * 100)), animation: 'shift-away-subtle' }; diff --git a/src/app/templates/SwapForm/SwapForm.tsx b/src/app/templates/SwapForm/SwapForm.tsx index 13bc3697f5..474d26a691 100644 --- a/src/app/templates/SwapForm/SwapForm.tsx +++ b/src/app/templates/SwapForm/SwapForm.tsx @@ -26,14 +26,12 @@ import { T, t } from 'lib/i18n'; import { useAssetMetadata, useGetAssetMetadata } from 'lib/metadata'; import { BURN_ADDREESS, - MAX_ROUTING_FEE_CHAINS, ROUTING_FEE_ADDRESS, + ROUTING_FEE_RATIO, ROUTING_FEE_SLIPPAGE_RATIO, + SWAP_CASHBACK_RATIO, SWAP_THRESHOLD_TO_GET_CASHBACK, - TEMPLE_TOKEN, - ATOMIC_INPUT_THRESHOLD_FOR_FEE_FROM_INPUT, - ROUTING_FEE_PERCENT, - SWAP_CASHBACK_PERCENT + TEMPLE_TOKEN } from 'lib/route3/constants'; import { isLiquidityBakingParamsResponse } from 'lib/route3/interfaces'; import { getPercentageRatio } from 'lib/route3/utils/get-percentage-ratio'; @@ -44,8 +42,8 @@ import useTippy from 'lib/ui/useTippy'; import { ZERO } from 'lib/utils/numbers'; import { parseTransferParamsToParamsWithKind } from 'lib/utils/parse-transfer-params'; import { - calculateFeeFromOutput, - calculateRoutingInputAndFeeFromInput, + calculateSidePaymentsFromInput, + calculateOutputFeeAtomic, getRoutingFeeTransferParams } from 'lib/utils/swap.utils'; import { HistoryAction, navigate } from 'lib/woozie'; @@ -59,12 +57,17 @@ import { SlippageToleranceInput } from './SwapFormInput/SlippageToleranceInput/S import { slippageToleranceInputValidationFn } from './SwapFormInput/SlippageToleranceInput/SlippageToleranceInput.validation'; import { SwapFormInput } from './SwapFormInput/SwapFormInput'; import { SwapMinimumReceived } from './SwapMinimumReceived/SwapMinimumReceived'; -import { SwapRoute } from './SwapRoute/SwapRoute'; + +// These values have been set after some experimentation. They are different to the respective values in +// templewallet-mobile because the mobile app still uses taquito v19.0.0, which has a different gas estimation algorithm. +const SINGLE_SWAP_IN_BATCH_MAX_DEXES = 12; +const LB_OPERATION_DEXES_COST = 3; export const SwapForm: FC = () => { const dispatch = useDispatch(); const tezos = useTezos(); const blockLevel = useBlockLevel(); + const prevBlockLevelRef = useRef(blockLevel); const { publicKeyHash } = useAccount(); const getSwapParams = useSwap(); const { data: route3Tokens } = useSwapTokensSelector(); @@ -111,39 +114,89 @@ export const SwapForm: FC = () => { } }, [swapParams.data.output, outputAssetMetadata.decimals, slippageRatio]); - const chainsAreAbsent = isLiquidityBakingParamsResponse(swapParams.data) - ? swapParams.data.tzbtcChain.chains.length === 0 && swapParams.data.xtzChain.chains.length === 0 - : swapParams.data.chains.length === 0; + const hopsAreAbsent = isLiquidityBakingParamsResponse(swapParams.data) + ? swapParams.data.tzbtcHops.length === 0 && swapParams.data.xtzHops.length === 0 + : swapParams.data.hops.length === 0; const atomsInputValue = useMemo( () => tokensToAtoms(inputValue.amount ?? ZERO, inputAssetMetadata.decimals), [inputAssetMetadata.decimals, inputValue.amount] ); - const routingFeeIsTakenFromOutput = atomsInputValue.lt(ATOMIC_INPUT_THRESHOLD_FOR_FEE_FROM_INPUT) ?? false; - useEffect(() => { - const { swapInputMinusFeeAtomic } = calculateRoutingInputAndFeeFromInput( - tokensToAtoms(inputValue.amount ?? ZERO, inputAssetMetadata.decimals) - ); + const getSwapWithFeeParams = useCallback( + (newInputValue: SwapInputValue, newOutputValue: SwapInputValue) => { + const { assetSlug: inputAssetSlug, amount: inputAmount } = newInputValue; + const outputAssetSlug = newOutputValue.assetSlug; + const inputTokenExchangeRate = inputAssetSlug ? allUsdToTokenRates[inputAssetSlug] : '0'; + const inputAmountInUsd = inputAmount?.multipliedBy(inputTokenExchangeRate) ?? ZERO; + + const isInputTokenTempleToken = inputAssetSlug === KNOWN_TOKENS_SLUGS.TEMPLE; + const isOutputTokenTempleToken = outputAssetSlug === KNOWN_TOKENS_SLUGS.TEMPLE; + const isSirsSwap = inputAssetSlug === KNOWN_TOKENS_SLUGS.SIRS || outputAssetSlug === KNOWN_TOKENS_SLUGS.SIRS; + const isSwapAmountMoreThreshold = inputAmountInUsd.isGreaterThanOrEqualTo(SWAP_THRESHOLD_TO_GET_CASHBACK); + const totalMaxDexes = SINGLE_SWAP_IN_BATCH_MAX_DEXES - (isSirsSwap ? LB_OPERATION_DEXES_COST : 0); + const cashbackSwapMaxDexes = Math.ceil(totalMaxDexes / (isSirsSwap ? 3 : 2)); + const mainSwapMaxDexes = + totalMaxDexes - (isSwapAmountMoreThreshold && !isInputTokenTempleToken ? cashbackSwapMaxDexes : 0); + + return { + isInputTokenTempleToken, + isOutputTokenTempleToken, + isSwapAmountMoreThreshold, + mainSwapMaxDexes, + cashbackSwapMaxDexes + }; + }, + [allUsdToTokenRates] + ); + + const dispatchLoadSwapParams = useCallback( + (input: SwapInputValue, output: SwapInputValue) => { + if (!input.assetSlug || !output.assetSlug) { + return; + } + const inputMetadata = getTokenMetadata(input.assetSlug); + + if (!inputMetadata) { + return; + } + + const { swapInputMinusFeeAtomic: amount } = calculateSidePaymentsFromInput( + tokensToAtoms(input.amount ?? ZERO, inputMetadata.decimals) + ); + + const route3FromToken = getRoute3TokenBySlug(route3Tokens, input.assetSlug); + const route3ToToken = getRoute3TokenBySlug(route3Tokens, output.assetSlug); + const { mainSwapMaxDexes } = getSwapWithFeeParams(input, output); - if (isDefined(fromRoute3Token) && isDefined(toRoute3Token)) { dispatch( loadSwapParamsAction.submit({ - fromSymbol: fromRoute3Token.symbol, - toSymbol: toRoute3Token.symbol, - amount: atomsToTokens(swapInputMinusFeeAtomic, fromRoute3Token.decimals).toFixed() + fromSymbol: route3FromToken?.symbol ?? '', + toSymbol: route3ToToken?.symbol ?? '', + toTokenDecimals: route3ToToken?.decimals ?? 0, + amount: atomsToTokens(amount, route3FromToken?.decimals ?? 0).toFixed(), + dexesLimit: mainSwapMaxDexes, + rpcUrl: tezos.rpc.getRpcUrl() }) ); + }, + [dispatch, getSwapWithFeeParams, getTokenMetadata, route3Tokens, tezos.rpc] + ); + + useEffect(() => { + if (isDefined(fromRoute3Token) && isDefined(toRoute3Token) && prevBlockLevelRef.current !== blockLevel) { + dispatchLoadSwapParams(inputValue, outputValue); } - }, [blockLevel]); + prevBlockLevelRef.current = blockLevel; + }, [blockLevel, dispatchLoadSwapParams, fromRoute3Token, inputValue, outputValue, toRoute3Token]); useEffect(() => { - if (Number(swapParams.data.input) > 0 && chainsAreAbsent) { + if (Number(swapParams.data.input) > 0 && hopsAreAbsent) { setIsAlertVisible(true); } else { setIsAlertVisible(false); } - }, [chainsAreAbsent, swapParams.data]); + }, [hopsAreAbsent, swapParams.data]); useEffect( () => @@ -168,21 +221,29 @@ export const SwapForm: FC = () => { amount: undefined }); } else { - const outputAtomicAmountPlusFee = tokensToAtoms(new BigNumber(currentOutput), outputAssetMetadata.decimals); - const feeFromOutput = calculateFeeFromOutput( + const outputAtomicAmountBeforeFee = tokensToAtoms(new BigNumber(currentOutput), outputAssetMetadata.decimals); + const outputFeeAtomic = calculateOutputFeeAtomic( tokensToAtoms(inputValue.amount ?? ZERO, inputAssetMetadata.decimals), - outputAtomicAmountPlusFee + outputAtomicAmountBeforeFee ); setValue('output', { assetSlug: outputValue.assetSlug, - amount: atomsToTokens(outputAtomicAmountPlusFee.minus(feeFromOutput), outputAssetMetadata.decimals) + amount: atomsToTokens(outputAtomicAmountBeforeFee.minus(outputFeeAtomic), outputAssetMetadata.decimals) }); } if (isSubmitButtonPressedRef.current) { triggerValidation(); } - }, [swapParams.data.output, setValue, triggerValidation]); + }, [ + swapParams.data.output, + setValue, + triggerValidation, + outputValue.assetSlug, + outputAssetMetadata.decimals, + inputValue.amount, + inputAssetMetadata.decimals + ]); useEffect(() => { register('input', { @@ -225,9 +286,12 @@ export const SwapForm: FC = () => { formAnalytics.trackSubmit(analyticsProperties); - const { swapInputMinusFeeAtomic, routingFeeFromInputAtomic } = - calculateRoutingInputAndFeeFromInput(atomsInputValue); - const routingFeeFromOutputAtomic = calculateFeeFromOutput(atomsInputValue, minimumReceivedAmountAtomic); + const { + swapInputMinusFeeAtomic, + inputFeeAtomic: routingFeeFromInputAtomic, + cashbackSwapInputAtomic: cashbackSwapInputFromInAtomic + } = calculateSidePaymentsFromInput(atomsInputValue); + const routingFeeFromOutputAtomic = calculateOutputFeeAtomic(atomsInputValue, minimumReceivedAmountAtomic); if (!fromRoute3Token || !toRoute3Token || !swapParams.data.output || !inputValue.assetSlug) { return; @@ -253,20 +317,17 @@ export const SwapForm: FC = () => { swapParams.data ); - if (!route3SwapOpParams) { + if (route3SwapOpParams.length === 0) { return; } - const inputTokenExhangeRate = allUsdToTokenRates[inputValue.assetSlug]; - const inputAmountInUsd = inputValue.amount?.multipliedBy(inputTokenExhangeRate) ?? ZERO; - - const isInputTokenTempleToken = inputValue.assetSlug === KNOWN_TOKENS_SLUGS.TEMPLE; - const isSwapAmountMoreThreshold = inputAmountInUsd.isGreaterThanOrEqualTo(SWAP_THRESHOLD_TO_GET_CASHBACK); + const { isInputTokenTempleToken, isOutputTokenTempleToken, isSwapAmountMoreThreshold, cashbackSwapMaxDexes } = + getSwapWithFeeParams(inputValue, outputValue); if (isInputTokenTempleToken && isSwapAmountMoreThreshold) { const routingInputFeeOpParams = await getRoutingFeeTransferParams( fromRoute3Token, - routingFeeFromInputAtomic.dividedToIntegerBy(2), + routingFeeFromInputAtomic.minus(cashbackSwapInputFromInAtomic), publicKeyHash, BURN_ADDREESS, tezos @@ -285,8 +346,10 @@ export const SwapForm: FC = () => { const swapToTempleParams = await fetchRoute3SwapParams({ fromSymbol: fromRoute3Token.symbol, toSymbol: TEMPLE_TOKEN.symbol, + toTokenDecimals: TEMPLE_TOKEN.decimals, amount: atomsToTokens(routingFeeFromInputAtomic, fromRoute3Token.decimals).toFixed(), - chainsLimit: MAX_ROUTING_FEE_CHAINS + dexesLimit: cashbackSwapMaxDexes, + rpcUrl: tezos.rpc.getRpcUrl() }); const templeOutputAtomic = tokensToAtoms( @@ -308,18 +371,30 @@ export const SwapForm: FC = () => { const routingFeeOpParams = await getRoutingFeeTransferParams( TEMPLE_TOKEN, - templeOutputAtomic.dividedToIntegerBy(2), + templeOutputAtomic.times(ROUTING_FEE_RATIO - SWAP_CASHBACK_RATIO).dividedToIntegerBy(ROUTING_FEE_RATIO), publicKeyHash, BURN_ADDREESS, tezos ); allSwapParams.push(...routingFeeOpParams); + } else if (!isInputTokenTempleToken && isSwapAmountMoreThreshold && isOutputTokenTempleToken) { + routingOutputFeeTransferParams = await getRoutingFeeTransferParams( + TEMPLE_TOKEN, + routingFeeFromOutputAtomic + .times(ROUTING_FEE_RATIO - SWAP_CASHBACK_RATIO) + .dividedToIntegerBy(ROUTING_FEE_RATIO), + publicKeyHash, + BURN_ADDREESS, + tezos + ); } else if (!isInputTokenTempleToken && isSwapAmountMoreThreshold) { const swapToTempleParams = await fetchRoute3SwapParams({ fromSymbol: toRoute3Token.symbol, toSymbol: TEMPLE_TOKEN.symbol, + toTokenDecimals: TEMPLE_TOKEN.decimals, amount: atomsToTokens(routingFeeFromOutputAtomic, toRoute3Token.decimals).toFixed(), - chainsLimit: MAX_ROUTING_FEE_CHAINS + dexesLimit: cashbackSwapMaxDexes, + rpcUrl: tezos.rpc.getRpcUrl() }); const templeOutputAtomic = tokensToAtoms( @@ -339,7 +414,7 @@ export const SwapForm: FC = () => { const routingFeeOpParams = await getRoutingFeeTransferParams( TEMPLE_TOKEN, - templeOutputAtomic.dividedToIntegerBy(2), + templeOutputAtomic.times(ROUTING_FEE_RATIO - SWAP_CASHBACK_RATIO).dividedToIntegerBy(ROUTING_FEE_RATIO), publicKeyHash, BURN_ADDREESS, tezos @@ -375,31 +450,6 @@ export const SwapForm: FC = () => { } }; - const dispatchLoadSwapParams = useCallback((input: SwapInputValue, output: SwapInputValue) => { - if (!input.assetSlug || !output.assetSlug) { - return; - } - const inputMetadata = getTokenMetadata(input.assetSlug); - - if (!inputMetadata) { - return; - } - - const { swapInputMinusFeeAtomic: amount } = calculateRoutingInputAndFeeFromInput( - tokensToAtoms(input.amount ?? ZERO, inputMetadata.decimals) - ); - - const route3FromToken = getRoute3TokenBySlug(route3Tokens, input.assetSlug); - - dispatch( - loadSwapParamsAction.submit({ - fromSymbol: route3FromToken?.symbol ?? '', - toSymbol: getRoute3TokenBySlug(route3Tokens, output.assetSlug)?.symbol ?? '', - amount: amount && atomsToTokens(amount, route3FromToken?.decimals ?? 0).toFixed() - }) - ); - }, []); - const handleErrorClose = () => setError(undefined); const handleOperationClose = () => setOperation(undefined); @@ -518,7 +568,7 @@ export const SwapForm: FC = () => { - {ROUTING_FEE_PERCENT}% + {ROUTING_FEE_RATIO * 100}% @@ -568,7 +618,7 @@ export const SwapForm: FC = () => { - {SWAP_CASHBACK_PERCENT}% + {SWAP_CASHBACK_RATIO * 100}% @@ -585,13 +635,7 @@ export const SwapForm: FC = () => { /> )} - + {/* TODO: add a route display */}

diff --git a/src/app/templates/SwapForm/SwapFormInput/SwapFormInput.tsx b/src/app/templates/SwapForm/SwapFormInput/SwapFormInput.tsx index 5f7ed892dc..63f290f059 100644 --- a/src/app/templates/SwapForm/SwapFormInput/SwapFormInput.tsx +++ b/src/app/templates/SwapForm/SwapFormInput/SwapFormInput.tsx @@ -51,8 +51,8 @@ export const SwapFormInput: FC = ({ const { trackChange } = useFormAnalytics('SwapForm'); const { assetSlug, amount } = value; - const isTezosSlug = assetSlug === 'tez'; - const assetSlugWithFallback = assetSlug ?? 'tez'; + const isTezosSlug = assetSlug === TEZ_TOKEN_SLUG; + const assetSlugWithFallback = assetSlug ?? TEZ_TOKEN_SLUG; const assetMetadataWithFallback = useAssetMetadata(assetSlugWithFallback)!; const assetMetadata = useMemo( @@ -138,7 +138,7 @@ export const SwapFormInput: FC = ({ header={ } @@ -270,13 +270,13 @@ const SwapInput: FC = ({ ); }; -const SwapInputHeader: FC<{ label: ReactNode; selectedAssetSlug: string; selectedAssetSymbol: string }> = ({ +const SwapInputHeader: FC<{ label: ReactNode; selectedAssetSlug?: string; selectedAssetSymbol: string }> = ({ selectedAssetSlug, selectedAssetSymbol, label }) => { const { publicKeyHash } = useAccount(); - const { value: balance } = useBalance(selectedAssetSlug, publicKeyHash); + const { value: balance } = useBalance(selectedAssetSlug ?? TEZ_TOKEN_SLUG, publicKeyHash); return (

diff --git a/src/app/templates/SwapForm/SwapRoute/SwapRoute.tsx b/src/app/templates/SwapForm/SwapRoute/SwapRoute.tsx deleted file mode 100644 index ff65a5839c..0000000000 --- a/src/app/templates/SwapForm/SwapRoute/SwapRoute.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import React, { memo, useEffect, useMemo, useState } from 'react'; - -import { isDefined } from '@rnw-community/shared'; -import { BigNumber } from 'bignumber.js'; - -import { ReactComponent as ChevronDown } from 'app/icons/chevron-down.svg'; -import { ReactComponent as ChevronUp } from 'app/icons/chevron-up.svg'; -import { useSwapParamsSelector } from 'app/store/swap/selectors'; -import { T } from 'lib/i18n'; -import { AssetMetadataBase } from 'lib/metadata'; -import { ROUTING_FEE_RATIO } from 'lib/route3/constants'; -import { isSwapChains, Route3Chain } from 'lib/route3/interfaces'; - -import { LbPoolPart } from './lb-pool-part'; -import { SwapRouteItem } from './SwapRouteItem/SwapRouteItem'; - -interface Props { - isLbOutput: boolean; - isLbInput: boolean; - outputToken: AssetMetadataBase; - routingFeeIsTakenFromOutput: boolean; - className?: string; -} - -export const SwapRoute = memo( - ({ isLbInput, isLbOutput, routingFeeIsTakenFromOutput, outputToken, className }) => { - const [isVisible, setIsVisible] = useState(false); - - const { - data: { input, output, ...chains } - } = useSwapParamsSelector(); - - const chainsHeap = useMemo(() => { - let chainsHeapBeforeOutputFee: Route3Chain[] = []; - - if (isSwapChains(chains)) { - chainsHeapBeforeOutputFee = chains.chains; - } else { - const { tzbtcChain, xtzChain } = chains; - const tzbtcChains: Route3Chain[] = - tzbtcChain.chains.length === 0 - ? [ - { - input: tzbtcChain.input ?? '0', - output: tzbtcChain.output ?? '0', - hops: [] - } - ] - : tzbtcChain.chains; - const xtzChains: Route3Chain[] = - xtzChain.chains.length === 0 - ? [ - { - input: xtzChain.input ?? '0', - output: xtzChain.output ?? '0', - hops: [] - } - ] - : xtzChain.chains; - - chainsHeapBeforeOutputFee = tzbtcChains.concat(xtzChains); - } - - return routingFeeIsTakenFromOutput - ? chainsHeapBeforeOutputFee.map(chain => ({ - ...chain, - output: new BigNumber(chain.output) - .times(ROUTING_FEE_RATIO) - .toFixed(outputToken.decimals, BigNumber.ROUND_DOWN) - })) - : chainsHeapBeforeOutputFee; - }, [chains, routingFeeIsTakenFromOutput, outputToken.decimals]); - - const totalChains = chainsHeap.length; - - useEffect(() => { - if (totalChains === 0) { - setIsVisible(false); - } - }, [totalChains]); - - const totalHops = - chainsHeap.reduce((accum, chain) => accum + chain.hops.length, 0) + - ((isLbInput || isLbOutput) && chainsHeap.length > 0 ? 1 : 0); - const shouldShowRoute = isVisible && totalChains > 0; - - const outputAfterFee = useMemo( - () => - routingFeeIsTakenFromOutput && isDefined(output) - ? new BigNumber(output).times(ROUTING_FEE_RATIO).toFixed(outputToken.decimals, BigNumber.ROUND_DOWN) - : output, - [output, outputToken.decimals, routingFeeIsTakenFromOutput] - ); - - const hadleToggleVisible = () => setIsVisible(prev => !prev); - - const Chevron = isVisible ? ChevronUp : ChevronDown; - - return ( -
-

- - - - - - - - - -

- {shouldShowRoute && ( -
- {isLbInput && } -
- {chainsHeap.map((chain, index) => ( - - ))} -
- {isLbOutput && } -
- )} -
- ); - } -); diff --git a/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/SwapRouteItem.tsx b/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/SwapRouteItem.tsx deleted file mode 100644 index 26928c5b48..0000000000 --- a/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/SwapRouteItem.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { FC } from 'react'; - -import { ReactComponent as Separator } from 'app/icons/separator.svg'; -import { useSwapDexesSelector } from 'app/store/swap/selectors'; -import { Route3Chain } from 'lib/route3/interfaces'; - -import { HopItem } from './hop-item'; -import { SwapRouteAmounts } from './swap-route-amounts'; - -interface Props { - baseInput: string | undefined; - baseOutput: string | undefined; - chain: Route3Chain; - shouldShowInput: boolean; - shouldShowOutput: boolean; -} - -export const SwapRouteItem: FC = ({ chain, baseInput, baseOutput, shouldShowInput, shouldShowOutput }) => { - const { data: route3Dexes } = useSwapDexesSelector(); - - return ( -
- {shouldShowInput && } -
-
- -
- - {chain.hops.map((hop, index) => { - const dex = route3Dexes.find(dex => dex.id === hop.dex); - - const aToken = hop.forward ? dex?.token1 : dex?.token2; - const bToken = hop.forward ? dex?.token2 : dex?.token1; - - return ; - })} -
- - {shouldShowOutput && } -
- ); -}; diff --git a/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/hop-item.tsx b/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/hop-item.tsx deleted file mode 100644 index 9ddce885fb..0000000000 --- a/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/hop-item.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React, { FC } from 'react'; - -import { isDefined } from '@rnw-community/shared'; -import classNames from 'clsx'; - -import { useAppEnv } from 'app/env'; -import { AssetIcon } from 'app/templates/AssetIcon'; -import { Route3Dex } from 'lib/apis/route3/fetch-route3-dexes'; -import { Route3Token } from 'lib/apis/route3/fetch-route3-tokens'; -import { toTokenSlug, TEZ_TOKEN_SLUG } from 'lib/assets'; -import { getDexName } from 'lib/route3/utils/get-dex-name'; -import { DexTypeIcon } from 'lib/swap-router'; -import useTippy from 'lib/ui/useTippy'; - -interface Props { - dex: Route3Dex | undefined; - aToken: Route3Token | undefined; - bToken: Route3Token | undefined; - className?: string; -} - -export const HopItem: FC = ({ dex, aToken, bToken, className }) => { - const { popup } = useAppEnv(); - - const dexInfoDivRef = useTippy({ - trigger: 'mouseenter', - hideOnClick: false, - content: `Dex: ${getDexName(dex?.type)}`, - animation: 'shift-away-subtle' - }); - const tokenAInfoDivRef = useTippy({ - trigger: 'mouseenter', - hideOnClick: false, - content: `${aToken?.symbol}`, - animation: 'shift-away-subtle' - }); - const tokenBInfoDivRef = useTippy({ - trigger: 'mouseenter', - hideOnClick: false, - content: `${bToken?.symbol}`, - animation: 'shift-away-subtle' - }); - - return ( -
-
- -
-
-
- -
-
- -
-
-
- ); -}; - -const toAssetSlugLocal = (asset: Route3Token | nullish) => { - if (!isDefined(asset)) return ''; - - if (!isDefined(asset.contract)) return TEZ_TOKEN_SLUG; - - return toTokenSlug(asset.contract, asset.tokenId ?? undefined); -}; diff --git a/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/swap-route-amounts.tsx b/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/swap-route-amounts.tsx deleted file mode 100644 index dff725fdeb..0000000000 --- a/src/app/templates/SwapForm/SwapRoute/SwapRouteItem/swap-route-amounts.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React, { FC } from 'react'; - -import { BigNumber } from 'bignumber.js'; -import classNames from 'clsx'; - -import { kFormatter } from 'lib/utils/numbers'; - -interface Props { - amount: string; - baseAmount: string | undefined; - className?: string; -} - -const BASE = new BigNumber(100); -const PERCENTAGE_DECIMALS = 1; -const AMOUNT_DECIMALS = 2; - -const calculatePercentage = (base: string | undefined, part: string) => { - if (base === undefined) { - return; - } - - const amountToFormat = BASE.multipliedBy(part).dividedBy(base); - - if (amountToFormat.isGreaterThanOrEqualTo(BASE)) { - return BASE.toFixed(); - } - - return amountToFormat.toFixed(PERCENTAGE_DECIMALS); -}; - -export const SwapRouteAmounts: FC = ({ amount, baseAmount, className }) => { - return ( -
-
{kFormatter(Number(new BigNumber(amount).toFixed(AMOUNT_DECIMALS)))}
-
{calculatePercentage(baseAmount, amount)}%
-
- ); -}; diff --git a/src/app/templates/SwapForm/SwapRoute/lb-pool-part.tsx b/src/app/templates/SwapForm/SwapRoute/lb-pool-part.tsx deleted file mode 100644 index 837610cfb0..0000000000 --- a/src/app/templates/SwapForm/SwapRoute/lb-pool-part.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React, { FC, useMemo } from 'react'; - -import classNames from 'clsx'; - -import { ReactComponent as Separator } from 'app/icons/separator.svg'; -import { AssetImage } from 'app/templates/AssetImage'; -import { SIRS_TOKEN_METADATA } from 'lib/assets/known-tokens'; -import useTippy from 'lib/ui/useTippy'; - -import { SwapRouteAmounts } from './SwapRouteItem/swap-route-amounts'; - -interface Props { - isLbOutput: boolean; - amount: string | undefined; - totalChains: number; -} - -export const LbPoolPart: FC = ({ amount, isLbOutput, totalChains }) => { - const dexInfoDivRef = useTippy({ - trigger: 'mouseenter', - hideOnClick: false, - content: '3Route SIRS', - animation: 'shift-away-subtle' - }); - - const advancedLbPoolItemStyles = useMemo( - () => ({ height: 36 * totalChains + 8 * (totalChains - 1) - 6 }), - [totalChains] - ); - - return ( -
- - -
-
- -
- -
-
- -
-
-
-
- ); -}; diff --git a/src/lib/apis/route3/fetch-route3-dexes.ts b/src/lib/apis/route3/fetch-route3-dexes.ts index 2f87b070c4..85e9b50b80 100644 --- a/src/lib/apis/route3/fetch-route3-dexes.ts +++ b/src/lib/apis/route3/fetch-route3-dexes.ts @@ -13,10 +13,14 @@ export interface Route3Dex { export enum Route3DexTypeEnum { PlentyTokenToToken = 'PlentyTokenToToken', + PlentyTokenTez = 'PlentyTokenTez', PlentyTokenToTokenStable = 'PlentyTokenToTokenStable', PlentyTokenToTokenVolatile = 'PlentyTokenToTokenVolatile', PlentyCtezStable = 'PlentyCtezStable', + PlentyWrappedTokenBridgeSwap = 'PlentyWrappedTokenBridgeSwap', + PlentySwapV3 = 'PlentySwapV3', QuipuSwapTokenToTokenStable = 'QuipuSwapTokenToTokenStable', + QuipuSwapTokenToTokenStableV2 = 'QuipuSwapTokenToTokenStableV2', QuipuSwapTezToTokenFa12 = 'QuipuSwapTezToTokenFa12', QuipuSwapTezToTokenFa2 = 'QuipuSwapTezToTokenFa2', QuipuSwapTokenToToken = 'QuipuSwapTokenToToken', @@ -25,13 +29,19 @@ export enum Route3DexTypeEnum { DexterLb = 'DexterLb', FlatYouvesStable = 'FlatYouvesStable', FlatYouvesStableUXTZ = 'FlatYouvesStableUXTZ', + FlatYouvesCPMM = 'FlatYouvesCPMM', + YouvesTargetMultiToken2 = 'YouvesTargetMultiToken2', VortexTokenToTokenFa12 = 'VortexTokenToTokenFa12', VortexTokenToTokenFa2 = 'VortexTokenToTokenFa2', SpicyTokenToToken = 'SpicyTokenToToken', + SpicySwapStable = 'SpicySwapStable', WTZSwap = 'WTZSwap', wTEZSwap = 'wTEZSwap', CtezToXtz = 'CtezToXtz', - PlentyWrappedTokenBridgeSwap = 'PlentyWrappedTokenBridgeSwap' + oXTZSwap = 'oXTZSwap', + KordTezLend = 'KordTezLend', + SiriusRemoveLiquidityToTez = 'SiriusRemoveLiquidityToTez', + SiriusRemoveLiquidityToTzBtc = 'SiriusRemoveLiquidityToTzBtc' } export const fetchRoute3Dexes$ = () => diff --git a/src/lib/apis/route3/fetch-route3-swap-params.ts b/src/lib/apis/route3/fetch-route3-swap-params.ts index 5060cc8088..544cdc5769 100644 --- a/src/lib/apis/route3/fetch-route3-swap-params.ts +++ b/src/lib/apis/route3/fetch-route3-swap-params.ts @@ -1,10 +1,21 @@ -import { THREE_ROUTE_SIRS_TOKEN } from 'lib/assets/three-route-tokens'; +import axios from 'axios'; +import BigNumber from 'bignumber.js'; +import { intersection, transform } from 'lodash'; +import memoizee from 'memoizee'; + +import { THREE_ROUTE_SIRS_TOKEN, THREE_ROUTE_TEZ_TOKEN } from 'lib/assets/three-route-tokens'; +import { LIQUIDITY_BAKING_DEX_ADDRESS } from 'lib/constants'; import { EnvVars } from 'lib/env'; +import { BLOCK_DURATION } from 'lib/fixed-times'; import { + Route3LbSwapParamsRequest, Route3LiquidityBakingParamsResponse, Route3SwapParamsRequest, Route3TraditionalSwapParamsResponse } from 'lib/route3/interfaces'; +import { ONE_MINUTE_S } from 'lib/utils/numbers'; + +import { ROUTE3_BASE_URL } from './route3.api'; const parser = (origJSON: string): ReturnType => { const stringedJSON = origJSON @@ -14,13 +25,27 @@ const parser = (origJSON: string): ReturnType => { return JSON.parse(stringedJSON); }; -const fetchRoute3TraditionalSwapParams = ({ - fromSymbol, - toSymbol, - amount, - chainsLimit = 2 -}: Route3SwapParamsRequest): Promise => - fetch(`https://temple.3route.io/v3/swap/${fromSymbol}/${toSymbol}/${amount}?chainsLimit=${chainsLimit}`, { +function getRoute3ParametrizedUrlPart(params: Route3SwapParamsRequest): string; +function getRoute3ParametrizedUrlPart(params: Route3LbSwapParamsRequest): string; +function getRoute3ParametrizedUrlPart(params: Route3SwapParamsRequest | Route3LbSwapParamsRequest) { + const { fromSymbol, toSymbol, amount, toTokenDecimals, rpcUrl, ...queryParams } = params; + const searchParams = new URLSearchParams( + transform( + queryParams, + (res, value, key) => { + res[key] = String(value); + }, + {} + ) + ); + + return `/${fromSymbol}/${toSymbol}/${amount}?${searchParams.toString()}`; +} + +const fetchRoute3TraditionalSwapParams = ( + params: Route3SwapParamsRequest +): Promise => + fetch(`${ROUTE3_BASE_URL}/swap${getRoute3ParametrizedUrlPart(params)}`, { headers: { Authorization: EnvVars.TEMPLE_WALLET_ROUTE3_AUTH_TOKEN } @@ -28,21 +53,84 @@ const fetchRoute3TraditionalSwapParams = ({ .then(res => res.text()) .then(res => parser(res)); -const fetchRoute3LiquidityBakingParams = ({ - fromSymbol, - toSymbol, - amount, - chainsLimit = 2 -}: Route3SwapParamsRequest): Promise => - fetch(`https://temple.3route.io/v3/swap-sirs/${fromSymbol}/${toSymbol}/${amount}?chainsLimit=${chainsLimit}`, { +const getLbSubsidyCausedXtzDeviation = memoizee( + async (rpcUrl: string) => { + const currentBlockRpcBaseURL = `${rpcUrl}/chains/main/blocks/head/context`; + const [{ data: constants }, { data: rawSirsDexBalance }] = await Promise.all([ + axios.get<{ minimal_block_delay: string; liquidity_baking_subsidy: string }>( + `${currentBlockRpcBaseURL}/constants` + ), + axios.get(`${currentBlockRpcBaseURL}/contracts/${LIQUIDITY_BAKING_DEX_ADDRESS}/balance`) + ]); + const { minimal_block_delay: blockDuration = String(BLOCK_DURATION), liquidity_baking_subsidy: lbSubsidyPerMin } = + constants; + const lbSubsidyPerBlock = Math.floor(Number(lbSubsidyPerMin) / Math.floor(ONE_MINUTE_S / Number(blockDuration))); + + return lbSubsidyPerBlock / Number(rawSirsDexBalance); + }, + { promise: true, maxAge: 1000 * ONE_MINUTE_S * 5 } +); + +const fetchRoute3LiquidityBakingParams = ( + params: Route3LbSwapParamsRequest +): Promise => + fetch(`${ROUTE3_BASE_URL}/swap-sirs${getRoute3ParametrizedUrlPart(params)}`, { headers: { Authorization: EnvVars.TEMPLE_WALLET_ROUTE3_AUTH_TOKEN } }) .then(res => res.text()) - .then(res => parser(res)); + .then(async res => { + const { rpcUrl, fromSymbol, toSymbol, toTokenDecimals } = params; + const originalParams: Route3LiquidityBakingParamsResponse = parser(res); + + if ( + fromSymbol !== THREE_ROUTE_SIRS_TOKEN.symbol || + toSymbol === THREE_ROUTE_TEZ_TOKEN.symbol || + originalParams.output === undefined + ) { + return originalParams; + } + + // SIRS -> not XTZ swaps are likely to fail with tez.subtraction_underflow error, preventing it + try { + const lbSubsidyCausedXtzDeviation = await getLbSubsidyCausedXtzDeviation(rpcUrl); + const initialXtzInput = new BigNumber(originalParams.xtzHops[0].tokenInAmount); + const correctedXtzInput = initialXtzInput.times(1 - lbSubsidyCausedXtzDeviation).integerValue(); + const initialOutput = new BigNumber(originalParams.output); + // The difference between inputs is usually pretty small, so we can use the following formula + const correctedOutput = initialOutput + .times(correctedXtzInput) + .div(initialXtzInput) + .decimalPlaces(toTokenDecimals, BigNumber.ROUND_FLOOR); -export const fetchRoute3SwapParams = (params: Route3SwapParamsRequest) => - [params.fromSymbol, params.toSymbol].includes(THREE_ROUTE_SIRS_TOKEN.symbol) - ? fetchRoute3LiquidityBakingParams(params) - : fetchRoute3TraditionalSwapParams(params); + return { + ...originalParams, + output: correctedOutput.toString(), + xtzHops: [ + { + ...originalParams.xtzHops[0], + tokenInAmount: correctedXtzInput.toFixed() + } + ].concat(originalParams.xtzHops.slice(1)) + }; + } catch (err) { + console.error(err); + return originalParams; + } + }); + +export const fetchRoute3SwapParams = ({ fromSymbol, toSymbol, dexesLimit, ...restParams }: Route3SwapParamsRequest) => { + const isLbUnderlyingTokenSwap = intersection([fromSymbol, toSymbol], ['TZBTC', 'XTZ']).length > 0; + + return [fromSymbol, toSymbol].includes(THREE_ROUTE_SIRS_TOKEN.symbol) + ? fetchRoute3LiquidityBakingParams({ + fromSymbol, + toSymbol, + // XTZ <-> SIRS and TZBTC <-> SIRS swaps have either XTZ or TZBTC hops, so a total number of hops cannot exceed the limit + xtzDexesLimit: isLbUnderlyingTokenSwap ? dexesLimit : Math.ceil(dexesLimit / 2), + tzbtcDexesLimit: isLbUnderlyingTokenSwap ? dexesLimit : Math.floor(dexesLimit / 2), + ...restParams + }) + : fetchRoute3TraditionalSwapParams({ fromSymbol, toSymbol, dexesLimit, ...restParams }); +}; diff --git a/src/lib/apis/route3/route3.api.ts b/src/lib/apis/route3/route3.api.ts index ba544c775e..37571a4ee2 100644 --- a/src/lib/apis/route3/route3.api.ts +++ b/src/lib/apis/route3/route3.api.ts @@ -2,8 +2,10 @@ import axios from 'axios'; import { EnvVars } from 'lib/env'; +export const ROUTE3_BASE_URL = 'https://temple.3route.io/v4'; + export const route3Api = axios.create({ - baseURL: 'https://temple.3route.io/v3', + baseURL: ROUTE3_BASE_URL, headers: { Authorization: EnvVars.TEMPLE_WALLET_ROUTE3_AUTH_TOKEN } diff --git a/src/lib/assets/known-tokens.ts b/src/lib/assets/known-tokens.ts index 1cfe7a767d..09a79954e9 100644 --- a/src/lib/assets/known-tokens.ts +++ b/src/lib/assets/known-tokens.ts @@ -33,7 +33,7 @@ const DEPRECATED_TKEY_METADATA: TokenMetadata = { standard: TokenStandardsEnum.Fa2 }; -export const TZBTC_TOKEN_METADATA: TokenMetadata = { +const TZBTC_TOKEN_METADATA: TokenMetadata = { id: '0', address: 'KT1PWx2mnDueood7fEmfbBDKx1D9BAnnXitn', name: 'Tezos BTC', @@ -43,16 +43,6 @@ export const TZBTC_TOKEN_METADATA: TokenMetadata = { standard: TokenStandardsEnum.Fa12 }; -export const SIRS_TOKEN_METADATA: TokenMetadata = { - id: '0', - address: 'KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo', - name: 'Sirius', - symbol: 'SIRS', - decimals: 0, - thumbnailUri: 'ipfs://QmNXQPkRACxaR17cht5ZWaaKiQy46qfCwNVT5FGZy6qnyp', - standard: TokenStandardsEnum.Fa12 -}; - const PREDEFINED_MAINNET_TOKENS_METADATA: TokenMetadata[] = [ { id: '0', diff --git a/src/lib/assets/three-route-tokens.ts b/src/lib/assets/three-route-tokens.ts index d9da528910..9276f1d08f 100644 --- a/src/lib/assets/three-route-tokens.ts +++ b/src/lib/assets/three-route-tokens.ts @@ -8,3 +8,12 @@ export const THREE_ROUTE_SIRS_TOKEN: Route3Token = { tokenId: null, decimals: 0 }; + +export const THREE_ROUTE_TEZ_TOKEN: Route3Token = { + id: 0, + symbol: 'XTZ', + standard: Route3TokenStandardEnum.xtz, + contract: null, + tokenId: null, + decimals: 6 +}; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 98b1a03c3d..0b0e465d0b 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -49,3 +49,7 @@ export const MAX_SHOW_AGREEMENTS_COUNTER = 1; const isMacOS = /Mac OS/.test(navigator.userAgent); export const searchHotkey = ` (${isMacOS ? '⌘' : 'Ctrl + '}K)`; + +export const FEE_PER_GAS_UNIT = 0.1; + +export const LIQUIDITY_BAKING_DEX_ADDRESS = 'KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5'; diff --git a/src/lib/fixed-times.ts b/src/lib/fixed-times.ts index 49a64f19d2..b16c7713de 100644 --- a/src/lib/fixed-times.ts +++ b/src/lib/fixed-times.ts @@ -1,4 +1,4 @@ -export const BLOCK_DURATION = 15_000; +export const BLOCK_DURATION = 10_000; export const ASSETS_SYNC_INTERVAL = 4 * BLOCK_DURATION; diff --git a/src/lib/route3/constants.ts b/src/lib/route3/constants.ts index e27f5e31e8..7e7f0c341a 100644 --- a/src/lib/route3/constants.ts +++ b/src/lib/route3/constants.ts @@ -1,20 +1,23 @@ import { Route3Token, Route3TokenStandardEnum } from 'lib/apis/route3/fetch-route3-tokens'; import { TempleToken } from 'lib/assets/known-tokens'; -import { getPercentageRatio } from './utils/get-percentage-ratio'; - -export const ROUTE3_CONTRACT = 'KT1R7WEtNNim3YgkxPt8wPMczjH3eyhbJMtz'; -export const LIQUIDITY_BAKING_PROXY_CONTRACT = 'KT1WLWMMm9MywjCqnA8wBAYy9QhUE1LzfZ4j'; +export const ROUTE3_CONTRACT = 'KT1V5XKmeypanMS9pR65REpqmVejWBZURuuT'; +export const LIQUIDITY_BAKING_PROXY_CONTRACT = 'KT1DJRF7pTocLsoVgA9KQPBtrDrbzNUceSFK'; export const BURN_ADDREESS = 'tz1burnburnburnburnburnburnburjAYjjX'; export const ROUTING_FEE_ADDRESS = 'tz1UbRzhYjQKTtWYvGUWcRtVT4fN3NESDVYT'; -export const ROUTING_FEE_PERCENT = 0.6; -export const SWAP_CASHBACK_PERCENT = 0.3; -export const ROUTING_FEE_RATIO = getPercentageRatio(ROUTING_FEE_PERCENT); +export const ROUTING_FEE_RATIO = 0.006; +export const SWAP_CASHBACK_RATIO = 0.003; export const ROUTING_FEE_SLIPPAGE_RATIO = 0.995; -export const MAX_ROUTING_FEE_CHAINS = 1; export const SWAP_THRESHOLD_TO_GET_CASHBACK = 10; -export const ATOMIC_INPUT_THRESHOLD_FOR_FEE_FROM_INPUT = 286; +/** The measure of acceptable deviation of an input for cashback swap or an amount of tokens to burn or to send to + * `ROUTING_FEE_ADDRESS` from ideal caused by the discretion of tokens values. + */ +const MAX_FEE_OR_CASHBACK_DEVIATION_RATIO = 0.01; + +export const ATOMIC_INPUT_THRESHOLD_FOR_FEE_FROM_INPUT = Math.ceil( + 1 / MAX_FEE_OR_CASHBACK_DEVIATION_RATIO / Math.min(SWAP_CASHBACK_RATIO, ROUTING_FEE_RATIO - SWAP_CASHBACK_RATIO) +); export const TEMPLE_TOKEN: Route3Token = { id: 138, diff --git a/src/lib/route3/interfaces/index.ts b/src/lib/route3/interfaces/index.ts index 23b2d98c96..e288714e1d 100644 --- a/src/lib/route3/interfaces/index.ts +++ b/src/lib/route3/interfaces/index.ts @@ -3,56 +3,69 @@ import { BigNumber } from 'bignumber.js'; export interface Route3SwapParamsRequestRaw { fromSymbol: string; toSymbol: string; + toTokenDecimals: number; amount: string | undefined; - chainsLimit?: number; + dexesLimit: number; + /** Needed to make a correction of params if input is SIRS */ + rpcUrl: string; } -export interface Route3SwapParamsRequest { + +// TODO: add `showTree: boolean` when adding route view +interface Route3SwapParamsRequestBase { fromSymbol: string; toSymbol: string; + toTokenDecimals: number; amount: string; - chainsLimit?: number; + /** Needed to make a correction of params if input is SIRS */ + rpcUrl: string; +} + +export interface Route3SwapParamsRequest extends Route3SwapParamsRequestBase { + dexesLimit: number; +} + +export interface Route3LbSwapParamsRequest extends Route3SwapParamsRequestBase { + xtzDexesLimit: number; + tzbtcDexesLimit: number; } export interface Hop { - amount_opt: BigNumber | null; dex_id: number; code: number; - params: string; -} - -interface Route3Hop { - dex: number; - forward: boolean; + amount_from_token_in_reserves: BigNumber; + amount_from_trading_balance: BigNumber; + params: string | null; } -export interface Route3Chain { - input: string; - output: string; - hops: Array; +export interface Route3Hop { + dexId: number; + tokenInAmount: string; + tradingBalanceAmount: string; + code: number; + params: string | null; } export interface Route3TraditionalSwapParamsResponse { input: string | undefined; output: string | undefined; - chains: Array; + hops: Route3Hop[]; } export interface Route3LiquidityBakingParamsResponse { input: string | undefined; output: string | undefined; - tzbtcChain: Route3TraditionalSwapParamsResponse; - xtzChain: Route3TraditionalSwapParamsResponse; + tzbtcHops: Route3Hop[]; + xtzHops: Route3Hop[]; } -export type Route3SwapChains = Pick; +export type Route3SwapHops = Pick; -export type Route3LiquidityBakingChains = Pick; +export type Route3LiquidityBakingHops = Pick; export type Route3SwapParamsResponse = Route3TraditionalSwapParamsResponse | Route3LiquidityBakingParamsResponse; -export const isSwapChains = (chains: Route3SwapChains | Route3LiquidityBakingChains): chains is Route3SwapChains => - 'chains' in chains; +export const isSwapHops = (hops: Route3SwapHops | Route3LiquidityBakingHops): hops is Route3SwapHops => 'hops' in hops; export const isLiquidityBakingParamsResponse = ( response: Route3SwapParamsResponse -): response is Route3LiquidityBakingParamsResponse => 'tzbtcChain' in response && 'xtzChain' in response; +): response is Route3LiquidityBakingParamsResponse => 'tzbtcHops' in response && 'xtzHops' in response; diff --git a/src/lib/route3/utils/get-dex-name.ts b/src/lib/route3/utils/get-dex-name.ts index 8b17ce2272..0846df09f5 100644 --- a/src/lib/route3/utils/get-dex-name.ts +++ b/src/lib/route3/utils/get-dex-name.ts @@ -1,5 +1,7 @@ import { Route3DexTypeEnum } from 'lib/apis/route3/fetch-route3-dexes'; +// TODO: use this function to display a route +// ts-prune-ignore-next export const getDexName = (dexType: Route3DexTypeEnum | undefined) => { switch (dexType) { case Route3DexTypeEnum.QuipuSwapDex2: @@ -9,8 +11,12 @@ export const getDexName = (dexType: Route3DexTypeEnum | undefined) => { case Route3DexTypeEnum.QuipuSwapTokenToToken: return 'QuipuSwap Token to Token'; case Route3DexTypeEnum.QuipuSwapTokenToTokenStable: + case Route3DexTypeEnum.QuipuSwapTokenToTokenStableV2: return 'QuipuSwap Curve Like'; + case Route3DexTypeEnum.QuipuSwapV3: + return 'QuipuSwap V3'; case Route3DexTypeEnum.PlentyTokenToToken: + case Route3DexTypeEnum.PlentyTokenTez: case Route3DexTypeEnum.PlentyCtezStable: return 'Plenty'; case Route3DexTypeEnum.PlentyWrappedTokenBridgeSwap: @@ -19,19 +25,32 @@ export const getDexName = (dexType: Route3DexTypeEnum | undefined) => { return 'Plenty Stable Swap'; case Route3DexTypeEnum.PlentyTokenToTokenVolatile: return 'Plenty Volatile Swap'; + case Route3DexTypeEnum.PlentySwapV3: + return 'Plenty V3'; case Route3DexTypeEnum.DexterLb: return 'Dexter LB'; case Route3DexTypeEnum.FlatYouvesStable: + case Route3DexTypeEnum.FlatYouvesStableUXTZ: + case Route3DexTypeEnum.FlatYouvesCPMM: + case Route3DexTypeEnum.YouvesTargetMultiToken2: return 'Youves'; case Route3DexTypeEnum.VortexTokenToTokenFa12: case Route3DexTypeEnum.VortexTokenToTokenFa2: return 'Vortex'; case Route3DexTypeEnum.SpicyTokenToToken: return 'Spicy'; + case Route3DexTypeEnum.SpicySwapStable: + return 'Spicy Stable Swap'; case Route3DexTypeEnum.CtezToXtz: return 'Ctez'; case Route3DexTypeEnum.WTZSwap: return 'WTZ'; + case Route3DexTypeEnum.wTEZSwap: + return 'wTEZ'; + case Route3DexTypeEnum.oXTZSwap: + return 'oXTZ'; + case Route3DexTypeEnum.KordTezLend: + return 'Kord'; default: return 'Unknown dex'; diff --git a/src/lib/route3/utils/map-to-route3-hops.ts b/src/lib/route3/utils/map-to-route3-hops.ts index 6d436ca693..d836fbe46f 100644 --- a/src/lib/route3/utils/map-to-route3-hops.ts +++ b/src/lib/route3/utils/map-to-route3-hops.ts @@ -1,22 +1,20 @@ +import { MichelsonMap } from '@taquito/michelson-encoder'; import { BigNumber } from 'bignumber.js'; -import { Hop, Route3Chain } from 'lib/route3/interfaces'; -import { tokensToAtoms } from 'lib/temple/helpers'; +import { Hop, Route3Hop } from 'lib/route3/interfaces'; -export const mapToRoute3ExecuteHops = (chains: Array, decimals: number) => { - const hops = new Array(); +export const mapToRoute3ExecuteHops = (hops: Route3Hop[]): MichelsonMap => { + const result = new MichelsonMap(); - for (const chain of chains) { - for (let j = 0; j < chain.hops.length; j++) { - const hop = chain.hops[j]; - hops.push({ - code: (j === 0 ? 1 : 0) + (hop.forward ? 2 : 0), - dex_id: hop.dex, - amount_opt: j === 0 ? tokensToAtoms(new BigNumber(chain.input), decimals) : null, - params: '' - }); - } - } + hops.forEach(({ dexId, tokenInAmount, tradingBalanceAmount, code, params }, index) => + result.set(index.toString(), { + dex_id: dexId, + code, + amount_from_token_in_reserves: new BigNumber(tokenInAmount), + amount_from_trading_balance: new BigNumber(tradingBalanceAmount), + params: params ?? '' + }) + ); - return hops; + return result; }; diff --git a/src/lib/swap-router/components/DexTypeIcon/DexTypeIcon.tsx b/src/lib/swap-router/components/DexTypeIcon/DexTypeIcon.tsx index a71e131438..930c65ba61 100644 --- a/src/lib/swap-router/components/DexTypeIcon/DexTypeIcon.tsx +++ b/src/lib/swap-router/components/DexTypeIcon/DexTypeIcon.tsx @@ -5,10 +5,13 @@ import { Route3DexTypeEnum } from 'lib/apis/route3/fetch-route3-dexes'; import { ReactComponent as CtezIcon } from './icons/ctez-icon.svg'; import DexterLogoSrc from './icons/dexter.png'; +import KordLogoSrc from './icons/kord.png'; +import { ReactComponent as OxtzIcon } from './icons/oxtz.svg'; import { ReactComponent as PlentyIcon } from './icons/plenty.svg'; import { ReactComponent as QuipuSwapIcon } from './icons/quipu-swap-icon.svg'; import { ReactComponent as SpicyIcon } from './icons/spicy.svg'; import { ReactComponent as VortexIcon } from './icons/vortex.svg'; +import { ReactComponent as WtezIcon } from './icons/wtez.svg'; import WtzLogoSrc from './icons/wtz.png'; import { ReactComponent as YouvesIcon } from './icons/youves.svg'; @@ -16,6 +19,8 @@ interface Props { dexType: Route3DexTypeEnum | null; } +// TODO: use this component to display a route +// ts-prune-ignore-next export const DexTypeIcon: FC = ({ dexType }) => { switch (dexType) { case Route3DexTypeEnum.QuipuSwapDex2: @@ -23,29 +28,40 @@ export const DexTypeIcon: FC = ({ dexType }) => { case Route3DexTypeEnum.QuipuSwapTezToTokenFa2: case Route3DexTypeEnum.QuipuSwapTokenToToken: case Route3DexTypeEnum.QuipuSwapTokenToTokenStable: + case Route3DexTypeEnum.QuipuSwapTokenToTokenStableV2: case Route3DexTypeEnum.QuipuSwapV3: return ; case Route3DexTypeEnum.PlentyCtezStable: case Route3DexTypeEnum.PlentyTokenToToken: + case Route3DexTypeEnum.PlentyTokenTez: case Route3DexTypeEnum.PlentyTokenToTokenStable: case Route3DexTypeEnum.PlentyTokenToTokenVolatile: case Route3DexTypeEnum.PlentyWrappedTokenBridgeSwap: + case Route3DexTypeEnum.PlentySwapV3: return ; case Route3DexTypeEnum.FlatYouvesStable: case Route3DexTypeEnum.FlatYouvesStableUXTZ: + case Route3DexTypeEnum.FlatYouvesCPMM: + case Route3DexTypeEnum.YouvesTargetMultiToken2: return ; case Route3DexTypeEnum.VortexTokenToTokenFa12: case Route3DexTypeEnum.VortexTokenToTokenFa2: return ; case Route3DexTypeEnum.SpicyTokenToToken: + case Route3DexTypeEnum.SpicySwapStable: return ; case Route3DexTypeEnum.CtezToXtz: return ; case Route3DexTypeEnum.DexterLb: return Dexter logo; case Route3DexTypeEnum.WTZSwap: + return WTZ logo; case Route3DexTypeEnum.wTEZSwap: - return Dexter logo; + return ; + case Route3DexTypeEnum.oXTZSwap: + return ; + case Route3DexTypeEnum.KordTezLend: + return Kord logo; default: return ; diff --git a/src/lib/swap-router/components/DexTypeIcon/icons/kord.png b/src/lib/swap-router/components/DexTypeIcon/icons/kord.png new file mode 100644 index 0000000000000000000000000000000000000000..45d6807a1fb90a2e69427034ab1741939b8001a3 GIT binary patch literal 1722 zcmV;r21WUaP)OK|e?^@59{GC^p_ z%hkKU%y)sC@$&V_&e))*xP*+Pa(k6=JQ z{;rUaU{GX03`%DgrP91ONg6VB2$%u-{h@kS7I{?*vfECyPK*G+T{QWf_z*yi`u(G%-=>L*0 z7I-{lfCyMwS@da`>AL}<09UaN05;KvfP9otIPCGi3xJve7!M&I0B!{!004!wYyFS) z`5Mm3A+ z2tW%_L8+A11tfZ$uRXXAF&>W}VLXP=U0~}90I+?p>cC#N>t2LAw> z+;gl!2!P|6c*qLYcH<@hK(|Ya@bw7>tbhQ%Kj8TA(xHI?tYGb$R3IMQ^Zf1$v{AEx zeRyT0zP%qi0V!C69sn>u2tbWor^8_ILO#Axi?9rU^@w#70J4*OfakcEQ9u^j`1Moy zx~TzcYwJg>8LR*Z3xR;9ISlN1CmB4%fe7?(}{CbEA%wb{=`SUC8L-Zh)vdBZWz#OP|1VA1d zz(@Z4Q`!g>Y*=O$RUaC_bGAVCvNmC4JS2eGN-V&wfCM1H3)q5y4F=R8bP15}1IV2s zB|IYm;2|hjw-V@~oJQKjZvudP4anIoWg-Bm1gIbd%SZyq0^c$sprI>xty;0b63~KE z)>*N@4=@VE!*}voH8KLuShEOV6N3PCt^f%WX^*#%FM!xa)Vg5~R6l?&CGpT~CK4bD zj#^v!K&=D=OdAYT{+ogm5P<`w&zre86#)60KlH~5_aV1I3U39|hhO15!x+ooK0JUJ zjYdP>MP?&t4|n3Bs@uSf79oc!oo58Voj}89+ + + + diff --git a/src/lib/swap-router/components/DexTypeIcon/icons/wtez.svg b/src/lib/swap-router/components/DexTypeIcon/icons/wtez.svg new file mode 100644 index 0000000000..560bc4b4de --- /dev/null +++ b/src/lib/swap-router/components/DexTypeIcon/icons/wtez.svg @@ -0,0 +1,5 @@ + + + + diff --git a/src/lib/swap-router/index.ts b/src/lib/swap-router/index.ts deleted file mode 100644 index d101e77d22..0000000000 --- a/src/lib/swap-router/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { DexTypeIcon } from './components/DexTypeIcon/DexTypeIcon'; diff --git a/src/lib/temple/__tests__/helpers.test.ts b/src/lib/temple/__tests__/helpers.test.ts index 7e4fabfe0c..f7a2b8ecbf 100644 --- a/src/lib/temple/__tests__/helpers.test.ts +++ b/src/lib/temple/__tests__/helpers.test.ts @@ -24,7 +24,7 @@ describe('Helpers', () => { expect(atomsValue.toFixed()).toBe('1000000000000'); }); - it('atomsToTokens', async () => { + it('formatOpParamsBeforeSend', async () => { let params: any = { kind: 'transaction', script: {} }; expect(Helpers.formatOpParamsBeforeSend(params)).toBe(params); @@ -41,6 +41,14 @@ describe('Helpers', () => { a: 'A', init: { b: 'B' } }); + + params = { + kind: 'transaction' + }; + expect(Helpers.formatOpParamsBeforeSend(params, 'source')).toStrictEqual({ + kind: 'transaction', + source: 'source' + }); }); it('isAddressValid', async () => { diff --git a/src/lib/temple/activity-new/fetch.ts b/src/lib/temple/activity-new/fetch.ts index f32dc31eff..d37292362d 100644 --- a/src/lib/temple/activity-new/fetch.ts +++ b/src/lib/temple/activity-new/fetch.ts @@ -2,6 +2,7 @@ import type { TzktApiChainId, TzktOperation } from 'lib/apis/tzkt'; import * as TZKT from 'lib/apis/tzkt'; import { TEZ_TOKEN_SLUG } from 'lib/assets'; import { detectTokenStandard } from 'lib/assets/standards'; +import { LIQUIDITY_BAKING_DEX_ADDRESS } from 'lib/constants'; import { ReactiveTezosToolkit } from 'lib/temple/front'; import { TempleAccount } from 'lib/temple/types'; import { filterUnique } from 'lib/utils'; @@ -9,8 +10,6 @@ import { filterUnique } from 'lib/utils'; import type { Activity, OperationsGroup } from './types'; import { operationsGroupToActivity } from './utils'; -const LIQUIDITY_BAKING_DEX_ADDRESS = 'KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5'; - export default async function fetchActivities( chainId: TzktApiChainId, account: TempleAccount, diff --git a/src/lib/temple/back/dryrun.ts b/src/lib/temple/back/dryrun.ts index 583d951d9c..783f29789c 100644 --- a/src/lib/temple/back/dryrun.ts +++ b/src/lib/temple/back/dryrun.ts @@ -2,6 +2,7 @@ import { localForger } from '@taquito/local-forging'; import { ForgeOperationsParams } from '@taquito/rpc'; import { Estimate, TezosToolkit } from '@taquito/taquito'; +import { FEE_PER_GAS_UNIT } from 'lib/constants'; import { formatOpParamsBeforeSend, michelEncoder, loadFastRpcClient } from 'lib/temple/helpers'; import { ReadOnlySigner } from 'lib/temple/read-only-signer'; @@ -22,8 +23,6 @@ export interface DryRunResult { }; } -const FEE_PER_GAS_UNIT = 0.1; - export async function dryRunOpParams({ opParams, networkRpc, @@ -44,7 +43,7 @@ export async function dryRunOpParams({ let estimates: Estimate[] | undefined; let error: any = []; try { - const formatted = opParams.map(formatOpParamsBeforeSend); + const formatted = opParams.map(operation => formatOpParamsBeforeSend(operation, sourcePkh)); const result = [ await tezos.estimate.batch(formatted).catch(e => ({ ...e, isError: true })), await tezos.contract diff --git a/src/lib/temple/back/vault/index.ts b/src/lib/temple/back/vault/index.ts index 8b46b77239..8167a244e0 100644 --- a/src/lib/temple/back/vault/index.ts +++ b/src/lib/temple/back/vault/index.ts @@ -522,7 +522,7 @@ export class Vault { tezos.setSignerProvider(signer); tezos.setForgerProvider(new CompositeForger([tezos.getFactory(RpcForger)(), localForger])); tezos.setPackerProvider(michelEncoder); - return tezos.contract.batch(opParams.map(formatOpParamsBeforeSend)); + return tezos.contract.batch(opParams.map(operation => formatOpParamsBeforeSend(operation, accPublicKeyHash))); }); try { diff --git a/src/lib/temple/front/client.ts b/src/lib/temple/front/client.ts index 1e23009c8b..e9f587b3db 100644 --- a/src/lib/temple/front/client.ts +++ b/src/lib/temple/front/client.ts @@ -5,6 +5,7 @@ import { createOriginationOperation, createSetDelegateOperation, createIncreasePaidStorageOperation, + createTransferTicketOperation, createTransferOperation, WalletDelegateParams, WalletOriginateParams, @@ -13,7 +14,8 @@ import { WalletStakeParams, WalletUnstakeParams, WalletFinalizeUnstakeParams, - Signer + Signer, + WalletTransferTicketParams } from '@taquito/taquito'; import { buf2hex } from '@taquito/utils'; import constate from 'constate'; @@ -410,6 +412,11 @@ class TaquitoWallet implements WalletProvider { return getPublicKey(this.pkh); } + async mapTransferTicketParamsToWalletParams(params: () => Promise) { + const walletParams = await params(); + return withoutFeesOverride(walletParams, await createTransferTicketOperation(walletParams)); + } + async mapIncreasePaidStorageWalletParams(params: () => Promise) { const walletParams = await params(); return withoutFeesOverride(walletParams, await createIncreasePaidStorageOperation(walletParams)); diff --git a/src/lib/temple/helpers.ts b/src/lib/temple/helpers.ts index a657ff2fd6..52a8c65762 100644 --- a/src/lib/temple/helpers.ts +++ b/src/lib/temple/helpers.ts @@ -46,11 +46,11 @@ export function mutezToTz(mutez: BigNumber.Value) { } export function atomsToTokens(x: BigNumber.Value, decimals: number) { - return new BigNumber(x).integerValue().div(new BigNumber(10).pow(decimals)); + return new BigNumber(x).integerValue().shiftedBy(-decimals); } export function tokensToAtoms(x: BigNumber.Value, decimals: number) { - return new BigNumber(x).times(10 ** decimals).integerValue(); + return new BigNumber(x).shiftedBy(decimals).integerValue(); } export function isAddressValid(address: string) { @@ -63,7 +63,7 @@ export function isKTAddress(address: string) { export const isValidContractAddress = (address: string) => isAddressValid(address) && isKTAddress(address); -export function formatOpParamsBeforeSend(params: any) { +export function formatOpParamsBeforeSend(params: any, sourcePkh?: string) { if (params.kind === 'origination' && params.script) { const newParams = { ...params, ...params.script }; newParams.init = newParams.storage; @@ -71,6 +71,11 @@ export function formatOpParamsBeforeSend(params: any) { delete newParams.storage; return newParams; } + + if (params.kind === 'transaction' && sourcePkh) { + return { ...params, source: sourcePkh }; + } + return params; } diff --git a/src/lib/utils/numbers.ts b/src/lib/utils/numbers.ts index daca8ed2cb..3ee405537e 100644 --- a/src/lib/utils/numbers.ts +++ b/src/lib/utils/numbers.ts @@ -10,6 +10,10 @@ const BILLION = 1_000_000_000; export const ONE_HOUR_MS = 3600_000; +export const ONE_MINUTE_S = 60; + +// TODO: Use this formatter for inputs in a swap route view +// ts-prune-ignore-next export const kFormatter = (num: number): string => { if (isNaN(num)) { return ''; diff --git a/src/lib/utils/swap.utils.ts b/src/lib/utils/swap.utils.ts index c25ea3dbc9..df1ace906b 100644 --- a/src/lib/utils/swap.utils.ts +++ b/src/lib/utils/swap.utils.ts @@ -1,18 +1,17 @@ -import { ContractMethod, ContractProvider, TezosToolkit, TransferParams, Wallet } from '@taquito/taquito'; +import { ContractMethodObject, ContractProvider, OpKind, TezosToolkit, TransferParams, Wallet } from '@taquito/taquito'; import { BigNumber } from 'bignumber.js'; import { Route3Token } from 'lib/apis/route3/fetch-route3-tokens'; -import { TZBTC_TOKEN_METADATA } from 'lib/assets/known-tokens'; -import { THREE_ROUTE_SIRS_TOKEN } from 'lib/assets/three-route-tokens'; -import { TEZOS_METADATA } from 'lib/metadata'; +import { FEE_PER_GAS_UNIT } from 'lib/constants'; import { APP_ID, ATOMIC_INPUT_THRESHOLD_FOR_FEE_FROM_INPUT, LIQUIDITY_BAKING_PROXY_CONTRACT, ROUTE3_CONTRACT, - ROUTING_FEE_RATIO + ROUTING_FEE_RATIO, + SWAP_CASHBACK_RATIO } from 'lib/route3/constants'; -import { isSwapChains, Route3LiquidityBakingChains, Route3SwapChains } from 'lib/route3/interfaces'; +import { isSwapHops, Route3LiquidityBakingHops, Route3SwapHops } from 'lib/route3/interfaces'; import { isRoute3GasToken } from 'lib/route3/utils/assets.utils'; import { mapToRoute3ExecuteHops } from 'lib/route3/utils/map-to-route3-hops'; import { loadContract } from 'lib/temple/contract'; @@ -20,94 +19,150 @@ import { loadContract } from 'lib/temple/contract'; import { getTransferPermissions } from './get-transfer-permissions'; import { ZERO } from './numbers'; +const GAS_CAP_PER_INTERNAL_OPERATION = 1000; + +const isSwapTransaction = (params: TransferParams) => + params.to === ROUTE3_CONTRACT || params.to === LIQUIDITY_BAKING_PROXY_CONTRACT; + +/** + * Estimates a batch of transfers and applies the estimations to the transfer params. If the estimation fails, + * the transfer params are returned as is. + * @param transfersParams The transfer params to estimate and apply the estimations to. + * @param tezos The TezosToolkit instance to use for the estimations. + * @param sourcePkh The public key hash of the sender. + * @param gasCapFn A function that returns the gas cap for a given transfer params. + */ +const withBatchEstimations = async ( + transfersParams: TransferParams[], + tezos: TezosToolkit, + sourcePkh: string, + gasCapFn: (params: TransferParams) => number = () => GAS_CAP_PER_INTERNAL_OPERATION +) => { + if (transfersParams.length === 0) { + return []; + } + + try { + const estimations = await tezos.estimate.batch( + transfersParams.map(params => ({ kind: OpKind.TRANSACTION, source: sourcePkh, ...params })) + ); + + return transfersParams.map((params, index) => { + const { suggestedFeeMutez, storageLimit, gasLimit } = estimations[index]; + const gasCap = gasCapFn(params); + + return { + ...params, + fee: suggestedFeeMutez + Math.ceil(gasCap * FEE_PER_GAS_UNIT), + storageLimit, + gasLimit: gasLimit + gasCap + }; + }); + } catch (e) { + console.error(e); + + return transfersParams; + } +}; + export const getSwapTransferParams = async ( fromRoute3Token: Route3Token, toRoute3Token: Route3Token, inputAmountAtomic: BigNumber, minimumReceivedAtomic: BigNumber, - chains: Route3SwapChains | Route3LiquidityBakingChains, + chains: Route3LiquidityBakingHops | Route3SwapHops, tezos: TezosToolkit, accountPkh: string ) => { - const resultParams: Array = []; - let swapMethod: ContractMethod; + const swapParams: Array = []; + let swapMethod: ContractMethodObject; - if (isSwapChains(chains)) { + if (isSwapHops(chains)) { const swapContract = await loadContract(tezos, ROUTE3_CONTRACT, false); - swapMethod = swapContract.methods.execute( - fromRoute3Token.id, - toRoute3Token.id, - minimumReceivedAtomic, - accountPkh, - mapToRoute3ExecuteHops(chains.chains, fromRoute3Token.decimals), - APP_ID - ); + swapMethod = swapContract.methodsObject.execute({ + token_in_id: fromRoute3Token.id, + token_out_id: toRoute3Token.id, + min_out: minimumReceivedAtomic, + receiver: accountPkh, + hops: mapToRoute3ExecuteHops(chains.hops), + app_id: APP_ID + }); } else { const liquidityBakingProxyContract = await loadContract(tezos, LIQUIDITY_BAKING_PROXY_CONTRACT, false); - const isDivestingFromLb = fromRoute3Token.symbol === THREE_ROUTE_SIRS_TOKEN.symbol; - swapMethod = liquidityBakingProxyContract.methods.swap( - fromRoute3Token.id, - toRoute3Token.id, - mapToRoute3ExecuteHops( - chains.xtzChain.chains, - isDivestingFromLb ? TEZOS_METADATA.decimals : fromRoute3Token.decimals - ), - mapToRoute3ExecuteHops( - chains.tzbtcChain.chains, - isDivestingFromLb ? TZBTC_TOKEN_METADATA.decimals : fromRoute3Token.decimals - ), - inputAmountAtomic, - minimumReceivedAtomic, - accountPkh, - APP_ID - ); + swapMethod = liquidityBakingProxyContract.methodsObject.swap({ + token_in_id: fromRoute3Token.id, + token_out_id: toRoute3Token.id, + tez_hops: mapToRoute3ExecuteHops(chains.xtzHops), + tzbtc_hops: mapToRoute3ExecuteHops(chains.tzbtcHops), + amount_in: inputAmountAtomic, + min_out: minimumReceivedAtomic, + receiver: accountPkh, + app_id: APP_ID + }); } if (fromRoute3Token.symbol.toLowerCase() === 'xtz') { - resultParams.push( + swapParams.push( swapMethod.toTransferParams({ amount: inputAmountAtomic.toNumber(), mutez: true }) ); } else { - resultParams.push(swapMethod.toTransferParams()); + swapParams.push(swapMethod.toTransferParams()); } const { approve, revoke } = await getTransferPermissions( tezos, - isSwapChains(chains) ? ROUTE3_CONTRACT : LIQUIDITY_BAKING_PROXY_CONTRACT, + isSwapHops(chains) ? ROUTE3_CONTRACT : LIQUIDITY_BAKING_PROXY_CONTRACT, accountPkh, fromRoute3Token, inputAmountAtomic ); - resultParams.unshift(...approve); - resultParams.push(...revoke); + const [swapWithApproveParams, revokeParams] = await Promise.all([ + withBatchEstimations(approve.concat(swapParams), tezos, accountPkh, params => { + const approximateInternalOperationsCount = isSwapTransaction(params) + ? isSwapHops(chains) + ? 1 + chains.hops.length + : 2 + chains.xtzHops.length + chains.tzbtcHops.length + : 1; + + return approximateInternalOperationsCount * GAS_CAP_PER_INTERNAL_OPERATION; + }), + withBatchEstimations(revoke, tezos, accountPkh) + ]); - return resultParams; + return swapWithApproveParams.concat(revokeParams); }; -export const calculateRoutingInputAndFeeFromInput = (inputAmount: BigNumber | undefined) => { +export const calculateSidePaymentsFromInput = (inputAmount: BigNumber | undefined) => { const swapInputAtomic = (inputAmount ?? ZERO).integerValue(BigNumber.ROUND_DOWN); const shouldTakeFeeFromInput = swapInputAtomic.gte(ATOMIC_INPUT_THRESHOLD_FOR_FEE_FROM_INPUT); - const swapInputMinusFeeAtomic = shouldTakeFeeFromInput - ? swapInputAtomic.times(ROUTING_FEE_RATIO).integerValue(BigNumber.ROUND_DOWN) - : swapInputAtomic; - const routingFeeFromInputAtomic = swapInputAtomic.minus(swapInputMinusFeeAtomic); + const inputFeeAtomic = shouldTakeFeeFromInput + ? swapInputAtomic.times(ROUTING_FEE_RATIO).integerValue(BigNumber.ROUND_CEIL) + : ZERO; + const cashbackSwapInputAtomic = shouldTakeFeeFromInput + ? swapInputAtomic.times(SWAP_CASHBACK_RATIO).integerValue() + : ZERO; + const swapInputMinusFeeAtomic = swapInputAtomic.minus(inputFeeAtomic); return { - swapInputMinusFeeAtomic, - routingFeeFromInputAtomic + inputFeeAtomic, + cashbackSwapInputAtomic, + swapInputMinusFeeAtomic }; }; -export const calculateFeeFromOutput = (inputAmount: BigNumber | undefined, outputAmount: BigNumber) => - (inputAmount ?? ZERO).gte(ATOMIC_INPUT_THRESHOLD_FOR_FEE_FROM_INPUT) +export const calculateOutputFeeAtomic = (inputAmount: BigNumber | undefined, outputAmount: BigNumber) => { + const swapInputAtomic = (inputAmount ?? ZERO).integerValue(BigNumber.ROUND_DOWN); + + return swapInputAtomic.gte(ATOMIC_INPUT_THRESHOLD_FOR_FEE_FROM_INPUT) ? ZERO - : outputAmount.times(1 - ROUTING_FEE_RATIO).integerValue(BigNumber.ROUND_UP); + : outputAmount.times(ROUTING_FEE_RATIO).integerValue(BigNumber.ROUND_CEIL); +}; -export const getRoutingFeeTransferParams = async ( +const getRoutingFeeTransferParamsBeforeEstimate = async ( token: Route3Token, feeAmountAtomic: BigNumber, senderPublicKeyHash: string, @@ -132,14 +187,14 @@ export const getRoutingFeeTransferParams = async ( if (token.standard === 'fa12') { return [ - assetContract.methods - .transfer(senderPublicKeyHash, routingFeeAddress, feeAmountAtomic.toNumber()) + assetContract.methodsObject + .transfer({ from: senderPublicKeyHash, to: routingFeeAddress, value: feeAmountAtomic }) .toTransferParams({ mutez: true }) ]; } if (token.standard === 'fa2') { return [ - assetContract.methods + assetContract.methodsObject .transfer([ { from_: senderPublicKeyHash, @@ -147,7 +202,7 @@ export const getRoutingFeeTransferParams = async ( { to_: routingFeeAddress, token_id: token.tokenId, - amount: feeAmountAtomic.toNumber() + amount: feeAmountAtomic } ] } @@ -158,3 +213,22 @@ export const getRoutingFeeTransferParams = async ( return []; }; + +export const getRoutingFeeTransferParams = async ( + token: Route3Token, + feeAmountAtomic: BigNumber, + senderPublicKeyHash: string, + routingFeeAddress: string, + tezos: TezosToolkit +) => + withBatchEstimations( + await getRoutingFeeTransferParamsBeforeEstimate( + token, + feeAmountAtomic, + senderPublicKeyHash, + routingFeeAddress, + tezos + ), + tezos, + senderPublicKeyHash + ); diff --git a/yarn.lock b/yarn.lock index 228ef3e79d..0cfbd31c47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2576,6 +2576,26 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jsonjoy.com/base64@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" + integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== + +"@jsonjoy.com/json-pack@^1.0.3": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz#33ca57ee29d12feef540f2139225597469dec894" + integrity sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg== + dependencies: + "@jsonjoy.com/base64" "^1.1.1" + "@jsonjoy.com/util" "^1.1.2" + hyperdyperid "^1.2.0" + thingies "^1.20.0" + +"@jsonjoy.com/util@^1.1.2", "@jsonjoy.com/util@^1.3.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-1.5.0.tgz#6008e35b9d9d8ee27bc4bfaa70c8cbf33a537b4c" + integrity sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA== + "@ledgerhq/devices@^5.34.0", "@ledgerhq/devices@^5.51.1": version "5.51.1" resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.51.1.tgz#d741a4a5d8f17c2f9d282fd27147e6fe1999edb7" @@ -2596,6 +2616,16 @@ rxjs "^7.8.1" semver "^7.3.5" +"@ledgerhq/devices@^8.4.4": + version "8.4.4" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-8.4.4.tgz#0d195c1650fe57da2fad7f0d9074a0190947cd6f" + integrity sha512-sz/ryhe/R687RHtevIE9RlKaV8kkKykUV4k29e7GAVwzHX1gqG+O75cu1NCJUHLbp3eABV5FdvZejqRUlLis9A== + dependencies: + "@ledgerhq/errors" "^6.19.1" + "@ledgerhq/logs" "^6.12.0" + rxjs "^7.8.1" + semver "^7.3.5" + "@ledgerhq/errors@^5.34.0", "@ledgerhq/errors@^5.50.0": version "5.50.0" resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.50.0.tgz#e3a6834cb8c19346efca214c1af84ed28e69dad9" @@ -2606,6 +2636,11 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.16.4.tgz#a38baffe8b096d9fff3ad839cadb55704c8d8e7b" integrity sha512-M57yFaLYSN+fZCX0E0zUqOmrV6eipK+s5RhijHoUNlHUqrsvUz7iRQgpd5gRgHB5VkIjav7KdaZjKiWGcHovaQ== +"@ledgerhq/errors@^6.19.1": + version "6.19.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.19.1.tgz#d9ac45ad4ff839e468b8f63766e665537aaede58" + integrity sha512-75yK7Nnit/Gp7gdrJAz0ipp31CCgncRp+evWt6QawQEtQKYEDfGo10QywgrrBBixeRxwnMy1DP6g2oCWRf1bjw== + "@ledgerhq/hw-transport-http@^6.29.6": version "6.29.6" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-http/-/hw-transport-http-6.29.6.tgz#983c966613391a6f91800e867378f9757e209f69" @@ -2656,7 +2691,7 @@ "@ledgerhq/errors" "^5.50.0" events "^3.3.0" -"@ledgerhq/hw-transport@^6.30.5", "@ledgerhq/hw-transport@^6.30.6": +"@ledgerhq/hw-transport@^6.30.6": version "6.30.6" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.30.6.tgz#c6d84672ac4828f311831998f4101ea205215a6d" integrity sha512-fT0Z4IywiuJuZrZE/+W0blkV5UCotDPFTYKLkKCLzYzuE6javva7D/ajRaIeR+hZ4kTmKF4EqnsmDCXwElez+w== @@ -2666,6 +2701,16 @@ "@ledgerhq/logs" "^6.12.0" events "^3.3.0" +"@ledgerhq/hw-transport@^6.31.4": + version "6.31.4" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.31.4.tgz#9b23a6de4a4caaa5c24b149c2dea8adde46f0eb1" + integrity sha512-6c1ir/cXWJm5dCWdq55NPgCJ3UuKuuxRvf//Xs36Bq9BwkV2YaRQhZITAkads83l07NAdR16hkTWqqpwFMaI6A== + dependencies: + "@ledgerhq/devices" "^8.4.4" + "@ledgerhq/errors" "^6.19.1" + "@ledgerhq/logs" "^6.12.0" + events "^3.3.0" + "@ledgerhq/logs@^5.30.0", "@ledgerhq/logs@^5.50.0": version "5.50.0" resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.50.0.tgz#29c6419e8379d496ab6d0426eadf3c4d100cd186" @@ -2676,6 +2721,11 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-6.12.0.tgz#ad903528bf3687a44da435d7b2479d724d374f5d" integrity sha512-ExDoj1QV5eC6TEbMdLUMMk9cfvNKhhv5gXol4SmULRVCx/3iyCPhJ74nsb3S0Vb+/f+XujBEj3vQn5+cwS0fNA== +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" + integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== + "@lit-labs/ssr-dom-shim@^1.0.0", "@lit-labs/ssr-dom-shim@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.1.tgz#64df34e2f12e68e78ac57e571d25ec07fa460ca9" @@ -3441,94 +3491,94 @@ "@svgr/plugin-jsx" "^6.4.0" "@svgr/plugin-svgo" "^6.3.1" -"@taquito/beacon-wallet@20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/beacon-wallet/-/beacon-wallet-20.0.0.tgz#5a8eaaaa440a9897ed2dc0177df337da4ecacc5a" - integrity sha512-Ks2iPaanQHRUI+nYReAVZod3s9knLAZwLShrrR9oH/QKxPRtm568ojckQ1iZmOC0VTII/l89F+fkGbCRLSBLIA== +"@taquito/beacon-wallet@20.0.0", "@taquito/beacon-wallet@20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/beacon-wallet/-/beacon-wallet-20.1.0.tgz#4e70d2ec759f110350a9ab7a5201bc57bb938a75" + integrity sha512-bMj9kUJNrAIgjhAiw7wW5CkUmrA+VhA5qCA2oY5ugHfH8ngQK8VNsE6wMliNmrp2We+NhNw1lBjwvz9hw7gQMA== dependencies: "@airgap/beacon-dapp" "^4.2.2" - "@taquito/core" "^20.0.0" - "@taquito/taquito" "^20.0.0" - -"@taquito/contracts-library@20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/contracts-library/-/contracts-library-20.0.0.tgz#ffa3c93706e7b2b6e3d7ccf637b4c4b5629ade8a" - integrity sha512-x8YPg4C/FupehA7YW/YX79OPTeA27APrIt1GA+4UE+Yc7UcQ78maKOolLqX4LSdzSDmDSUkBarTeEIRNd8OY/Q== - dependencies: - "@taquito/core" "^20.0.0" - "@taquito/rpc" "^20.0.0" - "@taquito/taquito" "^20.0.0" - "@taquito/utils" "^20.0.0" + "@taquito/core" "^20.1.0" + "@taquito/taquito" "^20.1.0" + +"@taquito/contracts-library@20.0.0", "@taquito/contracts-library@20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/contracts-library/-/contracts-library-20.1.0.tgz#8ecdfa4adabc9186319c22de6ab46d0878dc0ae5" + integrity sha512-WCbqB8ngBzb2pdKmSvzAR8GzZIroEvQWjXdsMhV72E0PBz9Xouf+C26UxNz0P92O9jcuv4JNMjm0YX6DCsEroQ== + dependencies: + "@taquito/core" "^20.1.0" + "@taquito/rpc" "^20.1.0" + "@taquito/taquito" "^20.1.0" + "@taquito/utils" "^20.1.0" bignumber.js "^9.1.2" -"@taquito/core@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/core/-/core-20.0.0.tgz#9f371bb398338a04f5e29bd004cf213fda3e7a43" - integrity sha512-JSDWLaVeaSqI98Xwd2TQwNy/fznSLEhikUxM7da6WbGJGtH8lG9SI9q6N9LLPfOFNGlP5RVQLO9HK/Pcmn4H8Q== +"@taquito/core@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/core/-/core-20.1.0.tgz#e7405ee8bdc98da2a5db6b341bd258c4e0371e10" + integrity sha512-UngkJKG65Q57FifaFFBlvvrFRjJwpzmk5kCr00WeTVun92WMt2hPx0k3B5ymeCj0u7yELLF7IhOg5ZmIRtDXdA== dependencies: json-stringify-safe "^5.0.1" -"@taquito/http-utils@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/http-utils/-/http-utils-20.0.0.tgz#47d274f882eb123975cf2ee099ea7e9b34e4c11e" - integrity sha512-R4Qen9oA/wQ7S5jC8K3viJkY/o9uQFEPQfuyPJCm90Tlg5HMd8UFRbJKqMvsW/nNVo39kukzEMS8o5wFST6dBA== +"@taquito/http-utils@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/http-utils/-/http-utils-20.1.0.tgz#e9315ac188254b6f317537031902ff0b6193529c" + integrity sha512-d8E6nKRBQFaPXpOXqSV1jGw1xsOujBTDXEWWWCJqV4H6JC/sXPMdpH3o/uIsOFR/jHH6v9oE1dSwRSM03ZoiNw== dependencies: - "@taquito/core" "^20.0.0" + "@taquito/core" "^20.1.0" node-fetch "^2.7.0" -"@taquito/ledger-signer@20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/ledger-signer/-/ledger-signer-20.0.0.tgz#017b3efc78abd19f82f25e3ad364756c01497fb3" - integrity sha512-wfl1plx/uAIbmHsYxwsO2pXKDa9aMOmuuw25rjwsniBP36hM0Ly9GSrQ0z1CozteQF9ThP+OwrNMCwlfqXx43Q== +"@taquito/ledger-signer@20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/ledger-signer/-/ledger-signer-20.1.0.tgz#45773b375d8cb1032afe7e0fee306f592695e40c" + integrity sha512-idrcWyUcMWcwoa1VK94EFwQKRmkGAUSVNnl1w5f1fLK7x3lgWT9KyEk5HYO3k3qL4I1/NohEiNPGZkk4wYGjsg== dependencies: - "@ledgerhq/hw-transport" "^6.30.5" + "@ledgerhq/hw-transport" "^6.31.4" "@stablelib/blake2b" "^1.0.1" - "@taquito/core" "^20.0.0" - "@taquito/taquito" "^20.0.0" - "@taquito/utils" "^20.0.0" + "@taquito/core" "^20.1.0" + "@taquito/taquito" "^20.1.0" + "@taquito/utils" "^20.1.0" buffer "^6.0.3" -"@taquito/local-forging@20.0.0", "@taquito/local-forging@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/local-forging/-/local-forging-20.0.0.tgz#e28f548569d11efd4c98f380c8388561ab7b63fe" - integrity sha512-oxeyoqXjuTyl7gWqJGXoOqfWwH1bTiO76P/eOA5ULXgGwx9Muvt/yW5EPoIn6lK3Ajl41IE2sT+4JbKjQsAkuw== +"@taquito/local-forging@20.1.0", "@taquito/local-forging@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/local-forging/-/local-forging-20.1.0.tgz#f4df4cb7e91f7df08836b4908102bfb4eda5f60d" + integrity sha512-KepobM5U6dM6GKnA6oFMb0aZA0SXNKrkgi/87n+C82RcVM37ogW2s3w4ZYCgfkrKFkPWjS8bCbbYoF6KM7krCw== dependencies: - "@taquito/core" "^20.0.0" - "@taquito/utils" "^20.0.0" + "@taquito/core" "^20.1.0" + "@taquito/utils" "^20.1.0" bignumber.js "^9.1.2" -"@taquito/michel-codec@20.0.0", "@taquito/michel-codec@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/michel-codec/-/michel-codec-20.0.0.tgz#c7d4831e3875dfbbd43ea02b7c0628ce76cae1b0" - integrity sha512-Xe6zHI8d5o/v9xNFJSvtspMK9Zf/iPDgUU7mIbucF/ppAYm1pofm5zL4SY5+tK0/Xz7irXjVx0a5l2sgGCBZmQ== +"@taquito/michel-codec@20.1.0", "@taquito/michel-codec@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/michel-codec/-/michel-codec-20.1.0.tgz#fcf946d67bde190925c5769b39c2c2cd9c9af157" + integrity sha512-hFFhOc3pHUt0KmlaGkb9WAX3lRtJ8faumV6xL0l4t07mXafQbI2LIJi3oCGnNz5GeCvyjhK5M1bIzwB1zkgZ9A== dependencies: - "@taquito/core" "^20.0.0" + "@taquito/core" "^20.1.0" -"@taquito/michelson-encoder@20.0.0", "@taquito/michelson-encoder@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/michelson-encoder/-/michelson-encoder-20.0.0.tgz#9e8464477ef78500c2d1637f3ae3b30ac942529c" - integrity sha512-b28UTIX733vLmE1R/wW3J5cMz4EIf8ioZen2u6Ms8enT7MMQw4svM9Eq/D+Wr6di3VDeGh1Aqvgl+XRbEw8AQA== +"@taquito/michelson-encoder@20.1.0", "@taquito/michelson-encoder@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/michelson-encoder/-/michelson-encoder-20.1.0.tgz#ad83bdc2ac556371dc7142462d9a0efab058f53a" + integrity sha512-hOL5fL1Sr6u6WqgIzEZ2WVYLSm93wS7GNC5dUnQwktKkMXCT/zIeXJAra+j9mp/WvlGetTVrm+ZAJ6/XOpbFIw== dependencies: - "@taquito/core" "^20.0.0" - "@taquito/rpc" "^20.0.0" - "@taquito/utils" "^20.0.0" + "@taquito/core" "^20.1.0" + "@taquito/rpc" "^20.1.0" + "@taquito/utils" "^20.1.0" bignumber.js "^9.1.2" fast-json-stable-stringify "^2.1.0" -"@taquito/rpc@20.0.0", "@taquito/rpc@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/rpc/-/rpc-20.0.0.tgz#ec1a202840bc0610e28708d3a40488e18baa93ac" - integrity sha512-4ijTIKGAl3NnB9ibvZzBpruf00w4TDi9CSLeoNOiP0T/laTZsUfmtR7p5AwirGNGBqAXr7mWSqSCrn2IEwSjAw== +"@taquito/rpc@20.1.0", "@taquito/rpc@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/rpc/-/rpc-20.1.0.tgz#6c74e3bee48067c506e2a579f00116932b557fcb" + integrity sha512-+tUtzFGuShj38Nxayo5SSoSIb+MDYQPtRGkn5i6QEtyMwpH8vz8EoCnL7m1AjfvMq+SO1qtxBXKAPmO+9iBFsA== dependencies: - "@taquito/core" "^20.0.0" - "@taquito/http-utils" "^20.0.0" - "@taquito/utils" "^20.0.0" + "@taquito/core" "^20.1.0" + "@taquito/http-utils" "^20.1.0" + "@taquito/utils" "^20.1.0" bignumber.js "^9.1.2" -"@taquito/signer@20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/signer/-/signer-20.0.0.tgz#492dba3da42973c1a5a200cc6d1c71c4634cc981" - integrity sha512-3XvZJ8EabzPX+KHoQ/c8MxsdDuP2hAv2sljZHNVkj2ECz2aX2mXSlcw21b0qbKOTDimZHIeL3QQTE67UfkSUsw== +"@taquito/signer@20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/signer/-/signer-20.1.0.tgz#524449ca78f7de9c03b7a3cad05ce8845cb329de" + integrity sha512-1V/J+IoepZ9KTKl4TiUTnXugy/0PusfJ09oYDNWwl6kprPSyjVNyd5PXEmG1+szvW0gQ1S9d9OeSktOYE0NHUA== dependencies: "@stablelib/blake2b" "^1.0.1" "@stablelib/ed25519" "^1.0.3" @@ -3536,68 +3586,68 @@ "@stablelib/nacl" "^1.0.4" "@stablelib/pbkdf2" "^1.0.1" "@stablelib/sha512" "^1.0.1" - "@taquito/core" "^20.0.0" - "@taquito/taquito" "^20.0.0" - "@taquito/utils" "^20.0.0" - "@types/bn.js" "^5.1.2" + "@taquito/core" "^20.1.0" + "@taquito/taquito" "^20.1.0" + "@taquito/utils" "^20.1.0" + "@types/bn.js" "^5.1.5" bip39 "3.1.0" - elliptic "^6.5.4" + elliptic "^6.5.7" pbkdf2 "^3.1.2" typedarray-to-buffer "^4.0.0" -"@taquito/taquito@20.0.0", "@taquito/taquito@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/taquito/-/taquito-20.0.0.tgz#221eb2c5b261fa08d0c736e4db75ce9250d73da2" - integrity sha512-iA53YlMdElAb919vhS7UswjHFumiDGOB6IE1vAh5dOLdPvK8L6uDlSXU6Aaz/nQyTJGe6I6RusjXEoMVnZUe2g== - dependencies: - "@taquito/core" "^20.0.0" - "@taquito/http-utils" "^20.0.0" - "@taquito/local-forging" "^20.0.0" - "@taquito/michel-codec" "^20.0.0" - "@taquito/michelson-encoder" "^20.0.0" - "@taquito/rpc" "^20.0.0" - "@taquito/utils" "^20.0.0" +"@taquito/taquito@20.0.0", "@taquito/taquito@20.1.0", "@taquito/taquito@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/taquito/-/taquito-20.1.0.tgz#9c6fca2aa2c813809a1e09c3b01fda82907facf0" + integrity sha512-pBQUe/OhX/d3jltcpLhe/dSgX8set/Pmc5RYHA+KIIa8smG6CEHib4HVXzczHumbRj9wr/FR77BLDSoxTZXc6w== + dependencies: + "@taquito/core" "^20.1.0" + "@taquito/http-utils" "^20.1.0" + "@taquito/local-forging" "^20.1.0" + "@taquito/michel-codec" "^20.1.0" + "@taquito/michelson-encoder" "^20.1.0" + "@taquito/rpc" "^20.1.0" + "@taquito/utils" "^20.1.0" bignumber.js "^9.1.2" rxjs "^7.8.1" -"@taquito/tzip12@20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/tzip12/-/tzip12-20.0.0.tgz#48a21f6d86171d399aa90d73b7f2124237648b98" - integrity sha512-tM6Vze/mRjInV/mjxol6aIbyxdVFveFBPauLfq3q4d/gVXPFKuYEsIDdx5Q8pZ/APpxG6AvpnXdKZejlNOg1RQ== - dependencies: - "@taquito/core" "^20.0.0" - "@taquito/michelson-encoder" "^20.0.0" - "@taquito/taquito" "^20.0.0" - "@taquito/tzip16" "^20.0.0" - -"@taquito/tzip16@20.0.0", "@taquito/tzip16@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/tzip16/-/tzip16-20.0.0.tgz#6bedf7b0f1adc1269bb7edc83fafaf552a8c6e8a" - integrity sha512-aCisyUga0wnBj8uTGYEZ1OiAEgrGdmM3fFltYe2/0xTda3eoO146XGQrxR3BvcHTB7BiJeZOwmZByvJ6Lel0tg== - dependencies: - "@taquito/core" "^20.0.0" - "@taquito/http-utils" "^20.0.0" - "@taquito/michelson-encoder" "^20.0.0" - "@taquito/rpc" "^20.0.0" - "@taquito/taquito" "^20.0.0" - "@taquito/utils" "^20.0.0" +"@taquito/tzip12@20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/tzip12/-/tzip12-20.1.0.tgz#51df7324207dc55bf1896d493ee06fa9510ad0bf" + integrity sha512-UsAXfoPVGe6DWoad0+j1tqQFOrtrtLLoZKI46Sp9x+jcODNUXy4kppXgGXK9lfznwCWSf25qf6rVJESqYV9E7w== + dependencies: + "@taquito/core" "^20.1.0" + "@taquito/michelson-encoder" "^20.1.0" + "@taquito/taquito" "^20.1.0" + "@taquito/tzip16" "^20.1.0" + +"@taquito/tzip16@20.0.0", "@taquito/tzip16@20.1.0", "@taquito/tzip16@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/tzip16/-/tzip16-20.1.0.tgz#273c06637de16ddbff14c6b1b93fee9a3c58037e" + integrity sha512-M8P9yO9AnzqbXbX1escZgl9ewpbIG2PC3YNOStUCtbsolsns8R9zvhCyV8BnETUcjSXNGrISuahPVYjd0m/Iaw== + dependencies: + "@taquito/core" "^20.1.0" + "@taquito/http-utils" "^20.1.0" + "@taquito/michelson-encoder" "^20.1.0" + "@taquito/rpc" "^20.1.0" + "@taquito/taquito" "^20.1.0" + "@taquito/utils" "^20.1.0" bignumber.js "^9.1.2" crypto-js "^4.2.0" -"@taquito/utils@20.0.0", "@taquito/utils@^20.0.0": - version "20.0.0" - resolved "https://registry.yarnpkg.com/@taquito/utils/-/utils-20.0.0.tgz#35a512336fd033c8b8b2319e847289608e058bee" - integrity sha512-45GT2caKPpi8sC6BdlTNZRgsqjXy6D2hVfisymzU68EWXZ6Rss5aNNj6OZgDMVmwAnSJok41D2DCdUegiJJBbw== +"@taquito/utils@20.1.0", "@taquito/utils@^20.1.0": + version "20.1.0" + resolved "https://registry.yarnpkg.com/@taquito/utils/-/utils-20.1.0.tgz#23032edbbc82f9e059b956318f9f83b5b9e9558b" + integrity sha512-3sIqowczUmJo7Lei/Msgu1+6Wi7UJISUifsYXMPsUsA5p5P1FB56g8JPT1t5nx5bXl21amvz+mprh7/LRrZARA== dependencies: "@stablelib/blake2b" "^1.0.1" "@stablelib/ed25519" "^1.0.3" - "@taquito/core" "^20.0.0" - "@types/bs58check" "^2.1.0" + "@taquito/core" "^20.1.0" + "@types/bs58check" "^2.1.2" bignumber.js "^9.1.2" blakejs "^1.2.1" bs58check "^3.0.1" buffer "^6.0.3" - elliptic "^6.5.4" + elliptic "^6.5.7" typedarray-to-buffer "^4.0.0" "@temple-wallet/dapp@5.0.2": @@ -3796,10 +3846,10 @@ dependencies: "@types/node" "*" -"@types/bn.js@^5.1.2": - version "5.1.5" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" - integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== +"@types/bn.js@^5.1.5": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.6.tgz#9ba818eec0c85e4d3c679518428afdf611d03203" + integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== dependencies: "@types/node" "*" @@ -3811,6 +3861,13 @@ "@types/connect" "*" "@types/node" "*" +"@types/bonjour@^3.5.13": + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" + integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== + dependencies: + "@types/node" "*" + "@types/bs58check@^2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@types/bs58check/-/bs58check-2.1.0.tgz#7d25a8b88fe7a9e315d2647335ee3c43c8fdb0c0" @@ -3818,6 +3875,13 @@ dependencies: "@types/node" "*" +"@types/bs58check@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@types/bs58check/-/bs58check-2.1.2.tgz#ca6264599cd9c0bdfeb839a0927f13a9cb77ba0f" + integrity sha512-xpXaQlOIY1KoXlA/ytHGHpEIU87PJt+g9SH7nC6HdCgaBwT2IEZIwBMHbjuX6BpnfbiUMlmwqurdLDwXpcdmSA== + dependencies: + "@types/node" "*" + "@types/chrome@0.0.246": version "0.0.246" resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.246.tgz#412ee1b162a67d1cfebe413887b9aa0c28998ef1" @@ -3834,10 +3898,10 @@ "@types/node" "*" source-map "^0.6.0" -"@types/connect-history-api-fallback@*": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== +"@types/connect-history-api-fallback@^1.5.4": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" + integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" @@ -3904,6 +3968,16 @@ "@types/qs" "*" "@types/range-parser" "*" +"@types/express-serve-static-core@^4.17.33": + version "4.19.6" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" + integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + "@types/express@*": version "4.17.14" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.14.tgz#143ea0557249bc1b3b54f15db4c81c3d4eb3569c" @@ -3914,6 +3988,16 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/express@^4.17.21": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/filesystem@*": version "0.0.32" resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.32.tgz#307df7cc084a2293c3c1a31151b178063e0a8edf" @@ -3987,10 +4071,15 @@ "@types/tapable" "^1" "@types/webpack" "^4" -"@types/http-proxy@^1.17.5": - version "1.17.9" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" - integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + +"@types/http-proxy@^1.17.8": + version "1.17.15" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.15.tgz#12118141ce9775a6499ecb4c01d02f90fc839d36" + integrity sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ== dependencies: "@types/node" "*" @@ -4078,11 +4167,23 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/node-forge@^1.3.0": + version "1.3.11" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" + integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== + dependencies: + "@types/node" "*" + "@types/node-forge@^1.3.1": version "1.3.10" resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.10.tgz#62a19d4f75a8b03290578c2b04f294b1a5a71b07" @@ -4212,6 +4313,11 @@ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== +"@types/retry@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" + integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== + "@types/scheduler@*": version "0.16.2" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" @@ -4229,6 +4335,21 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-index@^1.9.4": + version "1.9.4" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" + integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== + dependencies: + "@types/express" "*" + "@types/serve-static@*": version "1.15.0" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" @@ -4237,6 +4358,15 @@ "@types/mime" "*" "@types/node" "*" +"@types/serve-static@^1.15.5": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + "@types/sha.js@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@types/sha.js/-/sha.js-2.4.0.tgz#bce682ef860b40f419d024fa08600c3b8d24bb01" @@ -4244,6 +4374,13 @@ dependencies: "@types/node" "*" +"@types/sockjs@^0.3.36": + version "0.3.36" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" + integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== + dependencies: + "@types/node" "*" + "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" @@ -4298,16 +4435,12 @@ resolved "https://registry.yarnpkg.com/@types/webextension-polyfill/-/webextension-polyfill-0.9.1.tgz#fcb5c352e2e461d0287774db89bc326b15b47844" integrity sha512-6aNzPIhqKlAV9t06nwSH3/veAceYE2dS2RVFZI8V1+UXHqsFNB6cRwxNmheiBvEGRc45E/gyZNzH0xAYIC27KA== -"@types/webpack-dev-server@3": - version "3.11.6" - resolved "https://registry.yarnpkg.com/@types/webpack-dev-server/-/webpack-dev-server-3.11.6.tgz#d8888cfd2f0630203e13d3ed7833a4d11b8a34dc" - integrity sha512-XCph0RiiqFGetukCTC3KVnY1jwLcZ84illFRMbyFzCcWl90B/76ew0tSqF46oBhnLC4obNDG7dMO0JfTN0MgMQ== +"@types/webpack-dev-server@3", "@types/webpack-dev-server@^4": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@types/webpack-dev-server/-/webpack-dev-server-4.7.2.tgz#a12d9881aa23cdd4cecbb2d31fa784a45c4967e0" + integrity sha512-Y3p0Fmfvp0MHBDoCzo+xFJaWTw0/z37mWIo6P15j+OtmUDLvznJWdZNeD7Q004R+MpQlys12oXbXsrXRmxwg4Q== dependencies: - "@types/connect-history-api-fallback" "*" - "@types/express" "*" - "@types/serve-static" "*" - "@types/webpack" "^4" - http-proxy-middleware "^1.0.0" + webpack-dev-server "*" "@types/webpack-sources@*", "@types/webpack-sources@^3.2.0": version "3.2.0" @@ -4346,6 +4479,13 @@ dependencies: "@types/node" "*" +"@types/ws@^8.5.10": + version "8.5.12" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e" + integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -4914,6 +5054,14 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + acorn-globals@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" @@ -5014,7 +5162,7 @@ ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv-keywords@^5.0.0: +ajv-keywords@^5.0.0, ajv-keywords@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== @@ -5041,6 +5189,16 @@ ajv@^8.0.0, ajv@^8.8.0: require-from-string "^2.0.2" uri-js "^4.2.2" +ajv@^8.9.0: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + ansi-escapes@^4.2.1: version "4.3.1" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" @@ -5048,6 +5206,11 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.11.0" +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -5159,6 +5322,11 @@ array-buffer-byte-length@^1.0.0: call-bind "^1.0.2" is-array-buffer "^3.0.1" +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + array-includes@^3.1.6, array-includes@^3.1.7: version "3.1.7" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" @@ -5559,15 +5727,20 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bignumber.js@9.1.0, bignumber.js@^9.1.0, bignumber.js@^9.1.2: - version "9.1.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.0.tgz#8d340146107fe3a6cb8d40699643c302e8773b62" - integrity sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A== +bignumber.js@9.1.2, bignumber.js@^9.1.0, bignumber.js@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" + integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== binary-extensions@^2.0.0: version "2.1.0" @@ -5633,6 +5806,32 @@ bn.js@^5.0.0, bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.13.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour-service@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== + dependencies: + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -5818,6 +6017,23 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + dependencies: + run-applescript "^7.0.0" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + bytes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" @@ -5840,6 +6056,17 @@ call-bind@^1.0.4, call-bind@^1.0.5: get-intrinsic "^1.2.1" set-function-length "^1.1.1" +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -5925,7 +6152,7 @@ chokidar@^3.4.2, chokidar@^3.5.2: optionalDependencies: fsevents "~2.3.2" -chokidar@^3.5.3: +chokidar@^3.5.3, chokidar@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -6091,6 +6318,11 @@ colord@^2.9.1: resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== +colorette@^2.0.10: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + colorette@^2.0.14: version "2.0.19" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" @@ -6148,6 +6380,26 @@ compress-commons@^4.1.0: normalize-path "^3.0.0" readable-stream "^3.6.0" +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -6158,6 +6410,11 @@ confusing-browser-globals@^1.0.11: resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + consola@^2.15.3: version "2.15.3" resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" @@ -6178,6 +6435,18 @@ consumable-stream@^2.0.0: resolved "https://registry.yarnpkg.com/consumable-stream/-/consumable-stream-2.0.0.tgz#11d3c7281b747eb9efd31c199b3a8b1711bec654" integrity sha512-I6WA2JVYXs/68rEvi1ie3rZjP6qusTVFEQkbzR+WC+fY56TpwiGTIDJETsrnlxv5CsnmK69ps6CkYvIbpEEqBA== +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -6195,6 +6464,16 @@ cookie-es@^1.0.0: resolved "https://registry.yarnpkg.com/cookie-es/-/cookie-es-1.0.0.tgz#4759684af168dfc54365b2c2dda0a8d7ee1e4865" integrity sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ== +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== + copy-webpack-plugin@11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" @@ -6603,6 +6882,13 @@ debounce@^1.2.1: resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== +debug@2.6.9, debug@^2.6.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -6610,13 +6896,6 @@ debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" -debug@^2.6.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -6657,6 +6936,19 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +default-browser-id@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" + integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== + +default-browser@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" + integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== + dependencies: + bundle-name "^4.1.0" + default-browser-id "^5.0.0" + define-data-property@^1.0.1, define-data-property@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" @@ -6666,11 +6958,25 @@ define-data-property@^1.0.1, define-data-property@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -6729,6 +7035,16 @@ denque@^2.1.0: resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" @@ -6747,6 +7063,11 @@ destr@^2.0.1, destr@^2.0.2: resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.2.tgz#8d3c0ee4ec0a76df54bc8b819bca215592a8c218" integrity sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg== +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + detect-browser@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" @@ -6762,6 +7083,11 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + detect-port-alt@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" @@ -6820,6 +7146,13 @@ dlv@^1.1.3: resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== +dns-packet@^5.2.2: + version "5.6.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" + integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -6928,6 +7261,11 @@ ed25519-hd-key@1.1.2: create-hmac "1.1.7" tweetnacl "1.0.3" +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + effector@21.2.0: version "21.2.0" resolved "https://registry.yarnpkg.com/effector/-/effector-21.2.0.tgz#7f5e17bfbd41f9a8fb07f6fe8d6b2a14fc63e451" @@ -6951,6 +7289,19 @@ elliptic@^6.5.3, elliptic@^6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +elliptic@^6.5.7: + version "6.5.7" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" + integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emittery@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" @@ -6971,6 +7322,16 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -7053,6 +7414,18 @@ es-abstract@^1.19.0, es-abstract@^1.22.1: unbox-primitive "^1.0.2" which-typed-array "^1.1.13" +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" @@ -7154,6 +7527,11 @@ escalade@^3.1.1, escalade@^3.1.2: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -7474,6 +7852,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + event-emitter@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" @@ -7567,6 +7950,43 @@ expect@^27.4.2: jest-message-util "^27.4.2" jest-regex-util "^27.4.0" +express@^4.19.2: + version "4.21.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281" + integrity sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.3" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.7.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~2.0.0" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.3.1" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.3" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.10" + proxy-addr "~2.0.7" + qs "6.13.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.19.0" + serve-static "1.16.2" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + ext@^1.1.2: version "1.7.0" resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" @@ -7610,6 +8030,11 @@ fast-redact@^3.0.0: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.2.0.tgz#b1e2d39bc731376d28bde844454fa23e26919987" integrity sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw== +fast-uri@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.3.tgz#892a1c91802d5d7860de728f18608a0573142241" + integrity sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw== + fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -7622,6 +8047,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -7694,6 +8126,19 @@ filter-obj@^1.1.0: resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== + dependencies: + debug "2.6.9" + encodeurl "~2.0.0" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + find-cache-dir@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" @@ -7806,11 +8251,21 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + fraction.js@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" @@ -7934,6 +8389,17 @@ get-intrinsic@^1.2.2: has-symbols "^1.0.3" hasown "^2.0.0" +get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -8116,7 +8582,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -8173,6 +8639,11 @@ h3@^1.10.1, h3@^1.8.2: uncrypto "^0.1.3" unenv "^1.9.0" +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -8195,6 +8666,13 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + has-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" @@ -8288,6 +8766,16 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + hsl-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" @@ -8305,6 +8793,11 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" +html-entities@^2.4.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -8349,6 +8842,37 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + http-proxy-agent@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" @@ -8358,12 +8882,12 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy-middleware@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz#43700d6d9eecb7419bf086a128d0f7205d9eb665" - integrity sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg== +http-proxy-middleware@^2.0.3: + version "2.0.7" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6" + integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA== dependencies: - "@types/http-proxy" "^1.17.5" + "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" is-glob "^4.0.1" is-plain-obj "^3.0.0" @@ -8401,6 +8925,11 @@ human-signals@^5.0.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== +hyperdyperid@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hyperdyperid/-/hyperdyperid-1.2.0.tgz#59668d323ada92228d2a869d3e474d5a33b69e6b" + integrity sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -8479,7 +9008,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -8533,6 +9062,16 @@ ioredis@^5.3.2: redis-parser "^3.0.0" standard-as-callback "^2.1.0" +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +ipaddr.js@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== + iron-webcrypto@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.0.0.tgz#e3b689c0c61b434a0a4cb82d0aeabbc8b672a867" @@ -8709,6 +9248,11 @@ is-negative-zero@^2.0.2: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-network-error@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.1.0.tgz#d26a760e3770226d11c169052f266a4803d9c997" + integrity sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g== + is-number-object@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" @@ -9577,6 +10121,14 @@ language-tags@^1.0.9: dependencies: language-subtag-registry "^0.3.20" +launch-editor@^2.6.1: + version "2.9.1" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.9.1.tgz#253f173bd441e342d4344b4dae58291abb425047" + integrity sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.8.1" + lazystream@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" @@ -9888,6 +10440,11 @@ mdn-data@2.0.14: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + memfs@^3.1.2: version "3.4.11" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.11.tgz#3a34837ade675825d805a2c135e88cefe5e53aaf" @@ -9895,6 +10452,16 @@ memfs@^3.1.2: dependencies: fs-monkey "^1.0.3" +memfs@^4.6.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.14.0.tgz#48d5e85a03ea0b428280003212fbca3063531be3" + integrity sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA== + dependencies: + "@jsonjoy.com/json-pack" "^1.0.3" + "@jsonjoy.com/util" "^1.3.0" + tree-dump "^1.0.1" + tslib "^2.0.0" + memoizee@^0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" @@ -9928,6 +10495,11 @@ memorystream@^0.3.1: resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -9938,6 +10510,11 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -9964,6 +10541,11 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +"mime-db@>= 1.43.0 < 2": + version "1.53.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" + integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== + mime-types@^2.1.12: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" @@ -9971,13 +10553,18 @@ mime-types@^2.1.12: dependencies: mime-db "1.51.0" -mime-types@^2.1.27: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + mime@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" @@ -10088,11 +10675,19 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + multiformats@^9.4.2: version "9.9.0" resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" @@ -10128,6 +10723,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -10182,7 +10782,7 @@ node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7, node-fetch@^2.7.0: dependencies: whatwg-url "^5.0.0" -node-forge@^1.3.1: +node-forge@^1, node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== @@ -10353,6 +10953,11 @@ object.values@^1.1.6, object.values@^1.1.7: define-properties "^1.2.0" es-abstract "^1.22.1" +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + ofetch@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.3.tgz#588cb806a28e5c66c2c47dd8994f9059a036d8c0" @@ -10380,6 +10985,18 @@ on-exit-leak-free@^0.2.0: resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== +on-finished@2.4.1, on-finished@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -10401,6 +11018,16 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +open@^10.0.3: + version "10.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.1.0.tgz#a7795e6e5d519abe4286d9937bb24b51122598e1" + integrity sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw== + dependencies: + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^3.1.0" + open@^8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" @@ -10487,6 +11114,15 @@ p-map@^2.0.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== +p-retry@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-6.2.0.tgz#8d6df01af298750009691ce2f9b3ad2d5968f3bd" + integrity sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA== + dependencies: + "@types/retry" "0.12.2" + is-network-error "^1.0.0" + retry "^0.13.1" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -10541,6 +11177,11 @@ parse5@6.0.1: resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + pascal-case@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" @@ -10602,6 +11243,11 @@ path-scurry@^1.6.1: lru-cache "^9.1.1 || ^10.0.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -11360,6 +12006,14 @@ property-expr@^2.0.5: resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4" integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA== +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -11434,6 +12088,13 @@ qrcode-svg@^1.1.0: resolved "https://registry.yarnpkg.com/qrcode-svg/-/qrcode-svg-1.1.0.tgz#2087549843dc5d0a3f8e8aa046cd9bcf23708cc3" integrity sha512-XyQCIXux1zEIA3NPb0AeR8UMYvXZzWEhgdBgBjH9gO7M48H9uoHzviNz8pXw3UzrAcxRRRn9gxHewAVK7bn9qw== +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + qs@^6.11.1: version "6.11.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" @@ -11491,6 +12152,21 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + react-base16-styling@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c" @@ -11683,7 +12359,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^2.3.5, readable-stream@~2.3.6: +readable-stream@^2.0.1, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -11696,19 +12372,19 @@ readable-stream@^2.3.5, readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== +readable-stream@^3.0.6, readable-stream@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -11990,7 +12666,7 @@ response-iterator@^0.2.6: resolved "https://registry.yarnpkg.com/response-iterator/-/response-iterator-0.2.6.tgz#249005fb14d2e4eeb478a3f735a28fd8b4c9f3da" integrity sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw== -retry@0.13.1: +retry@0.13.1, retry@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== @@ -12037,6 +12713,11 @@ rn-host-detect@^1.2.0: resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.2.0.tgz#8b0396fc05631ec60c1cb8789e5070cdb04d0da0" integrity sha512-btNg5kzHcjZZ7t7mvvV/4wNJ9e3MPgrWivkRgWURzXL0JJ0pwWlU4zrbmdlz3HHzHOxhBhHB4D+/dbMFfu4/4A== +run-applescript@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.0.0.tgz#e5a553c2bffd620e169d276c1cd8f1b64778fbeb" + integrity sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -12068,16 +12749,16 @@ safe-array-concat@^1.0.1: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -12149,6 +12830,16 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.0.0" +schema-utils@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + scryptsy@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790" @@ -12159,6 +12850,19 @@ seedrandom@^3.0.5: resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== + dependencies: + "@types/node-forge" "^1.3.0" + node-forge "^1" + "semver@2 || 3 || 4 || 5", semver@^5.5.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -12174,6 +12878,25 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" @@ -12191,6 +12914,29 @@ seroval@^1.0.3: resolved "https://registry.yarnpkg.com/seroval/-/seroval-1.0.4.tgz#0400d24a48b1f6f44b8a3d55af0476a1c5e8643f" integrity sha512-qQs/N+KfJu83rmszFQaTxcoJoPn6KNUruX4KmnmyD0oZkUoiNvJ1rpdYKDf4YHM05k+HOgCxa3yvf15QbVijGg== +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== + dependencies: + encodeurl "~2.0.0" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.19.0" + set-cookie-parser@^2.4.8: version "2.6.0" resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz#131921e50f62ff1a66a461d7d62d7b21d5d15a51" @@ -12206,6 +12952,18 @@ set-function-length@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + set-function-name@^2.0.0, set-function-name@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" @@ -12220,6 +12978,16 @@ setimmediate@^1.0.4, setimmediate@^1.0.5: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" @@ -12259,7 +13027,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.6.1, shell-quote@^1.7.3: +shell-quote@^1.6.1, shell-quote@^1.7.3, shell-quote@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== @@ -12273,6 +13041,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.6" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" @@ -12323,6 +13101,15 @@ socketcluster-client@^17.1.0: vinyl-buffer "^1.0.1" ws "^8.9.0" +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + solid-js@^1.7.11: version "1.8.14" resolved "https://registry.yarnpkg.com/solid-js/-/solid-js-1.8.14.tgz#979aa8000eedede07e7f5a5773a4714ab3eeb113" @@ -12388,6 +13175,29 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz#a14f64e0954f6e25cc6587bd4f392522db0d998f" integrity sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw== +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" @@ -12420,6 +13230,16 @@ standard-as-callback@^2.1.0: resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + std-env@^3.0.1, std-env@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" @@ -12772,6 +13592,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +thingies@^1.20.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/thingies/-/thingies-1.21.0.tgz#e80fbe58fd6fdaaab8fad9b67bd0a5c943c445c1" + integrity sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g== + thread-stream@^0.15.1: version "0.15.2" resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4" @@ -12802,6 +13627,11 @@ through2@^2.0.3: readable-stream "~2.3.6" xtend "~4.0.1" +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + timers-browserify@^2.0.12: version "2.0.12" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" @@ -12868,6 +13698,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + toposort@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" @@ -12894,6 +13729,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= +tree-dump@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tree-dump/-/tree-dump-1.0.2.tgz#c460d5921caeb197bde71d0e9a7b479848c5b8ac" + integrity sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ== + "true-myth@^4.1.0": version "4.1.1" resolved "https://registry.yarnpkg.com/true-myth/-/true-myth-4.1.1.tgz#ff4ac9d5130276e34aa338757e2416ec19248ba2" @@ -13035,6 +13875,14 @@ type-fest@^2.19.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + type@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" @@ -13192,6 +14040,11 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + unplugin@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.0.1.tgz#83b528b981cdcea1cad422a12cd02e695195ef3f" @@ -13337,6 +14190,11 @@ utila@~0.4: resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -13374,6 +14232,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + vinyl-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz#96c1a3479b8c5392542c612029013b5b27f88bbf" @@ -13423,6 +14286,13 @@ watchpack@^2.4.1: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + webcrypto-core@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.2.0.tgz#44fda3f9315ed6effe9a1e47466e0935327733b5" @@ -13478,6 +14348,52 @@ webpack-cli@^5: rechoir "^0.8.0" webpack-merge "^5.7.3" +webpack-dev-middleware@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz#40e265a3d3d26795585cff8207630d3a8ff05877" + integrity sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA== + dependencies: + colorette "^2.0.10" + memfs "^4.6.0" + mime-types "^2.1.31" + on-finished "^2.4.1" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@*: + version "5.1.0" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-5.1.0.tgz#8f44147402b4d8ab99bfeb9b6880daa1411064e5" + integrity sha512-aQpaN81X6tXie1FoOB7xlMfCsN19pSvRAeYUHOdFWOlhpQ/LlbfTqYwwmEDFV0h8GGuqmCmKmT+pxcUV/Nt2gQ== + dependencies: + "@types/bonjour" "^3.5.13" + "@types/connect-history-api-fallback" "^1.5.4" + "@types/express" "^4.17.21" + "@types/serve-index" "^1.9.4" + "@types/serve-static" "^1.15.5" + "@types/sockjs" "^0.3.36" + "@types/ws" "^8.5.10" + ansi-html-community "^0.0.8" + bonjour-service "^1.2.1" + chokidar "^3.6.0" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + express "^4.19.2" + graceful-fs "^4.2.6" + html-entities "^2.4.0" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.1.0" + launch-editor "^2.6.1" + open "^10.0.3" + p-retry "^6.2.0" + schema-utils "^4.2.0" + selfsigned "^2.4.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^7.4.2" + ws "^8.18.0" + webpack-ext-reloader-mv3@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/webpack-ext-reloader-mv3/-/webpack-ext-reloader-mv3-2.1.1.tgz#a96c8be4ab64966c4ac5c556a394c6db29b3360a" @@ -13559,6 +14475,20 @@ webpackbar@^5: pretty-time "^1.1.0" std-env "^3.0.1" +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" @@ -13716,6 +14646,11 @@ ws@^7.4.5, ws@^7.4.6, ws@^7.5.1, ws@^7.5.2: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== +ws@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + ws@^8.6.0, ws@^8.9.0: version "8.17.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" From fc9038405fc0e25feafd2089627fa8aaf23a0eda Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 31 Oct 2024 12:00:14 +0200 Subject: [PATCH 02/16] TW-1562: Referrals. Improve (#1212) * TW-1562: Referrals. Improve * TW-1562: Referrals. Improve. + Redirect URL to rules * TW-1562: Referrals. Improve. ++ Ads package * TW-1562: Referrals. Improve. Fix pipeline --- package.json | 2 +- src/lib/apis/ads-api.ts | 18 ++++++++++++++++-- src/lib/constants.ts | 2 +- src/lib/temple/back/main.ts | 8 ++++---- src/replaceReferrals.ts | 11 ++++++++--- yarn.lock | 8 ++++---- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 5b3cdaf238..cbd521a2a4 100644 --- a/package.json +++ b/package.json @@ -232,6 +232,6 @@ "follow-redirects": "^1.15.4" }, "optionalDependencies": { - "@temple-wallet/extension-ads": "9.0.0-dev.2" + "@temple-wallet/extension-ads": "9.0.0-dev.1562.3" } } diff --git a/src/lib/apis/ads-api.ts b/src/lib/apis/ads-api.ts index f4a86cb246..5587abf5fb 100644 --- a/src/lib/apis/ads-api.ts +++ b/src/lib/apis/ads-api.ts @@ -67,8 +67,22 @@ export async function postLinkAdsImpressions(accountPkh: string, installId: stri await axiosClient.post('/link-impressions', { accountPkh, installId, signature, appVersion: APP_VERSION }); } -export async function fetchReferralsSupportedDomains() { - const res = await axiosClient.get('/takeads/referrals/supported-domains'); +interface ReferralTextIconRule { + /** RegEx (string) to check page hostname against */ + hostRegExStr: string; + aMatchSelector?: string; + aChildSelector?: string; + iconHeight?: number; +} + +export interface ReferralsRulesResponse { + domains: string[]; + textIconRules: ReferralTextIconRule[]; + redirectUrl?: string; +} + +export async function fetchReferralsRules() { + const res = await axiosClient.get('/takeads/referrals/rules'); return res.data; } diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 0b0e465d0b..054dc9e08b 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -2,7 +2,7 @@ export enum ContentScriptType { ExternalLinksActivity = 'ExternalLinksActivity', ExternalAdsActivity = 'ExternalAdsActivity', UpdateAdsRules = 'UpdateAdsRules', - FetchReferralsSupportedDomains = 'FetchReferralsSupportedDomains', + FetchReferralsRules = 'FetchReferralsRules', FetchReferrals = 'FetchReferrals', ReferralClick = 'ReferralClick' } diff --git a/src/lib/temple/back/main.ts b/src/lib/temple/back/main.ts index 72ba36a992..a12108ad01 100644 --- a/src/lib/temple/back/main.ts +++ b/src/lib/temple/back/main.ts @@ -6,7 +6,7 @@ import { importExtensionAdsReferralsModule } from 'lib/ads/import-extension-ads- import { updateRulesStorage } from 'lib/ads/update-rules-storage'; import { fetchReferralsAffiliateLinks, - fetchReferralsSupportedDomains, + fetchReferralsRules, postAdImpression, postAnonymousAdImpression, postReferralClick @@ -309,8 +309,8 @@ browser.runtime.onMessage.addListener(async msg => { break; } - case ContentScriptType.FetchReferralsSupportedDomains: { - return await getReferralsSupportedDomains(); + case ContentScriptType.FetchReferralsRules: { + return await getReferralsRules(); } case ContentScriptType.FetchReferrals: { @@ -343,7 +343,7 @@ browser.runtime.onMessage.addListener(async msg => { return; }); -const getReferralsSupportedDomains = memoizee(fetchReferralsSupportedDomains, { +const getReferralsRules = memoizee(fetchReferralsRules, { promise: true, max: 1, maxAge: 5 * 60_000 diff --git a/src/replaceReferrals.ts b/src/replaceReferrals.ts index 88b8a4b604..12bc654ddb 100644 --- a/src/replaceReferrals.ts +++ b/src/replaceReferrals.ts @@ -1,5 +1,6 @@ import { checkIfShouldReplaceReferrals, throttleAsyncCalls } from 'content-scripts/utils'; import { importExtensionAdsReferralsModule } from 'lib/ads/import-extension-ads-module'; +import type { ReferralsRulesResponse } from 'lib/apis/ads-api'; import { browser } from 'lib/browser'; import { ContentScriptType } from 'lib/constants'; @@ -20,8 +21,12 @@ checkIfShouldReplaceReferrals().then(shouldReplace => { const replaceReferrals = throttleAsyncCalls(async () => { const { getCurrentPageDomain, processAnchors } = await importExtensionAdsReferralsModule(); - const supportedDomains: string[] = await browser.runtime.sendMessage({ - type: ContentScriptType.FetchReferralsSupportedDomains + const { + domains: supportedDomains, + textIconRules, + redirectUrl + }: ReferralsRulesResponse = await browser.runtime.sendMessage({ + type: ContentScriptType.FetchReferralsRules }); if (!supportedDomains.length) { @@ -40,5 +45,5 @@ const replaceReferrals = throttleAsyncCalls(async () => { console.log('Replacing referrals for', supportedDomains.length, 'domains ...'); - return processAnchors(new Set(supportedDomains), ContentScriptType); + return processAnchors(new Set(supportedDomains), textIconRules, ContentScriptType, redirectUrl); }); diff --git a/yarn.lock b/yarn.lock index 0cfbd31c47..07b862bdb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3657,10 +3657,10 @@ dependencies: nanoid "^3.1.25" -"@temple-wallet/extension-ads@9.0.0-dev.2": - version "9.0.0-dev.2" - resolved "https://registry.yarnpkg.com/@temple-wallet/extension-ads/-/extension-ads-9.0.0-dev.2.tgz#9ba67b3cb01368650f591e5893655a3d8bde95af" - integrity sha512-eUxOuIXqIL5OUYQrXGrZa3pgacNxbmrUzLaaGJofZI5wi0VAVJSvjRfPwvE7KwBGoYw7g3sE2/gIraU/qmzYhA== +"@temple-wallet/extension-ads@9.0.0-dev.1562.3": + version "9.0.0-dev.1562.3" + resolved "https://registry.yarnpkg.com/@temple-wallet/extension-ads/-/extension-ads-9.0.0-dev.1562.3.tgz#ca6f284cfb3798b112b9a94debf0302bc91d0c01" + integrity sha512-cBI5I69b7nfnVvkn9WEDt31jnt/AebLKrtWiCDmGLkm9PUxl+x/RXdBTnc68JKn50rRIhFeqhfJwTXrjHA2koA== dependencies: axios "^1.7.4" crypto-js "^4.2.0" From 379a4ff7298273be4f8dc0789f133d3433af3e34 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 31 Oct 2024 12:01:52 +0200 Subject: [PATCH 03/16] Bump version to 1.28 --- package.json | 4 ++-- yarn.lock | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index cbd521a2a4..5a24deb8db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "temple-wallet", - "version": "1.27.0", + "version": "1.28.0", "private": true, "scripts": { "start-run": "cross-env TS_NODE_PROJECT=\"webpack/tsconfig.json\" webpack --watch --stats errors-warnings", @@ -232,6 +232,6 @@ "follow-redirects": "^1.15.4" }, "optionalDependencies": { - "@temple-wallet/extension-ads": "9.0.0-dev.1562.3" + "@temple-wallet/extension-ads": "9.1.0" } } diff --git a/yarn.lock b/yarn.lock index 07b862bdb2..2c5f84ced4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3657,10 +3657,10 @@ dependencies: nanoid "^3.1.25" -"@temple-wallet/extension-ads@9.0.0-dev.1562.3": - version "9.0.0-dev.1562.3" - resolved "https://registry.yarnpkg.com/@temple-wallet/extension-ads/-/extension-ads-9.0.0-dev.1562.3.tgz#ca6f284cfb3798b112b9a94debf0302bc91d0c01" - integrity sha512-cBI5I69b7nfnVvkn9WEDt31jnt/AebLKrtWiCDmGLkm9PUxl+x/RXdBTnc68JKn50rRIhFeqhfJwTXrjHA2koA== +"@temple-wallet/extension-ads@9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@temple-wallet/extension-ads/-/extension-ads-9.1.0.tgz#dc3e786584b26528604f5ffa629090da4a7d0838" + integrity sha512-2m5vgvfp3FnY6mt8e0cf9S1H6uDB7D9OWiiSJv5OJpxuTfo+IGbxmcqmDZVXK292qgxpvuZxCopDZfObZbUg/A== dependencies: axios "^1.7.4" crypto-js "^4.2.0" From f6419a2ff41b9ac1762ac8b49565cd981ac3ff37 Mon Sep 17 00:00:00 2001 From: Danyl Mishyn <35381314+lendihop@users.noreply.github.com> Date: Mon, 2 Dec 2024 13:35:10 +0100 Subject: [PATCH 04/16] TW-1588: Referral links improvements (#1232) * form ux changes * add redux state migration * update version * sync background script constant * cancel migration if advertising checkbox is enabled * fix audit --- package.json | 1 + public/_locales/en/messages.json | 8 ++-- ...se-user-analytics-and-ads-settings.hook.ts | 18 ++++++-- .../setWalletPassword/SetWalletPassword.tsx | 25 ++++++----- src/app/store/index.ts | 2 +- src/app/store/migrations.ts | 19 ++++++++ .../referral-links-settings.tsx | 3 -- yarn.lock | 45 +++---------------- 8 files changed, 58 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index 5a24deb8db..e0f232dffd 100644 --- a/package.json +++ b/package.json @@ -217,6 +217,7 @@ "source-map": "^0.7.4" }, "resolutions": { + "npm-run-all/cross-spawn": "^7.0.6", "tslib": "^2.4.0", "@types/react": "18.0.15", "@types/react-dev-utils/@types/webpack-dev-server": "^4", diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index dc8aa1fab4..222063a918 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -3160,11 +3160,11 @@ "selectedAccountCannotSignTx": { "message": "Selected account cannot sign transactions" }, "attributes": { "message": "Attributes" }, "properties": { "message": "Properties" }, - "earnRewardsWithAds": { - "message": "Earn Rewards with Ads" + "earnTkeyRewards": { + "message": "Earn TKEY Rewards" }, - "earnRewardsWithAdsDescription": { - "message": "I agree to share my wallet address and IP to receive ads and rewards in TKEY token." + "earnTkeyRewardsDescription": { + "message": "I agree to share my wallet address and IP to receive ads, referral links and rewards in TKEY token." }, "dropdownNoItems": { "message": "No items" diff --git a/src/app/hooks/use-user-analytics-and-ads-settings.hook.ts b/src/app/hooks/use-user-analytics-and-ads-settings.hook.ts index 187eb872ed..1d5b43f177 100644 --- a/src/app/hooks/use-user-analytics-and-ads-settings.hook.ts +++ b/src/app/hooks/use-user-analytics-and-ads-settings.hook.ts @@ -1,24 +1,27 @@ import { useEffect, useRef } from 'react'; import { useShouldShowPartnersPromoSelector } from 'app/store/partners-promotion/selectors'; -import { useAnalyticsEnabledSelector } from 'app/store/settings/selectors'; +import { useReferralLinksEnabledSelector } from 'app/store/settings/selectors'; import { useAnalytics } from 'lib/analytics'; -import { WEBSITES_ANALYTICS_ENABLED } from 'lib/constants'; +import { REPLACE_REFERRALS_ENABLED, WEBSITES_ANALYTICS_ENABLED } from 'lib/constants'; import { AnalyticsEventCategory } from 'lib/temple/analytics-types'; import { useAccountPkh } from 'lib/temple/front'; import { usePassiveStorage } from 'lib/temple/front/storage'; export const useUserAnalyticsAndAdsSettings = () => { const { trackEvent } = useAnalytics(); - const isAnalyticsEnabled = useAnalyticsEnabledSelector(); const isAdsEnabled = useShouldShowPartnersPromoSelector(); + const isReferralLinksEnabled = useReferralLinksEnabledSelector(); const [, setIsWebsitesAnalyticsEnabled] = usePassiveStorage(WEBSITES_ANALYTICS_ENABLED); + const [, setIsReplaceReferralsEnabled] = usePassiveStorage(REPLACE_REFERRALS_ENABLED); + const prevAdsEnabledRef = useRef(isAdsEnabled); const accountPkh = useAccountPkh(); useEffect(() => { setIsWebsitesAnalyticsEnabled(isAdsEnabled); + setIsReplaceReferralsEnabled(isReferralLinksEnabled); // It happens when the wallet is not ready although `registerWallet` promise has been resolved if (typeof accountPkh !== 'string') { @@ -30,5 +33,12 @@ export const useUserAnalyticsAndAdsSettings = () => { } prevAdsEnabledRef.current = isAdsEnabled; - }, [isAdsEnabled, setIsWebsitesAnalyticsEnabled, trackEvent, accountPkh, isAnalyticsEnabled]); + }, [ + isAdsEnabled, + isReferralLinksEnabled, + setIsWebsitesAnalyticsEnabled, + setIsReplaceReferralsEnabled, + trackEvent, + accountPkh + ]); }; diff --git a/src/app/pages/NewWallet/setWalletPassword/SetWalletPassword.tsx b/src/app/pages/NewWallet/setWalletPassword/SetWalletPassword.tsx index ba2d5d7c6d..43d5b96db5 100644 --- a/src/app/pages/NewWallet/setWalletPassword/SetWalletPassword.tsx +++ b/src/app/pages/NewWallet/setWalletPassword/SetWalletPassword.tsx @@ -50,8 +50,8 @@ interface FormData extends TestIDProps { password?: string; repeatPassword?: string; termsAccepted: boolean; - analytics?: boolean; - earnRewardsWithAds: boolean; + analytics: boolean; + earnTkeyRewards: boolean; testID?: string; } @@ -102,7 +102,7 @@ export const SetWalletPassword: FC = ({ defaultValues: { shouldUseKeystorePassword: !isKeystorePasswordWeak, analytics: true, - earnRewardsWithAds: true + earnTkeyRewards: true }, mode: 'onChange' }); @@ -140,20 +140,21 @@ export const SetWalletPassword: FC = ({ : data.password : data.password; try { - const shouldEnableAnalytics = Boolean(data.analytics); - const adsViewEnabled = data.earnRewardsWithAds; + const analyticsEnabled = data.analytics; + const adsViewEnabled = data.earnTkeyRewards; + + setAnalyticsEnabled(analyticsEnabled); setAdsViewEnabled(adsViewEnabled); - setAnalyticsEnabled(shouldEnableAnalytics); - setReferralLinksEnabled(true); + setReferralLinksEnabled(adsViewEnabled); setTermsAccepted(); await setOnboardingCompleted(true); const accountPkh = await registerWallet(password!, formatMnemonic(seedPhrase)); // registerWallet function clears async storages - await putToStorage(REPLACE_REFERRALS_ENABLED, true); + await putToStorage(REPLACE_REFERRALS_ENABLED, adsViewEnabled); await putToStorage(WEBSITES_ANALYTICS_ENABLED, adsViewEnabled); - trackEvent('AnalyticsEnabled', AnalyticsEventCategory.General, { accountPkh }, shouldEnableAnalytics); + trackEvent('AnalyticsEnabled', AnalyticsEventCategory.General, { accountPkh }, analyticsEnabled); trackEvent('AdsEnabled', AnalyticsEventCategory.General, { accountPkh }, adsViewEnabled); navigate('/loading'); @@ -287,10 +288,10 @@ export const SetWalletPassword: FC = ({ } + label={t('earnTkeyRewards')} + labelDescription={} testID={setWalletPasswordSelectors.viewAdsCheckBox} /> diff --git a/src/app/store/index.ts b/src/app/store/index.ts index 152ccb5414..64a5737931 100644 --- a/src/app/store/index.ts +++ b/src/app/store/index.ts @@ -24,7 +24,7 @@ const persistConfigBlacklist: (keyof RootState)[] = SLICES_BLACKLIST; const persistedReducer = persistReducer( { key: 'temple-root', - version: 4, + version: 5, ...storageConfig, stateReconciler: autoMergeLevel2, blacklist: persistConfigBlacklist, diff --git a/src/app/store/migrations.ts b/src/app/store/migrations.ts index 1fbaf66026..54092de9e7 100644 --- a/src/app/store/migrations.ts +++ b/src/app/store/migrations.ts @@ -2,6 +2,7 @@ import { cloneDeep } from 'lodash'; import type { MigrationManifest, PersistedState } from 'redux-persist'; import { toTokenSlug } from 'lib/assets'; +import { IS_MISES_BROWSER } from 'lib/env'; import { isCollectible } from 'lib/metadata'; import { collectiblesMetadataInitialState } from './collectibles-metadata/state'; @@ -99,6 +100,24 @@ export const MIGRATIONS: MigrationManifest = { } }; + return newState; + }, + + '5': (persistedState: PersistedState) => { + if (!persistedState || IS_MISES_BROWSER) return persistedState; + + const typedPersistedState = persistedState as TypedPersistedRootState; + + if (typedPersistedState.partnersPromotion.shouldShowPromotion) return persistedState; + + const newState: TypedPersistedRootState = { + ...typedPersistedState, + settings: { + ...typedPersistedState.settings, + referralLinksEnabled: false + } + }; + return newState; } }; diff --git a/src/app/templates/AdvancedFeatures/referral-links-settings.tsx b/src/app/templates/AdvancedFeatures/referral-links-settings.tsx index 0e219d1d53..b542b609e3 100644 --- a/src/app/templates/AdvancedFeatures/referral-links-settings.tsx +++ b/src/app/templates/AdvancedFeatures/referral-links-settings.tsx @@ -7,12 +7,10 @@ import { useAcceptedTermsVersionSelector, useReferralLinksEnabledSelector } from import { PRIVACY_POLICY_URL, RECENT_TERMS_VERSION, - REPLACE_REFERRALS_ENABLED, TERMS_OF_USE_URL, TERMS_WITH_REFERRALS_VERSION } from 'lib/constants'; import { t, T } from 'lib/i18n'; -import { putToStorage } from 'lib/storage'; import { useConfirm } from 'lib/ui/dialog'; import { EnablingSetting } from '../EnablingSetting'; @@ -65,7 +63,6 @@ export const ReferralLinksSettings = memo(() => { dispatch(setAcceptedTermsVersionAction(RECENT_TERMS_VERSION)); dispatch(setReferralLinksEnabledAction(toChecked)); - putToStorage(REPLACE_REFERRALS_ENABLED, toChecked); }, [acceptedTermsVersion, confirm, dispatch] ); diff --git a/yarn.lock b/yarn.lock index 2c5f84ced4..4b8262e0bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6605,21 +6605,10 @@ cross-fetch@^3.0.4, cross-fetch@^3.1.5: dependencies: node-fetch "^2.6.12" -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== +cross-spawn@^6.0.5, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" @@ -10738,11 +10727,6 @@ next-tick@1, next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -11215,11 +11199,6 @@ path-is-inside@^1.0.2: resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -12863,7 +12842,7 @@ selfsigned@^2.4.1: "@types/node-forge" "^1.3.0" node-forge "^1" -"semver@2 || 3 || 4 || 5", semver@^5.5.0: +"semver@2 || 3 || 4 || 5": version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== @@ -13003,13 +12982,6 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -13017,11 +12989,6 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -14579,7 +14546,7 @@ which-typed-array@^1.1.13, which-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.0" -which@^1.2.9, which@^1.3.1: +which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== From 6e8145e85be2f9062a076773534e7c4a2b280fe0 Mon Sep 17 00:00:00 2001 From: Inokentii Mazhara Date: Mon, 2 Dec 2024 14:47:39 +0200 Subject: [PATCH 05/16] TW-1589: Prevent infinite spawning empty divs when an ad fails to load (#1226) * Update @temple-wallet/extension-ads * Update @temple-wallet/extension-ads --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e0f232dffd..b30b5f3756 100644 --- a/package.json +++ b/package.json @@ -233,6 +233,6 @@ "follow-redirects": "^1.15.4" }, "optionalDependencies": { - "@temple-wallet/extension-ads": "9.1.0" + "@temple-wallet/extension-ads": "9.1.1-dev.1589.2" } } diff --git a/yarn.lock b/yarn.lock index 4b8262e0bc..638e8b2c7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3657,10 +3657,10 @@ dependencies: nanoid "^3.1.25" -"@temple-wallet/extension-ads@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@temple-wallet/extension-ads/-/extension-ads-9.1.0.tgz#dc3e786584b26528604f5ffa629090da4a7d0838" - integrity sha512-2m5vgvfp3FnY6mt8e0cf9S1H6uDB7D9OWiiSJv5OJpxuTfo+IGbxmcqmDZVXK292qgxpvuZxCopDZfObZbUg/A== +"@temple-wallet/extension-ads@9.1.1-dev.1589.2": + version "9.1.1-dev.1589.2" + resolved "https://registry.yarnpkg.com/@temple-wallet/extension-ads/-/extension-ads-9.1.1-dev.1589.2.tgz#6f57e8881016769018671ddfcaa2417647d74d45" + integrity sha512-upUeIqLT5L3z5loTM4kTEWLYKldYV7j23aa/tpL/7VNknGGvGWP1wzu3rge+FSYg7pex6swmQpV1URrdpbxLQA== dependencies: axios "^1.7.4" crypto-js "^4.2.0" From 86f39ce02cef1f2fa312b2703ec1bb92b6df7a64 Mon Sep 17 00:00:00 2001 From: Inokentii Mazhara Date: Mon, 2 Dec 2024 15:12:24 +0200 Subject: [PATCH 06/16] TW-1563: Implement theming for native ads that support it (#1227) * TW-1563 Implement theming for native ads that support it * TW-1563 Revert early version increment * Bump tw-ext-ads dep version --------- Co-authored-by: Alex --- package.json | 2 +- .../replace-ads/ads-stack.iframe.ts | 27 +++++++++---- src/lib/ads/configure-ads.ts | 40 +++++++++++++++++-- src/lib/constants.ts | 4 ++ yarn.lock | 8 ++-- 5 files changed, 65 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index b30b5f3756..c7bb96950d 100644 --- a/package.json +++ b/package.json @@ -233,6 +233,6 @@ "follow-redirects": "^1.15.4" }, "optionalDependencies": { - "@temple-wallet/extension-ads": "9.1.1-dev.1589.2" + "@temple-wallet/extension-ads": "10.0.1" } } diff --git a/src/content-scripts/replace-ads/ads-stack.iframe.ts b/src/content-scripts/replace-ads/ads-stack.iframe.ts index 9ab9ef8015..cd274abc05 100644 --- a/src/content-scripts/replace-ads/ads-stack.iframe.ts +++ b/src/content-scripts/replace-ads/ads-stack.iframe.ts @@ -1,11 +1,21 @@ import { configureAds } from 'lib/ads/configure-ads'; import { importExtensionAdsModule } from 'lib/ads/import-extension-ads-module'; -import { ADS_META_SEARCH_PARAM_NAME, AD_CATEGORIES_PARAM_NAME, ORIGIN_SEARCH_PARAM_NAME } from 'lib/constants'; +import { + ADS_META_SEARCH_PARAM_NAME, + AD_CATEGORIES_PARAM_NAME, + FONT_SIZE_SEARCH_PARAM_NAME, + LINE_HEIGHT_SEARCH_PARAM_NAME, + ORIGIN_SEARCH_PARAM_NAME, + THEME_COLOR_SEARCH_PARAM_NAME +} from 'lib/constants'; import { getRulesFromStorage } from './ads-rules'; const usp = new URLSearchParams(window.location.search); const id = usp.get('id'); +const rawThemeColor = usp.get(THEME_COLOR_SEARCH_PARAM_NAME); +const rawFontSize = usp.get(FONT_SIZE_SEARCH_PARAM_NAME); +const rawLineHeight = usp.get(LINE_HEIGHT_SEARCH_PARAM_NAME); const origin = usp.get(ORIGIN_SEARCH_PARAM_NAME) ?? window.location.href; const adsMetadataIds = usp.getAll(ADS_META_SEARCH_PARAM_NAME).map(value => JSON.parse(value)); const adCategories = usp.getAll(AD_CATEGORIES_PARAM_NAME); @@ -16,13 +26,16 @@ configureAds() .then(({ renderAdsStack, rules }) => { const { blacklistedHypelabCampaignsSlugs, permanentAdPlacesRules, adPlacesRules } = rules; - renderAdsStack( - id ?? '', - adsMetadataIds, + renderAdsStack({ + id: id ?? '', + initialAdsMetadata: adsMetadataIds, origin, - permanentAdPlacesRules.length > 0 || adPlacesRules.length > 0, + pageHasPlacesRules: permanentAdPlacesRules.length > 0 || adPlacesRules.length > 0, adCategories, - blacklistedHypelabCampaignsSlugs - ); + hypelabBlacklistedCampaignsSlugs: blacklistedHypelabCampaignsSlugs, + themeColor: rawThemeColor ?? undefined, + fontSize: rawFontSize ? Number(rawFontSize) : undefined, + lineHeight: rawLineHeight ? Number(rawLineHeight) : undefined + }); }) .catch(error => console.error(error)); diff --git a/src/lib/ads/configure-ads.ts b/src/lib/ads/configure-ads.ts index 667038c574..4dce82ea3e 100644 --- a/src/lib/ads/configure-ads.ts +++ b/src/lib/ads/configure-ads.ts @@ -5,14 +5,17 @@ import { ADS_META_SEARCH_PARAM_NAME, AD_CATEGORIES_PARAM_NAME, ContentScriptType, - ORIGIN_SEARCH_PARAM_NAME + FONT_SIZE_SEARCH_PARAM_NAME, + LINE_HEIGHT_SEARCH_PARAM_NAME, + ORIGIN_SEARCH_PARAM_NAME, + THEME_COLOR_SEARCH_PARAM_NAME } from 'lib/constants'; import { APP_VERSION, EnvVars, IS_MISES_BROWSER } from 'lib/env'; import { isTruthy } from 'lib/utils'; import { importExtensionAdsModule } from './import-extension-ads-module'; -// Three interfaces below are copied from '@temple-wallet/extension-ads' to avoid importing it to ensure that a core +// Four interfaces below are copied from '@temple-wallet/extension-ads' to avoid importing it to ensure that a core // build runs without errors. interface AdSource { shouldNotUseStrictContainerLimits?: boolean; @@ -36,6 +39,16 @@ interface AdMetadata { dimensions: AdDimensions; } +interface AdsStackIframeURLParams { + id: string; + adsMetadataIds: any[]; + origin: string; + adCategories: string[]; + themeColor?: string; + fontSize?: number; + lineHeight?: number; +} + const smallTkeyInpageAdUrl = browser.runtime.getURL(`/misc/ad-banners/small-tkey-inpage-ad.png`); const tkeyInpageAdUrl = browser.runtime.getURL(`/misc/ad-banners/tkey-inpage-ad.png`); @@ -45,9 +58,28 @@ const swapTkeyUrl = `${browser.runtime.getURL('fullpage.html')}#/swap?${buildSwa true )}`; -const getAdsStackIframeURL = (id: string, adsMetadataIds: any[], origin: string, adCategories: string[]) => { +const searchParamsNames = { + id: 'id', + themeColor: THEME_COLOR_SEARCH_PARAM_NAME, + fontSize: FONT_SIZE_SEARCH_PARAM_NAME, + lineHeight: LINE_HEIGHT_SEARCH_PARAM_NAME +}; + +const getAdsStackIframeURL = ({ + adsMetadataIds, + origin, + adCategories, + ...plainSearchParamsInput +}: AdsStackIframeURLParams) => { const url = new URL(browser.runtime.getURL('iframes/ads-stack.html')); - url.searchParams.set('id', id); + for (const searchParamsInputName in plainSearchParamsInput) { + const searchParamsInputNameTyped = searchParamsInputName as keyof typeof plainSearchParamsInput; + const key = searchParamsNames[searchParamsInputNameTyped]; + const value = plainSearchParamsInput[searchParamsInputNameTyped]; + if (value || value === 0) { + url.searchParams.set(key, String(value)); + } + } adsMetadataIds.forEach(adMetadataId => url.searchParams.append(ADS_META_SEARCH_PARAM_NAME, JSON.stringify(adMetadataId)) ); diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 054dc9e08b..a7da071008 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -53,3 +53,7 @@ export const searchHotkey = ` (${isMacOS ? '⌘' : 'Ctrl + '}K)`; export const FEE_PER_GAS_UNIT = 0.1; export const LIQUIDITY_BAKING_DEX_ADDRESS = 'KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5'; + +export const THEME_COLOR_SEARCH_PARAM_NAME = 'tc'; +export const FONT_SIZE_SEARCH_PARAM_NAME = 'fs'; +export const LINE_HEIGHT_SEARCH_PARAM_NAME = 'lh'; diff --git a/yarn.lock b/yarn.lock index 638e8b2c7b..b566e0bc27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3657,10 +3657,10 @@ dependencies: nanoid "^3.1.25" -"@temple-wallet/extension-ads@9.1.1-dev.1589.2": - version "9.1.1-dev.1589.2" - resolved "https://registry.yarnpkg.com/@temple-wallet/extension-ads/-/extension-ads-9.1.1-dev.1589.2.tgz#6f57e8881016769018671ddfcaa2417647d74d45" - integrity sha512-upUeIqLT5L3z5loTM4kTEWLYKldYV7j23aa/tpL/7VNknGGvGWP1wzu3rge+FSYg7pex6swmQpV1URrdpbxLQA== +"@temple-wallet/extension-ads@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@temple-wallet/extension-ads/-/extension-ads-10.0.1.tgz#76a05a83b037ad539d2a67a271ddb1cc35025660" + integrity sha512-rRY2xFvSwJXhLLOeOmxfJqprAGfPtpoWOmFxgF1Rx/f3ajogqNYcYH0dLn8Q3T8Vit2xzr5T4S7BdzDbLijNSQ== dependencies: axios "^1.7.4" crypto-js "^4.2.0" From 4353481d21fbbf387173f60c3827d818fb555cdc Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 2 Dec 2024 15:15:01 +0200 Subject: [PATCH 07/16] Bump version to 1.29 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c7bb96950d..b7c9916d3d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "temple-wallet", - "version": "1.28.0", + "version": "1.29.0", "private": true, "scripts": { "start-run": "cross-env TS_NODE_PROJECT=\"webpack/tsconfig.json\" webpack --watch --stats errors-warnings", From 80825937205b722d7cb2dfd369e2934281c899fb Mon Sep 17 00:00:00 2001 From: Danyl Mishyn <35381314+lendihop@users.noreply.github.com> Date: Tue, 10 Dec 2024 10:20:23 +0100 Subject: [PATCH 08/16] TW-1605: Apply Christmas theme (#1236) * Revert "TW-1262: Revert "TW-1219: Christmas theme (#1035)" (#1054)" This reverts commit e7e71851 * rm pkg --- src/app/layouts/PageLayout/Header.tsx | 25 +- src/app/layouts/SimplePageLayout.tsx | 37 ++- src/app/misc/christmas-popup-bg.png | Bin 0 -> 18955 bytes src/app/misc/logo-title.svg | 384 ++++++-------------------- src/app/misc/logo-white-title.svg | 341 ++++++----------------- src/app/misc/logo-white.svg | 291 ++++++------------- 6 files changed, 295 insertions(+), 783 deletions(-) create mode 100644 src/app/misc/christmas-popup-bg.png diff --git a/src/app/layouts/PageLayout/Header.tsx b/src/app/layouts/PageLayout/Header.tsx index 7cc34fbfde..74ace52a07 100644 --- a/src/app/layouts/PageLayout/Header.tsx +++ b/src/app/layouts/PageLayout/Header.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react'; +import React, { FC, useMemo } from 'react'; import classNames from 'clsx'; @@ -18,22 +18,19 @@ import styles from './Header.module.css'; import { HeaderSelectors } from './Header.selectors'; const Header: FC = () => { - const appEnv = useAppEnv(); + const { fullPage } = useAppEnv(); const { ready } = useTempleClient(); - return ( -
- -
-
- -
- -
- + const logoStyles = useMemo(() => ({ height: fullPage ? 64 : 52, marginTop: 0, marginBottom: 0 }), [fullPage]); - {ready && } -
+ return ( +
+ +
+ + + +
{ready && }
diff --git a/src/app/layouts/SimplePageLayout.tsx b/src/app/layouts/SimplePageLayout.tsx index d9b25eb269..99c9a9e031 100644 --- a/src/app/layouts/SimplePageLayout.tsx +++ b/src/app/layouts/SimplePageLayout.tsx @@ -6,43 +6,50 @@ import DocBg from 'app/a11y/DocBg'; import Logo from 'app/atoms/Logo'; import { useAppEnv } from 'app/env'; import ContentContainer from 'app/layouts/ContentContainer'; +import ChristmasBgPopupImg from 'app/misc/christmas-popup-bg.png'; + +const logoStyles = { height: 64, marginTop: 0, marginBottom: 0 }; interface SimplePageLayoutProps extends PropsWithChildren { title: ReactNode; } const SimplePageLayout: FC = ({ title, children }) => { - const appEnv = useAppEnv(); + const { popup } = useAppEnv(); return ( <> - {!appEnv.fullPage && } - - -
-
- + {popup && } + + +
+
+
-
+
{title}
{children}
-
+
); diff --git a/src/app/misc/christmas-popup-bg.png b/src/app/misc/christmas-popup-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..a2e758948e8506832d8efeddec87c7e685f5077b GIT binary patch literal 18955 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 literal 0 HcmV?d00001 diff --git a/src/app/misc/logo-title.svg b/src/app/misc/logo-title.svg index cada7ca79c..6603f12969 100644 --- a/src/app/misc/logo-title.svg +++ b/src/app/misc/logo-title.svg @@ -1,294 +1,92 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/misc/logo-white-title.svg b/src/app/misc/logo-white-title.svg index 1a54fe4396..74d40ed5dc 100644 --- a/src/app/misc/logo-white-title.svg +++ b/src/app/misc/logo-white-title.svg @@ -1,251 +1,92 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/misc/logo-white.svg b/src/app/misc/logo-white.svg index 335758ef15..d7f2d11ef4 100644 --- a/src/app/misc/logo-white.svg +++ b/src/app/misc/logo-white.svg @@ -1,212 +1,81 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 35c95f8473cb60bfb01b4fb68b51337b0f8c4e38 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 10 Dec 2024 11:23:33 +0200 Subject: [PATCH 09/16] Bump version to 1.30.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b7c9916d3d..2837f8798e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "temple-wallet", - "version": "1.29.0", + "version": "1.30.0", "private": true, "scripts": { "start-run": "cross-env TS_NODE_PROJECT=\"webpack/tsconfig.json\" webpack --watch --stats errors-warnings", From 73a0de2610872455a5a7ee315b2d24d3b5587f34 Mon Sep 17 00:00:00 2001 From: Inokentii Mazhara Date: Mon, 23 Dec 2024 18:03:38 +0200 Subject: [PATCH 10/16] TW-1615: Make limits for dexes amount in a swap stricter (#1240) --- src/app/templates/SwapForm/SwapForm.tsx | 26 ++++++++++++------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/app/templates/SwapForm/SwapForm.tsx b/src/app/templates/SwapForm/SwapForm.tsx index 474d26a691..de8cd6a7ea 100644 --- a/src/app/templates/SwapForm/SwapForm.tsx +++ b/src/app/templates/SwapForm/SwapForm.tsx @@ -58,10 +58,10 @@ import { slippageToleranceInputValidationFn } from './SwapFormInput/SlippageTole import { SwapFormInput } from './SwapFormInput/SwapFormInput'; import { SwapMinimumReceived } from './SwapMinimumReceived/SwapMinimumReceived'; -// These values have been set after some experimentation. They are different to the respective values in -// templewallet-mobile because the mobile app still uses taquito v19.0.0, which has a different gas estimation algorithm. -const SINGLE_SWAP_IN_BATCH_MAX_DEXES = 12; -const LB_OPERATION_DEXES_COST = 3; +const CASHBACK_SWAP_MAX_DEXES = 3; +// Actually, at most 2 dexes for each of underlying SIRS -> tzBTC -> X swap and SIRS -> XTZ -> X swap +const MAIN_SIRS_SWAP_MAX_DEXES = 4; +const MAIN_NON_SIRS_SWAP_MAX_DEXES = 3; export const SwapForm: FC = () => { const dispatch = useDispatch(); @@ -134,17 +134,13 @@ export const SwapForm: FC = () => { const isOutputTokenTempleToken = outputAssetSlug === KNOWN_TOKENS_SLUGS.TEMPLE; const isSirsSwap = inputAssetSlug === KNOWN_TOKENS_SLUGS.SIRS || outputAssetSlug === KNOWN_TOKENS_SLUGS.SIRS; const isSwapAmountMoreThreshold = inputAmountInUsd.isGreaterThanOrEqualTo(SWAP_THRESHOLD_TO_GET_CASHBACK); - const totalMaxDexes = SINGLE_SWAP_IN_BATCH_MAX_DEXES - (isSirsSwap ? LB_OPERATION_DEXES_COST : 0); - const cashbackSwapMaxDexes = Math.ceil(totalMaxDexes / (isSirsSwap ? 3 : 2)); - const mainSwapMaxDexes = - totalMaxDexes - (isSwapAmountMoreThreshold && !isInputTokenTempleToken ? cashbackSwapMaxDexes : 0); + const mainSwapMaxDexes = isSirsSwap ? MAIN_SIRS_SWAP_MAX_DEXES : MAIN_NON_SIRS_SWAP_MAX_DEXES; return { isInputTokenTempleToken, isOutputTokenTempleToken, isSwapAmountMoreThreshold, - mainSwapMaxDexes, - cashbackSwapMaxDexes + mainSwapMaxDexes }; }, [allUsdToTokenRates] @@ -321,8 +317,10 @@ export const SwapForm: FC = () => { return; } - const { isInputTokenTempleToken, isOutputTokenTempleToken, isSwapAmountMoreThreshold, cashbackSwapMaxDexes } = - getSwapWithFeeParams(inputValue, outputValue); + const { isInputTokenTempleToken, isOutputTokenTempleToken, isSwapAmountMoreThreshold } = getSwapWithFeeParams( + inputValue, + outputValue + ); if (isInputTokenTempleToken && isSwapAmountMoreThreshold) { const routingInputFeeOpParams = await getRoutingFeeTransferParams( @@ -348,7 +346,7 @@ export const SwapForm: FC = () => { toSymbol: TEMPLE_TOKEN.symbol, toTokenDecimals: TEMPLE_TOKEN.decimals, amount: atomsToTokens(routingFeeFromInputAtomic, fromRoute3Token.decimals).toFixed(), - dexesLimit: cashbackSwapMaxDexes, + dexesLimit: CASHBACK_SWAP_MAX_DEXES, rpcUrl: tezos.rpc.getRpcUrl() }); @@ -393,7 +391,7 @@ export const SwapForm: FC = () => { toSymbol: TEMPLE_TOKEN.symbol, toTokenDecimals: TEMPLE_TOKEN.decimals, amount: atomsToTokens(routingFeeFromOutputAtomic, toRoute3Token.decimals).toFixed(), - dexesLimit: cashbackSwapMaxDexes, + dexesLimit: CASHBACK_SWAP_MAX_DEXES, rpcUrl: tezos.rpc.getRpcUrl() }); From 7298c6e63822a629069ed94bc39a38cbd24358fe Mon Sep 17 00:00:00 2001 From: Inokentii Mazhara Date: Mon, 23 Dec 2024 18:04:01 +0200 Subject: [PATCH 11/16] TW-1599: Rewards page (#1239) * TW-1599 Add layout for 'Rewards' page * TW-1599 Implement fetching rewards * TW-1599 Remove an unused property * TW-1599 Refactoring according to comments * TW-1599 Implement star animation as a webm video * TW-1599 Fix star animation for Chrome --- public/_locales/en/messages.json | 39 +++++ src/app/PageRouter.tsx | 2 + .../atoms/DonationBanner/DonationBanner.tsx | 28 ---- src/app/atoms/DonationBanner/selectors.ts | 3 - .../hooks/use-partners-promotion-settings.tsx | 47 ++++++ src/app/hooks/use-referral-links-settings.tsx | 67 +++++++++ src/app/icons/triangle-down.svg | 4 + src/app/layouts/PageLayout.selectors.ts | 3 +- src/app/layouts/PageLayout.tsx | 25 +--- .../RewardsButton/firefox-star-animation.tsx | 39 +++++ .../PageLayout/RewardsButton/index.tsx | 34 +++++ .../RewardsButton/star-animation.tsx | 65 +++++++++ .../RewardsButton/star_animation.webm | Bin 0 -> 224818 bytes .../RewardsButton/star_animation_poster.gif | Bin 0 -> 216 bytes .../RewardsButton/star_animation_small.gif | Bin 0 -> 6885 bytes src/app/pages/Home/Home.tsx | 1 - src/app/pages/Rewards/achievements/index.tsx | 24 +++ src/app/pages/Rewards/active-features/ads.svg | 3 + .../Rewards/active-features/disabled.svg | 3 + .../pages/Rewards/active-features/enabled.svg | 3 + .../Rewards/active-features/feature-item.tsx | 76 ++++++++++ .../pages/Rewards/active-features/icon_bg.svg | 3 + .../pages/Rewards/active-features/index.tsx | 41 ++++++ .../Rewards/active-features/referrals.svg | 3 + src/app/pages/Rewards/index.tsx | 92 ++++++++++++ .../pages/Rewards/lifetime-earnings/index.tsx | 138 ++++++++++++++++++ .../pages/Rewards/recent-earnings/index.tsx | 54 +++++++ .../recent-earnings.module.css | 9 ++ .../Rewards/recent-earnings/stats-card.tsx | 70 +++++++++ src/app/pages/Rewards/section.tsx | 32 ++++ src/app/pages/Rewards/selectors.ts | 8 + src/app/pages/Rewards/tooltip.tsx | 33 +++++ src/app/pages/Rewards/utils.ts | 7 + src/app/store/rewards/actions.ts | 22 +++ src/app/store/rewards/epics.ts | 44 ++++++ src/app/store/rewards/reducers.ts | 35 +++++ src/app/store/rewards/selectors.ts | 47 ++++++ src/app/store/rewards/state.mock.ts | 7 + src/app/store/rewards/state.ts | 14 ++ src/app/store/root-state.epics.ts | 4 +- src/app/store/root-state.mock.ts | 4 +- src/app/store/root-state.reducer.ts | 4 +- .../partners-promotion-settings.tsx | 49 +------ .../referral-links-settings.tsx | 68 +-------- src/lib/apis/ads-api.ts | 58 ++++++-- src/lib/apis/utils.ts | 9 ++ src/lib/icons/assets/bell-read.svg | 16 ++ src/lib/icons/assets/bell-unread.svg | 20 +++ src/lib/icons/index.ts | 2 + src/lib/notifications/components/bell.tsx | 20 +-- src/lib/utils/numbers.ts | 2 + tailwind.config.js | 4 + 52 files changed, 1199 insertions(+), 186 deletions(-) delete mode 100644 src/app/atoms/DonationBanner/DonationBanner.tsx delete mode 100644 src/app/atoms/DonationBanner/selectors.ts create mode 100644 src/app/hooks/use-partners-promotion-settings.tsx create mode 100644 src/app/hooks/use-referral-links-settings.tsx create mode 100644 src/app/icons/triangle-down.svg create mode 100644 src/app/layouts/PageLayout/RewardsButton/firefox-star-animation.tsx create mode 100644 src/app/layouts/PageLayout/RewardsButton/index.tsx create mode 100644 src/app/layouts/PageLayout/RewardsButton/star-animation.tsx create mode 100644 src/app/layouts/PageLayout/RewardsButton/star_animation.webm create mode 100644 src/app/layouts/PageLayout/RewardsButton/star_animation_poster.gif create mode 100644 src/app/layouts/PageLayout/RewardsButton/star_animation_small.gif create mode 100644 src/app/pages/Rewards/achievements/index.tsx create mode 100644 src/app/pages/Rewards/active-features/ads.svg create mode 100644 src/app/pages/Rewards/active-features/disabled.svg create mode 100644 src/app/pages/Rewards/active-features/enabled.svg create mode 100644 src/app/pages/Rewards/active-features/feature-item.tsx create mode 100644 src/app/pages/Rewards/active-features/icon_bg.svg create mode 100644 src/app/pages/Rewards/active-features/index.tsx create mode 100644 src/app/pages/Rewards/active-features/referrals.svg create mode 100644 src/app/pages/Rewards/index.tsx create mode 100644 src/app/pages/Rewards/lifetime-earnings/index.tsx create mode 100644 src/app/pages/Rewards/recent-earnings/index.tsx create mode 100644 src/app/pages/Rewards/recent-earnings/recent-earnings.module.css create mode 100644 src/app/pages/Rewards/recent-earnings/stats-card.tsx create mode 100644 src/app/pages/Rewards/section.tsx create mode 100644 src/app/pages/Rewards/selectors.ts create mode 100644 src/app/pages/Rewards/tooltip.tsx create mode 100644 src/app/pages/Rewards/utils.ts create mode 100644 src/app/store/rewards/actions.ts create mode 100644 src/app/store/rewards/epics.ts create mode 100644 src/app/store/rewards/reducers.ts create mode 100644 src/app/store/rewards/selectors.ts create mode 100644 src/app/store/rewards/state.mock.ts create mode 100644 src/app/store/rewards/state.ts create mode 100644 src/lib/apis/utils.ts create mode 100644 src/lib/icons/assets/bell-read.svg create mode 100644 src/lib/icons/assets/bell-unread.svg diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index 222063a918..fea6aff841 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -3168,5 +3168,44 @@ }, "dropdownNoItems": { "message": "No items" + }, + "earnings": { + "message": "Earnings" + }, + "earningsInfoTooltip": { + "message": "Earnings are only an estimation of your daily and monthly activity, including ad views and interactions with referral links. At the end of each month, your RP (reward points) will be converted into TKEY and distributed to your Tezos address. The more RP you accumulate, the greater your rewards will be." + }, + "ads": { + "message": "Ads" + }, + "today": { + "message": "Today" + }, + "activeFeatures": { + "message": "Active features" + }, + "advertisingFeatureDescription": { + "message": "Get RP by viewing ads" + }, + "advertisingFeatureTooltip": { + "message": "The advertising feature is used to display ads within Temple Wallet and on websites. To earn TKEY and enable ads, we request your permission to share your wallet address and IP, this information is used solely to serve you relevant ads and distribute rewards." + }, + "referralLinksFeatureDescription": { + "message": "Get RP while use favorite websites" + }, + "referralLinksFeatureTooltip": { + "message": "The referral links feature allows users to engage with affiliate offers from our partners. These offers will appear as links while you browse your favorite websites. To enable this feature, we request your permission to share your wallet address and IP address, this information is used solely to serve you relevant offers and distribute rewards." + }, + "achievements": { + "message": "Achievements" + }, + "lifetimeEarnings": { + "message": "Lifetime earnings" + }, + "noEarningsFound": { + "message": "No earnings found" + }, + "somethingWentWrong": { + "message": "Something went wrong" } } diff --git a/src/app/PageRouter.tsx b/src/app/PageRouter.tsx index 3097171b5d..69b6661f5c 100644 --- a/src/app/PageRouter.tsx +++ b/src/app/PageRouter.tsx @@ -30,6 +30,7 @@ import { Notifications, NotificationsItem } from 'lib/notifications/components'; import { useTempleClient } from 'lib/temple/front'; import * as Woozie from 'lib/woozie'; +import { RewardsPage } from './pages/Rewards'; import { StakingPage } from './pages/Staking'; import { WithDataLoading } from './WithDataLoading'; @@ -98,6 +99,7 @@ const ROUTE_MAP = Woozie.createMap([ ['/attention', onlyReady(onlyInFullPage(() => ))], ['/notifications', onlyReady(() => )], ['/notifications/:id', onlyReady(({ id }) => )], + ['/rewards', onlyReady(() => )], ['*', () => ] ]); diff --git a/src/app/atoms/DonationBanner/DonationBanner.tsx b/src/app/atoms/DonationBanner/DonationBanner.tsx deleted file mode 100644 index a3310101fb..0000000000 --- a/src/app/atoms/DonationBanner/DonationBanner.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { FC } from 'react'; - -import { Anchor } from 'app/atoms/Anchor'; -import { ReactComponent as Ukraine } from 'app/icons/ukraine.svg'; -import { T } from 'lib/i18n'; - -import { DonationBannerSelectors } from './selectors'; - -const DONATE_MAD_FISH_URL = 'https://donate.mad.fish'; - -export const DonationBanner: FC = () => ( - -
-
- - - -
-
- -
-
- -); diff --git a/src/app/atoms/DonationBanner/selectors.ts b/src/app/atoms/DonationBanner/selectors.ts deleted file mode 100644 index cc6fca5c88..0000000000 --- a/src/app/atoms/DonationBanner/selectors.ts +++ /dev/null @@ -1,3 +0,0 @@ -export enum DonationBannerSelectors { - ukraineDonationBanner = 'DonationBanner/Ukraine Donation Banner' -} diff --git a/src/app/hooks/use-partners-promotion-settings.tsx b/src/app/hooks/use-partners-promotion-settings.tsx new file mode 100644 index 0000000000..7ad32e9b02 --- /dev/null +++ b/src/app/hooks/use-partners-promotion-settings.tsx @@ -0,0 +1,47 @@ +import { ChangeEvent } from 'react'; + +import { useDispatch } from 'react-redux'; + +import { togglePartnersPromotionAction } from 'app/store/partners-promotion/actions'; +import { useShouldShowPartnersPromoSelector } from 'app/store/partners-promotion/selectors'; +import { t } from 'lib/i18n'; +import { useConfirm } from 'lib/ui/dialog'; + +export const usePartnersPromotionSettings = () => { + const dispatch = useDispatch(); + const confirm = useConfirm(); + + const isEnabled = useShouldShowPartnersPromoSelector(); + + const handleHidePromotion = async () => { + const confirmed = await confirm({ + title: t('closePartnersPromotion'), + children: t('closePartnersPromoConfirm'), + comfirmButtonText: t('disable') + }); + + if (confirmed) { + dispatch(togglePartnersPromotionAction(false)); + } + }; + + const handleShowPromotion = async () => { + const confirmed = await confirm({ + title: t('enablePartnersPromotionConfirm'), + children: t('enablePartnersPromotionDescriptionConfirm'), + comfirmButtonText: t('enable') + }); + + if (confirmed) { + dispatch(togglePartnersPromotionAction(true)); + } + }; + + const setEnabled = (toChecked: boolean, event?: ChangeEvent) => { + event?.preventDefault(); + + return toChecked ? handleShowPromotion() : handleHidePromotion(); + }; + + return { isEnabled, setEnabled }; +}; diff --git a/src/app/hooks/use-referral-links-settings.tsx b/src/app/hooks/use-referral-links-settings.tsx new file mode 100644 index 0000000000..309982e46c --- /dev/null +++ b/src/app/hooks/use-referral-links-settings.tsx @@ -0,0 +1,67 @@ +import React, { ChangeEvent, useCallback } from 'react'; + +import { useDispatch } from 'react-redux'; + +import { setAcceptedTermsVersionAction, setReferralLinksEnabledAction } from 'app/store/settings/actions'; +import { useAcceptedTermsVersionSelector, useReferralLinksEnabledSelector } from 'app/store/settings/selectors'; +import { + PRIVACY_POLICY_URL, + RECENT_TERMS_VERSION, + TERMS_OF_USE_URL, + TERMS_WITH_REFERRALS_VERSION +} from 'lib/constants'; +import { t, T } from 'lib/i18n'; +import { useConfirm } from 'lib/ui/dialog'; + +export const useReferralLinksSettings = () => { + const dispatch = useDispatch(); + const enabled = useReferralLinksEnabledSelector(); + const acceptedTermsVersion = useAcceptedTermsVersionSelector(); + const confirm = useConfirm(); + + const setEnabled = useCallback( + async (toChecked: boolean, event?: ChangeEvent) => { + event?.preventDefault(); + + if (toChecked && acceptedTermsVersion < TERMS_WITH_REFERRALS_VERSION) { + const confirmed = await confirm({ + title: , + description: ( + + + , + + + + ]} + /> + ), + comfirmButtonText: t('agreeAndContinue') + }); + + if (!confirmed) { + return; + } + } + + dispatch(setAcceptedTermsVersionAction(RECENT_TERMS_VERSION)); + dispatch(setReferralLinksEnabledAction(toChecked)); + }, + [acceptedTermsVersion, confirm, dispatch] + ); + + return { isEnabled: enabled, setEnabled }; +}; diff --git a/src/app/icons/triangle-down.svg b/src/app/icons/triangle-down.svg new file mode 100644 index 0000000000..cff0a93f49 --- /dev/null +++ b/src/app/icons/triangle-down.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/app/layouts/PageLayout.selectors.ts b/src/app/layouts/PageLayout.selectors.ts index 17e613c8e2..60e409f646 100644 --- a/src/app/layouts/PageLayout.selectors.ts +++ b/src/app/layouts/PageLayout.selectors.ts @@ -1,4 +1,5 @@ export enum PageLayoutSelectors { backButton = 'Page Layout/Back Button', - skipButton = 'Page Layout/Skip Button' + skipButton = 'Page Layout/Skip Button', + rewardsButton = 'Page Layout/Rewards Button' } diff --git a/src/app/layouts/PageLayout.tsx b/src/app/layouts/PageLayout.tsx index 0ecf2594a9..c3e81736d5 100644 --- a/src/app/layouts/PageLayout.tsx +++ b/src/app/layouts/PageLayout.tsx @@ -14,7 +14,6 @@ import clsx from 'clsx'; import DocBg from 'app/a11y/DocBg'; import { Button } from 'app/atoms/Button'; -import { DonationBanner } from 'app/atoms/DonationBanner/DonationBanner'; import Spinner from 'app/atoms/Spinner/Spinner'; import { useAppEnv } from 'app/env'; import ErrorBoundary from 'app/ErrorBoundary'; @@ -35,6 +34,7 @@ import Header from './PageLayout/Header'; import { NewsletterOverlay } from './PageLayout/NewsletterOverlay/NewsletterOverlay'; import { OnRampOverlay } from './PageLayout/OnRampOverlay/OnRampOverlay'; import { ReactivateAdsOverlay } from './PageLayout/ReactivateAdsOverlay'; +import { RewardsButton } from './PageLayout/RewardsButton'; import { ShortcutAccountSwitchOverlay } from './PageLayout/ShortcutAccountSwitchOverlay'; import { PageLayoutSelectors } from './PageLayout.selectors'; @@ -116,7 +116,6 @@ type ToolbarProps = { hasBackAction?: boolean; step?: number; setStep?: (step: number) => void; - adShow?: boolean; skip?: boolean; attention?: boolean; }; @@ -126,15 +125,7 @@ export let ToolbarElement: HTMLDivElement | null = null; /** Defined for reference in code to highlight relation between multiple sticky elements & their sizes */ export const TOOLBAR_IS_STICKY = true; -const Toolbar: FC = ({ - pageTitle, - hasBackAction = true, - step, - setStep, - adShow = false, - skip, - attention -}) => { +const Toolbar: FC = ({ pageTitle, hasBackAction = true, step, setStep, skip, attention }) => { const { historyPosition, pathname } = useLocation(); const { fullPage } = useAppEnv(); const { setOnboardingCompleted } = useOnboardingProgress(); @@ -203,10 +194,8 @@ const Toolbar: FC = ({ return (
-
- {!isBackButtonAvailable && adShow && } - - {isBackButtonAvailable && ( + {isBackButtonAvailable ? ( +
- )} -
+
+ ) : ( + + )} {pageTitle && (

{pageTitle}

diff --git a/src/app/layouts/PageLayout/RewardsButton/firefox-star-animation.tsx b/src/app/layouts/PageLayout/RewardsButton/firefox-star-animation.tsx new file mode 100644 index 0000000000..40a6e403cc --- /dev/null +++ b/src/app/layouts/PageLayout/RewardsButton/firefox-star-animation.tsx @@ -0,0 +1,39 @@ +import React, { memo, useEffect, useRef } from 'react'; + +const starAnimationVideo = require('./star_animation.webm'); +const starAnimationPoster = require('./star_animation_poster.gif'); + +interface Props { + loop: boolean; +} + +export const FirefoxStarAnimation = memo(({ loop }) => { + const videoRef = useRef(null); + const prevLoopRef = useRef(loop); + + useEffect(() => { + if (loop && !prevLoopRef.current) { + videoRef.current!.play(); + } else if (!loop && prevLoopRef.current) { + videoRef.current!.currentTime = 0; + videoRef.current!.pause(); + } + prevLoopRef.current = loop; + }, [loop]); + + return ( +