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 { useEffect, useState } from 'react'
|
||||
import { isAddress } from 'utils'
|
||||
import { isSameAddress } from 'utils/addresses'
|
||||
import { NumberType, useFormatter } from 'utils/formatNumbers'
|
||||
|
||||
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) {
|
||||
const supportedChain = supportedChainIdFromGQLChain(assetActivity.chain)
|
||||
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 Modal from '../Modal'
|
||||
import { MOONPAY_SUPPORTED_CURRENCY_CODES } from './constants'
|
||||
import { getDefaultCurrencyCode, parsePathParts } from './utils'
|
||||
|
||||
const MOONPAY_DARK_BACKGROUND = '#1c1c1e'
|
||||
const Wrapper = styled.div<{ isDarkMode: boolean }>`
|
||||
@ -55,20 +57,6 @@ const StyledSpinner = styled(CustomLightSpinner)`
|
||||
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() {
|
||||
const { account } = useWeb3React()
|
||||
const theme = useTheme()
|
||||
@ -76,6 +64,8 @@ export default function FiatOnrampModal() {
|
||||
const closeModal = useCloseModal()
|
||||
const fiatOnrampModalOpen = useModalIsOpen(ApplicationModal.FIAT_ONRAMP)
|
||||
|
||||
const { network, tokenAddress } = parsePathParts(location.pathname)
|
||||
|
||||
const [signedIframeUrl, setSignedIframeUrl] = useState<string | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
@ -100,7 +90,7 @@ export default function FiatOnrampModal() {
|
||||
body: JSON.stringify({
|
||||
theme: isDarkMode ? 'dark' : 'light',
|
||||
colorCode: theme.accent1,
|
||||
defaultCurrencyCode: 'eth',
|
||||
defaultCurrencyCode: getDefaultCurrencyCode(tokenAddress, network),
|
||||
redirectUrl: swapUrl,
|
||||
walletAddresses: JSON.stringify(
|
||||
MOONPAY_SUPPORTED_CURRENCY_CODES.reduce(
|
||||
@ -121,7 +111,7 @@ export default function FiatOnrampModal() {
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [account, isDarkMode, swapUrl, theme.accent1])
|
||||
}, [account, isDarkMode, network, swapUrl, theme.accent1, tokenAddress])
|
||||
|
||||
useEffect(() => {
|
||||
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 stable coin'
|
||||
)
|
||||
export const MATIC = new Token(
|
||||
ChainId.MAINNET,
|
||||
'0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0',
|
||||
18,
|
||||
'MATIC',
|
||||
'Polygon Matic'
|
||||
)
|
||||
export const DAI_POLYGON = new Token(
|
||||
ChainId.POLYGON,
|
||||
'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
|
||||
export function shortenAddress(address = '', charsStart = 4, charsEnd = 4): string {
|
||||
const parsed = isAddress(address)
|
||||
|
Loading…
Reference in New Issue
Block a user