feat(wallet): implement bridge to aurora button (#14452)
* feat: implement bridge to aurora button * feedback: Add rel="noopener noreferrer" to link * feedback: separate opening and closing modal functions * chore: move openRainbowAppClick up and add openRainbowAppClick to deps list
This commit is contained in:
@@ -680,7 +680,14 @@ constexpr webui::LocalizedString kLocalizedStrings[] = {
|
||||
{"braveWalletHelpCenter", IDS_BRAVE_WALLET_HELP_CENTER},
|
||||
{"braveWalletHelpCenterText", IDS_BRAVE_WALLET_HELP_CENTER_TEXT},
|
||||
{"braveWalletBuyTapBuyNotSupportedMessage",
|
||||
IDS_BRAVE_WALLET_BUY_TAB_BUY_NOT_SUPPORTED_MESSAGE}};
|
||||
IDS_BRAVE_WALLET_BUY_TAB_BUY_NOT_SUPPORTED_MESSAGE},
|
||||
{"braveWalletAuroraModalTitle", IDS_BRAVE_WALLET_AURORA_MODAL_TITLE},
|
||||
{"braveWalletAuroraModalDescription",
|
||||
IDS_BRAVE_WALLET_AURORA_MODAL_DESCRIPTION},
|
||||
{"braveWalletAuroraModalLearnMore",
|
||||
IDS_BRAVE_WALLET_AURORA_MODAL_LEARN_MORE},
|
||||
{"braveWalletAuroraModalOPenButtonText",
|
||||
IDS_BRAVE_WALLET_AURORA_MODAL_OPEN_BUTTON_TEXT}};
|
||||
|
||||
// 0x swap constants
|
||||
constexpr char kRopstenSwapBaseAPIURL[] = "https://ropsten.api.0x.org/";
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 15 KiB |
+83
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// you can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import styled from 'styled-components'
|
||||
import { WalletButton } from '../../../shared/style'
|
||||
import GlobeConnectIcon from '../../../../assets/svg-icons/globe-connect-icon.svg'
|
||||
|
||||
export const modalWidth = '442px'
|
||||
|
||||
export const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
margin: 32px 78px 39px;
|
||||
`
|
||||
|
||||
export const Title = styled.h4`
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
color: ${p => p.theme.color.text02};
|
||||
text-align: center;
|
||||
margin: 0 0 7px;
|
||||
align-self: center;
|
||||
`
|
||||
|
||||
export const Description = styled.p`
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: ${p => p.theme.color.text02};
|
||||
margin: 0;
|
||||
`
|
||||
|
||||
export const LearnMoreLink = styled.a`
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: ${p => p.theme.color.interactive05};
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding-bottom: 56px;
|
||||
`
|
||||
|
||||
export const OpenRainbowAppButton = styled(WalletButton)`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 8px 14px;
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
border-radius: 40px;
|
||||
background-color: ${(p) => p.theme.palette.blurple500};
|
||||
border: none;
|
||||
align-self: center;
|
||||
`
|
||||
|
||||
export const ButtonText = styled.span`
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
color: ${(p) => p.theme.palette.white};
|
||||
`
|
||||
|
||||
export const GlobeIcon = styled.div`
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: url(${GlobeConnectIcon});
|
||||
margin-right: 8px;
|
||||
`
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// you can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import * as React from 'react'
|
||||
import { getLocale } from '../../../../../common/locale'
|
||||
|
||||
import { PopupModal } from '../..'
|
||||
import {
|
||||
ButtonText,
|
||||
Description,
|
||||
GlobeIcon,
|
||||
LearnMoreLink,
|
||||
modalWidth,
|
||||
OpenRainbowAppButton,
|
||||
StyledWrapper,
|
||||
Title
|
||||
} from './bridge-to-aurora-modal-styles'
|
||||
|
||||
interface Props {
|
||||
onClose: () => void
|
||||
onOpenRainbowAppClick: () => void
|
||||
}
|
||||
|
||||
const learnMoreLink = 'https://ethereum.org/en/bridges/#bridge-risk'
|
||||
|
||||
export const BridgeToAuroraModal = ({ onClose, onOpenRainbowAppClick }: Props) => {
|
||||
return (
|
||||
<PopupModal
|
||||
title=''
|
||||
onClose={onClose}
|
||||
width={modalWidth}
|
||||
>
|
||||
<StyledWrapper>
|
||||
<Title>{getLocale('braveWalletAuroraModalTitle')}</Title>
|
||||
<Description>{getLocale('braveWalletAuroraModalDescription')}</Description>
|
||||
<LearnMoreLink
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
href={learnMoreLink}
|
||||
>
|
||||
{getLocale('braveWalletAuroraModalLearnMore')}
|
||||
</LearnMoreLink>
|
||||
<OpenRainbowAppButton
|
||||
onClick={onOpenRainbowAppClick}
|
||||
>
|
||||
<GlobeIcon />
|
||||
<ButtonText>{getLocale('braveWalletAuroraModalOPenButtonText')}</ButtonText>
|
||||
</OpenRainbowAppButton>
|
||||
</StyledWrapper>
|
||||
</PopupModal>
|
||||
)
|
||||
}
|
||||
@@ -13,12 +13,13 @@ export interface Props {
|
||||
children?: React.ReactNode
|
||||
onClose: () => void
|
||||
title: string
|
||||
width?: string
|
||||
}
|
||||
|
||||
const ESC_KEY = 'Escape'
|
||||
|
||||
const PopupModal = (props: Props) => {
|
||||
const { title, onClose, children } = props
|
||||
const { title, width, onClose, children } = props
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === ESC_KEY) {
|
||||
@@ -36,7 +37,7 @@ const PopupModal = (props: Props) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<Modal>
|
||||
<Modal width={width}>
|
||||
<Header>
|
||||
<Title>{title}</Title>
|
||||
<CloseButton onClick={onClose} />
|
||||
|
||||
@@ -17,13 +17,13 @@ export const StyledWrapper = styled.div`
|
||||
backdrop-filter: blur(16px);
|
||||
`
|
||||
|
||||
export const Modal = styled.div`
|
||||
export const Modal = styled.div<{ width?: string }>`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-conent: center;
|
||||
min-width: 580px;
|
||||
max-width: 580px;
|
||||
min-width: ${p => p.width ? p.width : '580px'};
|
||||
max-width: ${p => p.width ? p.width : '580px'};
|
||||
background-color: ${(p) => p.theme.color.background02};
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.25);
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
UpdateLoadingMessage, UpdateNFtMetadataMessage,
|
||||
UpdateSelectedAssetMessage, UpdateTokenNetworkMessage
|
||||
} from '../../../../nft/nft-ui-messages'
|
||||
import { auroraSupportedContractAddresses } from '../../../../utils/asset-utils'
|
||||
|
||||
// actions
|
||||
import { WalletPageActions } from '../../../../page/actions'
|
||||
@@ -42,6 +43,7 @@ import { BackButton } from '../../../shared'
|
||||
import withPlaceholderIcon from '../../../shared/create-placeholder-icon'
|
||||
import { ChartControlBar, LineChart } from '../../'
|
||||
import AccountsAndTransactionsList from './components/accounts-and-transctions-list'
|
||||
import { BridgeToAuroraModal } from '../../popup-modals/bridge-to-aurora-modal/bridge-to-aurora-modal'
|
||||
|
||||
// Hooks
|
||||
import { useBalance, usePricing, useTransactionParser } from '../../../../common/hooks'
|
||||
@@ -53,7 +55,7 @@ import {
|
||||
AssetIcon,
|
||||
AssetNameText,
|
||||
AssetRow,
|
||||
BalanceRow,
|
||||
BalanceRow, BridgeToAuroraButton,
|
||||
DetailText,
|
||||
InfoColumn,
|
||||
NetworkDescription,
|
||||
@@ -69,8 +71,13 @@ import {
|
||||
import { Skeleton } from '../../../shared/loading-skeleton/styles'
|
||||
|
||||
const AssetIconWithPlaceholder = withPlaceholderIcon(AssetIcon, { size: 'big', marginLeft: 0, marginRight: 12 })
|
||||
const rainbowbridgeLink = 'https://rainbowbridge.app'
|
||||
const bridgeToAuroraWarningShownKey = 'bridgeToAuroraWarningShown'
|
||||
|
||||
export const PortfolioAsset = () => {
|
||||
// state
|
||||
const [showBridgeToAuroraModal, setShowBridgeToAuroraModal] = React.useState<boolean>(false)
|
||||
const [bridgeToAuroraWarningShown, setBridgeToAuroraWarningShown] = React.useState<boolean>()
|
||||
// routing
|
||||
const history = useHistory()
|
||||
const { id: assetId, tokenId } = useParams<{ id?: string, tokenId?: string }>()
|
||||
@@ -174,6 +181,13 @@ export const PortfolioAsset = () => {
|
||||
: userVisibleTokensInfo.find((token) => token.symbol.toLowerCase() === assetId?.toLowerCase())
|
||||
}, [assetId, userVisibleTokensInfo, selectedTimeline, tokenId])
|
||||
|
||||
const isSelectedAssetBridgeSupported = React.useMemo(() => {
|
||||
if (!selectedAssetFromParams) return false
|
||||
return auroraSupportedContractAddresses
|
||||
.includes(selectedAssetFromParams.contractAddress.toLowerCase()) ||
|
||||
selectedAssetFromParams.symbol.toUpperCase() === 'ETH'
|
||||
}, [selectedAssetFromParams])
|
||||
|
||||
// This will scrape all of the user's accounts and combine the fiat value for every asset
|
||||
const fullPortfolioFiatBalance = React.useMemo(() => {
|
||||
const visibleAssetOptions = userAssetList
|
||||
@@ -295,6 +309,28 @@ export const PortfolioAsset = () => {
|
||||
|
||||
const onNftDetailsLoad = React.useCallback(() => setNftIframeLoaded(true), [])
|
||||
|
||||
const onOpenRainbowAppClick = React.useCallback(() => {
|
||||
chrome.tabs.create({ url: rainbowbridgeLink }, () => {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error('tabs.create failed: ' + chrome.runtime.lastError.message)
|
||||
}
|
||||
})
|
||||
setShowBridgeToAuroraModal(false)
|
||||
}, [])
|
||||
|
||||
const onBridgeToAuroraButton = React.useCallback(() => {
|
||||
if (bridgeToAuroraWarningShown) {
|
||||
onOpenRainbowAppClick()
|
||||
} else {
|
||||
localStorage.setItem(bridgeToAuroraWarningShownKey, 'true')
|
||||
setShowBridgeToAuroraModal(true)
|
||||
}
|
||||
}, [bridgeToAuroraWarningShown, onOpenRainbowAppClick])
|
||||
|
||||
const onCloseAuroraModal = React.useCallback(() => {
|
||||
setShowBridgeToAuroraModal(false)
|
||||
}, [])
|
||||
|
||||
// effects
|
||||
React.useEffect(() => {
|
||||
setfilteredAssetList(userAssetList)
|
||||
@@ -348,6 +384,10 @@ export const PortfolioAsset = () => {
|
||||
}
|
||||
}, [nftIframeLoaded, nftDetailsRef, selectedAsset, nftMetadata, networkList])
|
||||
|
||||
React.useEffect(() => {
|
||||
setBridgeToAuroraWarningShown(localStorage.getItem(bridgeToAuroraWarningShownKey) === 'true')
|
||||
})
|
||||
|
||||
// token list needs to load before we can find an asset to select from the url params
|
||||
if (userVisibleTokensInfo.length === 0) {
|
||||
return <Skeleton />
|
||||
@@ -426,6 +466,21 @@ export const PortfolioAsset = () => {
|
||||
/>
|
||||
}
|
||||
|
||||
{!isNftAsset && isSelectedAssetBridgeSupported &&
|
||||
<BridgeToAuroraButton
|
||||
onClick={onBridgeToAuroraButton}
|
||||
>
|
||||
Bridge to Aurora
|
||||
</BridgeToAuroraButton>
|
||||
}
|
||||
|
||||
{showBridgeToAuroraModal &&
|
||||
<BridgeToAuroraModal
|
||||
onClose={onCloseAuroraModal}
|
||||
onOpenRainbowAppClick={onOpenRainbowAppClick}
|
||||
/>
|
||||
}
|
||||
|
||||
<NftDetails
|
||||
onLoad={onNftDetailsLoad}
|
||||
visible={selectedAsset?.isErc721}
|
||||
|
||||
@@ -251,7 +251,29 @@ export const FilterTokenRow = styled.div`
|
||||
|
||||
export const NftDetails = styled.iframe<{ visible?: boolean }>`
|
||||
width: 100%;
|
||||
min-height: ${p => p.visible ? '490px' : 'hidden'};
|
||||
min-height: ${p => p.visible ? '490px' : '0px'};
|
||||
height: ${p => p.visible ? 'auto' : '0px'};
|
||||
border: none;
|
||||
visibility: ${p => p.visible ? 'visible' : 'hidden'};
|
||||
`
|
||||
|
||||
export const BridgeToAuroraButton = styled(WalletButton)`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 8px 14px;
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
border-radius: 40px;
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
background-color: ${(p) => p.theme.palette.blurple500};
|
||||
color: ${(p) => p.theme.palette.white};
|
||||
border: none;
|
||||
margin-bottom: 32px;
|
||||
`
|
||||
|
||||
@@ -581,5 +581,12 @@ provideStrings({
|
||||
|
||||
// Help Center
|
||||
braveWalletHelpCenter: 'Help Center',
|
||||
braveWalletHelpCenterText: 'Need help? See'
|
||||
braveWalletHelpCenterText: 'Need help? See',
|
||||
|
||||
// Bridge to Aurora
|
||||
braveWalletAuroraModalTitle: 'Open rainbowbridge.app',
|
||||
braveWalletAuroraModalDescription: 'Bridging assets across networks allows you to use your crypto on other networks and other DApp' +
|
||||
' ecosystems. Bridging assets to other networks has some risks',
|
||||
braveWalletAuroraModalLearnMore: 'Learn more',
|
||||
braveWalletAuroraModalOPenButtonText: 'Open rainbowbridge.app'
|
||||
})
|
||||
|
||||
@@ -31,3 +31,34 @@ export const getRampAssetSymbol = (asset: BraveWallet.BlockchainToken) => {
|
||||
const rampNetworkPrefix = getRampNetworkPrefix(asset.chainId)
|
||||
return rampNetworkPrefix !== '' ? `${rampNetworkPrefix}_${asset.symbol.toUpperCase()}` : asset.symbol
|
||||
}
|
||||
|
||||
export const auroraSupportedContractAddresses = [
|
||||
'0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9', // AAVE
|
||||
'0xaaaaaa20d9e0e2461697782ef11675f668207961', // AURORA
|
||||
'0xba100000625a3754423978a60c9317c58a424e3d', // BAL
|
||||
'0x0d8775f648430679a709e98d2b0cb6250d2887ef', // BAT
|
||||
'0xc00e94cb662c3520282e6f5717214004a7f26888', // COMP
|
||||
'0x2ba592f78db6436527729929aaf6c908497cb200', // CREAM
|
||||
'0x6b175474e89094c44da98b954eedeac495271d0f', // DAI
|
||||
'0x43dfc4159d86f3a37a5a4b3d4580b888ad7d4ddd', // DODO
|
||||
'0x3ea8ea4237344c9931214796d9417af1a1180770', // FLX
|
||||
'0x853d955acef822db058eb8505911ed77f175b99e', // FRAX
|
||||
'0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0', // FXS
|
||||
'0xd9c2d319cd7e6177336b0a9c93c21cb48d84fb54', // HAPI
|
||||
'0x514910771af9ca656af840dff83e8264ecf986ca', // LINK
|
||||
'0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', // MKR
|
||||
'0x1117ac6ad6cdf1a3bc543bad3b133724620522d5', // MODA
|
||||
'0xf5cfbc74057c610c8ef151a439252680ac68c6dc', // OCT
|
||||
'0x9aeb50f542050172359a0e1a25a9933bc8c01259', // OIN
|
||||
'0xea7cc765ebc94c4805e3bff28d7e4ae48d06468a', // PAD
|
||||
'0x429881672b9ae42b8eba0e26cd9c73711b891ca5', // PICKLE
|
||||
'0x408e41876cccdc0f92210600ef50372656052a38', // REN
|
||||
'0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f', // SNX
|
||||
'0x6b3595068778dd592e39a122f4f5a5cf09c90fe2', // SUSHI
|
||||
'0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', // UNI
|
||||
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
|
||||
'0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
|
||||
'0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', // WBTC
|
||||
'0x4691937a7508860f876c9c0a2a617e7d9e945d4b', // WOO
|
||||
'0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e' // YFI
|
||||
].map(contractAddress => contractAddress.toLowerCase())
|
||||
|
||||
@@ -512,4 +512,8 @@
|
||||
<message name="IDS_BRAVE_WALLET_HELP_CENTER_TEXT" desc="Help Center text description below buy-send-swap">Need help? See</message>
|
||||
<message name="IDS_BRAVE_WALLET_HARDWARE_OPERATION_UNSUPPORTED_ERROR" desc="Error message of unsupported hardware wallet operation">This hardware wallet does not support this operation.</message>
|
||||
<message name="IDS_BRAVE_WALLET_ENTER_YOUR_PASSWORD" desc="Prompt for the user to enter their password">Enter your Brave Wallet password</message>
|
||||
<message name="IDS_BRAVE_WALLET_AURORA_MODAL_TITLE" desc="Bridge to Aurora modal title">Open rainbowbridge.app?</message>
|
||||
<message name="IDS_BRAVE_WALLET_AURORA_MODAL_DESCRIPTION" desc="Bridge to Aurora modal description">Bridging assets across networks allows you to use your crypto on other networks and other DApp ecosystems. Bridging assets to other networks has some risks.</message>
|
||||
<message name="IDS_BRAVE_WALLET_AURORA_MODAL_LEARN_MORE" desc="Bridge to Aurora modal learn more link text">Learn more</message>
|
||||
<message name="IDS_BRAVE_WALLET_AURORA_MODAL_OPEN_BUTTON_TEXT" desc="Bridge to Aurora modal action button text">Open rainbowbridge.app</message>
|
||||
</grit-part>
|
||||
|
||||
Reference in New Issue
Block a user