@@ -30,6 +30,7 @@ import {
3030 BridgeOrchestrator ,
3131 type UIOptions ,
3232} from "./Bridge/BridgeOrchestrator.js" ;
33+ import { UnsupportedTokenScreen } from "./Bridge/UnsupportedTokenScreen.js" ;
3334import { EmbedContainer } from "./ConnectWallet/Modal/ConnectEmbed.js" ;
3435import { useConnectLocale } from "./ConnectWallet/locale/getConnectLocale.js" ;
3536import BuyScreen from "./ConnectWallet/screens/Buy/BuyScreen.js" ;
@@ -159,6 +160,15 @@ export type PayEmbedProps = {
159160 paymentLinkId ?: string ;
160161} ;
161162
163+ // Enhanced UIOptions to handle unsupported token state
164+ type UIOptionsResult =
165+ | { type : "success" ; data : UIOptions }
166+ | {
167+ type : "unsupported_token" ;
168+ token ?: { address : string ; symbol ?: string ; name ?: string } ;
169+ chain : Chain ;
170+ } ;
171+
162172/**
163173 * Embed a prebuilt UI for funding wallets, purchases or transactions with crypto or fiat.
164174 *
@@ -320,13 +330,16 @@ export function PayEmbed(props: PayEmbedProps) {
320330
321331 const bridgeDataQuery = useQuery ( {
322332 queryKey : [ "bridgeData" , props ] ,
323- queryFn : async ( ) : Promise < UIOptions > => {
333+ queryFn : async ( ) : Promise < UIOptionsResult > => {
324334 if ( ! props . payOptions ?. mode ) {
325335 const ETH = await getToken ( props . client , NATIVE_TOKEN_ADDRESS , 1 ) ;
326336 return {
327- mode : "fund_wallet" ,
328- destinationToken : ETH ,
329- initialAmount : "0.01" ,
337+ type : "success" ,
338+ data : {
339+ mode : "fund_wallet" ,
340+ destinationToken : ETH ,
341+ initialAmount : "0.01" ,
342+ } ,
330343 } ;
331344 }
332345
@@ -335,23 +348,38 @@ export function PayEmbed(props: PayEmbedProps) {
335348 if ( ! prefillInfo ) {
336349 const ETH = await getToken ( props . client , NATIVE_TOKEN_ADDRESS , 1 ) ;
337350 return {
338- mode : "fund_wallet" ,
339- destinationToken : ETH ,
351+ type : "success" ,
352+ data : {
353+ mode : "fund_wallet" ,
354+ destinationToken : ETH ,
355+ } ,
340356 } ;
341357 }
342358 const token = await getToken (
343359 props . client ,
344360 prefillInfo . token ?. address || NATIVE_TOKEN_ADDRESS ,
345361 prefillInfo . chain . id ,
362+ ) . catch ( ( err ) =>
363+ err . message . includes ( "not found" ) ? undefined : Promise . reject ( err ) ,
346364 ) ;
347365 if ( ! token ) {
348- console . error ( "Token not found for prefillInfo" , prefillInfo ) ;
349- throw new Error ( "Token not found" ) ;
366+ return {
367+ type : "unsupported_token" ,
368+ token : {
369+ address : prefillInfo . token ?. address || NATIVE_TOKEN_ADDRESS ,
370+ symbol : prefillInfo . token ?. symbol ,
371+ name : prefillInfo . token ?. name ,
372+ } ,
373+ chain : prefillInfo . chain ,
374+ } ;
350375 }
351376 return {
352- mode : "fund_wallet" ,
353- destinationToken : token ,
354- initialAmount : prefillInfo . amount ,
377+ type : "success" ,
378+ data : {
379+ mode : "fund_wallet" ,
380+ destinationToken : token ,
381+ initialAmount : prefillInfo . amount ,
382+ } ,
355383 } ;
356384 }
357385
@@ -361,41 +389,66 @@ export function PayEmbed(props: PayEmbedProps) {
361389 props . client ,
362390 paymentInfo . token ?. address || NATIVE_TOKEN_ADDRESS ,
363391 paymentInfo . chain . id ,
392+ ) . catch ( ( err ) =>
393+ err . message . includes ( "not found" ) ? undefined : Promise . reject ( err ) ,
364394 ) ;
365395 if ( ! token ) {
366- console . error ( "Token not found for paymentInfo" , paymentInfo ) ;
367- throw new Error ( "Token not found" ) ;
396+ return {
397+ type : "unsupported_token" ,
398+ token : {
399+ address : paymentInfo . token ?. address || NATIVE_TOKEN_ADDRESS ,
400+ symbol : paymentInfo . token ?. symbol ,
401+ name : paymentInfo . token ?. name ,
402+ } ,
403+ chain : paymentInfo . chain ,
404+ } ;
368405 }
369406 const amount =
370407 "amount" in paymentInfo
371408 ? paymentInfo . amount
372409 : toTokens ( paymentInfo . amountWei , token . decimals ) ;
373410 return {
374- mode : "direct_payment" ,
375- paymentInfo : {
376- token,
377- amount,
378- sellerAddress : paymentInfo . sellerAddress as `0x${string } `,
379- metadata : {
380- name : props . payOptions ?. metadata ?. name || "Direct Payment" ,
381- image : props . payOptions ?. metadata ?. image || "" ,
411+ type : "success" ,
412+ data : {
413+ mode : "direct_payment" ,
414+ paymentInfo : {
415+ token,
416+ amount,
417+ sellerAddress : paymentInfo . sellerAddress as `0x${string } `,
418+ metadata : {
419+ name : props . payOptions ?. metadata ?. name || "Direct Payment" ,
420+ image : props . payOptions ?. metadata ?. image || "" ,
421+ } ,
422+ feePayer : paymentInfo . feePayer ,
382423 } ,
383- feePayer : paymentInfo . feePayer ,
384424 } ,
385425 } ;
386426 }
387427
388428 if ( props . payOptions ?. mode === "transaction" ) {
389429 return {
390- mode : "transaction" ,
391- transaction : props . payOptions . transaction ,
430+ type : "success" ,
431+ data : {
432+ mode : "transaction" ,
433+ transaction : props . payOptions . transaction ,
434+ } ,
392435 } ;
393436 }
394437
395438 throw new Error ( "Invalid mode" ) ;
396439 } ,
397440 } ) ;
398441
442+ const handleTryDifferentToken = ( ) => {
443+ // Refetch to allow user to try again (they might have changed something)
444+ bridgeDataQuery . refetch ( ) ;
445+ } ;
446+
447+ const handleContactSupport = ( ) => {
448+ // Open support link or modal (this could be configurable via props)
449+ window . open ( "https://support.thirdweb.com" , "_blank" ) ;
450+ } ;
451+
399452 let content = null ;
400453 if ( ! localeQuery . data || bridgeDataQuery . isLoading ) {
401454 content = (
@@ -410,17 +463,27 @@ export function PayEmbed(props: PayEmbedProps) {
410463 < Spinner size = "xl" color = "secondaryText" />
411464 </ div >
412465 ) ;
413- } else {
414- content = bridgeDataQuery . data ? (
466+ } else if ( bridgeDataQuery . data ?. type === "unsupported_token" ) {
467+ // Show unsupported token screen
468+ content = (
469+ < UnsupportedTokenScreen
470+ chain = { bridgeDataQuery . data . chain }
471+ onTryDifferentToken = { handleTryDifferentToken }
472+ onContactSupport = { handleContactSupport }
473+ />
474+ ) ;
475+ } else if ( bridgeDataQuery . data ?. type === "success" ) {
476+ // Show normal bridge orchestrator
477+ content = (
415478 < BridgeOrchestrator
416479 client = { props . client }
417- uiOptions = { bridgeDataQuery . data }
480+ uiOptions = { bridgeDataQuery . data . data }
418481 connectOptions = { props . connectOptions }
419482 connectLocale = { localeQuery . data }
420483 purchaseData = { props . payOptions ?. purchaseData }
421484 paymentLinkId = { props . paymentLinkId }
422485 />
423- ) : null ;
486+ ) ;
424487 }
425488
426489 return (
0 commit comments