@@ -15,7 +15,9 @@ import {
1515 normalizeProviderCode ,
1616 RampsOrderStatus ,
1717} from '@metamask/ramps-controller' ;
18+ import { isBailedOrderStatus } from '../BuildQuote/BuildQuote' ;
1819import { extractOrderCode } from '../../utils/extractOrderCode' ;
20+ import { getNavigateAfterExternalBrowserRoutes } from '../../utils/rampsNavigation' ;
1921import Button , {
2022 ButtonVariants ,
2123 ButtonSize ,
@@ -37,8 +39,11 @@ import { useAnalytics } from '../../../../hooks/useAnalytics/useAnalytics';
3739import { MetaMetricsEvents } from '../../../../../core/Analytics' ;
3840import { RampsOrderDetailsSelectorsIDs } from './OrderDetails.testIds' ;
3941interface RampsOrderDetailsParams {
40- orderId : string ;
42+ orderId ? : string ;
4143 showCloseButton ?: boolean ;
44+ callbackUrl ?: string ;
45+ providerCode ?: string ;
46+ walletAddress ?: string ;
4247}
4348
4449export const createRampsOrderDetailsNavDetails =
@@ -69,19 +74,75 @@ const styles = StyleSheet.create({
6974
7075const OrderDetails = ( ) => {
7176 const params = useParams < RampsOrderDetailsParams > ( ) ;
72- const { getOrderById, refreshOrder } = useRampsOrders ( ) ;
77+ const { getOrderById, refreshOrder, getOrderFromCallback, addOrder } =
78+ useRampsOrders ( ) ;
7379 const orderCode = params . orderId ? extractOrderCode ( params . orderId ) : '' ;
7480 const order = getOrderById ( orderCode ) ;
7581 const isPending = order ? PENDING_STATUSES . has ( order . status ) : false ;
82+ const hasCallbackParams = Boolean (
83+ params . callbackUrl && params . providerCode && params . walletAddress ,
84+ ) ;
7685
77- const [ isLoading , setIsLoading ] = useState ( isPending ) ;
86+ const [ isLoading , setIsLoading ] = useState ( isPending || hasCallbackParams ) ;
7887 const [ error , setError ] = useState < string | null > ( null ) ;
7988 const theme = useTheme ( ) ;
8089 const { colors } = theme ;
8190 const navigation = useNavigation ( ) ;
8291 const { trackEvent, createEventBuilder } = useAnalytics ( ) ;
8392
8493 const [ isRefreshing , setIsRefreshing ] = useState ( false ) ;
94+ const hasFetchedFromCallback = useRef ( false ) ;
95+
96+ const handleRetryCallbackFetch = useCallback ( async ( ) => {
97+ if ( ! params . callbackUrl || ! params . providerCode || ! params . walletAddress ) {
98+ return ;
99+ }
100+ try {
101+ setError ( null ) ;
102+ setIsLoading ( true ) ;
103+ const fetchedOrder = await getOrderFromCallback (
104+ params . providerCode ,
105+ params . callbackUrl ,
106+ params . walletAddress ,
107+ ) ;
108+ if ( ! fetchedOrder || isBailedOrderStatus ( fetchedOrder . status ) ) {
109+ navigation . reset ( {
110+ index : 0 ,
111+ routes : getNavigateAfterExternalBrowserRoutes ( {
112+ returnDestination : 'buildQuote' ,
113+ } ) ,
114+ } ) ;
115+ return ;
116+ }
117+ addOrder ( fetchedOrder ) ;
118+ navigation . setParams ( {
119+ orderId : fetchedOrder . providerOrderId ,
120+ callbackUrl : undefined ,
121+ providerCode : undefined ,
122+ walletAddress : undefined ,
123+ } ) ;
124+ } catch ( fetchError ) {
125+ Logger . error ( fetchError as Error , {
126+ message :
127+ 'RampsOrderDetails: error fetching order from callback URL (retry)' ,
128+ callbackUrl : params . callbackUrl ,
129+ } ) ;
130+ setError (
131+ fetchError instanceof Error && fetchError . message
132+ ? fetchError . message
133+ : strings ( 'ramps_order_details.error_message' ) ,
134+ ) ;
135+ } finally {
136+ setIsLoading ( false ) ;
137+ }
138+ } , [
139+ params . callbackUrl ,
140+ params . providerCode ,
141+ params . walletAddress ,
142+ getOrderFromCallback ,
143+ addOrder ,
144+ navigation ,
145+ ] ) ;
85146
86147 useEffect ( ( ) => {
87148 navigation . setOptions (
@@ -148,12 +209,79 @@ const OrderDetails = () => {
148209 } , [ order , refreshOrder ] ) ;
149210
150211 useEffect ( ( ) => {
151- if ( isPending ) {
212+ if ( isPending && ! hasCallbackParams ) {
152213 handleOnRefresh ( ) ;
153214 }
154215 // eslint-disable-next-line react-hooks/exhaustive-deps
155216 } , [ ] ) ;
156217
218+ useEffect ( ( ) => {
219+ if (
220+ ! hasCallbackParams ||
221+ hasFetchedFromCallback . current ||
222+ ! params . callbackUrl ||
223+ ! params . providerCode ||
224+ ! params . walletAddress
225+ ) {
226+ return ;
227+ }
228+ hasFetchedFromCallback . current = true ;
229+
230+ const providerCode = params . providerCode ;
231+ const callbackUrl = params . callbackUrl ;
232+ const walletAddress = params . walletAddress ;
233+ if ( ! providerCode || ! callbackUrl || ! walletAddress ) return ;
234+
235+ const fetchFromCallback = async ( ) => {
236+ try {
237+ setError ( null ) ;
238+ const fetchedOrder = await getOrderFromCallback (
239+ providerCode ,
240+ callbackUrl ,
241+ walletAddress ,
242+ ) ;
243+ if ( ! fetchedOrder || isBailedOrderStatus ( fetchedOrder . status ) ) {
244+ navigation . reset ( {
245+ index : 0 ,
246+ routes : getNavigateAfterExternalBrowserRoutes ( {
247+ returnDestination : 'buildQuote' ,
248+ } ) ,
249+ } ) ;
250+ return ;
251+ }
252+ addOrder ( fetchedOrder ) ;
253+ navigation . setParams ( {
254+ orderId : fetchedOrder . providerOrderId ,
255+ callbackUrl : undefined ,
256+ providerCode : undefined ,
257+ walletAddress : undefined ,
258+ } ) ;
259+ } catch ( fetchError ) {
260+ Logger . error ( fetchError as Error , {
261+ message : 'RampsOrderDetails: error fetching order from callback URL' ,
262+ callbackUrl,
263+ } ) ;
264+ setError (
265+ fetchError instanceof Error && fetchError . message
266+ ? fetchError . message
267+ : strings ( 'ramps_order_details.error_message' ) ,
268+ ) ;
269+ } finally {
270+ setIsLoading ( false ) ;
271+ }
272+ } ;
273+
274+ fetchFromCallback ( ) ;
275+ } , [
276+ hasCallbackParams ,
277+ params . callbackUrl ,
278+ params . providerCode ,
279+ params . walletAddress ,
280+ getOrderFromCallback ,
281+ addOrder ,
282+ navigation ,
283+ ] ) ;
284+
157285 if ( isLoading ) {
158286 return (
159287 < ScreenLayout >
@@ -166,11 +294,10 @@ const OrderDetails = () => {
166294 ) ;
167295 }
168296
169- if ( ! order ) {
170- return < ScreenLayout /> ;
171- }
172-
173297 if ( error ) {
298+ const onRetry = hasCallbackParams
299+ ? handleRetryCallbackFetch
300+ : handleOnRefresh ;
174301 return (
175302 < ScreenLayout >
176303 < ScreenLayout . Body >
@@ -198,14 +325,18 @@ const OrderDetails = () => {
198325 size = { ButtonSize . Lg }
199326 width = { ButtonWidthTypes . Full }
200327 label = { strings ( 'ramps_order_details.try_again' ) }
201- onPress = { handleOnRefresh }
328+ onPress = { onRetry }
202329 />
203330 </ Box >
204331 </ ScreenLayout . Body >
205332 </ ScreenLayout >
206333 ) ;
207334 }
208335
336+ if ( ! order ) {
337+ return < ScreenLayout /> ;
338+ }
339+
209340 return (
210341 < ScreenLayout testID = { RampsOrderDetailsSelectorsIDs . CONTAINER } >
211342 < ScrollView
0 commit comments