1- import { useIndexerClient } from '@0xsequence/hooks'
1+ import { useProjectAccessKey } from '@0xsequence/connect'
2+ import { useIndexerClient , useConfig } from '@0xsequence/hooks'
23import { compareAddress , waitForTransactionReceipt , TRANSACTION_CONFIRMATIONS_DEFAULT } from '@0xsequence/connect'
34import { findSupportedNetwork } from '@0xsequence/network'
45import { ContractInfo , TokenMetadata } from '@0xsequence/metadata'
@@ -8,10 +9,12 @@ import React, { useEffect } from 'react'
89import { Hex , formatUnits , zeroAddress } from 'viem'
910import { usePublicClient } from 'wagmi'
1011
12+ import { fetchSardineOrderStatus } from '../../api'
1113import { Collectible , CreditCardProviders } from '../../contexts/SelectPaymentModal'
1214import { TransakConfig } from '../../contexts/CheckoutModal'
1315import { TRANSAK_PROXY_ADDRESS } from '../../utils/transak'
1416import { useEnvironmentContext } from '../../contexts'
17+ import { useSardineClientToken } from '../useSardineClientToken'
1518
1619const POLLING_TIME = 10 * 1000
1720const TRANSAK_IFRAME_ID = 'credit-card-payment-transak-iframe'
@@ -81,18 +84,50 @@ export const useCreditCardPayment =
8184 errorCurrencyInfo
8285 } : UseCreditCardPaymentArgs ) =>
8386 ( ) : UseCreditCardPaymentReturn => {
84- const missingCreditCardProvider = ! creditCardProvider
85- const missingTransakConfig = ! transakConfig && creditCardProvider === 'transak'
86- const { transakApiUrl } = useEnvironmentContext ( )
87+ const projectAccessKey = useProjectAccessKey ( )
88+ const { env } = useConfig ( )
89+ const disableSardineClientTokenFetch =
90+ isLoadingTokenMetadatas || isLoadingCurrencyInfo || isLoadingCollectionInfo || creditCardProvider !== 'sardine'
91+ const { transakApiUrl, sardineApiUrl : sardineProxyUrl } = useEnvironmentContext ( )
92+ const network = findSupportedNetwork ( chain )
8793 const error = errorCollectionInfo || errorTokenMetadata || errorCurrencyInfo
8894 const isLoading = isLoadingCollectionInfo || isLoadingTokenMetadatas || isLoadingCurrencyInfo
89- const network = findSupportedNetwork ( chain )
9095 const isNativeCurrency = compareAddress ( currencyAddress , zeroAddress )
9196 const currencySymbol = isNativeCurrency ? network ?. nativeToken . symbol : currencyInfo ?. symbol || 'POL'
9297 const currencyDecimals = isNativeCurrency ? network ?. nativeToken . decimals : currencyInfo ?. decimals || 18
9398
9499 const tokenMetadata = tokenMetadatas ?. [ 0 ]
95100
101+ const {
102+ data : dataClientToken ,
103+ isLoading : isLoadingClientToken ,
104+ error : errorClientToken
105+ } = useSardineClientToken (
106+ {
107+ order : {
108+ chainId : network ?. chainId || 137 ,
109+ contractAddress : targetContractAddress ,
110+ recipientAddress,
111+ currencyQuantity : totalPriceRaw ,
112+ currencySymbol : currencyInfo ?. symbol || 'POL' ,
113+ currencyDecimals : String ( currencyDecimals || 18 ) ,
114+ currencyAddress,
115+ nftId : collectible . tokenId ,
116+ nftAddress : collectionAddress ,
117+ nftQuantity : collectible . quantity ,
118+ nftDecimals : String ( dataCollectionInfo ?. decimals || 18 ) ,
119+ calldata : txData
120+ } ,
121+ projectAccessKey : projectAccessKey ,
122+ apiClientUrl : env . apiUrl ,
123+ tokenMetadata : tokenMetadata
124+ } ,
125+ disableSardineClientTokenFetch
126+ )
127+
128+ const missingCreditCardProvider = ! creditCardProvider
129+ const missingTransakConfig = ! transakConfig && creditCardProvider === 'transak'
130+
96131 if ( missingCreditCardProvider || missingTransakConfig ) {
97132 return {
98133 error : new Error ( 'Missing credit card provider or transak config' ) ,
@@ -123,7 +158,7 @@ export const useCreditCardPayment =
123158
124159 const transakCallData = encodeURIComponent ( btoa ( String . fromCharCode . apply ( null , pakoData ) ) )
125160
126- const price = Number ( formatUnits ( BigInt ( totalPriceRaw ) , Number ( currencyInfo ?. decimals || 18 ) ) )
161+ const price = Number ( formatUnits ( BigInt ( totalPriceRaw ) , Number ( currencyDecimals || 18 ) ) )
127162
128163 const transakNftDataJson = JSON . stringify ( [
129164 {
@@ -182,22 +217,48 @@ export const useCreditCardPayment =
182217 }
183218
184219 // Sardine credit card provider
220+ const sardineApiUrl = sardineProxyUrl . replace ( 'checkout' , 'api' )
221+ const authToken = dataClientToken ?. token
222+ const url = `${ sardineProxyUrl } ?api_url=${ sardineApiUrl } &client_token=${ authToken } &show_features=true`
223+
224+ const isLoadingSardine = isLoadingClientToken || isLoading
225+ const errorSardine = errorClientToken || error
226+
227+ const data =
228+ ! isLoadingSardine && ! errorSardine
229+ ? {
230+ iframeId : SARDINE_IFRAME_ID ,
231+ paymentUrl : url ,
232+ CreditCardIframe : (
233+ < div className = "flex items-center justify-center" style = { { height : '770px' } } >
234+ < iframe
235+ id = { SARDINE_IFRAME_ID }
236+ src = { url }
237+ style = { {
238+ maxHeight : '650px' ,
239+ height : '100%' ,
240+ maxWidth : '380px' ,
241+ width : '100%'
242+ } }
243+ />
244+ </ div >
245+ ) ,
246+ EventListener : (
247+ < SardineEventListener
248+ transactionConfirmations = { transactionConfirmations }
249+ chainId = { network ?. chainId || 137 }
250+ onSuccess = { onSuccess }
251+ onError = { onError }
252+ orderId = { dataClientToken ?. orderId || '' }
253+ />
254+ )
255+ }
256+ : null
257+
185258 return {
186- error,
187- isLoading,
188- data : {
189- iframeId : SARDINE_IFRAME_ID ,
190- paymentUrl : 'https://checkout.transak.com/checkout.html' ,
191- CreditCardIframe : < iframe id = { SARDINE_IFRAME_ID } /> ,
192- EventListener : (
193- < SardineEventListener
194- transactionConfirmations = { transactionConfirmations }
195- chainId = { network ?. chainId || 137 }
196- onSuccess = { onSuccess }
197- onError = { onError }
198- />
199- )
200- }
259+ error : errorSardine ,
260+ isLoading : isLoadingSardine ,
261+ data
201262 }
202263 }
203264
@@ -270,8 +331,43 @@ interface SardineEventListenerProps {
270331 onError ?: ( error : Error ) => void
271332 chainId : number
272333 transactionConfirmations ?: number
334+ orderId : string
273335}
274336
275- const SardineEventListener = ( { onSuccess, onError, chainId } : SardineEventListenerProps ) => {
337+ const SardineEventListener = ( { onSuccess, onError, chainId, orderId } : SardineEventListenerProps ) => {
338+ const { env } = useConfig ( )
339+ const projectAccessKey = useProjectAccessKey ( )
340+
341+ const pollForOrderStatus = async ( ) => {
342+ try {
343+ console . log ( 'Polling for transaction status' )
344+ const pollResponse = await fetchSardineOrderStatus ( orderId , projectAccessKey , env . apiUrl )
345+ const status = pollResponse . resp . status
346+ const transactionHash = pollResponse . resp ?. transactionHash
347+
348+ console . log ( 'transaction status poll response:' , status )
349+
350+ if ( status === 'Complete' ) {
351+ onSuccess ?.( transactionHash )
352+ }
353+ if ( status === 'Declined' || status === 'Cancelled' ) {
354+ onError ?.( new Error ( 'Failed to transfer collectible' ) )
355+ }
356+ } catch ( e ) {
357+ console . error ( 'An error occurred while fetching the transaction status' )
358+ onError ?.( e as Error )
359+ }
360+ }
361+
362+ useEffect ( ( ) => {
363+ const interval = setInterval ( ( ) => {
364+ pollForOrderStatus ( )
365+ } , POLLING_TIME )
366+
367+ return ( ) => {
368+ clearInterval ( interval )
369+ }
370+ } , [ ] )
371+
276372 return null
277373}
0 commit comments