Skip to content

Commit

Permalink
add funds (#60)
Browse files Browse the repository at this point in the history
* add funds(wip_

* add funds

* add transak flow

* build fix

* more documentation

* docs cleanup
  • Loading branch information
SamueleA authored May 27, 2024
1 parent 54957f3 commit 9c801a4
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 39 deletions.
15 changes: 13 additions & 2 deletions examples/react/src/components/Homepage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -377,6 +378,12 @@ export const Homepage = () => {
}
}

const onClickAddFunds = () => {
triggerAddFunds({
walletAddress: address || '',
})
}

const SwitchThemeButton = () => {
return <IconButton onClick={onClickChangeTheme} icon={theme === 'dark' ? SunIcon : MoonIcon} />
}
Expand Down Expand Up @@ -466,7 +473,11 @@ export const Homepage = () => {
</Text>
</Card>
)}

<ClickableCard
title="Add Funds"
description="Buy Cryptocurrency with a Credit Card"
onClick={() => onClickAddFunds()}
/>
<ClickableCard
title="Mint an NFT"
description="Test minting an NFT to your wallet"
Expand Down
23 changes: 22 additions & 1 deletion packages/checkout/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ An example usecase might be interacting with a minting contract.
The actual cryptoTransaction must be passed down to the `triggerTransaction` field.

```js
cons checkoutConfig = {
const checkoutConfig = {
{...},
cryptoCheckout: {
chainId: 137,
Expand All @@ -107,4 +107,25 @@ This field specific the list of collectibles that will show up in the order summ
quantityRaw: '100'
},
]
```

### Adding Funds with a Credit Card
Kit allows users to buy cryptocurrencies using credit card. Calling the triggerAddFunds function will cause a modal to appear.

```js
import { useAddFundsModal } from '@0xsequence/kit-checkout'

const MyComponent = () => {
const { triggerAddFunds } = useAddFundsModal()

const onClick = () => {
triggerAddFunds({
walletAddress: recipientAddress,
})
}

return (
<button onClick={onClick}>Add Funds</button>
)
}
```
19 changes: 19 additions & 0 deletions packages/checkout/src/contexts/AddFundsModal.ts
Original file line number Diff line number Diff line change
@@ -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<AddFundsModalContext>()
1 change: 1 addition & 0 deletions packages/checkout/src/contexts/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './AddFundsModal'
export * from './CheckoutModal'
export * from './Navigation'
1 change: 1 addition & 0 deletions packages/checkout/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './useAddFundsModal'
export * from './useCheckoutModal'
export * from './useNavigation'
export * from './useModalTheme'
7 changes: 7 additions & 0 deletions packages/checkout/src/hooks/useAddFundsModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useAddFundsModalContext } from '../contexts/AddFundsModal'

export const useAddFundsModal = () => {
const { triggerAddFunds, closeAddFunds, addFundsSettings } = useAddFundsModalContext()

return { triggerAddFunds, closeAddFunds, addFundsSettings }
}
5 changes: 5 additions & 0 deletions packages/checkout/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
147 changes: 111 additions & 36 deletions packages/checkout/src/shared/components/KitCheckoutProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand All @@ -33,7 +47,9 @@ export const KitCheckoutProvider = (props: KitCheckoutProvider) => {
export const KitCheckoutContent = ({ children }: KitCheckoutProvider) => {
const { theme, position } = useTheme()
const [openCheckoutModal, setOpenCheckoutModal] = useState<boolean>(false)
const [openAddFundsModal, setOpenAddFundsModal] = useState<boolean>(false)
const [settings, setSettings] = useState<CheckoutSettings>()
const [addFundsSettings, setAddFundsSettings] = useState<AddFundsSettings>()
const [history, setHistory] = useState<History>([])
const navigation = history.length > 0 ? history[history.length - 1] : DEFAULT_LOCATION

Expand All @@ -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':
Expand All @@ -63,7 +88,7 @@ export const KitCheckoutContent = ({ children }: KitCheckoutProvider) => {
}
}

const getHeader = () => {
const getCheckoutHeader = () => {
const { location } = navigation
switch (location) {
case 'select-method-checkout':
Expand All @@ -78,42 +103,92 @@ export const KitCheckoutContent = ({ children }: KitCheckoutProvider) => {
}
}

const getAddFundsHeader = () => {
const { location } = navigation
switch (location) {
default:
return <NavigationHeader primaryText="Add funds with credit card or debit card" />
}
}

const getAddFundsContent = () => {
const { location } = navigation
switch (location) {
default:
return <AddFundsContent />
}
}

useEffect(() => {
if (openCheckoutModal) {
if (openCheckoutModal || openAddFundsModal) {
setHistory([])
}
}, [openCheckoutModal])
}, [openCheckoutModal, openAddFundsModal])

return (
<CheckoutModalContextProvider value={{ triggerCheckout, closeCheckout, settings, theme }}>
<NavigationContextProvider value={{ history, setHistory }}>
<div id="kit-checkout">
<ThemeProvider root="#kit-checkout" scope="kit" theme={theme}>
<AnimatePresence>
{openCheckoutModal && (
<Modal
contentProps={{
style: {
maxWidth: '400px',
height: 'auto',
...getModalPositionCss(position)
}
}}
scroll={false}
backdropColor="backgroundBackdrop"
onClose={() => setOpenCheckoutModal(false)}
>
<Box id="sequence-kit-checkout-content">
{getHeader()}
{getContent()}
</Box>
</Modal>
)}
</AnimatePresence>
</ThemeProvider>
</div>
{children}
</NavigationContextProvider>
</CheckoutModalContextProvider>
<AddFundsContextProvider
value={{
triggerAddFunds,
closeAddFunds,
addFundsSettings,
}}
>
<CheckoutModalContextProvider
value={{
triggerCheckout,
closeCheckout,
settings,
theme,
}}
>
<NavigationContextProvider value={{ history, setHistory }}>
<div id="kit-checkout">
<ThemeProvider root="#kit-checkout" scope="kit" theme={theme}>
<AnimatePresence>
{openCheckoutModal && (
<Modal
contentProps={{
style: {
maxWidth: '400px',
height: 'auto',
...getModalPositionCss(position)
}
}}
scroll={false}
backdropColor="backgroundBackdrop"
onClose={() => setOpenCheckoutModal(false)}
>
<Box id="sequence-kit-checkout-content">
{getCheckoutHeader()}
{getCheckoutContent()}
</Box>
</Modal>
)}
{openAddFundsModal && (
<Modal
contentProps={{
style: {
maxWidth: '400px',
height: 'auto',
...getModalPositionCss(position)
}
}}
scroll={false}
backdropColor="backgroundBackdrop"
onClose={() => setOpenAddFundsModal(false)}
>
<Box id="sequence-kit-add-funds-content">
{getAddFundsHeader()}
{getAddFundsContent()}
</Box>
</Modal>
)}
</AnimatePresence>
</ThemeProvider>
</div>
{children}
</NavigationContextProvider>
</CheckoutModalContextProvider>
</AddFundsContextProvider>
)
}
40 changes: 40 additions & 0 deletions packages/checkout/src/utils/transak.ts
Original file line number Diff line number Diff line change
@@ -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)
}
23 changes: 23 additions & 0 deletions packages/checkout/src/views/AddFunds.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Box alignItems="center" width="full" paddingX="4" paddingBottom="4" height="full" style={{ height: '600px' }}>
<Box as="iframe" width="full" height="full" borderWidth="none" src={link} />
</Box>
)
}
1 change: 1 addition & 0 deletions packages/checkout/src/views/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './PendingTransaction'
export * from './TransactionSuccess'
export * from './TransactionError'
export * from './CheckoutSelection'
export * from './AddFunds'

0 comments on commit 9c801a4

Please sign in to comment.