Skip to content

Commit

Permalink
Merge branch 'develop' into rfox-address
Browse files Browse the repository at this point in the history
  • Loading branch information
NeOMakinG authored Sep 12, 2024
2 parents 73986b8 + ba7e007 commit b8f98ca
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 19 deletions.
8 changes: 5 additions & 3 deletions src/assets/translations/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@
},
"update": {
"title": "Multichain Snap needs updating",
"subtitle": "Uninstall the ShapeShift multichain Snap and click 'Update' to keep using ShapeShifts multichain features with MetaMask!"
"subtitle": "Click 'Update' to continue using ShapeShift's multichain features with MetaMask!"
},
"secondaryTitle": "The best Multichain experience for MetaMask: Powered by ShapeShift",
"secondaryBody": "Send, receive, track, trade, and earn with the ShapeShift Multichain Snap on the following chains:",
Expand All @@ -1551,6 +1551,7 @@
},
"metaMaskSnapConfirm": {
"title": "Install Multichain Snap",
"updateTitle": "Update Multichain Snap",
"warningExperimental": "The ShapeShift Multichain Snap is a new, experimental feature, provided \"as is\"",
"warningBackup": "Ensure you have backed up your MetaMask seed phrase. Any funds you send to non-EVM chains using this Snap will be directed to the default account you set up with MetaMask.",
"agreeIntro": "Before continuing please read the following:",
Expand All @@ -1564,7 +1565,8 @@
"agreeItem4": "By enabling the ShapeShift Multichain Snap, you acknowledge you are using it at your own risk",
"readAndUnderstood": "I have read and understand",
"seedBackedUp": "I have backed up my MetaMask seed phrase",
"acceptInstall": "Confirm & Install"
"acceptInstall": "Confirm & Install",
"acceptUpdate": "Confirm & Update"
},
"coinbase": {
"errors": {
Expand Down Expand Up @@ -2520,7 +2522,7 @@
"newAddressInfo": "This will update for the next reward cycle",
"confirmAndUpdateAddress": "Confirm & Update Address",
"unstakeFrom": "Unstake from r%{assetSymbol}",
"claimPending": "Requesting withdraw",
"claimPending": "Awaiting your claim of %{amount} %{symbol}",
"claimSuccess": "You have successfully claimed %{amount} %{symbol}.",
"claimReceiveAddress": "Claim Receive Address",
"noRewardsYet": "No rewards yet",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,17 @@ export const OpportunityRow: React.FC<

const handleClick = useCallback(
(action: DefiAction) => {
if (asset?.isPool && opportunity.isReadOnly) {
return history.push(`/trade/${assetId}`)
}
if (opportunity.isReadOnly) {
const url = getMetadataForProvider(opportunity.provider)?.url
url && window.open(url, '_blank')
return
}
onClick(opportunity, action)
},
[onClick, opportunity],
[asset, assetId, history, onClick, opportunity],
)

const handleClaimClick = useCallback(() => handleClick(DefiAction.Claim), [handleClick])
Expand Down Expand Up @@ -137,7 +140,7 @@ export const OpportunityRow: React.FC<
<NestedAsset
key={rewardAssetId}
isClaimableRewards={isClaimableRewards}
isExternal={opportunity.isReadOnly}
isExternal={opportunity.isReadOnly && !asset?.isPool}
assetId={rewardAssetId}
balances={rewardBalance}
onClick={handleClaimClick}
Expand Down Expand Up @@ -171,6 +174,7 @@ export const OpportunityRow: React.FC<
underlyingAssetBalances,
isClaimableRewards,
opportunity.isReadOnly,
asset?.isPool,
handleClaimClick,
translate,
assetId,
Expand Down Expand Up @@ -215,7 +219,7 @@ export const OpportunityRow: React.FC<
icons={icons}
subText={assetCellSubText}
justifyContent='flex-start'
isExternal={opportunity.isReadOnly}
isExternal={opportunity.isReadOnly && !asset?.isPool}
opportunityName={opportunity.opportunityName}
/>
<Amount.Crypto
Expand Down
16 changes: 14 additions & 2 deletions src/components/Modals/Snaps/SnapConfirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { useTranslate } from 'react-polyglot'
import { enableShapeShiftSnap } from 'utils/snaps'
import { CircularProgress } from 'components/CircularProgress/CircularProgress'
import { RawText } from 'components/Text'
import { useIsSnapInstalled } from 'hooks/useIsSnapInstalled/useIsSnapInstalled'
import { getMixPanel } from 'lib/mixpanel/mixPanelSingleton'
import { MixPanelEvent } from 'lib/mixpanel/types'

Expand All @@ -24,6 +25,7 @@ type SnapConfirmProps = {
}

export const SnapConfirm: React.FC<SnapConfirmProps> = ({ onClose }) => {
const { isSnapInstalled, isCorrectVersion } = useIsSnapInstalled()
const [isInstalling, setIsInstalling] = useState(false)
const [hasAgreed, setHasAgreed] = useState(false)
const [hasPinkySworeSeedPhraseIsBackedUp, setHasPinkySworeSeedPhraseIsBackedUp] = useState(false)
Expand Down Expand Up @@ -69,7 +71,13 @@ export const SnapConfirm: React.FC<SnapConfirmProps> = ({ onClose }) => {
return (
<>
<ModalHeader textAlign='center'>
<Heading as='h4'>{translate('walletProvider.metaMaskSnapConfirm.title')}</Heading>
<Heading as='h4'>
{translate(
isSnapInstalled && !isCorrectVersion
? 'walletProvider.metaMaskSnapConfirm.updateTitle'
: 'walletProvider.metaMaskSnapConfirm.title',
)}
</Heading>
</ModalHeader>
<ModalBody>
<Alert status='warning' borderRadius='lg' mb={4}>
Expand Down Expand Up @@ -116,7 +124,11 @@ export const SnapConfirm: React.FC<SnapConfirmProps> = ({ onClose }) => {
isDisabled={!(hasAgreed && hasPinkySworeSeedPhraseIsBackedUp)}
onClick={handleAddSnap}
>
{translate('walletProvider.metaMaskSnapConfirm.acceptInstall')}
{translate(
isSnapInstalled && !isCorrectVersion
? 'walletProvider.metaMaskSnapConfirm.acceptUpdate'
: 'walletProvider.metaMaskSnapConfirm.acceptInstall',
)}
</Button>
</ModalFooter>
</>
Expand Down
39 changes: 30 additions & 9 deletions src/state/apis/zapper/zapperApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { createApi } from '@reduxjs/toolkit/dist/query/react'
import type { AccountId, AssetId } from '@shapeshiftoss/caip'
import { ethChainId, fromAssetId, toAccountId, toAssetId } from '@shapeshiftoss/caip'
import {
ASSET_NAMESPACE,
bscChainId,
ethChainId,
fromAssetId,
toAccountId,
toAssetId,
} from '@shapeshiftoss/caip'
import { evmChainIds } from '@shapeshiftoss/chain-adapters'
import { makeAsset } from '@shapeshiftoss/utils'
import type { AxiosRequestConfig } from 'axios'
Expand Down Expand Up @@ -368,7 +375,29 @@ export const zapper = createApi({
assets.map(asset => Object.assign(asset, { label })),
)
.map<ReadOnlyOpportunityType | undefined>(asset => {
const chainId = zapperNetworkToChainId(asset.network)
if (!chainId) throw new Error('chainIs is required')

const maybeTopLevelLpAssetId = toAssetId({
chainId,
assetNamespace:
chainId === bscChainId ? ASSET_NAMESPACE.bep20 : ASSET_NAMESPACE.erc20,
assetReference: asset.address,
})
const maybeTopLevelLpAsset = assets[maybeTopLevelLpAssetId]

const topLevelAsset = (() => {
if (maybeTopLevelLpAsset?.isPool) return asset
const maybeUnderlyingLpAsset = asset.tokens.find(
token => token.metaType === 'supplied' || token.metaType === 'borrowed',
)
if (maybeUnderlyingLpAsset) return maybeUnderlyingLpAsset
return asset
})()

const stakedAmountCryptoBaseUnitAccessor = (() => {
// This is a LP token, the top-level asset holds the staked amount
if (maybeTopLevelLpAsset?.isPool) return asset
// Liquidity Pool of sorts
const maybeLpAcesssor = asset.tokens.find(
token => token.metaType === 'supplied' || token.metaType === 'borrowed',
Expand Down Expand Up @@ -460,14 +489,6 @@ export const zapper = createApi({
// This is our best bet until we bring in the concept of an "DefiType.GenericOpportunity"
const defiType = DefiType.Staking

const topLevelAsset = (() => {
const maybeLpAsset = asset.tokens.find(
token => token.metaType === 'supplied' || token.metaType === 'borrowed',
)
if (maybeLpAsset) return maybeLpAsset
return asset
})()

const assetId = zapperAssetToMaybeAssetId(topLevelAsset)

if (!assetId) return undefined
Expand Down
1 change: 1 addition & 0 deletions src/state/migrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,5 @@ export const migrations = {
105: clearPortfolio,
106: clearOpportunities,
107: clearAssets,
108: clearAssets,
}
88 changes: 88 additions & 0 deletions src/state/slices/portfolioSlice/utils/portals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {
ASSET_NAMESPACE,
type AssetId,
bscChainId,
type ChainId,
toAssetId,
} from '@shapeshiftoss/caip'
import axios from 'axios'
import { getConfig } from 'config'
import { CHAIN_ID_TO_PORTALS_NETWORK } from 'lib/market-service/portals/constants'
import type {
GetBalancesResponse,
GetPlatformsResponse,
PlatformsById,
TokenInfo,
} from 'lib/market-service/portals/types'

export const fetchPortalsPlatforms = async (): Promise<PlatformsById> => {
const url = `${getConfig().REACT_APP_PORTALS_BASE_URL}/v2/platforms`

try {
const { data: platforms } = await axios.get<GetPlatformsResponse>(url, {
headers: {
Authorization: `Bearer ${getConfig().REACT_APP_PORTALS_API_KEY}`,
},
})

const byId = platforms.reduce<PlatformsById>((acc, platform) => {
acc[platform.platform] = platform
return acc
}, {})

return byId
} catch (error) {
if (axios.isAxiosError(error)) {
console.error(`Failed to fetch Portals platforms: ${error.message}`)
}
console.error(`Failed to fetch Portals platforms: ${error}`)

return {}
}
}

export const fetchPortalsAccount = async (
chainId: ChainId,
owner: string,
): Promise<Record<AssetId, TokenInfo>> => {
const url = `${getConfig().REACT_APP_PORTALS_BASE_URL}/v2/account`

const network = CHAIN_ID_TO_PORTALS_NETWORK[chainId]

if (!network) throw new Error(`Unsupported chainId: ${chainId}`)

try {
const { data } = await axios.get<GetBalancesResponse>(url, {
params: {
networks: [network],
owner,
},
headers: {
Authorization: `Bearer ${getConfig().REACT_APP_PORTALS_API_KEY}`,
},
})

return data.balances.reduce<Record<AssetId, TokenInfo>>((acc, token) => {
const assetId = toAssetId({
chainId,
assetNamespace: chainId === bscChainId ? ASSET_NAMESPACE.bep20 : ASSET_NAMESPACE.erc20,
assetReference: token.address,
})
acc[assetId] = token
return acc
}, {})
} catch (error) {
if (axios.isAxiosError(error)) {
console.error(`Failed to fetch Portals account: ${error.message}`)
} else {
console.error(error)
}
return {}
}
}

export const maybeTokenImage = (image: string | undefined) => {
if (!image) return
if (image === 'missing_large.png') return
return image
}
13 changes: 11 additions & 2 deletions src/utils/snaps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import detectEthereumProvider from '@metamask/detect-provider'
import { enableShapeShiftSnap as _enableShapeShiftSnap } from '@shapeshiftoss/metamask-snaps-adapter'
import assert from 'assert'
import { getConfig } from 'config'
import type { Eip1193Provider } from 'ethers'
Expand All @@ -22,11 +21,21 @@ type GetSnapsResult = Record<
>

export const enableShapeShiftSnap = async (): Promise<void> => {
const provider = (await detectEthereumProvider()) as Eip1193Provider

const snapVersion = getConfig().REACT_APP_SNAP_VERSION
const isSnapFeatureEnabled = getConfig().REACT_APP_EXPERIMENTAL_MM_SNAPPY_FINGERS
assert(isSnapFeatureEnabled, 'Snap feature flag is disabled')
const snapId = getConfig().REACT_APP_SNAP_ID
await _enableShapeShiftSnap(snapId, snapVersion)

await provider.request({
method: 'wallet_requestSnaps',
params: {
[snapId]: {
version: snapVersion,
},
},
})
}

export const getSnapVersion = async (): Promise<string | null> => {
Expand Down

0 comments on commit b8f98ca

Please sign in to comment.