@@ -18,7 +18,6 @@ interface UseRampQuotesOptions {
18
18
/** The quote request to fetch quotes for. If null, no quotes will be fetched. */
19
19
rampQuoteRequest : RampQuoteRequest | null
20
20
plugins : Record < string , RampPlugin >
21
- precomputedQuotes ?: RampQuoteResult [ ]
22
21
staleTime ?: number
23
22
}
24
23
@@ -52,13 +51,13 @@ const isQuoteExpiringSoon = (
52
51
export const useRampQuotes = ( {
53
52
rampQuoteRequest,
54
53
plugins,
55
- precomputedQuotes = [ ] ,
56
54
staleTime = 30000
57
55
} : UseRampQuotesOptions ) : UseRampQuotesResult => {
58
56
const queryClient = useQueryClient ( )
59
57
60
58
// Stable query key that doesn't change based on expired quotes
61
- const queryKey = [ 'rampQuotes' , rampQuoteRequest ]
59
+ const pluginIds = Object . keys ( plugins ) . sort ( ) // Sort for stability
60
+ const queryKey = [ 'rampQuotes' , rampQuoteRequest , pluginIds ]
62
61
63
62
const {
64
63
data : quoteResults = [ ] ,
@@ -75,91 +74,38 @@ export const useRampQuotes = ({
75
74
queryKey
76
75
) ?? [ ]
77
76
78
- // Determine which plugins need fresh quotes
79
- const pluginsNeedingRefresh = new Set < string > ( )
80
- const validPrevResults = new Map <
77
+ // Create a map of previous results by plugin ID
78
+ const prevResultsMap = new Map <
81
79
string ,
82
80
Result < RampQuoteResult [ ] , QuoteError >
83
81
> ( )
84
-
85
- // Check previous results for expired quotes
86
82
prevResults . forEach ( result => {
87
- if ( result . ok ) {
88
- const pluginId = result . value [ 0 ] ?. pluginId
89
- if ( pluginId === '' ) return
90
-
91
- const validQuotes = result . value . filter (
92
- quote => ! isQuoteExpired ( quote )
93
- )
94
- const hasExpiredQuotes = result . value . some ( quote =>
95
- isQuoteExpired ( quote )
96
- )
97
-
98
- if ( hasExpiredQuotes || validQuotes . length === 0 ) {
99
- pluginsNeedingRefresh . add ( pluginId )
100
- } else {
101
- // Store the complete successful result with only valid quotes
102
- validPrevResults . set ( pluginId , { ok : true , value : validQuotes } )
103
- }
104
- } else {
105
- // Preserve error results as-is
106
- const pluginId = result . error . pluginId
107
- validPrevResults . set ( pluginId , result )
108
- // Don't add to pluginsNeedingRefresh - we keep the error
109
- }
83
+ const pluginId = result . ok
84
+ ? result . value [ 0 ] ?. pluginId
85
+ : result . error . pluginId
86
+ if ( pluginId !== '' ) prevResultsMap . set ( pluginId , result )
110
87
} )
111
88
112
- // If this is the first fetch (no prev results), use precomputed quotes or fetch all
113
- if ( prevResults . length === 0 ) {
114
- if ( precomputedQuotes . length > 0 ) {
115
- // Group precomputed quotes by plugin
116
- const groupedPrecomputed = new Map < string , RampQuoteResult [ ] > ( )
117
-
118
- precomputedQuotes . forEach ( quote => {
119
- const existing = groupedPrecomputed . get ( quote . pluginId ) ?? [ ]
120
- groupedPrecomputed . set ( quote . pluginId , [ ...existing , quote ] )
121
- } )
122
-
123
- // Convert to results format
124
- const initialResults : Array < Result < RampQuoteResult [ ] , QuoteError > > =
125
- [ ]
126
-
127
- groupedPrecomputed . forEach ( ( quotes , pluginId ) => {
128
- const validQuotes = quotes . filter ( quote => ! isQuoteExpired ( quote ) )
89
+ // Fetch quotes from all plugins, reusing valid cached quotes
90
+ const resultPromises = Object . entries ( plugins ) . map (
91
+ async ( [ pluginId , plugin ] ) : Promise <
92
+ Result < RampQuoteResult [ ] , QuoteError >
93
+ > => {
94
+ const prevResult = prevResultsMap . get ( pluginId )
95
+
96
+ // If we have valid non-expired quotes, use them
97
+ if ( prevResult ?. ok === true ) {
98
+ const validQuotes = prevResult . value . filter (
99
+ quote => ! isQuoteExpired ( quote )
100
+ )
129
101
if ( validQuotes . length > 0 ) {
130
- initialResults . push ( { ok : true , value : validQuotes } )
131
- } else {
132
- // All quotes expired for this plugin, need to fetch
133
- pluginsNeedingRefresh . add ( pluginId )
102
+ return { ok : true , value : validQuotes }
134
103
}
135
- } )
136
-
137
- // If we have some valid precomputed quotes, return them
138
- if ( initialResults . length > 0 && pluginsNeedingRefresh . size === 0 ) {
139
- return initialResults
140
104
}
141
- } else {
142
- // No precomputed quotes, fetch from all plugins
143
- Object . keys ( plugins ) . forEach ( pluginId => {
144
- pluginsNeedingRefresh . add ( pluginId )
145
- } )
146
- }
147
- }
148
-
149
- // If no plugins need refresh, return previous results
150
- if ( pluginsNeedingRefresh . size === 0 ) {
151
- return prevResults
152
- }
153
-
154
- // Fetch only from plugins that need refresh
155
- const freshResultsPromises = Array . from ( pluginsNeedingRefresh ) . map (
156
- async ( pluginId ) : Promise < Result < RampQuoteResult [ ] , QuoteError > > => {
157
- const plugin = plugins [ pluginId ]
158
- if ( plugin == null ) return { ok : true , value : [ ] }
159
105
106
+ // Otherwise fetch fresh quotes
160
107
try {
161
108
const quotes = await plugin . fetchQuote ( rampQuoteRequest )
162
- // Return quotes as-is (empty array means plugin doesn't support the request)
163
109
return { ok : true , value : quotes }
164
110
} catch ( error ) {
165
111
console . warn ( `Failed to get quote from ${ pluginId } :` , error )
@@ -175,24 +121,7 @@ export const useRampQuotes = ({
175
121
}
176
122
)
177
123
178
- const freshResults = await Promise . all ( freshResultsPromises )
179
-
180
- // Merge fresh results with valid previous results
181
- const mergedResults : Array < Result < RampQuoteResult [ ] , QuoteError > > = [ ]
182
-
183
- // Add fresh results
184
- freshResults . forEach ( result => {
185
- mergedResults . push ( result )
186
- } )
187
-
188
- // Add valid previous results (including errors) for plugins we didn't refresh
189
- validPrevResults . forEach ( ( result , pluginId ) => {
190
- if ( ! pluginsNeedingRefresh . has ( pluginId ) ) {
191
- mergedResults . push ( result )
192
- }
193
- } )
194
-
195
- return mergedResults
124
+ return await Promise . all ( resultPromises )
196
125
} ,
197
126
refetchOnMount : 'always' ,
198
127
refetchInterval : query => {
0 commit comments