diff --git a/examples/react/src/components/Homepage.tsx b/examples/react/src/components/Homepage.tsx index 05130e1a..b58b0bbc 100644 --- a/examples/react/src/components/Homepage.tsx +++ b/examples/react/src/components/Homepage.tsx @@ -27,7 +27,7 @@ import { useWaasFeeOptions, useIndexerClient } from '@0xsequence/kit' -import { useCheckoutModal } from '@0xsequence/kit-checkout' +import { useCheckoutModal, useAddFundsModal } from '@0xsequence/kit-checkout' import { useOpenWalletModal } from '@0xsequence/kit-wallet' import { ChainId, allNetworks } from '@0xsequence/network' import { ethers } from 'ethers' @@ -66,6 +66,7 @@ export const Homepage = () => { const { setOpenConnectModal } = useOpenConnectModal() const { setOpenWalletModal } = useOpenWalletModal() const { triggerCheckout } = useCheckoutModal() + const { triggerAddFunds } = useAddFundsModal() const { disconnect } = useDisconnect() const { data: walletClient } = useWalletClient() const { switchChain } = useSwitchChain() @@ -377,6 +378,12 @@ export const Homepage = () => { } } + const onClickAddFunds = () => { + triggerAddFunds({ + walletAddress: address || '', + }) + } + const SwitchThemeButton = () => { return } @@ -466,7 +473,11 @@ export const Homepage = () => { )} - + onClickAddFunds()} + /> { + const { triggerAddFunds } = useAddFundsModal() + + const onClick = () => { + triggerAddFunds({ + walletAddress: recipientAddress, + }) + } + + return ( + + ) + } ``` \ No newline at end of file diff --git a/packages/checkout/src/contexts/AddFundsModal.ts b/packages/checkout/src/contexts/AddFundsModal.ts new file mode 100644 index 00000000..4c53d8c7 --- /dev/null +++ b/packages/checkout/src/contexts/AddFundsModal.ts @@ -0,0 +1,19 @@ +import { Hex } from 'viem' + +import { createGenericContext } from './genericContext' + +export interface AddFundsSettings { + walletAddress: string | Hex, + fiatCurrency?: string, + defaultFiatAmount?: string, + defaultCryptoCurrency?: string, + networks?: string +} + +type AddFundsModalContext = { + triggerAddFunds: (settings: AddFundsSettings) => void + closeAddFunds: () => void + addFundsSettings?: AddFundsSettings +} + +export const [useAddFundsModalContext, AddFundsContextProvider] = createGenericContext() diff --git a/packages/checkout/src/contexts/index.ts b/packages/checkout/src/contexts/index.ts index c61c68be..5a647be5 100644 --- a/packages/checkout/src/contexts/index.ts +++ b/packages/checkout/src/contexts/index.ts @@ -1,2 +1,3 @@ +export * from './AddFundsModal' export * from './CheckoutModal' export * from './Navigation' diff --git a/packages/checkout/src/hooks/index.ts b/packages/checkout/src/hooks/index.ts index 9d84b724..fdc3b30d 100644 --- a/packages/checkout/src/hooks/index.ts +++ b/packages/checkout/src/hooks/index.ts @@ -1,3 +1,4 @@ +export * from './useAddFundsModal' export * from './useCheckoutModal' export * from './useNavigation' export * from './useModalTheme' diff --git a/packages/checkout/src/hooks/useAddFundsModal.ts b/packages/checkout/src/hooks/useAddFundsModal.ts new file mode 100644 index 00000000..e6ae9861 --- /dev/null +++ b/packages/checkout/src/hooks/useAddFundsModal.ts @@ -0,0 +1,7 @@ +import { useAddFundsModalContext } from '../contexts/AddFundsModal' + +export const useAddFundsModal = () => { + const { triggerAddFunds, closeAddFunds, addFundsSettings } = useAddFundsModalContext() + + return { triggerAddFunds, closeAddFunds, addFundsSettings } +} diff --git a/packages/checkout/src/index.ts b/packages/checkout/src/index.ts index f67d1dd2..af76a557 100644 --- a/packages/checkout/src/index.ts +++ b/packages/checkout/src/index.ts @@ -3,5 +3,10 @@ export { KitCheckoutProvider } from './shared/components/KitCheckoutProvider' // Hooks export { useCheckoutModal } from './hooks/useCheckoutModal' +export { useAddFundsModal } from './hooks/useAddFundsModal' export { type CheckoutSettings } from './contexts/CheckoutModal' +export { type AddFundsSettings } from './contexts/AddFundsModal' + +// utils +export { fetchTransakSupportedCountries } from './utils/transak' \ No newline at end of file diff --git a/packages/checkout/src/shared/components/KitCheckoutProvider.tsx b/packages/checkout/src/shared/components/KitCheckoutProvider.tsx index 58173db8..f4fcf26a 100644 --- a/packages/checkout/src/shared/components/KitCheckoutProvider.tsx +++ b/packages/checkout/src/shared/components/KitCheckoutProvider.tsx @@ -6,9 +6,23 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { AnimatePresence } from 'framer-motion' import React, { useState, useEffect } from 'react' -import { History, Navigation, NavigationContextProvider, CheckoutModalContextProvider, CheckoutSettings } from '../../contexts' +import { + History, + Navigation, + NavigationContextProvider, + CheckoutModalContextProvider, + CheckoutSettings, + AddFundsContextProvider, + AddFundsSettings +} from '../../contexts' import { NavigationHeader } from '../../shared/components/NavigationHeader' -import { PendingTransaction, TransactionError, TransactionSuccess, CheckoutSelection } from '../../views' +import { + PendingTransaction, + TransactionError, + TransactionSuccess, + CheckoutSelection, + AddFundsContent, +} from '../../views' import '@0xsequence/design-system/styles.css' @@ -33,7 +47,9 @@ export const KitCheckoutProvider = (props: KitCheckoutProvider) => { export const KitCheckoutContent = ({ children }: KitCheckoutProvider) => { const { theme, position } = useTheme() const [openCheckoutModal, setOpenCheckoutModal] = useState(false) + const [openAddFundsModal, setOpenAddFundsModal] = useState(false) const [settings, setSettings] = useState() + const [addFundsSettings, setAddFundsSettings] = useState() const [history, setHistory] = useState([]) const navigation = history.length > 0 ? history[history.length - 1] : DEFAULT_LOCATION @@ -46,7 +62,16 @@ export const KitCheckoutContent = ({ children }: KitCheckoutProvider) => { setOpenCheckoutModal(false) } - const getContent = () => { + const triggerAddFunds = (settings: AddFundsSettings) => { + setAddFundsSettings(settings) + setOpenAddFundsModal(true) + } + + const closeAddFunds = () => { + setOpenAddFundsModal(false) + } + + const getCheckoutContent = () => { const { location } = navigation switch (location) { case 'select-method-checkout': @@ -63,7 +88,7 @@ export const KitCheckoutContent = ({ children }: KitCheckoutProvider) => { } } - const getHeader = () => { + const getCheckoutHeader = () => { const { location } = navigation switch (location) { case 'select-method-checkout': @@ -78,42 +103,92 @@ export const KitCheckoutContent = ({ children }: KitCheckoutProvider) => { } } + const getAddFundsHeader = () => { + const { location } = navigation + switch (location) { + default: + return + } + } + + const getAddFundsContent = () => { + const { location } = navigation + switch (location) { + default: + return + } + } + useEffect(() => { - if (openCheckoutModal) { + if (openCheckoutModal || openAddFundsModal) { setHistory([]) } - }, [openCheckoutModal]) + }, [openCheckoutModal, openAddFundsModal]) return ( - - -
- - - {openCheckoutModal && ( - setOpenCheckoutModal(false)} - > - - {getHeader()} - {getContent()} - - - )} - - -
- {children} -
-
+ + + +
+ + + {openCheckoutModal && ( + setOpenCheckoutModal(false)} + > + + {getCheckoutHeader()} + {getCheckoutContent()} + + + )} + {openAddFundsModal && ( + setOpenAddFundsModal(false)} + > + + {getAddFundsHeader()} + {getAddFundsContent()} + + + )} + + +
+ {children} +
+
+
) } diff --git a/packages/checkout/src/utils/transak.ts b/packages/checkout/src/utils/transak.ts new file mode 100644 index 00000000..ae872813 --- /dev/null +++ b/packages/checkout/src/utils/transak.ts @@ -0,0 +1,40 @@ +import { AddFundsSettings } from "../contexts" + +export const TRANSAK_API_KEY = '5911d9ec-46b5-48fa-a755-d59a715ff0cf' + +export const getTransakLink = (addFundsSettings: AddFundsSettings) => { + const defaultNetworks = "ethereum,mainnet,arbitrum,optimism,polygon,polygonzkevm,zksync,base,bnb,oasys,astar,avaxcchain" + + interface Options { + [index: string]: string | undefined + } + + const options: Options = { + apiKey: TRANSAK_API_KEY, + referrerDomain: window.location.origin, + walletAddress: addFundsSettings.walletAddress, + fiatCurrency: addFundsSettings?.fiatCurrency, + disableWalletAddressForm: 'true', + defaultFiatAmount: addFundsSettings?.defaultFiatAmount || '50', + defaultCryptoCurrency: addFundsSettings?.defaultCryptoCurrency || 'USDC', + networks: addFundsSettings?.networks || defaultNetworks + } + + const url = new URL('https://global.transak.com') + Object.keys(options).forEach(k => { + const option = options[k] + if (option) { + url.searchParams.append(k, option) + } + }) + + return url.href +} + +export const fetchTransakSupportedCountries = async () => { + const res = await fetch('https://api.transak.com/api/v2/countries') + const data = await res.json() + + // @ts-ignore-next-line + return data.response.filter(x => x.isAllowed).map(x => x.alpha2) +} \ No newline at end of file diff --git a/packages/checkout/src/views/AddFunds.tsx b/packages/checkout/src/views/AddFunds.tsx new file mode 100644 index 00000000..57c87ca7 --- /dev/null +++ b/packages/checkout/src/views/AddFunds.tsx @@ -0,0 +1,23 @@ +import React from 'react' +import { + Box, +} from '@0xsequence/design-system' + +import { useAddFundsModal } from '../hooks' +import { getTransakLink } from '../utils/transak' + +export const AddFundsContent = () => { + const { addFundsSettings } = useAddFundsModal() + + if (!addFundsSettings) { + return + } + + const link = getTransakLink(addFundsSettings) + + return ( + + + + ) +} diff --git a/packages/checkout/src/views/index.ts b/packages/checkout/src/views/index.ts index 5110bd5a..e77ab8c6 100644 --- a/packages/checkout/src/views/index.ts +++ b/packages/checkout/src/views/index.ts @@ -2,3 +2,4 @@ export * from './PendingTransaction' export * from './TransactionSuccess' export * from './TransactionError' export * from './CheckoutSelection' +export * from './AddFunds'