diff --git a/examples/react/src/components/Connected.tsx b/examples/react/src/components/Connected.tsx index a376f9cf8..ab12875a1 100644 --- a/examples/react/src/components/Connected.tsx +++ b/examples/react/src/components/Connected.tsx @@ -43,6 +43,9 @@ const checkoutProvider = searchParams.get('checkoutProvider') const onRampProvider = searchParams.get('onRampProvider') const checkoutPreset = searchParams.get('checkoutPreset') || 'forte-payment-erc1155-sale-native-token-testnet' +// @ts-ignore +const isDev = __SEQUENCE_WEB_SDK_IS_DEV__ + export const Connected = () => { const [isOpenCustomCheckout, setIsOpenCustomCheckout] = React.useState(false) const { setOpenConnectModal } = useOpenConnectModal() @@ -419,9 +422,6 @@ export const Connected = () => { recipientAddress: address, creditCardProviders: [creditCardProvider], onRampProvider: onRampProvider ? (onRampProvider as TransactionOnRampProvider) : TransactionOnRampProvider.transak, - transakConfig: { - contractId: '674eb5613d739107bbd18ed2' - }, onSuccess: (txnHash?: string) => { console.log('success!', txnHash) }, diff --git a/examples/react/src/components/CustomCheckout/index.tsx b/examples/react/src/components/CustomCheckout/index.tsx index 44eb6e32d..1f058cee2 100644 --- a/examples/react/src/components/CustomCheckout/index.tsx +++ b/examples/react/src/components/CustomCheckout/index.tsx @@ -55,10 +55,6 @@ export const CustomCheckout = () => { currencyAddress, collectionAddress, creditCardProvider: 'transak' as CreditCardProviders, - transakConfig: { - contractId, - apiKey: '5911d9ec-46b5-48fa-a755-d59a715ff0cf' - }, onSuccess: (txnHash?: string) => { console.log('success!', txnHash) }, diff --git a/examples/react/src/config.ts b/examples/react/src/config.ts index 5046e4238..2eea25548 100644 --- a/examples/react/src/config.ts +++ b/examples/react/src/config.ts @@ -184,8 +184,6 @@ export const checkoutConfig: SequenceCheckoutConfig = { ? { sardineCheckoutUrl: 'https://sardine-checkout-sandbox.sequence.info', sardineOnRampUrl: 'https://crypto.sandbox.sardine.ai/', - transakApiUrl: 'https://global-stg.transak.com', - transakApiKey: 'c20f2a0e-fe6a-4133-8fa7-77e9f84edf98', forteWidgetUrl: 'https://payments.sandbox.lemmax.com/forte-payments-widget.js' } : undefined diff --git a/examples/react/src/utils/checkout.ts b/examples/react/src/utils/checkout.ts index 2118f82d9..9dd90fd9e 100644 --- a/examples/react/src/utils/checkout.ts +++ b/examples/react/src/utils/checkout.ts @@ -178,7 +178,7 @@ export const checkoutPresets: Record Check } } }, - 'forte-payment-erc1155-sale-native-token-testnet': (recipientAddress: string) => { + 'forte-transak-payment-erc1155-sale-native-token-testnet': (recipientAddress: string) => { const collectibles = [ { tokenId: '1', diff --git a/packages/checkout/README.md b/packages/checkout/README.md index 6c78c2373..dfa192a9e 100644 --- a/packages/checkout/README.md +++ b/packages/checkout/README.md @@ -274,10 +274,6 @@ const CustomCheckoutUI = () => { currencyAddress, collectionAddress, creditCardProvider: 'transak' as CreditCardProviders, - transakConfig: { - contractId, - apiKey: '5911d9ec-46b5-48fa-a755-d59a715ff0cf' - }, onSuccess: (txnHash?: string) => { console.log('success!', txnHash) }, diff --git a/packages/checkout/src/api/data.ts b/packages/checkout/src/api/data.ts index fd0dfe2ea..d7924292d 100644 --- a/packages/checkout/src/api/data.ts +++ b/packages/checkout/src/api/data.ts @@ -499,3 +499,64 @@ export const fetchFortePaymentStatus = async ( status: (statuses[0]?.status as FortePaymentStatus) || '' } } + +export interface TransakNFTData { + imageURL: string + nftName: string + collectionAddress: string + tokenID: string[] + price: number[] + quantity: number + nftType: string +} + +export interface TransakWidgetUrlArgs { + isNFT?: boolean + calldata?: string + targetContractAddress?: string + cryptoCurrencyCode?: string + estimatedGasLimit?: number + nftData?: TransakNFTData[] + walletAddress: string + disableWalletAddressForm?: boolean + partnerOrderId?: string + network?: string + referrerDomain: string + fiatAmount?: number + fiatCurrency?: string + defaultFiatAmount?: number + defaultCryptoCurrency?: string + cryptoCurrencyList?: string + networks?: string +} + +export const getTransakWidgetUrl = async ( + sequenceApiUrl: string, + projectAccessKey: string, + args: TransakWidgetUrlArgs +): Promise<{ url: string }> => { + const queryUrl = `${sequenceApiUrl}/rpc/API/TransakGetWidgetURL` + + const res = await fetch(queryUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Access-Key': projectAccessKey + }, + body: JSON.stringify({ + params: { + ...args + } + }) + }) + + if (!res.ok) { + throw new Error(`Transak API error: ${res.status} ${res.statusText}`) + } + + const { url } = await res.json() + + return { + url + } +} diff --git a/packages/checkout/src/components/SequenceCheckoutProvider/SequenceCheckoutProvider.tsx b/packages/checkout/src/components/SequenceCheckoutProvider/SequenceCheckoutProvider.tsx index 10d4c008f..6ddd7af1e 100644 --- a/packages/checkout/src/components/SequenceCheckoutProvider/SequenceCheckoutProvider.tsx +++ b/packages/checkout/src/components/SequenceCheckoutProvider/SequenceCheckoutProvider.tsx @@ -246,8 +246,6 @@ export const SequenceCheckoutProvider = ({ children, config }: SequenceCheckoutP marketplaceApiUrl: config?.env?.marketplaceApiUrl ?? 'https://marketplace-api.sequence.app', sardineCheckoutUrl: config?.env?.sardineCheckoutUrl ?? 'https://sardine-checkout.sequence.info', sardineOnRampUrl: config?.env?.sardineOnRampUrl ?? 'https://crypto.sardine.ai/', - transakApiUrl: config?.env?.transakApiUrl ?? 'https://global.transak.com', - transakApiKey: config?.env?.transakApiKey ?? '5911d9ec-46b5-48fa-a755-d59a715ff0cf', forteWidgetUrl: config?.env?.forteWidgetUrl ?? 'https://payments.prod.lemmax.com/forte-payments-widget.js' }} > diff --git a/packages/checkout/src/contexts/CheckoutModal.ts b/packages/checkout/src/contexts/CheckoutModal.ts index 9a89166a1..eb710c5f3 100644 --- a/packages/checkout/src/contexts/CheckoutModal.ts +++ b/packages/checkout/src/contexts/CheckoutModal.ts @@ -19,8 +19,6 @@ interface OrderSummaryItem { } export interface TransakConfig { - apiKey?: string - contractId: string callDataOverride?: string } diff --git a/packages/checkout/src/contexts/Environment.ts b/packages/checkout/src/contexts/Environment.ts index 94cf353af..4c3c6580d 100644 --- a/packages/checkout/src/contexts/Environment.ts +++ b/packages/checkout/src/contexts/Environment.ts @@ -4,8 +4,6 @@ import { createGenericContext } from './genericContext.js' export interface EnvironmentOverrides { marketplaceApiUrl: string - transakApiUrl: string - transakApiKey: string sardineCheckoutUrl: string sardineOnRampUrl: string forteWidgetUrl: string diff --git a/packages/checkout/src/hooks/useCheckoutUI/useCreditCardPayment.tsx b/packages/checkout/src/hooks/useCheckoutUI/useCreditCardPayment.tsx index be07bc0e7..5a6287846 100644 --- a/packages/checkout/src/hooks/useCheckoutUI/useCreditCardPayment.tsx +++ b/packages/checkout/src/hooks/useCheckoutUI/useCreditCardPayment.tsx @@ -3,17 +3,17 @@ import { compareAddress } from '@0xsequence/connect' import { useConfig } from '@0xsequence/hooks' import type { ContractInfo, TokenMetadata } from '@0xsequence/metadata' import { findSupportedNetwork } from '@0xsequence/network' -import pako from 'pako' -import React, { useEffect, useRef } from 'react' +import React, { useEffect, useMemo, useRef } from 'react' import { formatUnits, zeroAddress, type Hex } from 'viem' import { fetchSardineOrderStatus } from '../../api/data.js' import type { TransakConfig } from '../../contexts/CheckoutModal.js' import { useEnvironmentContext } from '../../contexts/Environment.js' import type { Collectible, CreditCardProviders } from '../../contexts/SelectPaymentModal.js' -import { TRANSAK_PROXY_ADDRESS } from '../../utils/transak.js' +import { TRANSAK_PROXY_ADDRESS, getCurrencyCode } from '../../utils/transak.js' import { useSardineClientToken } from '../useSardineClientToken.js' +import { useTransakWidgetUrl } from '../useTransakWidgetUrl.js' const POLLING_TIME = 10 * 1000 const TRANSAK_IFRAME_ID = 'credit-card-payment-transak-iframe' const SARDINE_IFRAME_ID = 'credit-card-payment-sardine-iframe' @@ -82,7 +82,11 @@ export const useCreditCardPayment = ({ const { env } = useConfig() const disableSardineClientTokenFetch = isLoadingTokenMetadatas || isLoadingCurrencyInfo || isLoadingCollectionInfo || creditCardProvider !== 'sardine' - const { transakApiUrl, sardineCheckoutUrl: sardineProxyUrl, transakApiKey: transakGlobalApiKey } = useEnvironmentContext() + + const disableTransakWidgetUrlFetch = + isLoadingTokenMetadatas || isLoadingCurrencyInfo || isLoadingCollectionInfo || creditCardProvider !== 'transak' + + const { sardineCheckoutUrl: sardineProxyUrl } = useEnvironmentContext() const network = findSupportedNetwork(chain) const error = errorCollectionInfo || errorTokenMetadata || errorCurrencyInfo const isLoading = isLoadingCollectionInfo || isLoadingTokenMetadatas || isLoadingCurrencyInfo @@ -119,11 +123,66 @@ export const useCreditCardPayment = ({ disableSardineClientTokenFetch ) + // Transak requires the recipient address to be the proxy address + // so we need to replace the recipient address with the proxy address in the calldata + // this is a weird hack so that credit card integrations are as simple as possible and should work 99% of the time + // If an issue arises, the user can override the calldata in the transak settings + + const calldataWithProxy = + transakConfig?.callDataOverride ?? + txData.replace(recipientAddress.toLowerCase().substring(2), TRANSAK_PROXY_ADDRESS.toLowerCase().substring(2)) + + const price = Number(formatUnits(BigInt(totalPriceRaw), Number(currencyDecimals || 18))) + + const transakNftData = [ + { + imageURL: tokenMetadata?.image || '', + nftName: tokenMetadata?.name || 'collectible', + collectionAddress: collectionAddress, + tokenID: [collectible.tokenId || ''], + price: [price], + quantity: Number(collectible.quantity), + nftType: dataCollectionInfo?.type || 'ERC721' + } + ] + + const estimatedGasLimit = 500000 + + const partnerOrderId = useMemo(() => { + return `${recipientAddress}-${new Date().getTime()}` + }, [recipientAddress]) + + // Note: the network name might not always line up with Transak. A conversion function might be necessary + const networkName = network?.name.toLowerCase() + + const { + data: transakLinkData, + isLoading: isLoadingTransakLink, + error: errorTransakLink + } = useTransakWidgetUrl( + { + isNFT: true, + calldata: calldataWithProxy, + targetContractAddress, + cryptoCurrencyCode: getCurrencyCode({ + chainId: network?.chainId || 137, + currencyAddress, + defaultCurrencyCode: currencySymbol || 'ETH' + }), + estimatedGasLimit, + nftData: transakNftData, + walletAddress: recipientAddress, + disableWalletAddressForm: true, + partnerOrderId, + network: networkName, + referrerDomain: window.location.origin + }, + disableTransakWidgetUrlFetch + ) + const missingCreditCardProvider = !creditCardProvider - const missingTransakConfig = !transakConfig && creditCardProvider === 'transak' - const transakApiKey = transakConfig?.apiKey || transakGlobalApiKey - if (missingCreditCardProvider || missingTransakConfig) { + if (missingCreditCardProvider) { return { error: new Error('Missing credit card provider or transak config'), data: { @@ -148,46 +207,10 @@ export const useCreditCardPayment = ({ } if (creditCardProvider === 'transak') { - // Transak requires the recipient address to be the proxy address - // so we need to replace the recipient address with the proxy address in the calldata - // this is a weird hack so that credit card integrations are as simple as possible and should work 99% of the time - // If an issue arises, the user can override the calldata in the transak settings - - const calldataWithProxy = - transakConfig?.callDataOverride ?? - txData.replace(recipientAddress.toLowerCase().substring(2), TRANSAK_PROXY_ADDRESS.toLowerCase().substring(2)) - - const pakoData = Array.from(pako.deflate(calldataWithProxy)) - - const transakCallData = encodeURIComponent(btoa(String.fromCharCode.apply(null, pakoData))) - - const price = Number(formatUnits(BigInt(totalPriceRaw), Number(currencyDecimals || 18))) - - const transakNftDataJson = JSON.stringify([ - { - imageURL: tokenMetadata?.image || '', - nftName: tokenMetadata?.name || 'collectible', - collectionAddress: collectionAddress, - tokenID: [collectible.tokenId], - price: [price], - quantity: Number(collectible.quantity), - nftType: dataCollectionInfo?.type || 'ERC721' - } - ]) - - const transakNftData = encodeURIComponent(btoa(transakNftDataJson)) - - const estimatedGasLimit = '500000' - - const partnerOrderId = `${recipientAddress}-${new Date().getTime()}` - - // Note: the network name might not always line up with Transak. A conversion function might be necessary - const network = findSupportedNetwork(chain) - const networkName = network?.name.toLowerCase() - const transakLink = `${transakApiUrl}?apiKey=${transakApiKey}&isNFT=true&calldata=${transakCallData}&contractId=${transakConfig?.contractId}&cryptoCurrencyCode=${currencySymbol}&estimatedGasLimit=${estimatedGasLimit}&nftData=${transakNftData}&walletAddress=${recipientAddress}&disableWalletAddressForm=true&partnerOrderId=${partnerOrderId}&network=${networkName}` + const transakLink = transakLinkData?.url return { - error: null, + error: errorTransakLink, data: { iframeId: TRANSAK_IFRAME_ID, paymentUrl: transakLink, @@ -212,7 +235,7 @@ export const useCreditCardPayment = ({ ) }, - isLoading: false + isLoading: isLoadingTransakLink } } diff --git a/packages/checkout/src/hooks/useSelectPaymentModal.ts b/packages/checkout/src/hooks/useSelectPaymentModal.ts index 48537ba24..8fdaf3fee 100644 --- a/packages/checkout/src/hooks/useSelectPaymentModal.ts +++ b/packages/checkout/src/hooks/useSelectPaymentModal.ts @@ -80,10 +80,6 @@ type UseSelectPaymentModalReturnType = { * currencyAddress, * collectionAddress, * creditCardProviders: ['sardine', 'transak'], - * transakConfig: { - * contractId: 'your-contract-id', - * apiKey: 'your-api-key' - * }, * copyrightText: 'ⓒ2024 Your Company', * onSuccess: (txnHash: string) => { * console.log('success!', txnHash) diff --git a/packages/checkout/src/hooks/useTransakWidgetUrl.ts b/packages/checkout/src/hooks/useTransakWidgetUrl.ts new file mode 100644 index 000000000..16df9fd91 --- /dev/null +++ b/packages/checkout/src/hooks/useTransakWidgetUrl.ts @@ -0,0 +1,18 @@ +import { useQuery } from '@tanstack/react-query' +import { getTransakWidgetUrl, type TransakWidgetUrlArgs } from '../api/data.js' +import { useConfig } from '@0xsequence/hooks' + +export const useTransakWidgetUrl = (args: TransakWidgetUrlArgs, disabled?: boolean) => { + const { env, projectAccessKey } = useConfig() + + // const apiUrl = env.apiUrl + + const apiUrl = 'http://localhost:4422' + + return useQuery({ + queryKey: ['transakWidgetUrl', args], + queryFn: () => getTransakWidgetUrl(apiUrl, projectAccessKey, args), + staleTime: 5 * 60 * 1000, + enabled: !disabled && args.walletAddress !== '' + }) +} diff --git a/packages/checkout/src/index.ts b/packages/checkout/src/index.ts index de4ea8780..44fcc5817 100644 --- a/packages/checkout/src/index.ts +++ b/packages/checkout/src/index.ts @@ -22,7 +22,7 @@ export { type TransactionStatusSettings } from './contexts/TransactionStatusModa export { useTransactionStatusModal } from './hooks/useTransactionStatusModal.js' // utils -export { fetchTransakSupportedCountries, getTransakLink } from './utils/transak.js' +export { fetchTransakSupportedCountries } from './utils/transak.js' // OnRampProvider export { TransactionOnRampProvider } from '@0xsequence/marketplace' diff --git a/packages/checkout/src/utils/transak.ts b/packages/checkout/src/utils/transak.ts index 83522da8c..bf0161ca2 100644 --- a/packages/checkout/src/utils/transak.ts +++ b/packages/checkout/src/utils/transak.ts @@ -1,44 +1,10 @@ +import { ChainId } from '@0xsequence/network' +import { zeroAddress } from 'viem' + import type { AddFundsSettings } from '../contexts/AddFundsModal.js' export const TRANSAK_PROXY_ADDRESS = '0x4a598b7ec77b1562ad0df7dc64a162695ce4c78a' -export const getTransakLink = ( - addFundsSettings: AddFundsSettings, - { transakApiUrl, transakApiKey }: { transakApiUrl: string; transakApiKey: string } -) => { - const defaultNetworks = - 'ethereum,mainnet,arbitrum,optimism,polygon,polygonzkevm,zksync,base,bnb,oasys,astar,avaxcchain,immutablezkevm' - - interface Options { - [index: string]: string | undefined - } - - const url = new URL(transakApiUrl) - const apiKey = transakApiKey - - const options: Options = { - apiKey: apiKey, - referrerDomain: window.location.origin, - walletAddress: addFundsSettings.walletAddress, - fiatAmount: addFundsSettings?.fiatAmount, - fiatCurrency: addFundsSettings?.fiatCurrency, - disableWalletAddressForm: 'true', - defaultFiatAmount: addFundsSettings?.defaultFiatAmount || '50', - defaultCryptoCurrency: addFundsSettings?.defaultCryptoCurrency || 'USDC', - cryptoCurrencyList: addFundsSettings?.cryptoCurrencyList, - networks: addFundsSettings?.networks || defaultNetworks - } - - Object.keys(options).forEach(k => { - const option = options[k] - if (option) { - url.searchParams.append(k, option) - } - }) - - return url.href -} - interface CountriesResult { response: Country[] } @@ -66,3 +32,21 @@ export const fetchTransakSupportedCountries = async () => { return data.response.filter(x => x.isAllowed).map(x => x.alpha2) } + +interface GetCurrencyCodeParams { + chainId: number + currencyAddress: string + defaultCurrencyCode: string +} + +export const getCurrencyCode = ({ chainId, currencyAddress, defaultCurrencyCode }: GetCurrencyCodeParams) => { + const currencyCodeByAddress: { [chainId: number]: { [currencyAddress: string]: string | undefined } | undefined } = { + [ChainId.SEPOLIA]: { + [zeroAddress]: 'ETH' + } + } + + const foundCurrencyAddress = currencyCodeByAddress?.[chainId]?.[currencyAddress.toLowerCase()] + + return foundCurrencyAddress || defaultCurrencyCode +} diff --git a/packages/checkout/src/views/AddFunds.tsx b/packages/checkout/src/views/AddFunds.tsx index 89cfb4599..b6ec1f3f8 100644 --- a/packages/checkout/src/views/AddFunds.tsx +++ b/packages/checkout/src/views/AddFunds.tsx @@ -6,7 +6,7 @@ import { HEADER_HEIGHT } from '../constants/index.js' import type { AddFundsSettings } from '../contexts/AddFundsModal.js' import { useEnvironmentContext } from '../contexts/Environment.js' import { useAddFundsModal, useSardineOnRampLink } from '../hooks/index.js' -import { getTransakLink } from '../utils/transak.js' +import { useTransakWidgetUrl } from '../hooks/useTransakWidgetUrl.js' const EventTypeOrderCreated = 'TRANSAK_ORDER_CREATED' const EventTypeOrderSuccessful = 'TRANSAK_ORDER_SUCCESSFUL' @@ -109,7 +109,25 @@ export const AddFundsContentSardine = () => { export const AddFundsContentTransak = () => { const { addFundsSettings = {} as AddFundsSettings } = useAddFundsModal() - const { transakApiUrl, transakApiKey } = useEnvironmentContext() + + const defaultNetworks = + 'ethereum,mainnet,arbitrum,optimism,polygon,polygonzkevm,zksync,base,bnb,oasys,astar,avaxcchain,immutablezkevm' + + const { + data: transakLinkData, + isLoading: isLoadingTransakLink, + error: errorTransakLink + } = useTransakWidgetUrl({ + referrerDomain: window.location.origin, + walletAddress: addFundsSettings.walletAddress, + fiatAmount: addFundsSettings?.fiatAmount ? Number(addFundsSettings?.fiatAmount) : undefined, + fiatCurrency: addFundsSettings?.fiatCurrency, + disableWalletAddressForm: true, + defaultFiatAmount: Number(addFundsSettings?.defaultFiatAmount) || 50, + defaultCryptoCurrency: addFundsSettings?.defaultCryptoCurrency || 'USDC', + cryptoCurrencyList: addFundsSettings?.cryptoCurrencyList, + networks: addFundsSettings?.networks || defaultNetworks + }) const iframeRef = useRef(null) useEffect(() => { @@ -139,10 +157,23 @@ export const AddFundsContentTransak = () => { } }, []) - const link = getTransakLink(addFundsSettings, { - transakApiUrl, - transakApiKey - }) + const link = transakLinkData?.url + + if (isLoadingTransakLink) { + return ( +
+ +
+ ) + } + + if (errorTransakLink) { + return ( +
+ An error has occurred +
+ ) + } return (
{ const isFree = Number(price) == 0 - const validCreditCardProviders = creditCardProviders.filter(provider => { - if (provider === 'transak') { - return !!selectPaymentSettings?.transakConfig - } - return true - }) - const [selectedTab, setSelectedTab] = useState('crypto') const { clearCachedBalances } = useClearCachedBalances() @@ -52,7 +45,7 @@ export const PaymentSelectionContent = () => { const isTokenIdUnknown = collectibles.some(collectible => !collectible.tokenId) - const showCreditCardPayment = validCreditCardProviders.length > 0 && !isTokenIdUnknown && !isFree + const showCreditCardPayment = creditCardProviders.length > 0 && !isTokenIdUnknown && !isFree const tabs: { label: string; value: Tab }[] = [ { label: 'Crypto', value: 'crypto' as Tab }, diff --git a/packages/checkout/src/views/PaymentSelection/PayWithCreditCard/index.tsx b/packages/checkout/src/views/PaymentSelection/PayWithCreditCard/index.tsx index bc268c8c3..94a3ff2df 100644 --- a/packages/checkout/src/views/PaymentSelection/PayWithCreditCard/index.tsx +++ b/packages/checkout/src/views/PaymentSelection/PayWithCreditCard/index.tsx @@ -124,45 +124,36 @@ export const PayWithCreditCard = ({ settings, disableButtons, skipOnCloseCallbac return (
{/* Only 1 option will be displayed, even if multiple providers are passed */} - {creditCardProviders - .slice(0, 1) - .filter(provider => { - // cannot display transak checkout if the settings aren't provided - if (provider === 'transak' && !settings.transakConfig) { - return false - } - return true - }) - .map(creditCardProvider => { - switch (creditCardProvider) { - case 'sardine': - case 'transak': - case 'forte': - case 'custom': - return ( - { - setSelectedPaymentProvider(creditCardProvider) - }} - disabled={disableButtons} - > -
- - - Pay with credit or debit card - -
-
- -
-
- ) - default: - return null - } - })} + {creditCardProviders.slice(0, 1).map(creditCardProvider => { + switch (creditCardProvider) { + case 'sardine': + case 'transak': + case 'forte': + case 'custom': + return ( + { + setSelectedPaymentProvider(creditCardProvider) + }} + disabled={disableButtons} + > +
+ + + Pay with credit or debit card + +
+
+ +
+
+ ) + default: + return null + } + })}
) } diff --git a/packages/checkout/src/views/PendingCreditCardTransaction.tsx b/packages/checkout/src/views/PendingCreditCardTransaction.tsx index 83eda431e..be8873a7e 100644 --- a/packages/checkout/src/views/PendingCreditCardTransaction.tsx +++ b/packages/checkout/src/views/PendingCreditCardTransaction.tsx @@ -2,8 +2,7 @@ import { useAnalyticsContext, useProjectAccessKey } from '@0xsequence/connect' import { Spinner, Text } from '@0xsequence/design-system' import { useConfig, useGetContractInfo, useGetTokenMetadata } from '@0xsequence/hooks' import { findSupportedNetwork } from '@0xsequence/network' -import pako from 'pako' -import { useEffect, useRef } from 'react' +import { useEffect, useMemo, useRef } from 'react' import { formatUnits } from 'viem' import { fetchSardineOrderStatus } from '../api/data.js' @@ -17,7 +16,8 @@ import { useSkipOnCloseCallback, useTransactionStatusModal } from '../hooks/index.js' -import { TRANSAK_PROXY_ADDRESS } from '../utils/transak.js' +import { useTransakWidgetUrl } from '../hooks/useTransakWidgetUrl.js' +import { TRANSAK_PROXY_ADDRESS, getCurrencyCode } from '../utils/transak.js' const POLLING_TIME = 10 * 1000 @@ -47,7 +47,6 @@ export const PendingCreditCardTransaction = () => { } export const PendingCreditCardTransactionTransak = ({ skipOnCloseCallback }: PendingCreditTransactionProps) => { - const { transakApiUrl, transakApiKey: transakGlobalApiKey } = useEnvironmentContext() const { analytics } = useAnalyticsContext() const { openTransactionStatusModal } = useTransactionStatusModal() const nav = useNavigation() @@ -83,7 +82,6 @@ export const PendingCreditCardTransactionTransak = ({ skipOnCloseCallback }: Pen const tokenMetadata = tokensMetadata ? tokensMetadata[0] : undefined const transakConfig = settings?.creditCardCheckout?.transakConfig - const transakApiKey = transakConfig?.apiKey || transakGlobalApiKey // Transak requires the recipient address to be the proxy address // so we need to replace the recipient address with the proxy address in the calldata @@ -97,13 +95,9 @@ export const PendingCreditCardTransactionTransak = ({ skipOnCloseCallback }: Pen TRANSAK_PROXY_ADDRESS.toLowerCase().substring(2) ) - const pakoData = Array.from(pako.deflate(calldataWithProxy)) - - const transakCallData = encodeURIComponent(btoa(String.fromCharCode.apply(null, pakoData))) - const price = Number(formatUnits(BigInt(creditCardCheckout.currencyQuantity), Number(creditCardCheckout.currencyDecimals))) - const transakNftDataJson = JSON.stringify([ + const transakNftData = [ { imageURL: tokenMetadata?.image || '', nftName: tokenMetadata?.name || 'collectible', @@ -113,22 +107,47 @@ export const PendingCreditCardTransactionTransak = ({ skipOnCloseCallback }: Pen quantity: Number(creditCardCheckout.nftQuantity), nftType: collectionInfo?.type || 'ERC721' } - ]) - - console.log('transakNftDataJson', JSON.parse(transakNftDataJson)) - const transakNftData = encodeURIComponent(btoa(transakNftDataJson)) + ] - const estimatedGasLimit = '500000' + const estimatedGasLimit = 500000 - const partnerOrderId = `${creditCardCheckout.recipientAddress}-${new Date().getTime()}` + const partnerOrderId = useMemo(() => { + return `${creditCardCheckout.recipientAddress}-${new Date().getTime()}` + }, [creditCardCheckout.recipientAddress]) // Note: the network name might not always line up with Transak. A conversion function might be necessary const networkName = network?.name.toLowerCase() - const transakLink = `${transakApiUrl}?apiKey=${transakApiKey}&isNFT=true&calldata=${transakCallData}&contractId=${transakConfig?.contractId}&cryptoCurrencyCode=${creditCardCheckout.currencySymbol}&estimatedGasLimit=${estimatedGasLimit}&nftData=${transakNftData}&walletAddress=${creditCardCheckout.recipientAddress}&disableWalletAddressForm=true&partnerOrderId=${partnerOrderId}&network=${networkName}` + const disableTransakWidgetUrlFetch = isLoadingTokenMetadata || isLoadingCollectionInfo - const isLoading = isLoadingTokenMetadata || isLoadingCollectionInfo - const isError = isErrorTokenMetadata || isErrorCollectionInfo + const { + data: transakLinkData, + isLoading: isLoadingTransakLink, + isError: isErrorTransakLink + } = useTransakWidgetUrl( + { + isNFT: true, + calldata: calldataWithProxy, + targetContractAddress: creditCardCheckout.contractAddress, + cryptoCurrencyCode: getCurrencyCode({ + chainId: creditCardCheckout.chainId, + currencyAddress: creditCardCheckout.currencyAddress, + defaultCurrencyCode: creditCardCheckout.currencySymbol || 'ETH' + }), + estimatedGasLimit, + nftData: transakNftData, + walletAddress: creditCardCheckout.recipientAddress, + disableWalletAddressForm: true, + partnerOrderId, + network: networkName, + referrerDomain: window.location.origin + }, + disableTransakWidgetUrlFetch + ) + const transakLink = transakLinkData?.url || '' + + const isLoading = isLoadingTokenMetadata || isLoadingCollectionInfo || isLoadingTransakLink + const isError = isErrorTokenMetadata || isErrorCollectionInfo || isErrorTransakLink useEffect(() => { const readMessage = (message: any) => { @@ -207,7 +226,7 @@ export const PendingCreditCardTransactionTransak = ({ skipOnCloseCallback }: Pen return () => window.removeEventListener('message', readMessage) }, [isLoading]) - if (isError || !transakConfig) { + if (isError) { return (
- {!transakConfig ? ( - Error: No Transak configuration found - ) : ( - An error has occurred - )} + An error has occurred
)