Skip to content

Commit 43b0e1f

Browse files
committed
Add ramp plugin amount type filtering
1 parent ca0adc4 commit 43b0e1f

File tree

9 files changed

+125
-28
lines changed

9 files changed

+125
-28
lines changed

src/components/scenes/TradeCreateScene.tsx

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import { COUNTRY_CODES, FIAT_COUNTRY } from '../../constants/CountryConstants'
1212
import { useHandler } from '../../hooks/useHandler'
1313
import { useRampPlugins } from '../../hooks/useRampPlugins'
1414
import { useRampQuotes } from '../../hooks/useRampQuotes'
15-
import { useSupportedPlugins } from '../../hooks/useSupportedPlugins'
15+
import {
16+
type SupportedPluginResult,
17+
useSupportedPlugins
18+
} from '../../hooks/useSupportedPlugins'
1619
import { useWatch } from '../../hooks/useWatch'
1720
import { lstrings } from '../../locales/strings'
1821
import type {
@@ -53,6 +56,47 @@ export interface TradeCreateParams {
5356

5457
interface Props extends BuyTabSceneProps<'pluginListBuy'> {}
5558

59+
// Helper function to determine which input types should be disabled
60+
interface AmountTypeSupport {
61+
fiatInputDisabled: boolean
62+
cryptoInputDisabled: boolean
63+
}
64+
65+
function getAmountTypeSupport(
66+
supportedPlugins: SupportedPluginResult[]
67+
): AmountTypeSupport {
68+
if (supportedPlugins.length === 0) {
69+
return { fiatInputDisabled: false, cryptoInputDisabled: false }
70+
}
71+
72+
// Collect all supported amount types from all plugins
73+
const allSupportedTypes = new Set<'fiat' | 'crypto'>()
74+
75+
for (const { supportResult } of supportedPlugins) {
76+
if (supportResult.supportedAmountTypes != null) {
77+
for (const type of supportResult.supportedAmountTypes) {
78+
allSupportedTypes.add(type)
79+
}
80+
} else {
81+
// If a plugin doesn't specify supported types, assume both are supported
82+
allSupportedTypes.add('fiat')
83+
allSupportedTypes.add('crypto')
84+
}
85+
}
86+
87+
// If all plugins only support fiat, disable crypto input
88+
const onlyFiat =
89+
allSupportedTypes.has('fiat') && !allSupportedTypes.has('crypto')
90+
// If all plugins only support crypto, disable fiat input
91+
const onlyCrypto =
92+
allSupportedTypes.has('crypto') && !allSupportedTypes.has('fiat')
93+
94+
return {
95+
fiatInputDisabled: onlyCrypto,
96+
cryptoInputDisabled: onlyFiat
97+
}
98+
}
99+
56100
export const TradeCreateScene: React.FC<Props> = (props: Props) => {
57101
const { navigation, route } = props
58102
const { regionCode: initialRegionCode, forcedWalletResult } =
@@ -189,6 +233,10 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
189233
return info?.logoUrl ?? ''
190234
}, [selectedFiatCurrencyCode])
191235

236+
// Determine which input types should be disabled
237+
const { fiatInputDisabled, cryptoInputDisabled } =
238+
getAmountTypeSupport(supportedPlugins)
239+
192240
// Create rampQuoteRequest based on current form state
193241
const rampQuoteRequest: RampQuoteRequest | null = React.useMemo(() => {
194242
if (
@@ -201,6 +249,14 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
201249
return null
202250
}
203251

252+
// Guard against creating request with disabled input type
253+
if (
254+
(lastUsedInput === 'fiat' && fiatInputDisabled) ||
255+
(lastUsedInput === 'crypto' && cryptoInputDisabled)
256+
) {
257+
return null
258+
}
259+
204260
return {
205261
wallet: selectedWallet,
206262
pluginId: selectedWallet.currencyInfo.pluginId,
@@ -224,7 +280,9 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
224280
selectedFiatCurrencyCode,
225281
lastUsedInput,
226282
countryCode,
227-
stateProvinceCode
283+
stateProvinceCode,
284+
fiatInputDisabled,
285+
cryptoInputDisabled
228286
])
229287

230288
// Fetch quotes using the custom hook
@@ -236,7 +294,7 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
236294
} = useRampQuotes({
237295
rampQuoteRequest,
238296
plugins: Object.fromEntries(
239-
supportedPlugins.map(plugin => [plugin.pluginId, plugin])
297+
supportedPlugins.map(result => [result.plugin.pluginId, result.plugin])
240298
)
241299
})
242300

@@ -301,6 +359,9 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
301359

302360
// Derived state for display values
303361
const displayFiatAmount = React.useMemo(() => {
362+
// Don't show any value if fiat input is disabled
363+
if (fiatInputDisabled) return ''
364+
304365
if (isMaxAmount && bestQuote != null) {
305366
return bestQuote.fiatAmount
306367
}
@@ -312,9 +373,19 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
312373
// User entered crypto, convert to fiat only if we have a quote
313374
return convertCryptoToFiat(userInput)
314375
}
315-
}, [userInput, lastUsedInput, convertCryptoToFiat, isMaxAmount, bestQuote])
376+
}, [
377+
userInput,
378+
lastUsedInput,
379+
convertCryptoToFiat,
380+
isMaxAmount,
381+
bestQuote,
382+
fiatInputDisabled
383+
])
316384

317385
const displayCryptoAmount = React.useMemo(() => {
386+
// Don't show any value if crypto input is disabled
387+
if (cryptoInputDisabled) return ''
388+
318389
if (isMaxAmount && bestQuote != null) {
319390
return bestQuote.cryptoAmount
320391
}
@@ -326,7 +397,14 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
326397
// User entered fiat, convert to crypto only if we have a quote
327398
return convertFiatToCrypto(userInput)
328399
}
329-
}, [userInput, lastUsedInput, convertFiatToCrypto, isMaxAmount, bestQuote])
400+
}, [
401+
userInput,
402+
lastUsedInput,
403+
convertFiatToCrypto,
404+
isMaxAmount,
405+
bestQuote,
406+
cryptoInputDisabled
407+
])
330408

331409
//
332410
// Handlers
@@ -546,6 +624,7 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
546624
keyboardType="decimal-pad"
547625
numeric
548626
showSpinner={isFetchingQuotes && lastUsedInput === 'crypto'}
627+
disabled={fiatInputDisabled}
549628
/>
550629
</InputContainer>
551630
</InputRow>
@@ -573,6 +652,7 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
573652
keyboardType="decimal-pad"
574653
numeric
575654
showSpinner={isFetchingQuotes && lastUsedInput === 'fiat'}
655+
disabled={cryptoInputDisabled}
576656
/>
577657
{/* MAX Button */}
578658
<MaxButton onPress={handleMaxPress}>
@@ -656,7 +736,9 @@ export const TradeCreateScene: React.FC<Props> = (props: Props) => {
656736
isCheckingSupport ||
657737
supportedPlugins.length === 0 ||
658738
isLoadingQuotes ||
659-
sortedQuotes.length === 0
739+
sortedQuotes.length === 0 ||
740+
(lastUsedInput === 'fiat' && fiatInputDisabled) ||
741+
(lastUsedInput === 'crypto' && cryptoInputDisabled)
660742
}
661743
/>
662744
</>

src/components/scenes/TradeOptionSelectScene.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export const TradeOptionSelectScene: React.FC<Props> = (props: Props) => {
7777

7878
// Use supported plugins
7979
const pluginsToUse = Object.fromEntries(
80-
supportedPlugins.map(plugin => [plugin.pluginId, plugin])
80+
supportedPlugins.map(result => [result.plugin.pluginId, result.plugin])
8181
)
8282

8383
// Use the ramp quotes hook

src/hooks/useSupportedPlugins.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import * as React from 'react'
55
import type { FiatPluginRegionCode } from '../plugins/gui/fiatPluginTypes'
66
import type {
77
RampCheckSupportRequest,
8-
RampPlugin
8+
RampPlugin,
9+
RampSupportResult
910
} from '../plugins/ramps/rampPluginTypes'
1011

1112
interface UseSupportedPluginsParams {
@@ -21,8 +22,13 @@ interface UseSupportedPluginsParams {
2122
direction?: 'buy' | 'sell'
2223
}
2324

25+
export interface SupportedPluginResult {
26+
plugin: RampPlugin
27+
supportResult: RampSupportResult
28+
}
29+
2430
interface UseSupportedPluginsResult {
25-
supportedPlugins: RampPlugin[]
31+
supportedPlugins: SupportedPluginResult[]
2632
isLoading: boolean
2733
error: Error | null
2834
}
@@ -68,7 +74,7 @@ export const useSupportedPlugins = ({
6874
data: supportedPlugins = [],
6975
isLoading,
7076
error
71-
} = useQuery<RampPlugin[]>({
77+
} = useQuery<SupportedPluginResult[]>({
7278
queryKey,
7379
queryFn: async () => {
7480
// Early return if required params are missing
@@ -98,10 +104,10 @@ export const useSupportedPlugins = ({
98104
const supportChecks = await Promise.all(
99105
Object.values(plugins).map(async plugin => {
100106
try {
101-
const result = await plugin.checkSupport(checkSupportRequest)
107+
const supportResult = await plugin.checkSupport(checkSupportRequest)
102108
return {
103109
plugin,
104-
supported: result.supported
110+
supportResult
105111
}
106112
} catch (error) {
107113
console.warn(
@@ -110,16 +116,14 @@ export const useSupportedPlugins = ({
110116
)
111117
return {
112118
plugin,
113-
supported: false
119+
supportResult: { supported: false }
114120
}
115121
}
116122
})
117123
)
118124

119125
// Filter only supported plugins
120-
return supportChecks
121-
.filter(check => check.supported)
122-
.map(check => check.plugin)
126+
return supportChecks.filter(check => check.supportResult.supported)
123127
},
124128
enabled:
125129
selectedWallet != null &&

src/plugins/ramps/banxa/banxaRampPlugin.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,10 @@ export const banxaRampPlugin: RampPluginFactory = (
844844
return { supported: false }
845845
}
846846

847-
return { supported: true }
847+
return {
848+
supported: true,
849+
supportedAmountTypes: ['fiat', 'crypto']
850+
}
848851
},
849852

850853
fetchQuote: async (

src/plugins/ramps/bity/bityRampPlugin.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,10 @@ export const bityRampPlugin = (pluginConfig: RampPluginConfig): RampPlugin => {
666666
}
667667

668668
// All checks passed
669-
return { supported: true }
669+
return {
670+
supported: true,
671+
supportedAmountTypes: ['fiat', 'crypto']
672+
}
670673
},
671674

672675
fetchQuote: async (

src/plugins/ramps/paybis/paybisRampPlugin.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,10 @@ export const paybisRampPlugin: RampPluginFactory = (
707707
}
708708

709709
// If we get here, it's supported
710-
return { supported: true }
710+
return {
711+
supported: true,
712+
supportedAmountTypes: ['fiat', 'crypto']
713+
}
711714
},
712715

713716
fetchQuote: async (

src/plugins/ramps/rampPluginTypes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export interface RampCheckSupportRequest {
3131

3232
export interface RampSupportResult {
3333
supported: boolean
34+
// Indicates which amount types are supported by this plugin
35+
supportedAmountTypes?: Array<'fiat' | 'crypto'>
3436
}
3537

3638
export interface RampQuoteRequest {

src/plugins/ramps/revolut/revolutRampPlugin.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ export const revolutRampPlugin: RampPluginFactory = (
163163
assetMap
164164
})
165165

166-
return { supported: assetsSupported }
166+
return {
167+
supported: assetsSupported,
168+
supportedAmountTypes: assetsSupported ? ['fiat'] : undefined
169+
}
167170
},
168171

169172
fetchQuote: async (
@@ -188,13 +191,7 @@ export const revolutRampPlugin: RampPluginFactory = (
188191
return []
189192
}
190193

191-
// Only support fiat amount type (Revolut requires fiat-based quotes)
192-
if (request.amountType !== 'fiat') {
193-
throw new FiatProviderError({
194-
providerId: pluginId,
195-
errorType: 'amountTypeUnsupported'
196-
})
197-
}
194+
// Amount type check is now handled in checkSupport phase
198195

199196
// Fetch provider configuration (will use cache if valid)
200197
const config = await fetchProviderConfig()

src/plugins/ramps/simplex/simplexRampPlugin.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,10 @@ export const simplexRampPlugin: RampPluginFactory = (
536536
}
537537

538538
// All validations passed
539-
return { supported: true }
539+
return {
540+
supported: true,
541+
supportedAmountTypes: ['fiat', 'crypto']
542+
}
540543
},
541544

542545
fetchQuote: async (

0 commit comments

Comments
 (0)