From f4473c444e24e920cd98295aacfdcfd05355ac1a Mon Sep 17 00:00:00 2001 From: Richard Miguel Irala Date: Tue, 4 Nov 2025 18:05:46 -0300 Subject: [PATCH 1/4] feat(onramp): add optional Transak alternate flow with default and windowed modes --- .../checkout/src/contexts/AddFundsModal.ts | 1 + packages/checkout/src/utils/transak.ts | 85 ++++++++++++++ packages/checkout/src/views/AddFunds.tsx | 108 ++++++++++++++++++ packages/connect/src/styles.ts | 4 +- 4 files changed, 197 insertions(+), 1 deletion(-) diff --git a/packages/checkout/src/contexts/AddFundsModal.ts b/packages/checkout/src/contexts/AddFundsModal.ts index 2e949957c..96e2aa226 100644 --- a/packages/checkout/src/contexts/AddFundsModal.ts +++ b/packages/checkout/src/contexts/AddFundsModal.ts @@ -16,6 +16,7 @@ export interface AddFundsSettings { onOrderSuccessful?: (data: any) => void onOrderFailed?: (data: any) => void provider?: TransactionOnRampProvider + transakOnRampKind?: 'default' | 'windowed' cryptoAmount?: string } diff --git a/packages/checkout/src/utils/transak.ts b/packages/checkout/src/utils/transak.ts index 799284650..5a6f9b79b 100644 --- a/packages/checkout/src/utils/transak.ts +++ b/packages/checkout/src/utils/transak.ts @@ -3,6 +3,91 @@ import { zeroAddress } from 'viem' export const TRANSAK_PROXY_ADDRESS = '0x4a598b7ec77b1562ad0df7dc64a162695ce4c78a' +export const getTransakLink = ( + addFundsSettings: AddFundsSettings, + { transakApiUrl, transakApiKey }: { transakApiUrl: string; transakApiKey: string } +) => { + 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 + } + + Object.keys(options).forEach(k => { + const option = options[k] + if (option) { + url.searchParams.append(k, option) + } + }) + + return url.href +} + +export const getTransakLinkFromSequenceApi = async ( + addFundsSettings: AddFundsSettings, + transakApiUrl: string, + projectAccessKey: string +) => { + interface Options { + [index: string]: string | boolean | undefined + } + + const options: Options = { + referrerDomain: window.location.origin, + walletAddress: addFundsSettings.walletAddress, + fiatAmount: addFundsSettings?.fiatAmount, + fiatCurrency: addFundsSettings?.fiatCurrency, + disableWalletAddressForm: true, + defaultCryptoCurrency: addFundsSettings?.defaultCryptoCurrency, + networks: addFundsSettings?.networks + } + + const url = new URL(transakApiUrl) + + const data = { + params: { + referrerDomain: options.referrerDomain, + cryptoCurrencyCode: options.defaultCryptoCurrency, + fiatAmount: options?.fiatAmount, + fiatCurrency: options?.fiatCurrency, + network: options.networks ? (options.networks as string).split(',')[0].trim() : undefined, + disableWalletAddressForm: options.disableWalletAddressForm, + walletAddress: options.walletAddress + } + } + + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-access-key': projectAccessKey + }, + body: JSON.stringify(data) + }) + + const result = await response.json() + + return result?.url + } catch (error) { + console.error('Error:', error) + } +} + interface CountriesResult { response: Country[] } diff --git a/packages/checkout/src/views/AddFunds.tsx b/packages/checkout/src/views/AddFunds.tsx index fb8238ea1..3dbc2f4b4 100644 --- a/packages/checkout/src/views/AddFunds.tsx +++ b/packages/checkout/src/views/AddFunds.tsx @@ -1,10 +1,20 @@ +<<<<<<< HEAD import { Spinner, Text } from '@0xsequence/design-system' import { useEffect, useRef } from 'react' +======= +import { useProjectAccessKey } from '@0xsequence/connect' +import { Button, Spinner, Text } from '@0xsequence/design-system' +import { useEffect, useRef, useState } from 'react' +>>>>>>> 51730908 (feat(onramp): add optional Transak alternate flow with default and windowed modes) import { HEADER_HEIGHT } from '../constants/index.js' import type { AddFundsSettings } from '../contexts/AddFundsModal.js' import { useAddFundsModal } from '../hooks/index.js' +<<<<<<< HEAD import { useTransakWidgetUrl } from '../hooks/useTransakWidgetUrl.js' +======= +import { getTransakLink, getTransakLinkFromSequenceApi } from '../utils/transak.js' +>>>>>>> 51730908 (feat(onramp): add optional Transak alternate flow with default and windowed modes) const EventTypeOrderCreated = 'TRANSAK_ORDER_CREATED' const EventTypeOrderSuccessful = 'TRANSAK_ORDER_SUCCESSFUL' @@ -17,6 +27,7 @@ export const AddFundsContent = () => { export const AddFundsContentTransak = () => { const { addFundsSettings = {} as AddFundsSettings } = useAddFundsModal() +<<<<<<< HEAD const { data: transakLinkData, @@ -32,7 +43,15 @@ export const AddFundsContentTransak = () => { defaultCryptoCurrency: addFundsSettings?.defaultCryptoCurrency || 'USDC', cryptoCurrencyList: addFundsSettings?.cryptoCurrencyList }) +======= + const { transakApiUrl, transakApiKey, sequenceTransakApiUrl } = useEnvironmentContext() +>>>>>>> 51730908 (feat(onramp): add optional Transak alternate flow with default and windowed modes) const iframeRef = useRef(null) + const projectAccessKey = useProjectAccessKey() + const [isLoading, setIsLoading] = useState(false) + const [creationLinkFailed, setCreationLinkFailed] = useState(false) + const { transakOnRampKind = 'default' } = addFundsSettings + const isTransakOnRampKindWindowed = transakOnRampKind === 'windowed' useEffect(() => { const handleMessage = (message: MessageEvent) => { @@ -79,6 +98,95 @@ export const AddFundsContentTransak = () => { ) } + async function handleTransakLink({ + addFundsSettings, + sequenceTransakApiUrl, + projectAccessKey, + setCreationLinkFailed, + setIsLoading + }: { + addFundsSettings: AddFundsSettings + sequenceTransakApiUrl: string + projectAccessKey: string + setCreationLinkFailed: (value: boolean) => void + setIsLoading: (value: boolean) => void + }) { + try { + setCreationLinkFailed(false) + setIsLoading(true) + const link = await getTransakLinkFromSequenceApi(addFundsSettings, sequenceTransakApiUrl, projectAccessKey) + + if (link) { + window.open(link, '_blank') + } else { + setCreationLinkFailed(true) + } + setIsLoading(false) + } catch (error) { + console.error(`The creation of the Transak link has failed. Error: `, error) + setCreationLinkFailed(true) + setIsLoading(false) + } + } + + useEffect(() => { + if (!isTransakOnRampKindWindowed) { + return + } + + handleTransakLink({ addFundsSettings, sequenceTransakApiUrl, projectAccessKey, setIsLoading, setCreationLinkFailed }) + }, []) + + if (isLoading) { + return ( +
+ +
+ ) + } + + if (isTransakOnRampKindWindowed) { + return ( +
+ {creationLinkFailed ? ( +
+ The creation of the Transak link failed. + +
+ ) : ( +
+ Once you've added funds, you can close this window and try buying with crypto again. +
+ )} +
+ ) + } + return (
Date: Thu, 13 Nov 2025 12:29:38 -0500 Subject: [PATCH 2/4] useTransakLink hooks used for fetching url of windowed mode transak flow --- examples/react/src/components/Connected.tsx | 3 +- .../checkout/src/contexts/AddFundsModal.ts | 1 + packages/checkout/src/utils/transak.ts | 3 + packages/checkout/src/views/AddFunds.tsx | 110 ++++-------------- packages/connect/src/styles.ts | 4 +- 5 files changed, 28 insertions(+), 93 deletions(-) diff --git a/examples/react/src/components/Connected.tsx b/examples/react/src/components/Connected.tsx index 136fa38dd..136545dd7 100644 --- a/examples/react/src/components/Connected.tsx +++ b/examples/react/src/components/Connected.tsx @@ -467,7 +467,8 @@ export const Connected = () => { const onClickAddFunds = () => { triggerAddFunds({ walletAddress: address || '', - provider: onRampProvider ? (onRampProvider as TransactionOnRampProvider) : TransactionOnRampProvider.transak + provider: onRampProvider ? (onRampProvider as TransactionOnRampProvider) : TransactionOnRampProvider.transak, + transakOnRampKind: 'default' }) } diff --git a/packages/checkout/src/contexts/AddFundsModal.ts b/packages/checkout/src/contexts/AddFundsModal.ts index 96e2aa226..8eda9ea92 100644 --- a/packages/checkout/src/contexts/AddFundsModal.ts +++ b/packages/checkout/src/contexts/AddFundsModal.ts @@ -18,6 +18,7 @@ export interface AddFundsSettings { provider?: TransactionOnRampProvider transakOnRampKind?: 'default' | 'windowed' cryptoAmount?: string + windowedOnRampMessage?: string } type AddFundsModalContext = { diff --git a/packages/checkout/src/utils/transak.ts b/packages/checkout/src/utils/transak.ts index 5a6f9b79b..c840981a6 100644 --- a/packages/checkout/src/utils/transak.ts +++ b/packages/checkout/src/utils/transak.ts @@ -1,6 +1,8 @@ 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 = ( @@ -82,6 +84,7 @@ export const getTransakLinkFromSequenceApi = async ( const result = await response.json() + console.log('result', result) return result?.url } catch (error) { console.error('Error:', error) diff --git a/packages/checkout/src/views/AddFunds.tsx b/packages/checkout/src/views/AddFunds.tsx index 3dbc2f4b4..c21876a55 100644 --- a/packages/checkout/src/views/AddFunds.tsx +++ b/packages/checkout/src/views/AddFunds.tsx @@ -1,20 +1,10 @@ -<<<<<<< HEAD -import { Spinner, Text } from '@0xsequence/design-system' -import { useEffect, useRef } from 'react' -======= -import { useProjectAccessKey } from '@0xsequence/connect' import { Button, Spinner, Text } from '@0xsequence/design-system' -import { useEffect, useRef, useState } from 'react' ->>>>>>> 51730908 (feat(onramp): add optional Transak alternate flow with default and windowed modes) +import { useEffect, useRef } from 'react' import { HEADER_HEIGHT } from '../constants/index.js' import type { AddFundsSettings } from '../contexts/AddFundsModal.js' import { useAddFundsModal } from '../hooks/index.js' -<<<<<<< HEAD import { useTransakWidgetUrl } from '../hooks/useTransakWidgetUrl.js' -======= -import { getTransakLink, getTransakLinkFromSequenceApi } from '../utils/transak.js' ->>>>>>> 51730908 (feat(onramp): add optional Transak alternate flow with default and windowed modes) const EventTypeOrderCreated = 'TRANSAK_ORDER_CREATED' const EventTypeOrderSuccessful = 'TRANSAK_ORDER_SUCCESSFUL' @@ -27,12 +17,12 @@ export const AddFundsContent = () => { export const AddFundsContentTransak = () => { const { addFundsSettings = {} as AddFundsSettings } = useAddFundsModal() -<<<<<<< HEAD const { data: transakLinkData, isLoading: isLoadingTransakLink, - error: errorTransakLink + isError: isErrorTransakLink, + refetch: refetchTransakLink } = useTransakWidgetUrl({ referrerDomain: window.location.origin, walletAddress: addFundsSettings.walletAddress, @@ -43,13 +33,7 @@ export const AddFundsContentTransak = () => { defaultCryptoCurrency: addFundsSettings?.defaultCryptoCurrency || 'USDC', cryptoCurrencyList: addFundsSettings?.cryptoCurrencyList }) -======= - const { transakApiUrl, transakApiKey, sequenceTransakApiUrl } = useEnvironmentContext() ->>>>>>> 51730908 (feat(onramp): add optional Transak alternate flow with default and windowed modes) const iframeRef = useRef(null) - const projectAccessKey = useProjectAccessKey() - const [isLoading, setIsLoading] = useState(false) - const [creationLinkFailed, setCreationLinkFailed] = useState(false) const { transakOnRampKind = 'default' } = addFundsSettings const isTransakOnRampKindWindowed = transakOnRampKind === 'windowed' @@ -82,71 +66,16 @@ export const AddFundsContentTransak = () => { const link = transakLinkData?.url - if (isLoadingTransakLink) { - return ( -
- -
- ) - } - - if (errorTransakLink) { - return ( -
- An error has occurred -
- ) - } - - async function handleTransakLink({ - addFundsSettings, - sequenceTransakApiUrl, - projectAccessKey, - setCreationLinkFailed, - setIsLoading - }: { - addFundsSettings: AddFundsSettings - sequenceTransakApiUrl: string - projectAccessKey: string - setCreationLinkFailed: (value: boolean) => void - setIsLoading: (value: boolean) => void - }) { - try { - setCreationLinkFailed(false) - setIsLoading(true) - const link = await getTransakLinkFromSequenceApi(addFundsSettings, sequenceTransakApiUrl, projectAccessKey) - - if (link) { - window.open(link, '_blank') - } else { - setCreationLinkFailed(true) - } - setIsLoading(false) - } catch (error) { - console.error(`The creation of the Transak link has failed. Error: `, error) - setCreationLinkFailed(true) - setIsLoading(false) - } - } - useEffect(() => { - if (!isTransakOnRampKindWindowed) { - return + if (isTransakOnRampKindWindowed && !isLoadingTransakLink && link) { + window.open(link, '_blank', 'noopener') } + }, [isTransakOnRampKindWindowed, isLoadingTransakLink, link]) - handleTransakLink({ addFundsSettings, sequenceTransakApiUrl, projectAccessKey, setIsLoading, setCreationLinkFailed }) - }, []) - - if (isLoading) { + if (isLoadingTransakLink) { return ( -
- +
+
) } @@ -160,19 +89,14 @@ export const AddFundsContentTransak = () => { paddingTop: HEADER_HEIGHT }} > - {creationLinkFailed ? ( + {isErrorTransakLink ? (
The creation of the Transak link failed.
) : (
- Once you've added funds, you can close this window and try buying with crypto again. + {addFundsSettings?.windowedOnRampMessage || 'Funds will be added from another window.'}
)}
) } + if (isErrorTransakLink) { + return ( +
+ An error has occurred +
+ ) + } + return (
Date: Thu, 13 Nov 2025 12:34:44 -0500 Subject: [PATCH 3/4] usewindowedonRamp in checkout --- .../Checkout/PaymentMethodSelect/PayWithCrypto/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/checkout/src/views/Checkout/PaymentMethodSelect/PayWithCrypto/index.tsx b/packages/checkout/src/views/Checkout/PaymentMethodSelect/PayWithCrypto/index.tsx index c7e6e46a1..d0468db6b 100644 --- a/packages/checkout/src/views/Checkout/PaymentMethodSelect/PayWithCrypto/index.tsx +++ b/packages/checkout/src/views/Checkout/PaymentMethodSelect/PayWithCrypto/index.tsx @@ -561,6 +561,8 @@ export const PayWithCryptoTab = ({ skipOnCloseCallback, isSwitchingChainRef }: P return network?.name?.toLowerCase() } + const useWindowedOnRamp = !onRampProvider || onRampProvider == TransactionOnRampProvider.unknown + skipOnCloseCallback() closeSelectPaymentModal() triggerAddFunds({ @@ -568,7 +570,9 @@ export const PayWithCryptoTab = ({ skipOnCloseCallback, isSwitchingChainRef }: P provider: onRampProvider || TransactionOnRampProvider.transak, networks: getNetworks(), defaultCryptoCurrency: dataCurrencyInfo?.symbol || '', - onClose: selectPaymentSettings?.onClose + onClose: selectPaymentSettings?.onClose, + transakOnRampKind: useWindowedOnRamp ? 'windowed' : 'default', + windowedOnRampMessage: "Once you've added funds, you can close this window and try buying with crypto again." }) } From 4df17304e7e336c9b3b49d28a36961ec19c213fe Mon Sep 17 00:00:00 2001 From: samuelea Date: Thu, 13 Nov 2025 12:45:48 -0500 Subject: [PATCH 4/4] cleanup --- packages/checkout/src/utils/transak.ts | 88 -------------------------- 1 file changed, 88 deletions(-) diff --git a/packages/checkout/src/utils/transak.ts b/packages/checkout/src/utils/transak.ts index c840981a6..799284650 100644 --- a/packages/checkout/src/utils/transak.ts +++ b/packages/checkout/src/utils/transak.ts @@ -1,96 +1,8 @@ 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 } -) => { - 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 - } - - Object.keys(options).forEach(k => { - const option = options[k] - if (option) { - url.searchParams.append(k, option) - } - }) - - return url.href -} - -export const getTransakLinkFromSequenceApi = async ( - addFundsSettings: AddFundsSettings, - transakApiUrl: string, - projectAccessKey: string -) => { - interface Options { - [index: string]: string | boolean | undefined - } - - const options: Options = { - referrerDomain: window.location.origin, - walletAddress: addFundsSettings.walletAddress, - fiatAmount: addFundsSettings?.fiatAmount, - fiatCurrency: addFundsSettings?.fiatCurrency, - disableWalletAddressForm: true, - defaultCryptoCurrency: addFundsSettings?.defaultCryptoCurrency, - networks: addFundsSettings?.networks - } - - const url = new URL(transakApiUrl) - - const data = { - params: { - referrerDomain: options.referrerDomain, - cryptoCurrencyCode: options.defaultCryptoCurrency, - fiatAmount: options?.fiatAmount, - fiatCurrency: options?.fiatCurrency, - network: options.networks ? (options.networks as string).split(',')[0].trim() : undefined, - disableWalletAddressForm: options.disableWalletAddressForm, - walletAddress: options.walletAddress - } - } - - try { - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'x-access-key': projectAccessKey - }, - body: JSON.stringify(data) - }) - - const result = await response.json() - - console.log('result', result) - return result?.url - } catch (error) { - console.error('Error:', error) - } -} - interface CountriesResult { response: Country[] }