diff --git a/apps/api/src/config/env.server.mjs b/apps/api/src/config/env.server.mjs index 1ee3fde67..662868d0a 100644 --- a/apps/api/src/config/env.server.mjs +++ b/apps/api/src/config/env.server.mjs @@ -17,7 +17,6 @@ export const envSchema = z.object({ ]) .optional(), INFURA_API_KEY: z.string(), - MERCURYO_SECRET_KEY: z.string(), ALCHEMY_API_KEYS: z.string(), COINGECKO_API_KEY: z.string(), CRYPTOCOMPARE_API_KEYS: z.string(), diff --git a/apps/portfolio/src/app/_actions.ts b/apps/portfolio/src/app/_actions.ts index 39978fded..e9084ae86 100644 --- a/apps/portfolio/src/app/_actions.ts +++ b/apps/portfolio/src/app/_actions.ts @@ -1,38 +1,18 @@ 'use server' -import crypto from 'crypto' -import { match } from 'ts-pattern' - -import { serverEnv } from '../config/env.server.mjs' import { getAPIClient } from '../data/api' import type { NetworkType } from '@status-im/wallet/data' -export type Provider = 'mercuryo' | 'moonpay' +export type Provider = 'moonpay' type ApiInput = { name: Provider - asset?: string - network?: string address?: string } -function getChainIdFromCode(chainCode: string): number | undefined { - return match(chainCode) - .with('ETHEREUM', () => 1) - .otherwise(() => undefined) -} - -function convertIpfsUriToHttp(uri: string): string { - if (uri.startsWith('ipfs://')) { - const cid = uri.replace('ipfs://', '') - return `https://ipfs.io/ipfs/${cid}` - } - return uri -} - export async function handleCryptoOnRamp(input: ApiInput) { - const { name, network, asset, address } = input + const { name, address } = input // Redirect to the provider's website let redirectUrl = '' @@ -45,124 +25,9 @@ export async function handleCryptoOnRamp(input: ApiInput) { throw new Error('Address is required') } - if (name === 'mercuryo') { - const baseUrl = `https://exchange.mercuryo.io/?type=buy&network=${network}¤cy=${asset}&address=${address}&hide_address=false&fix_address=true&widget_id=6a7eb330-2b09-49b7-8fd3-1c77cfb6cd47` - - const signature = crypto - .createHmac('sha512', serverEnv.MERCURYO_SECRET_KEY) - .update(new URL(baseUrl).search) - .digest('hex') - - redirectUrl = `${baseUrl}&signature=${encodeURIComponent(signature)}` - } - return { url: redirectUrl } } -type Icons = { - png: string - relative: { png: string; svg: string } - svg: string -} - -type CryptoCurrency = { - contract: string - currency: string - network: string - network_label: string - show_network_icon: boolean -} - -type Response = { - data: { - config: { - base: Record - crypto_currencies: CryptoCurrency[] - default_networks: Record - display_options: Record< - string, - { fullname: string; total_digits: number; display_digits: number } - > - has_withdrawal_fee: Record - icons: Record - networks: Record - } - crypto: string[] - fiat: string[] - } - status: number -} - -export type Currency = { - contract_address: string - code: string - label: string - network: string - imageUrl: string -} - -export const getSupportedCurrencies = async (): Promise => { - // Fetch the data from Mercuryo and cache it for 24 hours - const response = await fetch('https://api.mercuryo.io/v1.6/lib/currencies', { - next: { - revalidate: 86400, // 24 hours - }, - }) - - const data: Response = await response.json() - - if (data.status !== 200) { - throw new Error('Failed to fetch data from Mercuryo') - } - - const supportedCurrencies = data.data.config.crypto_currencies - .filter(currency => { - // Get the chain ID from the network (e.g., 'ETHEREUM', 'ARBITRUM') - const chainId = getChainIdFromCode(currency.network) - - if (currency.currency === 'ETH' && !!chainId) { - return true - } - - // Find matching Mercuryo token by contract address and network chain ID. - return ([] as any).some((uniswapToken: any) => { - // Check if token is either Ethereum or the contract address matches - return ( - chainId === uniswapToken.chainId && - uniswapToken.address.toLowerCase() === currency.contract.toLowerCase() - ) - }) - }) - .map(currency => { - const tokenFromUniswap = ([] as any).find((uniswapToken: any) => { - return ( - uniswapToken.address.toLowerCase() === currency.contract.toLowerCase() - ) - }) - - // If the currency is ETH, return the Ether object because it's not in the Uniswap tokens list - if (currency.currency === 'ETH') { - return { - contract_address: currency.contract, - code: currency.currency, - label: 'Ether', - network: currency.network, - imageUrl: '/images/tokens/eth.png', - } - } - - return { - contract_address: tokenFromUniswap?.address || '', - code: tokenFromUniswap?.symbol || '', - label: tokenFromUniswap?.name || '', - network: currency.network || '', - imageUrl: convertIpfsUriToHttp(tokenFromUniswap?.imageUrl || ''), - } - }) - - return supportedCurrencies -} - export async function getAccountsData( addresses: string[], networks: NetworkType[] diff --git a/apps/portfolio/src/app/_components/buy-crypto-drawer.tsx b/apps/portfolio/src/app/_components/buy-crypto-drawer.tsx index cc480b4ab..91012c59d 100644 --- a/apps/portfolio/src/app/_components/buy-crypto-drawer.tsx +++ b/apps/portfolio/src/app/_components/buy-crypto-drawer.tsx @@ -1,12 +1,27 @@ 'use client' -import { - BuyCryptoDrawer as BuyCryptoDrawerBase, - type Provider, -} from '@status-im/wallet/components' +import { useState } from 'react' + +import { Avatar, useToast } from '@status-im/components' +import { FeesIcon } from '@status-im/icons/12' +import { ExternalIcon } from '@status-im/icons/20' +import NextImage from 'next/image' import { handleCryptoOnRamp } from '../_actions' import { useCurrentAccount } from '../_hooks/use-current-account' +import * as Drawer from './drawer' + +import type { Provider } from '../_actions' + +// Todo: pass images to cloudinary? +const PROVIDERS = [ + { + name: 'moonpay', + description: 'The new standard for fiat to crypto', + fee: '1% - 4.5%', + image: '/images/providers/moonpay.png', + }, +] as const type Props = { children: React.ReactElement @@ -14,23 +29,33 @@ type Props = { export const BuyCryptoDrawer = (props: Props) => { const { children } = props + const [open, setOpen] = useState(false) + const account = useCurrentAccount() + const toast = useToast() - const handleProviderSelect = async ( - provider: Provider, - network: string, - asset?: string - ) => { - return handleCryptoOnRamp({ - name: provider, - network, - address: account.address, - asset: asset || 'USD', - }) - } + const handleProviderSelect = async (provider: Provider) => { + const openProviderUrl = (url: string) => { + const newTab = window.open(url, '_blank', 'noopener,noreferrer') + if (!newTab) { + toast.negative( + 'Unable to open a new tab. Please check your browser settings.' + ) + } + } - const handleOpenTab = (url: string) => { - window.open(url, '_blank', 'noopener,noreferrer') + try { + const data = await handleCryptoOnRamp({ + name: provider, + address: account.address, + }) + + openProviderUrl(data.url) + } catch { + toast.negative( + 'Unable to open a new tab. Please check your browser settings.' + ) + } } if (!account) { @@ -38,12 +63,73 @@ export const BuyCryptoDrawer = (props: Props) => { } return ( - - {children} - + + {children} + + + + Buy crypto + +
+
+
+ +
+ + {account.name} + +
+
+
+ + +
+ {PROVIDERS.map(provider => ( + + ))} +
+
+
+
) } diff --git a/apps/portfolio/src/config/env.server.mjs b/apps/portfolio/src/config/env.server.mjs index dfe3afda7..45b9004b6 100644 --- a/apps/portfolio/src/config/env.server.mjs +++ b/apps/portfolio/src/config/env.server.mjs @@ -21,7 +21,6 @@ export const envSchema = z.object({ COINGECKO_API_KEY: z.string(), CRYPTOCOMPARE_API_KEYS: z.string(), PORT: z.coerce.number().optional(), - MERCURYO_SECRET_KEY: z.string(), }) const result = envSchema.safeParse(process.env) diff --git a/apps/status.app/content/help/getting-started/privacy-with-status-third-parties.mdx b/apps/status.app/content/help/getting-started/privacy-with-status-third-parties.mdx index 1efa2c44e..6b659e9b5 100644 --- a/apps/status.app/content/help/getting-started/privacy-with-status-third-parties.mdx +++ b/apps/status.app/content/help/getting-started/privacy-with-status-third-parties.mdx @@ -42,12 +42,6 @@ Status Software only shares the above personal data when the user explicitly nav For more information about the on-ramp providers, their APIs and widgets, and privacy policies, please see below: -#### Mercuryo - -- [https://uk.mercuryo.io/on-off-ramps/](https://uk.mercuryo.io/on-off-ramps/) -- [https://help.mercuryo.io/hc/en-gb/articles/14833411947037-How-does-the-Mercuryo-widget-work-for-on-ramp](https://help.mercuryo.io/hc/en-gb/articles/14833411947037-How-does-the-Mercuryo-widget-work-for-on-ramp) -- [https://help.mercuryo.io/hc/en-gb/articles/14495463995805-How-does-Mercuryo-keep-my-information-safe](https://help.mercuryo.io/hc/en-gb/articles/14495463995805-How-does-Mercuryo-keep-my-information-safe) - #### Moonpay - [https://www.moonpay.com/en-gb](https://www.moonpay.com/en-gb) diff --git a/apps/status.app/content/help/wallet/buy-crypto.mdx b/apps/status.app/content/help/wallet/buy-crypto.mdx index bd7bdda83..b0f0f3d79 100644 --- a/apps/status.app/content/help/wallet/buy-crypto.mdx +++ b/apps/status.app/content/help/wallet/buy-crypto.mdx @@ -58,13 +58,13 @@ In Status Wallet, you can buy crypto with fiat currencies such as USD, EUR and o ### Are crypto purchases handled by Status? -No. When you're buying crypto in Status, you're buying from our partners through their sites. If you have any issues or questions, please contact the support team of the partner you bought crypto from (Mercuryo, Ramp or MoonPay). +No. When you're buying crypto in Status, you're buying from our partners through their sites. If you have any issues or questions, please contact the support team of the partner you bought crypto from (Ramp or MoonPay). ### Why did I receive a different amount than I expected? An asset exchange rate is always changing and fluctuating, and blockchain transactions take some time to be processed. If the network is particularly busy while you're placing your order, it can take longer for your transaction to go through. -This can sometimes lead to you receiving more or less than the amount you were expecting. If you have any issues or questions, please contact the support team of the partner you bought crypto from (Mercuryo, Ramp or MoonPay). +This can sometimes lead to you receiving more or less than the amount you were expecting. If you have any issues or questions, please contact the support team of the partner you bought crypto from (Ramp or MoonPay). ### Does Status charge any fees for buying crypto? diff --git a/apps/wallet/wxt.config.ts b/apps/wallet/wxt.config.ts index fd15022c3..3a50318e1 100644 --- a/apps/wallet/wxt.config.ts +++ b/apps/wallet/wxt.config.ts @@ -53,7 +53,6 @@ export default defineConfig({ INFURA_API_KEY: 'test', CRYPTOCOMPARE_API_KEYS: 'test', COINGECKO_API_KEY: 'test', - MERCURYO_SECRET_KEY: 'test', VERCEL: 'test', VERCEL_ENV: 'test', }, diff --git a/packages/wallet/src/components/buy-crypto-drawer/index.tsx b/packages/wallet/src/components/buy-crypto-drawer/index.tsx index 98c299d80..df5239e5a 100644 --- a/packages/wallet/src/components/buy-crypto-drawer/index.tsx +++ b/packages/wallet/src/components/buy-crypto-drawer/index.tsx @@ -12,7 +12,7 @@ import { Image, type ImageId } from '../image' import type { Account } from '../address' -export type Provider = 'mercuryo' | 'moonpay' +export type Provider = 'moonpay' export type Currency = { contract_address: string @@ -61,12 +61,6 @@ export const BuyCryptoDrawer = (props: Props) => { children, account, providers = [ - { - name: 'mercuryo', - // description: 'Buy crypto within 15 seconds', - fee: '1% - 4.5%', - image: 'Wallet/Icons/Logos/mercuryo:64:64', - }, { name: 'moonpay', // description: 'The new standard for fiat to crypto', @@ -102,7 +96,6 @@ export const BuyCryptoDrawer = (props: Props) => { url = data.url } else { const providerUrls = { - mercuryo: `https://exchange.mercuryo.io/?type=buy&network=${network.id}¤cy=${currency.code}&address=${account.address}&hide_address=false&fix_address=true&widget_id=6a7eb330-2b09-49b7-8fd3-1c77cfb6cd47`, moonpay: `https://buy.moonpay.com?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR`, } @@ -159,8 +152,6 @@ export const BuyCryptoDrawer = (props: Props) => { {account.name} - - {/* Removed isMercuryoSelected and its related ContextTag */} diff --git a/packages/wallet/src/components/empty-state-actions/components/buy-tokens.tsx b/packages/wallet/src/components/empty-state-actions/components/buy-tokens.tsx index b96d40f3e..bc7f46b0e 100644 --- a/packages/wallet/src/components/empty-state-actions/components/buy-tokens.tsx +++ b/packages/wallet/src/components/empty-state-actions/components/buy-tokens.tsx @@ -3,13 +3,7 @@ import { cx } from 'class-variance-authority' import { Image, type ImageId } from '../../image' -type Props = { - address: string -} - -const BuyTokens = (props: Props) => { - const { address } = props - +const BuyTokens = () => { const PROVIDERS: ProviderProps[] = [ { name: 'MoonPay', @@ -21,16 +15,6 @@ const BuyTokens = (props: Props) => { ], url: 'https://buy.moonpay.com/v2/buy?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR', }, - { - name: 'Mercuryo', - image: 'Wallet/Icons/Logos/mercuryo-bigger:144:144', - list: [ - 'Pay with Credit/Debit Card, Bank Transfer, Apple/Google Pay, SEPA, +10 more', - 'Fees: from 1%', - 'Supported Countries: 135+', - ], - url: `https://exchange.mercuryo.io/?type=buy&network=ETHEREUM¤cy=ETH&address=${address}&hide_address=false&fix_address=true&widget_id=6a7eb330-2b09-49b7-8fd3-1c77cfb6cd47`, - }, ] return ( diff --git a/packages/wallet/src/components/empty-state-actions/index.tsx b/packages/wallet/src/components/empty-state-actions/index.tsx index a48dfe70c..6c2838458 100644 --- a/packages/wallet/src/components/empty-state-actions/index.tsx +++ b/packages/wallet/src/components/empty-state-actions/index.tsx @@ -10,7 +10,7 @@ const EmptyStateActions = (props: Props) => { return (
- +
) diff --git a/packages/wallet/src/components/image/types.ts b/packages/wallet/src/components/image/types.ts index 7f8d24196..7445e3b27 100644 --- a/packages/wallet/src/components/image/types.ts +++ b/packages/wallet/src/components/image/types.ts @@ -1,8 +1,6 @@ export type ImageType = | { id: 'Portfolio/Empty States/No_Balance:750:232'; alt: '' } - | { id: 'Wallet/Icons/Logos/mercuryo-bigger:144:144'; alt: '' } | { id: 'Wallet/Icons/Logos/moonpay-bigger:144:144'; alt: '' } - | { id: 'Wallet/Icons/Logos/mercuryo:64:64'; alt: '' } | { id: 'Wallet/Icons/Logos/moonpay:64:64'; alt: '' } | { id: 'Homepage/Screens/Extension Section/Extension_01:2127:2390'; alt: '' } | { diff --git a/packages/wallet/src/components/send-assets-modal/index.tsx b/packages/wallet/src/components/send-assets-modal/index.tsx index 39c9ac75e..74603e50e 100644 --- a/packages/wallet/src/components/send-assets-modal/index.tsx +++ b/packages/wallet/src/components/send-assets-modal/index.tsx @@ -514,7 +514,7 @@ const SendAssetsModal = (props: Props) => { variant="danger" size="24" className="ml-2" - href={`https://exchange.mercuryo.io/?type=buy&network=${asset.network}¤cy=ETH&address=${account.address}&hide_address=false&fix_address=true&widget_id=6a7eb330-2b09-49b7-8fd3-1c77cfb6cd47`} + href={`https://buy.moonpay.com?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR`} > Add ETH diff --git a/packages/wallet/src/config/env.server.mjs b/packages/wallet/src/config/env.server.mjs index 486ad37bb..873875543 100644 --- a/packages/wallet/src/config/env.server.mjs +++ b/packages/wallet/src/config/env.server.mjs @@ -13,7 +13,6 @@ export const envSchema = z.object({ COINGECKO_API_KEY: z.string(), CRYPTOCOMPARE_API_KEYS: z.string(), PORT: z.coerce.number().optional(), - MERCURYO_SECRET_KEY: z.string(), }) const result = envSchema.safeParse(process.env)