feat: dynamic defaultCurrencyCode for moonpay (#7383)
This commit is contained in:
parent
cbec108172
commit
524ce49fcb
@ -21,6 +21,7 @@ import { gqlToCurrency, logSentryErrorForUnsupportedChain, supportedChainIdFromG
|
|||||||
import ms from 'ms'
|
import ms from 'ms'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { isAddress } from 'utils'
|
import { isAddress } from 'utils'
|
||||||
|
import { isSameAddress } from 'utils/addresses'
|
||||||
import { NumberType, useFormatter } from 'utils/formatNumbers'
|
import { NumberType, useFormatter } from 'utils/formatNumbers'
|
||||||
|
|
||||||
import { MOONPAY_SENDER_ADDRESSES, OrderStatusTable, OrderTextTable } from '../constants'
|
import { MOONPAY_SENDER_ADDRESSES, OrderStatusTable, OrderTextTable } from '../constants'
|
||||||
@ -77,10 +78,6 @@ const COMMON_CONTRACTS: { [key: string]: Partial<Activity> | undefined } = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSameAddress(a?: string, b?: string) {
|
|
||||||
return a === b || a?.toLowerCase() === b?.toLowerCase() // Lazy-lowercases the addresses
|
|
||||||
}
|
|
||||||
|
|
||||||
function callsPositionManagerContract(assetActivity: TransactionActivity) {
|
function callsPositionManagerContract(assetActivity: TransactionActivity) {
|
||||||
const supportedChain = supportedChainIdFromGQLChain(assetActivity.chain)
|
const supportedChain = supportedChainIdFromGQLChain(assetActivity.chain)
|
||||||
if (!supportedChain) return false
|
if (!supportedChain) return false
|
||||||
|
17
src/components/FiatOnrampModal/constants.ts
Normal file
17
src/components/FiatOnrampModal/constants.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
export const MOONPAY_SUPPORTED_CURRENCY_CODES = [
|
||||||
|
'eth',
|
||||||
|
'eth_arbitrum',
|
||||||
|
'eth_optimism',
|
||||||
|
'eth_polygon',
|
||||||
|
'weth',
|
||||||
|
'wbtc',
|
||||||
|
'matic_polygon',
|
||||||
|
'polygon',
|
||||||
|
'usdc_arbitrum',
|
||||||
|
'usdc_optimism',
|
||||||
|
'usdc_polygon',
|
||||||
|
'usdc',
|
||||||
|
'usdt',
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export type MoonpaySupportedCurrencyCode = (typeof MOONPAY_SUPPORTED_CURRENCY_CODES)[number]
|
@ -10,6 +10,8 @@ import { useIsDarkMode } from 'theme/components/ThemeToggle'
|
|||||||
|
|
||||||
import Circle from '../../assets/images/blue-loader.svg'
|
import Circle from '../../assets/images/blue-loader.svg'
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
|
import { MOONPAY_SUPPORTED_CURRENCY_CODES } from './constants'
|
||||||
|
import { getDefaultCurrencyCode, parsePathParts } from './utils'
|
||||||
|
|
||||||
const MOONPAY_DARK_BACKGROUND = '#1c1c1e'
|
const MOONPAY_DARK_BACKGROUND = '#1c1c1e'
|
||||||
const Wrapper = styled.div<{ isDarkMode: boolean }>`
|
const Wrapper = styled.div<{ isDarkMode: boolean }>`
|
||||||
@ -55,20 +57,6 @@ const StyledSpinner = styled(CustomLightSpinner)`
|
|||||||
top: 0;
|
top: 0;
|
||||||
`
|
`
|
||||||
|
|
||||||
const MOONPAY_SUPPORTED_CURRENCY_CODES = [
|
|
||||||
'eth',
|
|
||||||
'eth_arbitrum',
|
|
||||||
'eth_optimism',
|
|
||||||
'eth_polygon',
|
|
||||||
'weth',
|
|
||||||
'wbtc',
|
|
||||||
'matic_polygon',
|
|
||||||
'polygon',
|
|
||||||
'usdc_arbitrum',
|
|
||||||
'usdc_optimism',
|
|
||||||
'usdc_polygon',
|
|
||||||
]
|
|
||||||
|
|
||||||
export default function FiatOnrampModal() {
|
export default function FiatOnrampModal() {
|
||||||
const { account } = useWeb3React()
|
const { account } = useWeb3React()
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
@ -76,6 +64,8 @@ export default function FiatOnrampModal() {
|
|||||||
const closeModal = useCloseModal()
|
const closeModal = useCloseModal()
|
||||||
const fiatOnrampModalOpen = useModalIsOpen(ApplicationModal.FIAT_ONRAMP)
|
const fiatOnrampModalOpen = useModalIsOpen(ApplicationModal.FIAT_ONRAMP)
|
||||||
|
|
||||||
|
const { network, tokenAddress } = parsePathParts(location.pathname)
|
||||||
|
|
||||||
const [signedIframeUrl, setSignedIframeUrl] = useState<string | null>(null)
|
const [signedIframeUrl, setSignedIframeUrl] = useState<string | null>(null)
|
||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
@ -100,7 +90,7 @@ export default function FiatOnrampModal() {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
theme: isDarkMode ? 'dark' : 'light',
|
theme: isDarkMode ? 'dark' : 'light',
|
||||||
colorCode: theme.accent1,
|
colorCode: theme.accent1,
|
||||||
defaultCurrencyCode: 'eth',
|
defaultCurrencyCode: getDefaultCurrencyCode(tokenAddress, network),
|
||||||
redirectUrl: swapUrl,
|
redirectUrl: swapUrl,
|
||||||
walletAddresses: JSON.stringify(
|
walletAddresses: JSON.stringify(
|
||||||
MOONPAY_SUPPORTED_CURRENCY_CODES.reduce(
|
MOONPAY_SUPPORTED_CURRENCY_CODES.reduce(
|
||||||
@ -121,7 +111,7 @@ export default function FiatOnrampModal() {
|
|||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}, [account, isDarkMode, swapUrl, theme.accent1])
|
}, [account, isDarkMode, network, swapUrl, theme.accent1, tokenAddress])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchSignedIframeUrl()
|
fetchSignedIframeUrl()
|
||||||
|
78
src/components/FiatOnrampModal/utils.test.ts
Normal file
78
src/components/FiatOnrampModal/utils.test.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import { ChainId, WETH9 } from '@uniswap/sdk-core'
|
||||||
|
import {
|
||||||
|
MATIC,
|
||||||
|
USDC_ARBITRUM,
|
||||||
|
USDC_MAINNET,
|
||||||
|
USDC_OPTIMISM,
|
||||||
|
USDC_POLYGON,
|
||||||
|
USDT,
|
||||||
|
WBTC,
|
||||||
|
WETH_POLYGON,
|
||||||
|
} from 'constants/tokens'
|
||||||
|
|
||||||
|
import { getDefaultCurrencyCode, parsePathParts } from './utils'
|
||||||
|
|
||||||
|
describe('getDefaultCurrencyCode', () => {
|
||||||
|
it('NATIVE/arbitrum should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode('NATIVE', 'arbitrum')).toBe('eth_arbitrum')
|
||||||
|
})
|
||||||
|
it('NATIVE/optimism should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode('NATIVE', 'optimism')).toBe('eth_optimism')
|
||||||
|
})
|
||||||
|
it('WETH/polygon should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(WETH_POLYGON.address, 'polygon')).toBe('eth_polygon')
|
||||||
|
})
|
||||||
|
it('WETH/ethereum should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(WETH9[ChainId.MAINNET].address, 'ethereum')).toBe('weth')
|
||||||
|
})
|
||||||
|
it('WBTC/ethereum should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(WBTC.address, 'ethereum')).toBe('wbtc')
|
||||||
|
})
|
||||||
|
it('NATIVE/polygon should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode('NATIVE', 'polygon')).toBe('matic_polygon')
|
||||||
|
})
|
||||||
|
it('MATIC/ethereum should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(MATIC.address, 'ethereum')).toBe('polygon')
|
||||||
|
})
|
||||||
|
it('USDC/arbitrum should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(USDC_ARBITRUM.address, 'arbitrum')).toBe('usdc_arbitrum')
|
||||||
|
})
|
||||||
|
it('USDC/optimism should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(USDC_OPTIMISM.address, 'optimism')).toBe('usdc_optimism')
|
||||||
|
})
|
||||||
|
it('USDC/polygon should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(USDC_POLYGON.address, 'polygon')).toBe('usdc_polygon')
|
||||||
|
})
|
||||||
|
it('native/ethereum should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode('NATIVE', 'ethereum')).toBe('eth')
|
||||||
|
})
|
||||||
|
it('usdc/ethereum should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(USDC_MAINNET.address, 'ethereum')).toBe('usdc')
|
||||||
|
})
|
||||||
|
it('usdt/ethereum should return the correct currency code', () => {
|
||||||
|
expect(getDefaultCurrencyCode(USDT.address, 'ethereum')).toBe('usdt')
|
||||||
|
})
|
||||||
|
it('chain/token mismatch should default to eth', () => {
|
||||||
|
expect(getDefaultCurrencyCode(USDC_ARBITRUM.address, 'ethereum')).toBe('eth')
|
||||||
|
expect(getDefaultCurrencyCode(USDC_OPTIMISM.address, 'ethereum')).toBe('eth')
|
||||||
|
expect(getDefaultCurrencyCode(USDC_POLYGON.address, 'ethereum')).toBe('eth')
|
||||||
|
expect(getDefaultCurrencyCode(MATIC.address, 'arbitrum')).toBe('eth')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('parseLocation', () => {
|
||||||
|
it('should parse the URL correctly', () => {
|
||||||
|
expect(parsePathParts('/tokens/ethereum/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599')).toEqual({
|
||||||
|
network: 'ethereum',
|
||||||
|
tokenAddress: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599',
|
||||||
|
})
|
||||||
|
expect(parsePathParts('tokens/ethereum/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599')).toEqual({
|
||||||
|
network: 'ethereum',
|
||||||
|
tokenAddress: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599',
|
||||||
|
})
|
||||||
|
expect(parsePathParts('/swap')).toEqual({
|
||||||
|
network: undefined,
|
||||||
|
tokenAddress: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
74
src/components/FiatOnrampModal/utils.ts
Normal file
74
src/components/FiatOnrampModal/utils.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import { ChainId, WETH9 } from '@uniswap/sdk-core'
|
||||||
|
import {
|
||||||
|
BRIDGED_USDC_ARBITRUM,
|
||||||
|
MATIC,
|
||||||
|
USDC_ARBITRUM,
|
||||||
|
USDC_MAINNET,
|
||||||
|
USDC_OPTIMISM,
|
||||||
|
USDC_POLYGON,
|
||||||
|
USDT,
|
||||||
|
WBTC,
|
||||||
|
WETH_POLYGON,
|
||||||
|
} from 'constants/tokens'
|
||||||
|
import { Chain } from 'graphql/data/__generated__/types-and-hooks'
|
||||||
|
import { validateUrlChainParam } from 'graphql/data/util'
|
||||||
|
|
||||||
|
import { MoonpaySupportedCurrencyCode } from './constants'
|
||||||
|
|
||||||
|
type MoonpaySupportedChain = Chain.Ethereum | Chain.Polygon | Chain.Arbitrum | Chain.Optimism
|
||||||
|
const moonPaySupportedChains = [Chain.Ethereum, Chain.Polygon, Chain.Arbitrum, Chain.Optimism]
|
||||||
|
|
||||||
|
const CURRENCY_CODES: {
|
||||||
|
[K in MoonpaySupportedChain]: {
|
||||||
|
[key: string]: MoonpaySupportedCurrencyCode
|
||||||
|
native: MoonpaySupportedCurrencyCode
|
||||||
|
}
|
||||||
|
} = {
|
||||||
|
[Chain.Ethereum]: {
|
||||||
|
[WETH9[ChainId.MAINNET]?.address.toLowerCase()]: 'weth',
|
||||||
|
[USDC_MAINNET.address.toLowerCase()]: 'usdc',
|
||||||
|
[USDT.address.toLowerCase()]: 'usdt',
|
||||||
|
[WBTC.address.toLowerCase()]: 'wbtc',
|
||||||
|
[MATIC.address.toLowerCase()]: 'polygon',
|
||||||
|
native: 'eth',
|
||||||
|
},
|
||||||
|
[Chain.Arbitrum]: {
|
||||||
|
[USDC_ARBITRUM.address.toLowerCase()]: 'usdc_arbitrum',
|
||||||
|
[BRIDGED_USDC_ARBITRUM.address.toLowerCase()]: 'usdc_arbitrum',
|
||||||
|
native: 'eth_arbitrum',
|
||||||
|
},
|
||||||
|
[Chain.Optimism]: {
|
||||||
|
[USDC_OPTIMISM.address.toLowerCase()]: 'usdc_optimism',
|
||||||
|
native: 'eth_optimism',
|
||||||
|
},
|
||||||
|
[Chain.Polygon]: {
|
||||||
|
[USDC_POLYGON.address.toLowerCase()]: 'usdc_polygon',
|
||||||
|
[WETH_POLYGON.address.toLowerCase()]: 'eth_polygon',
|
||||||
|
native: 'matic_polygon',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDefaultCurrencyCode(
|
||||||
|
address: string | undefined,
|
||||||
|
chainName: string | undefined
|
||||||
|
): MoonpaySupportedCurrencyCode {
|
||||||
|
const chain = validateUrlChainParam(chainName)
|
||||||
|
if (!address || !chain) return 'eth'
|
||||||
|
if (moonPaySupportedChains.includes(chain)) {
|
||||||
|
const code = CURRENCY_CODES[chain as MoonpaySupportedChain]?.[address.toLowerCase()]
|
||||||
|
return code ?? 'eth'
|
||||||
|
}
|
||||||
|
return 'eth'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You should use useParams() from react-router-dom instead of this function if possible.
|
||||||
|
* This function is only used in the case where we need to parse the path outside the scope of the router.
|
||||||
|
*/
|
||||||
|
export function parsePathParts(pathname: string): { network?: string; tokenAddress?: string } {
|
||||||
|
const pathParts = pathname.split('/')
|
||||||
|
// Matches the /tokens/<network>/<tokenAddress> path.
|
||||||
|
const network = pathParts.length > 2 ? pathParts[pathParts.length - 2] : undefined
|
||||||
|
const tokenAddress = pathParts.length > 2 ? pathParts[pathParts.length - 1] : undefined
|
||||||
|
return { network, tokenAddress }
|
||||||
|
}
|
@ -96,6 +96,13 @@ export const DAI_OPTIMISM = new Token(
|
|||||||
'DAI',
|
'DAI',
|
||||||
'Dai stable coin'
|
'Dai stable coin'
|
||||||
)
|
)
|
||||||
|
export const MATIC = new Token(
|
||||||
|
ChainId.MAINNET,
|
||||||
|
'0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0',
|
||||||
|
18,
|
||||||
|
'MATIC',
|
||||||
|
'Polygon Matic'
|
||||||
|
)
|
||||||
export const DAI_POLYGON = new Token(
|
export const DAI_POLYGON = new Token(
|
||||||
ChainId.POLYGON,
|
ChainId.POLYGON,
|
||||||
'0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063',
|
'0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063',
|
||||||
|
@ -11,6 +11,10 @@ export function isAddress(value: any): string | false {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSameAddress(a?: string, b?: string) {
|
||||||
|
return a === b || a?.toLowerCase() === b?.toLowerCase() // Lazy-lowercases the addresses
|
||||||
|
}
|
||||||
|
|
||||||
// Shortens an Ethereum address
|
// Shortens an Ethereum address
|
||||||
export function shortenAddress(address = '', charsStart = 4, charsEnd = 4): string {
|
export function shortenAddress(address = '', charsStart = 4, charsEnd = 4): string {
|
||||||
const parsed = isAddress(address)
|
const parsed = isAddress(address)
|
||||||
|
Loading…
Reference in New Issue
Block a user