Skip to content

Commit

Permalink
feat(fiatExchanges): use getCicoQuotes endpoint (#6309)
Browse files Browse the repository at this point in the history
### Description

Replace fetchProviders cloud function call with getCicoQuotes

### Test plan

CI - Unit test assertions have been retained for the most part

Manually by checking providers before and after

### Related issues

- Fixes ACT-1421

### Backwards compatibility

Yes

### Network scalability

N/A
  • Loading branch information
satish-ravi authored Dec 7, 2024
1 parent 71c400a commit 40a4fd2
Show file tree
Hide file tree
Showing 11 changed files with 340 additions and 610 deletions.
101 changes: 49 additions & 52 deletions src/fiatExchanges/PaymentMethodSection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import { getFeatureGate } from 'src/statsig'
import { NetworkId } from 'src/transactions/types'
import { createMockStore } from 'test/utils'
import {
mockCicoQuotes,
mockCusdAddress,
mockCusdTokenId,
mockFiatConnectQuotes,
mockProviderSelectionAnalyticsData,
mockProviders,
} from 'test/values'

const mockStore = createMockStore({
Expand Down Expand Up @@ -61,14 +61,12 @@ describe('PaymentMethodSection', () => {
beforeEach(() => {
props = {
paymentMethod: PaymentMethod.Card,
// the below creates 4 quotes - 1 Ramp (card), 2 Moonpay (bank, card), 1 Simplex (card)
normalizedQuotes: normalizeQuotes(
CICOFlow.CashIn,
[],
mockProviders,
mockCusdTokenId,
'cUSD'
),
normalizedQuotes: normalizeQuotes({
flow: CICOFlow.CashIn,
fiatConnectQuotes: [],
cicoQuotes: mockCicoQuotes,
tokenId: mockCusdTokenId,
}),
flow: CICOFlow.CashIn,
tokenId: mockCusdTokenId,
analyticsData: mockProviderSelectionAnalyticsData,
Expand All @@ -90,13 +88,12 @@ describe('PaymentMethodSection', () => {

it('shows a non-expandable view with receive amount if there is one provider available', async () => {
jest.mocked(getFeatureGate).mockReturnValue(true)
props.normalizedQuotes = normalizeQuotes(
CICOFlow.CashIn,
[],
[mockProviders[2]],
mockCusdTokenId,
'cUSD'
)
props.normalizedQuotes = normalizeQuotes({
flow: CICOFlow.CashIn,
fiatConnectQuotes: [],
cicoQuotes: [mockCicoQuotes[3]],
tokenId: mockCusdTokenId,
})
const { queryByText, queryByTestId } = render(
<Provider store={mockStore}>
<PaymentMethodSection {...props} />
Expand All @@ -111,13 +108,12 @@ describe('PaymentMethodSection', () => {
})

it('shows new info dialog in non expandable section', async () => {
props.normalizedQuotes = normalizeQuotes(
CICOFlow.CashIn,
[],
[mockProviders[2]],
mockCusdTokenId,
'cUSD'
)
props.normalizedQuotes = normalizeQuotes({
flow: CICOFlow.CashIn,
fiatConnectQuotes: [],
cicoQuotes: [mockCicoQuotes[3]],
tokenId: mockCusdTokenId,
})
jest.spyOn(props.normalizedQuotes[0], 'isProviderNew').mockReturnValue(true)
const { getByText, getByTestId } = render(
<Provider store={mockStore}>
Expand Down Expand Up @@ -173,13 +169,12 @@ describe('PaymentMethodSection', () => {
})

it('shows "ID required" when KYC is required', async () => {
props.normalizedQuotes = normalizeQuotes(
CICOFlow.CashIn,
[mockFiatConnectQuotes[3]] as FiatConnectQuoteSuccess[],
[],
mockCusdTokenId,
'cUSD'
)
props.normalizedQuotes = normalizeQuotes({
flow: CICOFlow.CashIn,
fiatConnectQuotes: [mockFiatConnectQuotes[3]] as FiatConnectQuoteSuccess[],
cicoQuotes: [],
tokenId: mockCusdTokenId,
})
props.paymentMethod = PaymentMethod.Bank
const { queryByTestId } = render(
<Provider store={mockStore}>
Expand All @@ -194,13 +189,12 @@ describe('PaymentMethodSection', () => {
})

it('shows no ID requirement when KYC not required', async () => {
props.normalizedQuotes = normalizeQuotes(
CICOFlow.CashIn,
[mockFiatConnectQuotes[1]] as FiatConnectQuoteSuccess[],
[],
mockCusdTokenId,
'cUSD'
)
props.normalizedQuotes = normalizeQuotes({
flow: CICOFlow.CashIn,
fiatConnectQuotes: [mockFiatConnectQuotes[1]] as FiatConnectQuoteSuccess[],
cicoQuotes: [],
tokenId: mockCusdTokenId,
})
props.paymentMethod = PaymentMethod.Bank
const { queryByTestId } = render(
<Provider store={mockStore}>
Expand All @@ -218,31 +212,34 @@ describe('PaymentMethodSection', () => {
it.each([
[
PaymentMethod.Card as const,
normalizeQuotes(CICOFlow.CashIn, [], [mockProviders[2]], mockCusdTokenId, 'cUSD'),
normalizeQuotes({
flow: CICOFlow.CashIn,
fiatConnectQuotes: [],
cicoQuotes: [mockCicoQuotes[3]],
tokenId: mockCusdTokenId,
}),
'card',
'oneHour',
],
[
PaymentMethod.Bank as const,
normalizeQuotes(
CICOFlow.CashIn,
[mockFiatConnectQuotes[1]] as FiatConnectQuoteSuccess[],
[],
mockCusdTokenId,
'cUSD'
),
normalizeQuotes({
flow: CICOFlow.CashIn,
fiatConnectQuotes: [mockFiatConnectQuotes[1]] as FiatConnectQuoteSuccess[],
cicoQuotes: [],
tokenId: mockCusdTokenId,
}),
'bank',
'xToYHours',
],
[
PaymentMethod.FiatConnectMobileMoney as const,
normalizeQuotes(
CICOFlow.CashIn,
[mockFiatConnectQuotes[4]] as FiatConnectQuoteSuccess[],
[],
mockCusdTokenId,
'cUSD'
),
normalizeQuotes({
flow: CICOFlow.CashIn,
fiatConnectQuotes: [mockFiatConnectQuotes[4]] as FiatConnectQuoteSuccess[],
cicoQuotes: [],
tokenId: mockCusdTokenId,
}),
'mobileMoney',
'xHours',
],
Expand Down
38 changes: 18 additions & 20 deletions src/fiatExchanges/SelectProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import {
} from 'src/fiatExchanges/types'
import {
LegacyMobileMoneyProvider,
fetchCicoQuotes,
fetchExchanges,
fetchLegacyMobileMoneyProviders,
fetchProviders,
getProviderSelectionAnalyticsData,
} from 'src/fiatExchanges/utils'
import { LocalCurrencyCode } from 'src/localCurrency/consts'
Expand All @@ -29,10 +29,10 @@ import { CiCoCurrency } from 'src/utils/currencies'
import { createMockStore, getMockStackScreenProps } from 'test/utils'
import {
mockAccount,
mockCicoQuotes,
mockCusdTokenId,
mockExchanges,
mockFiatConnectQuotes,
mockProviders,
} from 'test/values'
import mocked = jest.mocked

Expand All @@ -42,7 +42,7 @@ const FAKE_APP_ID = 'fake app id'

jest.mock('./utils', () => ({
...(jest.requireActual('./utils') as any),
fetchProviders: jest.fn(),
fetchCicoQuotes: jest.fn(),
fetchLegacyMobileMoneyProviders: jest.fn(),
fetchExchanges: jest.fn(),
getProviderSelectionAnalyticsData: jest.fn(),
Expand Down Expand Up @@ -131,26 +131,24 @@ describe(SelectProviderScreen, () => {
jest.mocked(getFeatureGate).mockReturnValue(false)
})

it('calls fetchProviders correctly', async () => {
it('calls fetchCicoQuotes correctly', async () => {
render(
<Provider store={mockStore}>
<SelectProviderScreen {...mockScreenProps()} />
</Provider>
)
await waitFor(() =>
expect(fetchProviders).toHaveBeenCalledWith({
digitalAsset: 'CUSD',
digitalAssetAmount: AMOUNT_TO_CASH_IN,
fiatAmount: AMOUNT_TO_CASH_IN,
expect(fetchCicoQuotes).toHaveBeenCalledWith({
fiatAmount: AMOUNT_TO_CASH_IN.toString(),
fiatCurrency: LocalCurrencyCode.USD,
txType: 'buy',
txType: 'cashIn',
userLocation: {
countryCodeAlpha2: 'MX',
region: null,
ipAddress: MOCK_IP_ADDRESS,
},
walletAddress: mockAccount.toLowerCase(),
networkId: NetworkId['celo-alfajores'],
address: mockAccount.toLowerCase(),
tokenId: mockCusdTokenId,
})
)
})
Expand Down Expand Up @@ -239,7 +237,7 @@ describe(SelectProviderScreen, () => {
})

it('shows the provider sections (bank, card, mobile money, airtime), legacy mobile money, and exchange section', async () => {
jest.mocked(fetchProviders).mockResolvedValue(mockProviders)
jest.mocked(fetchCicoQuotes).mockResolvedValue({ quotes: mockCicoQuotes })
jest.mocked(fetchLegacyMobileMoneyProviders).mockResolvedValue(mockLegacyProviders)
jest.mocked(fetchExchanges).mockResolvedValue(mockExchanges)
mockStore = createMockStore({
Expand Down Expand Up @@ -268,8 +266,8 @@ describe(SelectProviderScreen, () => {
expect(getByText('selectProviderScreen.disclaimer')).toBeTruthy()
})

it('shows you will pay fiat amount for cash ins if feature flag is true', async () => {
jest.mocked(fetchProviders).mockResolvedValue(mockProviders)
it('shows you will pay fiat amount for cash ins', async () => {
jest.mocked(fetchCicoQuotes).mockResolvedValue({ quotes: mockCicoQuotes })
jest.mocked(fetchLegacyMobileMoneyProviders).mockResolvedValue(mockLegacyProviders)
jest.mocked(fetchExchanges).mockResolvedValue(mockExchanges)
jest.mocked(getFeatureGate).mockReturnValue(true)
Expand All @@ -292,8 +290,8 @@ describe(SelectProviderScreen, () => {
expect(getByText(/selectProviderScreen.cashIn.amountSpentInfo/)).toBeTruthy()
expect(getByTestId('AmountSpentInfo/Fiat/value')).toBeTruthy()
})
it('shows you will withdraw crypto amount for cash outs if feature flag is true', async () => {
jest.mocked(fetchProviders).mockResolvedValue(mockProviders)
it('shows you will withdraw crypto amount for cash outs', async () => {
jest.mocked(fetchCicoQuotes).mockResolvedValue({ quotes: mockCicoQuotes })
jest.mocked(fetchLegacyMobileMoneyProviders).mockResolvedValue(mockLegacyProviders)
jest.mocked(fetchExchanges).mockResolvedValue(mockExchanges)
jest.mocked(getFeatureGate).mockReturnValue(true)
Expand All @@ -317,7 +315,7 @@ describe(SelectProviderScreen, () => {
expect(getByTestId('AmountSpentInfo/Crypto')).toBeTruthy()
})
it('shows the limit payment methods dialog when one of the provider types has no options', async () => {
jest.mocked(fetchProviders).mockResolvedValue([mockProviders[2]])
jest.mocked(fetchCicoQuotes).mockResolvedValue({ quotes: [] })
jest.mocked(fetchLegacyMobileMoneyProviders).mockResolvedValue(mockLegacyProviders)
jest.mocked(fetchExchanges).mockResolvedValue(mockExchanges)
const { getByText } = render(
Expand All @@ -330,7 +328,7 @@ describe(SelectProviderScreen, () => {
expect(getByText('selectProviderScreen.disclaimerWithSomePaymentsUnavailable')).toBeTruthy()
})
it('does not show exchange section if no exchanges', async () => {
jest.mocked(fetchProviders).mockResolvedValue(mockProviders)
jest.mocked(fetchCicoQuotes).mockResolvedValue({ quotes: mockCicoQuotes })
jest.mocked(fetchLegacyMobileMoneyProviders).mockResolvedValue(mockLegacyProviders)
jest.mocked(fetchExchanges).mockResolvedValue([])
const { queryByText } = render(
Expand All @@ -344,7 +342,7 @@ describe(SelectProviderScreen, () => {
expect(queryByText('selectProviderScreen.cryptoExchange')).toBeFalsy()
})
it('shows no payment screen when no providers or exchanges are available', async () => {
jest.mocked(fetchProviders).mockResolvedValue([])
jest.mocked(fetchCicoQuotes).mockResolvedValue({ quotes: [] })
jest.mocked(fetchLegacyMobileMoneyProviders).mockResolvedValue([])
jest.mocked(fetchExchanges).mockResolvedValue([])
const { queryByText, getByTestId } = render(
Expand All @@ -364,7 +362,7 @@ describe(SelectProviderScreen, () => {

describe('Exchanges section', () => {
beforeAll(() => {
jest.mocked(fetchProviders).mockResolvedValue([])
jest.mocked(fetchCicoQuotes).mockResolvedValue({ quotes: [] })
jest.mocked(fetchLegacyMobileMoneyProviders).mockResolvedValue([])
jest.mocked(fetchExchanges).mockResolvedValue(mockExchanges)
})
Expand Down
31 changes: 15 additions & 16 deletions src/fiatExchanges/SelectProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ import {
} from 'src/fiatExchanges/types'
import {
LegacyMobileMoneyProvider,
fetchCicoQuotes,
fetchExchanges,
fetchLegacyMobileMoneyProviders,
fetchProviders,
filterLegacyMobileMoneyProviders,
getProviderSelectionAnalyticsData,
} from 'src/fiatExchanges/utils'
Expand Down Expand Up @@ -159,16 +159,15 @@ export default function SelectProviderScreen({ route, navigation }: Props) {
return
}
try {
const [externalProviders, rawLegacyMobileMoneyProviders] = await Promise.all([
fetchProviders({
userLocation,
walletAddress: account,
const [cicoQuotesResponse, rawLegacyMobileMoneyProviders] = await Promise.all([
fetchCicoQuotes({
tokenId,
fiatCurrency: localCurrency,
digitalAsset: tokenInfo.symbol.toUpperCase(),
fiatAmount,
digitalAssetAmount: cryptoAmount,
txType: flow === CICOFlow.CashIn ? 'buy' : 'sell',
networkId: tokenInfo.networkId,
address: account,
userLocation,
...(flow === CICOFlow.CashIn
? { txType: 'cashIn', fiatAmount: fiatAmount.toString() }
: { txType: 'cashOut', cryptoAmount: cryptoAmount.toString() }),
}),
fetchLegacyMobileMoneyProviders(),
])
Expand All @@ -179,7 +178,8 @@ export default function SelectProviderScreen({ route, navigation }: Props) {
userLocation.countryCodeAlpha2,
tokenInfo.tokenId
)
return { externalProviders, legacyMobileMoneyProviders }

return { legacyMobileMoneyProviders, cicoQuotes: cicoQuotesResponse.quotes }
} catch (error) {
dispatch(showError(ErrorMessages.PROVIDER_FETCH_FAILED))
}
Expand All @@ -191,13 +191,12 @@ export default function SelectProviderScreen({ route, navigation }: Props) {
asyncExchanges.loading ||
selectFiatConnectQuoteLoading

const normalizedQuotes = normalizeQuotes(
const normalizedQuotes = normalizeQuotes({
flow,
fiatConnectQuotes,
asyncProviders.result?.externalProviders,
tokenInfo.tokenId,
tokenInfo.symbol
)
cicoQuotes: asyncProviders.result?.cicoQuotes,
tokenId,
})

const exchanges = asyncExchanges.result ?? []
const legacyMobileMoneyProviders = asyncProviders.result?.legacyMobileMoneyProviders
Expand Down
Loading

0 comments on commit 40a4fd2

Please sign in to comment.