Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: release v1.506.0 #5905

Merged
merged 4 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { usePrevious } from '@chakra-ui/react'
import { skipToken } from '@reduxjs/toolkit/dist/query'
import { fromAccountId } from '@shapeshiftoss/caip'
import { isEvmChainId } from '@shapeshiftoss/chain-adapters'
Expand Down Expand Up @@ -109,6 +110,8 @@ export const useGetTradeQuotes = () => {
const [tradeQuoteInput, setTradeQuoteInput] = useState<GetTradeQuoteInput | typeof skipToken>(
skipToken,
)
const previousTradeQuoteInput = usePrevious(tradeQuoteInput)
const isTradeQuoteUpdated = tradeQuoteInput !== previousTradeQuoteInput
const [hasFocus, setHasFocus] = useState(document.hasFocus())
const sellAsset = useAppSelector(selectSellAsset)
const buyAsset = useAppSelector(selectBuyAsset)
Expand All @@ -120,6 +123,9 @@ export const useGetTradeQuotes = () => {
)
const receiveAddress = useReceiveAddress(useReceiveAddressArgs)
const sellAmountCryptoPrecision = useAppSelector(selectSellAmountCryptoPrecision)
const debouncedSellAmountCryptoPrecision = useDebounce(sellAmountCryptoPrecision, 500)
const isDebouncing = debouncedSellAmountCryptoPrecision !== sellAmountCryptoPrecision

// User *may* donate if the fox discounts flag is off and they kept the donation checkbox on
// or if the fox discounts flag is on and they don't hold enough fox to wave fees out fully
const userMayDonate = useAppSelector(selectWillDonate) || isFoxDiscountsEnabled
Expand Down Expand Up @@ -163,14 +169,29 @@ export const useGetTradeQuotes = () => {
const shouldRefetchTradeQuotes = useMemo(
() =>
Boolean(
wallet && sellAccountId && sellAccountMetadata && receiveAddress && !isVotingPowerLoading,
isTradeQuoteUpdated &&
wallet &&
!isDebouncing &&
sellAccountId &&
sellAccountMetadata &&
receiveAddress &&
!isVotingPowerLoading,
),
[wallet, sellAccountId, sellAccountMetadata, receiveAddress, isVotingPowerLoading],
[
isTradeQuoteUpdated,
wallet,
isDebouncing,
sellAccountId,
sellAccountMetadata,
receiveAddress,
isVotingPowerLoading,
],
)

const debouncedTradeQuoteInput = useDebounce(tradeQuoteInput, 500)

useEffect(() => {
// Don't update tradeQuoteInput while we're still debouncing
if (isDebouncing) return

// Always invalidate tags when this effect runs - args have changed, and whether we want to fetch an actual quote
// or a "skipToken" no-op, we always want to ensure that the tags are invalidated before a new query is ran
// That effectively means we'll unsubscribe to queries, considering them stale
Expand All @@ -186,7 +207,7 @@ export const useGetTradeQuotes = () => {
// disable EVM donations on KeepKey until https://github.com/shapeshift/web/issues/4518 is resolved
const mayDonate = walletIsKeepKey ? userMayDonate && !isFromEvm : userMayDonate

const tradeAmountUsd = bnOrZero(sellAssetUsdRate).times(sellAmountCryptoPrecision)
const tradeAmountUsd = bnOrZero(sellAssetUsdRate).times(debouncedSellAmountCryptoPrecision)
const potentialAffiliateBps = mayDonate ? DEFAULT_SWAPPER_DONATION_BPS : '0'
const affiliateBps = (() => {
if (!isFoxDiscountsEnabled) return potentialAffiliateBps
Expand Down Expand Up @@ -260,6 +281,8 @@ export const useGetTradeQuotes = () => {
sellAccountId,
isVotingPowerLoading,
isBuyAssetChainSupported,
debouncedSellAmountCryptoPrecision,
isDebouncing,
])

useEffect(() => {
Expand All @@ -271,17 +294,15 @@ export const useGetTradeQuotes = () => {

// NOTE: we're using currentData here, not data, see https://redux-toolkit.js.org/rtk-query/usage/conditional-fetching
// This ensures we never return cached data, if skip has been set after the initial query load
const { currentData } = useGetTradeQuoteQuery(
shouldRefetchTradeQuotes ? debouncedTradeQuoteInput : skipToken,
{
pollingInterval: hasFocus ? GET_TRADE_QUOTE_POLLING_INTERVAL : undefined,
/*
const { currentData } = useGetTradeQuoteQuery(tradeQuoteInput, {
skip: !shouldRefetchTradeQuotes,
pollingInterval: hasFocus ? GET_TRADE_QUOTE_POLLING_INTERVAL : undefined,
/*
If we don't refresh on arg change might select a cached result with an old "started_at" timestamp
We can remove refetchOnMountOrArgChange if we want to make better use of the cache, and we have a better way to select from the cache.
*/
refetchOnMountOrArgChange: true,
},
)
refetchOnMountOrArgChange: true,
})

useEffect(() => {
if (currentData && mixpanel) {
Expand Down
23 changes: 14 additions & 9 deletions src/context/WalletProvider/MetaMask/components/Connect.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react'
import React, { useCallback, useMemo, useState } from 'react'
import { isMobile } from 'react-device-detect'
import { useSelector } from 'react-redux'
import type { RouteComponentProps } from 'react-router-dom'
Expand All @@ -7,7 +7,11 @@ import { WalletActions } from 'context/WalletProvider/actions'
import { KeyManager } from 'context/WalletProvider/KeyManager'
import { useLocalWallet } from 'context/WalletProvider/local-wallet'
import { useFeatureFlag } from 'hooks/useFeatureFlag/useFeatureFlag'
import { checkIsMetaMask, checkIsSnapInstalled } from 'hooks/useIsSnapInstalled/useIsSnapInstalled'
import {
checkIsMetaMask,
checkisMetaMaskMobileWebView,
checkIsSnapInstalled,
} from 'hooks/useIsSnapInstalled/useIsSnapInstalled'
import { useWallet } from 'hooks/useWallet/useWallet'
import { getEthersProvider } from 'lib/ethersProviderSingleton'
import { selectShowSnapsModal } from 'state/slices/selectors'
Expand All @@ -27,7 +31,7 @@ export interface MetaMaskSetupProps
}

export const MetaMaskConnect = ({ history }: MetaMaskSetupProps) => {
const { dispatch, state, getAdapter, onProviderChange } = useWallet()
const { dispatch, getAdapter, onProviderChange } = useWallet()
const localWallet = useLocalWallet()
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
Expand All @@ -39,6 +43,7 @@ export const MetaMaskConnect = ({ history }: MetaMaskSetupProps) => {
}, [])

const isSnapsEnabled = useFeatureFlag('Snaps')
const isMetaMaskMobileWebView = useMemo(() => checkisMetaMaskMobileWebView(), [])

const pairDevice = useCallback(async () => {
setError(null)
Expand Down Expand Up @@ -83,7 +88,8 @@ export const MetaMaskConnect = ({ history }: MetaMaskSetupProps) => {
if (!isMetaMask) return dispatch({ type: WalletActions.SET_WALLET_MODAL, payload: false })
const isSnapInstalled = await checkIsSnapInstalled()

if (isSnapsEnabled && !isSnapInstalled && showSnapModal) {
// We don't want to show the snaps modal on MM mobile browser, as snaps aren't supported on mobile
if (isSnapsEnabled && !isMetaMaskMobileWebView && !isSnapInstalled && showSnapModal) {
return history.push('/metamask/snap/install')
}

Expand All @@ -101,11 +107,12 @@ export const MetaMaskConnect = ({ history }: MetaMaskSetupProps) => {
}
setLoading(false)
}, [
onProviderChange,
getAdapter,
setErrorLoading,
dispatch,
localWallet,
onProviderChange,
isMetaMaskMobileWebView,
isSnapsEnabled,
showSnapModal,
history,
Expand All @@ -119,12 +126,10 @@ export const MetaMaskConnect = ({ history }: MetaMaskSetupProps) => {
.filter(x => !!x)
.join(':')

return window.location.assign(`https://metamask.app.link/dapp/${mmDeeplinkTarget}`)
return window.location.assign(`metamask://dapp//${mmDeeplinkTarget}`)
}, [])

// The MM mobile app itself injects a provider, so we'll use pairDevice once
// we've reopened ourselves in that environment.
return !state.provider && isMobile ? (
return isMobile && !isMetaMaskMobileWebView ? (
<RedirectModal
headerText={'walletProvider.metaMask.redirect.header'}
bodyText={'walletProvider.metaMask.redirect.body'}
Expand Down
2 changes: 2 additions & 0 deletions src/contracts/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export const ETH_FOX_STAKING_CONTRACT_ADDRESS_V6 =
'0xebb1761ad43034fd7faa64d84e5bbd8cb5c40b68' as const
export const ETH_FOX_STAKING_CONTRACT_ADDRESS_V7 =
'0x5939783dbf3e9f453a69bc9ddc1e492efac1fbcb' as const
export const ETH_FOX_STAKING_CONTRACT_ADDRESS_V8 =
'0x662da6c777a258382f08b979d9489c3fbbbd8ac3' as const

// Exported as a string literal for contract address discrimination purposes
export const ETH_FOX_POOL_CONTRACT_ADDRESS = '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c' as const
Expand Down
2 changes: 2 additions & 0 deletions src/contracts/contractManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
ETH_FOX_STAKING_CONTRACT_ADDRESS_V5,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V6,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V7,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V8,
FOX_TOKEN_CONTRACT_ADDRESS,
THOR_ROUTER_CONTRACT_ADDRESS_ETHEREUM,
UNISWAP_V2_ROUTER_02_CONTRACT_ADDRESS,
Expand All @@ -49,6 +50,7 @@ export const CONTRACT_ADDRESS_TO_ABI = {
[ETH_FOX_STAKING_CONTRACT_ADDRESS_V5]: FarmingABI,
[ETH_FOX_STAKING_CONTRACT_ADDRESS_V6]: FarmingABI,
[ETH_FOX_STAKING_CONTRACT_ADDRESS_V7]: FarmingABI,
[ETH_FOX_STAKING_CONTRACT_ADDRESS_V8]: FarmingABI,
[FOX_TOKEN_CONTRACT_ADDRESS]: erc20ABI,
[UNISWAP_V2_ROUTER_02_CONTRACT_ADDRESS]: IUniswapV2Router02,
// THOR Router Mainnet
Expand Down
11 changes: 11 additions & 0 deletions src/hooks/useIsSnapInstalled/useIsSnapInstalled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ export const checkIsMetaMask = pMemoize(
},
)

// https://github.com/MetaMask/metamask-sdk/blob/6230d8394157f53f1b020ae44601a0a69edc6155/packages/sdk/src/Platform/PlatfformManager.ts#L102C30-L111
export const checkisMetaMaskMobileWebView = () => {
if (typeof window === 'undefined') {
return false
}

return (
Boolean(window.ReactNativeWebView) && Boolean(navigator.userAgent.endsWith('MetaMaskMobile'))
)
}

export const useIsSnapInstalled = (): null | boolean => {
const [isSnapInstalled, setIsSnapInstalled] = useState<null | boolean>(null)

Expand Down
4 changes: 2 additions & 2 deletions src/plugins/arkeo/Arkeo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { WalletActions } from 'context/WalletProvider/actions'
import { KeyManager } from 'context/WalletProvider/KeyManager'
import { useWallet } from 'hooks/useWallet/useWallet'
import { isMobile as isMobileApp } from 'lib/globals'
import { foxEthLpAssetId, foxEthStakingAssetIdV7 } from 'state/slices/opportunitiesSlice/constants'
import { foxEthLpAssetId, foxEthStakingAssetIdV8 } from 'state/slices/opportunitiesSlice/constants'
import type { DefiType, OpportunityId } from 'state/slices/opportunitiesSlice/types'

import { FoxTokenHolders } from './FoxTokenHolders'
Expand All @@ -28,7 +28,7 @@ type OpportunityReturn = {
const FOXY_STAKING_CONTRACT = 'eip155:1/erc20:0xee77aa3fd23bbebaf94386dd44b548e9a785ea4b'

const opportunities: OpportunityReturn = {
staking: [FOXY_STAKING_CONTRACT, foxEthStakingAssetIdV7, cosmosAssetId] as OpportunityId[],
staking: [FOXY_STAKING_CONTRACT, foxEthStakingAssetIdV8, cosmosAssetId] as OpportunityId[],
lp: [foxEthLpAssetId],
}

Expand Down
6 changes: 3 additions & 3 deletions src/plugins/foxPage/hooks/useOtherOpportunities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { foxAssetId, foxyAssetId, fromAccountId, fromAssetId } from '@shapeshift
import { useMemo } from 'react'
import { bnOrZero } from 'lib/bignumber/bignumber'
import { foxyAddresses } from 'lib/investor/investor-foxy'
import { foxEthLpAssetId, foxEthStakingAssetIdV7 } from 'state/slices/opportunitiesSlice/constants'
import { foxEthLpAssetId, foxEthStakingAssetIdV8 } from 'state/slices/opportunitiesSlice/constants'
import type { StakingId } from 'state/slices/opportunitiesSlice/types'
import { DefiType } from 'state/slices/opportunitiesSlice/types'
import {
Expand All @@ -21,7 +21,7 @@ import { OpportunityTypes } from '../FoxCommon'
export const useOtherOpportunities = (assetId: AssetId) => {
const highestFarmingBalanceAccountIdFilter = useMemo(
() => ({
stakingId: foxEthStakingAssetIdV7 as StakingId,
stakingId: foxEthStakingAssetIdV8 as StakingId,
}),
[],
)
Expand Down Expand Up @@ -58,7 +58,7 @@ export const useOtherOpportunities = (assetId: AssetId) => {
const stakingOpportunities = useAppSelector(selectStakingOpportunitiesById)

const foxFarmingOpportunityMetadata = useMemo(
() => stakingOpportunities[foxEthStakingAssetIdV7 as StakingId],
() => stakingOpportunities[foxEthStakingAssetIdV8 as StakingId],
[stakingOpportunities],
)

Expand Down
6 changes: 6 additions & 0 deletions src/state/slices/opportunitiesSlice/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ETH_FOX_STAKING_CONTRACT_ADDRESS_V5,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V6,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V7,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V8,
} from 'contracts/constants'
import { getTypeGuardAssertion } from 'lib/utils'

Expand All @@ -23,6 +24,7 @@ export const foxEthLpAssetId: LpId = 'eip155:1/erc20:0x470e8de2ebaef52014a47cb5e
export const foxEthLpAssetIds = [foxEthLpAssetId] as const

export const foxEthStakingContractAddresses = [
ETH_FOX_STAKING_CONTRACT_ADDRESS_V8,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V7,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V6,
ETH_FOX_STAKING_CONTRACT_ADDRESS_V5,
Expand Down Expand Up @@ -60,6 +62,8 @@ export const foxEthStakingAssetIdV6: AssetId =
'eip155:1/erc20:0xebb1761ad43034fd7faa64d84e5bbd8cb5c40b68'
export const foxEthStakingAssetIdV7: AssetId =
'eip155:1/erc20:0x5939783dbf3e9f453a69bc9ddc1e492efac1fbcb'
export const foxEthStakingAssetIdV8: AssetId =
'eip155:1/erc20:0x662da6c777a258382f08b979d9489c3fbbbd8ac3'

// Tuple of all staking contracts as AssetIds, to iterate over and dispatch RTK queries for
export const foxEthAssetIds = [
Expand All @@ -70,6 +74,7 @@ export const foxEthAssetIds = [
foxEthStakingAssetIdV5,
foxEthStakingAssetIdV6,
foxEthStakingAssetIdV7,
foxEthStakingAssetIdV8,
] as const
export const foxEthStakingIds = foxEthAssetIds as readonly StakingId[]

Expand All @@ -81,6 +86,7 @@ export const STAKING_ID_TO_VERSION = {
[foxEthStakingAssetIdV5]: 'V5',
[foxEthStakingAssetIdV6]: 'V6',
[foxEthStakingAssetIdV7]: 'V7',
[foxEthStakingAssetIdV8]: 'V8',
}

export const STAKING_ID_DELIMITER = '*'
Expand Down
13 changes: 10 additions & 3 deletions src/state/slices/txHistorySlice/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,19 @@ export const selectMaybeNextAccountNumberByChainId = createSelector(
return [isAbleToAddNextAccount, isAbleToAddNextAccount ? nextAccountNumber : null]
},
)

export const selectTxsByQuery = createDeepEqualOutputSelector(
selectTxs,
selectTxIdsByFilter,
selectAssets,
selectSearchQueryFromFilter,
(txsById, assets, searchQuery): TxId[] => {
const txArray: [TxId, Tx][] = Object.entries(txsById)
if (!searchQuery) return Object.keys(txsById)
(txsById, txIds, assets, searchQuery): TxId[] => {
// Txs do *not* have a guaranteed order, but txIds do (most recent first)
// Ensure we honor the order of Txids when sorting Txs
const txArray: [TxId, Tx][] = txIds.map(txId => [txId, txsById[txId]])

if (!searchQuery) return txIds

const results = matchSorter(txArray, searchQuery, {
keys: [
'txid',
Expand All @@ -227,6 +233,7 @@ export const selectTxsByQuery = createDeepEqualOutputSelector(
],
threshold: matchSorter.rankings.CONTAINS,
})

return results.map(result => result[0])
},
)