From 648060dfb28a8e331011d9d4dd6340a36d6efdb1 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Wed, 11 Sep 2024 17:19:54 +0300 Subject: [PATCH] Feat/solana onramp (#2525) Co-authored-by: Enes Co-authored-by: valentyn-solana <156078272+valentyn-solana@users.noreply.github.com> Co-authored-by: Felipe Mendes --- .../tests/shared/validators/ModalValidator.ts | 8 ++--- .../core/src/controllers/OnRampController.ts | 24 ++++++++++++-- packages/core/src/utils/ConstantsUtil.ts | 13 +++++++- .../w3m-account-default-widget/index.ts | 3 +- .../views/w3m-onramp-providers-view/index.ts | 33 +++++++++++-------- packages/ui/src/assets/visual/meld.ts | 31 +++++++++++++++++ .../ui/src/components/wui-visual/index.ts | 3 ++ packages/ui/src/utils/TypeUtil.ts | 1 + 8 files changed, 91 insertions(+), 25 deletions(-) create mode 100644 packages/ui/src/assets/visual/meld.ts diff --git a/apps/laboratory/tests/shared/validators/ModalValidator.ts b/apps/laboratory/tests/shared/validators/ModalValidator.ts index 4bac72c8ff..260f1ca1ff 100644 --- a/apps/laboratory/tests/shared/validators/ModalValidator.ts +++ b/apps/laboratory/tests/shared/validators/ModalValidator.ts @@ -155,13 +155,9 @@ export class ModalValidator { await expect(switchNetworkButton).toBeVisible() } - async expectOnrampButton(library: string) { + async expectOnrampButton(_library: string) { const onrampButton = this.page.getByTestId('w3m-account-default-onramp-button') - if (library === 'solana') { - await expect(onrampButton).toBeHidden() - } else { - await expect(onrampButton).toBeVisible() - } + await expect(onrampButton).toBeVisible() } async expectAccountNameFound(name: string) { diff --git a/packages/core/src/controllers/OnRampController.ts b/packages/core/src/controllers/OnRampController.ts index 5e44155b04..e9b2c3d0f0 100644 --- a/packages/core/src/controllers/OnRampController.ts +++ b/packages/core/src/controllers/OnRampController.ts @@ -1,18 +1,26 @@ import { subscribeKey as subKey } from 'valtio/vanilla/utils' import { proxy, subscribe as sub } from 'valtio/vanilla' -import { ONRAMP_PROVIDERS } from '../utils/ConstantsUtil.js' +import { + ONRAMP_PROVIDERS, + MELD_DEV_PUBLIC_KEY, + MELD_PROD_PUBLIC_KEY +} from '../utils/ConstantsUtil.js' import type { PurchaseCurrency, PaymentCurrency } from '../utils/TypeUtil.js' import { BlockchainApiController } from './BlockchainApiController.js' import { ApiController } from './ApiController.js' +import { ChainController } from './ChainController.js' +import { AccountController } from './AccountController.js' +import { ConstantsUtil } from '@web3modal/common' // -- Types --------------------------------------------- // -export type OnRampProviderOption = 'coinbase' | 'moonpay' | 'stripe' | 'paypal' +export type OnRampProviderOption = 'coinbase' | 'moonpay' | 'stripe' | 'paypal' | 'meld' export type OnRampProvider = { label: string name: OnRampProviderOption feeRange: string url: string + supportedChains: string[] } export interface OnRampControllerState { @@ -93,6 +101,18 @@ export const OnRampController = { }, setSelectedProvider(provider: OnRampProvider | null) { + if (provider && provider.name === 'meld') { + const pubKey = + process.env['NODE_ENV'] === 'production' ? MELD_PROD_PUBLIC_KEY : MELD_DEV_PUBLIC_KEY + const currency = + ChainController.state.activeChain === ConstantsUtil.CHAIN.SOLANA ? 'SOL' : 'USDC' + const address = AccountController.state.address ?? '' + const url = new URL(provider.url) + url.searchParams.append('publicKey', pubKey) + url.searchParams.append('destinationCurrencyCode', currency) + url.searchParams.append('walletAddress', address) + provider.url = url.toString() + } state.selectedProvider = provider }, diff --git a/packages/core/src/utils/ConstantsUtil.ts b/packages/core/src/utils/ConstantsUtil.ts index e6f2ebdcd4..3020f6b31f 100644 --- a/packages/core/src/utils/ConstantsUtil.ts +++ b/packages/core/src/utils/ConstantsUtil.ts @@ -7,10 +7,21 @@ export const ONRAMP_PROVIDERS = [ label: 'Coinbase', name: 'coinbase', feeRange: '1-2%', - url: '' + url: '', + supportedChains: ['evm'] + }, + { + label: 'Meld.io', + name: 'meld', + feeRange: '1-2%', + url: 'https://meldcrypto.com', + supportedChains: ['evm', 'solana'] } ] +export const MELD_DEV_PUBLIC_KEY = 'WXETMsajb7XcQBm7mcxAab:q3MtzJpiEMtXVNXsqYkAnAaBkgStybGVtZ' +export const MELD_PROD_PUBLIC_KEY = 'WXETMuFUQmqqybHuRkSgxv:25B8LJHSfpG6LVjR2ytU5Cwh7Z4Sch2ocoU' + export const ConstantsUtil = { FOUR_MINUTES_MS: 240_000, diff --git a/packages/scaffold-ui/src/partials/w3m-account-default-widget/index.ts b/packages/scaffold-ui/src/partials/w3m-account-default-widget/index.ts index 6746b6d35b..96d482414c 100644 --- a/packages/scaffold-ui/src/partials/w3m-account-default-widget/index.ts +++ b/packages/scaffold-ui/src/partials/w3m-account-default-widget/index.ts @@ -107,9 +107,8 @@ export class W3mAccountDefaultWidget extends LitElement { // -- Private ------------------------------------------- // private onrampTemplate() { const { enableOnramp } = OptionsController.state - const isSolana = ChainController.state.activeChain === ConstantsUtil.CHAIN.SOLANA - if (!enableOnramp || isSolana) { + if (!enableOnramp) { return null } diff --git a/packages/scaffold-ui/src/views/w3m-onramp-providers-view/index.ts b/packages/scaffold-ui/src/views/w3m-onramp-providers-view/index.ts index 25a96bfd6b..57adb22975 100644 --- a/packages/scaffold-ui/src/views/w3m-onramp-providers-view/index.ts +++ b/packages/scaffold-ui/src/views/w3m-onramp-providers-view/index.ts @@ -7,7 +7,8 @@ import { RouterController, NetworkController, BlockchainApiController, - EventsController + EventsController, + ChainController } from '@web3modal/core' import { customElement } from '@web3modal/ui' import { LitElement, html } from 'lit' @@ -61,19 +62,23 @@ export class W3mOnRampProvidersView extends LitElement { // -- Private ------------------------------------------- // private onRampProvidersTemplate() { - return this.providers.map( - provider => html` - { - this.onClickProvider(provider) - }} - ?disabled=${!provider.url} - > - ` - ) + return this.providers + .filter(provider => + provider.supportedChains.includes(ChainController.state.activeChain ?? 'evm') + ) + .map( + provider => html` + { + this.onClickProvider(provider) + }} + ?disabled=${!provider.url} + > + ` + ) } private onClickProvider(provider: OnRampProvider) { diff --git a/packages/ui/src/assets/visual/meld.ts b/packages/ui/src/assets/visual/meld.ts new file mode 100644 index 0000000000..97b939ed04 --- /dev/null +++ b/packages/ui/src/assets/visual/meld.ts @@ -0,0 +1,31 @@ +import { svg } from 'lit' +export const meldSvg = svg` + + + + + + + + + + + + + + + + + + + + + + + + + + + + +` diff --git a/packages/ui/src/components/wui-visual/index.ts b/packages/ui/src/components/wui-visual/index.ts index c1135db139..8b3bdf68c0 100644 --- a/packages/ui/src/components/wui-visual/index.ts +++ b/packages/ui/src/components/wui-visual/index.ts @@ -25,6 +25,8 @@ import { onrampCardSvg } from '../../assets/visual/onramp-card.js' import { googleSvg } from '../../assets/visual/google.js' import { pencilSvg } from '../../assets/visual/pencil.js' import { lightbulbSvg } from '../../assets/visual/lightbulb.js' +import { meldSvg } from '../../assets/visual/meld.js' + import styles from './styles.js' // -- Svg's-------------------------------- // @@ -43,6 +45,7 @@ const svgOptions: Record> = { profile: profileSvg, system: systemSvg, coinbase: coinbaseSvg, + meld: meldSvg, onrampCard: onrampCardSvg, moonpay: moonpaySvg, stripe: stripeSvg, diff --git a/packages/ui/src/utils/TypeUtil.ts b/packages/ui/src/utils/TypeUtil.ts index 4b0080174c..22b0123ddb 100644 --- a/packages/ui/src/utils/TypeUtil.ts +++ b/packages/ui/src/utils/TypeUtil.ts @@ -174,6 +174,7 @@ export type IconType = export type VisualType = | 'browser' + | 'meld' | 'coinbase' | 'dao' | 'defi'