Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(swap): Allow cancellation of an open order #2683

Merged
merged 104 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
2a13fcb
Use real values in bottom sheet
michaeljscript Sep 11, 2023
038467c
Add basic values
michaeljscript Sep 11, 2023
d938158
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 12, 2023
a571600
Fix strings
michaeljscript Sep 12, 2023
7464eeb
Add logs
michaeljscript Sep 12, 2023
3101165
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 12, 2023
08153f3
Build unsigned tx
michaeljscript Sep 13, 2023
ddb065d
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 13, 2023
e377fad
Fix cbor fetching
michaeljscript Sep 14, 2023
7984bef
Build transaction from cbor
michaeljscript Sep 14, 2023
6c264f0
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 15, 2023
3ca5a39
Fix lint issues
michaeljscript Sep 15, 2023
45ae524
Log tx json
michaeljscript Sep 15, 2023
363c2a8
Update OpenOrders.tsx
michaeljscript Sep 15, 2023
30bb2c7
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 18, 2023
1cabcdd
Fix lint issues
michaeljscript Sep 18, 2023
ce01876
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 19, 2023
417cfce
Fix types after merge
michaeljscript Sep 19, 2023
986c642
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 19, 2023
8d47fc2
feat(analytics): swap remainder events
banklesss Sep 20, 2023
0672b38
CR: update
banklesss Sep 20, 2023
88210ce
Sign tx 2
michaeljscript Sep 21, 2023
287e5c8
Update label
michaeljscript Sep 21, 2023
5e94b7f
Add password modal
michaeljscript Sep 21, 2023
24845c6
Add error handling
michaeljscript Sep 21, 2023
6e65c24
Refactor naming and remove console logs
michaeljscript Sep 21, 2023
f940562
Fix lint
michaeljscript Sep 21, 2023
2a498f7
Remove logs
michaeljscript Sep 21, 2023
8506010
Fix tests
michaeljscript Sep 21, 2023
87033e7
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 21, 2023
ed61de4
Fix lint issues
michaeljscript Sep 21, 2023
65dd990
CR: update
banklesss Sep 22, 2023
24a485d
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 22, 2023
1e74c91
merge base branch
banklesss Sep 22, 2023
cd009a4
Merge branch 'feat/swap-cancel' into feat/swap-remainder-events
banklesss Sep 22, 2023
2aa0a9f
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 23, 2023
062a465
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 23, 2023
98ff10b
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 23, 2023
5f2aed6
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 23, 2023
0b69614
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 23, 2023
fffe681
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 23, 2023
5d1df22
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 23, 2023
5ec2a45
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 23, 2023
d65d800
CR: update
banklesss Sep 23, 2023
bc52f6d
CR: update
banklesss Sep 23, 2023
e8317d5
CR: update
banklesss Sep 23, 2023
b616926
Refactor
michaeljscript Sep 24, 2023
b62e2d4
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 24, 2023
609745a
Update apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/…
stackchain Sep 24, 2023
8be7a4d
Merge branch 'feat/swap-cancel' into feat/swap-remainder-events
stackchain Sep 24, 2023
50fdc3b
CR:update
banklesss Sep 25, 2023
30824ef
feat(analytics): swap remainder events (#2696)
stackchain Sep 25, 2023
7096988
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 25, 2023
7c61ebc
Fix lint issues
michaeljscript Sep 25, 2023
a71dc92
Connect collateral utxo
michaeljscript Sep 25, 2023
e0b1d43
Remove unused import
michaeljscript Sep 25, 2023
a4270a4
refactor utils
michaeljscript Sep 25, 2023
30ece4e
Remove unused imports
michaeljscript Sep 25, 2023
041876f
Fix lint issues
michaeljscript Sep 25, 2023
c807cb3
Add logs and alerts
michaeljscript Sep 25, 2023
aba8eda
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 26, 2023
0a35328
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 26, 2023
bc8563c
Refactor open orders
michaeljscript Sep 26, 2023
2901bc2
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 26, 2023
d345e69
Fix lint issues
michaeljscript Sep 26, 2023
7afc69c
Reset after tx is submitted
michaeljscript Sep 26, 2023
8748fc8
Remove logs and refactor open orders
michaeljscript Sep 26, 2023
a90f152
Fix modal
michaeljscript Sep 26, 2023
f864154
Fix spacing
michaeljscript Sep 26, 2023
729b409
Navigate to submittedTx after tx is signed
michaeljscript Sep 26, 2023
a193422
Revert BottomSheetModal changes
michaeljscript Sep 26, 2023
188fe01
Refactor variables
michaeljscript Sep 26, 2023
611147f
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 26, 2023
e0ba46e
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 26, 2023
893ff88
Refactor password check
michaeljscript Sep 26, 2023
695e57f
Use react-query and suspense
michaeljscript Sep 26, 2023
a5e54bb
Refactor open orders
michaeljscript Sep 26, 2023
274d3b1
Allow multiple signatures
michaeljscript Sep 26, 2023
7d2544d
Refactor derivation paths
michaeljscript Sep 26, 2023
379ba54
Remove unused improt
michaeljscript Sep 26, 2023
f413222
Add fixed tx body
michaeljscript Sep 26, 2023
b632e37
Fix lint issues
michaeljscript Sep 26, 2023
5f3372f
Add getRequiredSignersfn with hardcoded values
michaeljscript Sep 26, 2023
bf2954b
Prepare getRequiredSigners
michaeljscript Sep 26, 2023
9378da9
Fix lint issues
michaeljscript Sep 26, 2023
c9ba71a
Refactor cbor and signers
michaeljscript Sep 26, 2023
5963e97
Add todo
michaeljscript Sep 26, 2023
b98e4a4
Fix lint
michaeljscript Sep 26, 2023
160c110
Compute witnesses dynamically
michaeljscript Sep 26, 2023
7977c19
Fix mock
michaeljscript Sep 26, 2023
27334d1
Use new csl local version
michaeljscript Sep 27, 2023
002bbf2
Fix type issues
michaeljscript Sep 28, 2023
66ce8f6
Update CSL and yoroi lib
michaeljscript Sep 28, 2023
9be5bf3
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 28, 2023
0a5ca9c
add ConfirmWithSpendingPassword
michaeljscript Sep 28, 2023
bd62cd8
Fix error check
michaeljscript Sep 28, 2023
e378df5
CR
michaeljscript Sep 28, 2023
df4c5d8
Refactor signRawTx
michaeljscript Sep 28, 2023
e2f0872
Move signRawTransaction to common folder and remove mock file
michaeljscript Sep 28, 2023
47a8e55
Refactor error check
michaeljscript Sep 28, 2023
0dfc910
Merge branch 'develop' into feat/swap-cancel
michaeljscript Sep 28, 2023
d52b00f
Fix lint issues
michaeljscript Sep 28, 2023
4f7432b
Fix TS issues
michaeljscript Sep 28, 2023
4aad1c2
Update strings
michaeljscript Sep 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/wallet-mobile/.storybook/storybook.requires.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion apps/wallet-mobile/__mocks__/@emurgo/csl-mobile-bridge.js

This file was deleted.

10 changes: 5 additions & 5 deletions apps/wallet-mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@
"@cardano-foundation/ledgerjs-hw-app-cardano": "^6.0.0",
"@emurgo/cip14-js": "^3.0.1",
"@emurgo/cip4-js": "1.0.7",
"@emurgo/cross-csl-core": "^2.9.0",
"@emurgo/cross-csl-mobile": "^2.9.0",
"@emurgo/cross-csl-core": "^3.1.0",
"@emurgo/cross-csl-mobile": "^3.1.0",
"@emurgo/csl-mobile-bridge": "^5.1.2",
"@emurgo/react-native-blockies-svg": "^0.0.2",
"@emurgo/react-native-hid": "^5.15.6",
"@emurgo/yoroi-lib": "^0.8.1",
"@emurgo/yoroi-lib": "^0.9.0",
"@formatjs/intl-datetimeformat": "^6.7.0",
"@formatjs/intl-getcanonicallocales": "^2.1.0",
"@formatjs/intl-locale": "^3.2.1",
Expand Down Expand Up @@ -139,7 +139,7 @@
"add": "2.0.6",
"assert": "^2.0.0",
"base-64": "^1.0.0",
"bignumber.js": "^9.0.0",
"bignumber.js": "^9.0.1",
"bip39": "2.5.0",
"blake2b": "2.1.3",
"bs58": "^4.0.1",
Expand Down Expand Up @@ -212,7 +212,7 @@
"@babel/runtime": "^7.20.0",
"@config-plugins/detox": "^5.0.1",
"@emurgo/cardano-serialization-lib-nodejs": "^9.1.4",
"@emurgo/cross-csl-nodejs": "^2.7.0",
"@emurgo/cross-csl-nodejs": "^3.1.0",
"@formatjs/cli": "^6.1.0",
"@formatjs/ts-transformer": "^3.13.0",
"@react-navigation/devtools": "^6.0.13",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const BottomSheetModal = ({
<BottomSheet
ref={bottomSheetRef}
index={isOpen ? 1 : 0}
contentHeight={900}
snapPoints={snapPoints}
backdropComponent={(props) =>
showBackdropComp === false ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {Resolution} from '@unstoppabledomains/resolution'
import _ from 'lodash'
import React from 'react'
import {Text, View, ViewProps} from 'react-native'
import {useQuery, UseQueryOptions} from 'react-query'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ export const ManageCollateralScreen = () => {
return
}

const primaryTokenBalance = BigNumber(Amounts.getAmount(balances, wallet.primaryToken.identifier).quantity)
const lockedBalance = Quantities.isZero(lockedAmount) ? BigNumber(0) : BigNumber(lockedAmount)
const primaryTokenBalance = new BigNumber(Amounts.getAmount(balances, wallet.primaryToken.identifier).quantity)
const lockedBalance = Quantities.isZero(lockedAmount) ? new BigNumber(0) : new BigNumber(lockedAmount)

if (primaryTokenBalance.minus(lockedBalance).isLessThan(collateralConfig.minLovelace)) {
Alert.alert(
Expand Down
1 change: 1 addition & 0 deletions apps/wallet-mobile/src/features/Swap/SwapNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {ListOrders} from './useCases/StartSwapScreen/ListOrders/ListOrders'
const Tab = createMaterialTopTabNavigator<SwapTabRoutes>()
export const SwapTabNavigator = () => {
const strings = useStrings()

useHideBottomTabBar()

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {storiesOf} from '@storybook/react-native'
import React from 'react'
import {StyleSheet, View} from 'react-native'

import {ConfirmWithSpendingPassword} from './ConfirmWithSpendingPassword'

storiesOf('ConfirmWithSpendingPassword', module)
.addDecorator((story) => <View style={styles.container}>{story()}</View>)
.add('Initial', () => <ConfirmWithSpendingPassword />)
.add('Loading', () => <ConfirmWithSpendingPassword isLoading />)
.add('Error', () => <ConfirmWithSpendingPassword error={new Error('Example error')} />)

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react'
import {ActivityIndicator, StyleSheet, TextInput as RNTextInput, View} from 'react-native'

import {Button, Spacer, Text, TextInput} from '../../../../components'
import {debugWalletInfo, features} from '../../../../features'
import {COLORS} from '../../../../theme'
import {WrongPassword} from '../../../../yoroi-wallets/cardano/errors'
import {useStrings} from '../../common/strings'

type Props = {
onSubmit?: (spendingPassword: string) => void
isLoading?: boolean
error?: Error
}

export const ConfirmWithSpendingPassword = ({onSubmit, isLoading, error}: Props) => {
const spendingPasswordRef = React.useRef<RNTextInput>(null)
const [spendingPassword, setSpendingPassword] = React.useState(
features.prefillWalletInfo ? debugWalletInfo.PASSWORD : '',
)
const strings = useStrings()

return (
<>
<Text style={styles.modalText}>{strings.enterSpendingPassword}</Text>

<TextInput
secureTextEntry
ref={spendingPasswordRef}
enablesReturnKeyAutomatically
placeholder={strings.spendingPassword}
value={spendingPassword}
onChangeText={setSpendingPassword}
autoComplete="off"
/>

{error != null && (
<View>
<Text style={styles.errorMessage} numberOfLines={3}>
{getErrorMessage(error, strings)}
</Text>
</View>
)}

<Spacer fill />

<Button testID="swapButton" shelleyTheme title={strings.sign} onPress={() => onSubmit?.(spendingPassword)} />

{isLoading && (
<View style={styles.loading}>
<ActivityIndicator size="large" color="black" />
</View>
)}
</>
)
}

const getErrorMessage = (error: unknown, strings: Record<'wrongPasswordMessage' | 'error', string>) => {
if (error instanceof WrongPassword) {
return strings.wrongPasswordMessage
}
if (error instanceof Error) {
return error.message
}

return strings.error
}

const styles = StyleSheet.create({
modalText: {
paddingHorizontal: 70,
textAlign: 'center',
paddingBottom: 8,
},
errorMessage: {
color: COLORS.ERROR_TEXT_COLOR,
},
loading: {
position: 'absolute',
height: '100%',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {ConfirmWithSpendingPassword} from './ConfirmWithSpendingPassword'
20 changes: 20 additions & 0 deletions apps/wallet-mobile/src/features/Swap/common/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export const useStrings = () => {
transactionDisplay: intl.formatMessage(messages.transactionDisplay),
seeOnExplorer: intl.formatMessage(messages.seeOnExplorer),
goToOrders: intl.formatMessage(messages.goToOrders),
wrongPasswordMessage: intl.formatMessage(messages.wrongPasswordMessage),
assignCollateral: intl.formatMessage(messages.assignCollateral),
collateralNotFound: intl.formatMessage(messages.collateralNotFound),
noActiveCollateral: intl.formatMessage(messages.noActiveCollateral),
failedTxTitle: intl.formatMessage(messages.failedTxTitle),
failedTxText: intl.formatMessage(messages.failedTxText),
failedTxButton: intl.formatMessage(messages.failedTxButton),
Expand All @@ -110,6 +114,10 @@ export const useStrings = () => {
export const amountInputErrorMessages = defineMessages({})

export const messages = defineMessages({
wrongPasswordMessage: {
id: 'global.actions.dialogs.incorrectPassword.title',
defaultMessage: '!!!Incorrect password.',
},
swapTitle: {
id: 'swap.swapScreen.swapTitle',
defaultMessage: '!!!Swap',
Expand Down Expand Up @@ -462,6 +470,18 @@ export const messages = defineMessages({
id: 'components.send.confirmscreen.confirmButton',
defaultMessage: '!!!Confirm',
},
assignCollateral: {
id: 'components.send.confirmscreen.assignCollateral',
defaultMessage: '!!!Assign collateral',
},
collateralNotFound: {
id: 'components.send.confirmscreen.collateralNotFound',
defaultMessage: '!!!Collateral not found',
},
noActiveCollateral: {
id: 'components.send.confirmscreen.noActiveCollateral',
defaultMessage: "!!!You don't have an active collateral utxo",
},
failedTxTitle: {
id: 'components.send.sendscreen.failedTxTitle',
defaultMessage: '!!!Transaction failed',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import {SafeAreaView} from 'react-native-safe-area-context'

import {BottomSheet, BottomSheetRef, Button, Spacer} from '../../../../components'
import {LoadingOverlay} from '../../../../components/LoadingOverlay'
import {useMetrics} from '../../../../metrics/metricsManager'
import {useSelectedWallet} from '../../../../SelectedWallet'
import {COLORS} from '../../../../theme'
import {useAuthOsWithEasyConfirmation} from '../../../../yoroi-wallets/auth'
import {useSignAndSubmitTx} from '../../../../yoroi-wallets/hooks'
import {useSignAndSubmitTx, useTokenInfo} from '../../../../yoroi-wallets/hooks'
import {useNavigateTo} from '../../common/navigation'
import {useStrings} from '../../common/strings'
import {ConfirmTx} from './ConfirmTx'
Expand All @@ -27,8 +28,17 @@ export const ConfirmTxScreen = () => {
const strings = useStrings()
const wallet = useSelectedWallet()
const navigate = useNavigateTo()
const {track} = useMetrics()

const {unsignedTx} = useSwap()
const {unsignedTx, createOrder} = useSwap()
const sellTokenInfo = useTokenInfo({
wallet,
tokenId: createOrder.amounts.sell.tokenId,
})
const buyTokenInfo = useTokenInfo({
wallet,
tokenId: createOrder.amounts.buy.tokenId,
})

const {authWithOs, isLoading: authenticating} = useAuthOsWithEasyConfirmation(
{id: wallet.id},
Expand All @@ -41,6 +51,22 @@ export const ConfirmTxScreen = () => {
signTx: {useErrorBoundary: true},
submitTx: {
onSuccess: () => {
if (!createOrder.selectedPool) return
track.swapOrderSubmitted({
from_asset: [
{asset_name: sellTokenInfo.name, asset_ticker: sellTokenInfo.ticker, policy_id: sellTokenInfo.group},
],
to_asset: [
{asset_name: buyTokenInfo.name, asset_ticker: buyTokenInfo.ticker, policy_id: buyTokenInfo.group},
],
order_type: createOrder.type,
slippage_tolerance: createOrder.slippage,
from_amount: createOrder.amounts.sell.quantity,
to_amount: createOrder.amounts.buy.quantity,
pool_source: createOrder.selectedPool.provider,
swap_fees: Number(createOrder.selectedPool.fee),
})

navigate.submittedTx()
},
onError: () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import React from 'react'
import {ActivityIndicator, StyleSheet, TextInput as RNTextInput, View} from 'react-native'

import {Button, Spacer, Text, TextInput} from '../../../../components'
import {debugWalletInfo, features} from '../../../../features'
import {COLORS} from '../../../../theme'
import {isEmptyString} from '../../../../utils'
import {WrongPassword} from '../../../../yoroi-wallets/cardano/errors'
import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types'
import {useSignWithPasswordAndSubmitTx} from '../../../../yoroi-wallets/hooks'
import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types'
import {ConfirmWithSpendingPassword} from '../../common/ConfirmWithSpendingPassword'
import {useStrings} from '../../common/strings'

type ErrorData = {
Expand All @@ -24,20 +20,12 @@ type Props = {
}

export const ConfirmTxWithPassword = ({wallet, onSuccess, unsignedTx}: Props) => {
const spendingPasswordRef = React.useRef<RNTextInput>(null)
const [spendingPassword, setSpendingPassword] = React.useState(
features.prefillWalletInfo ? debugWalletInfo.PASSWORD : '',
)
const [errorData, setErrorData] = React.useState<ErrorData>({
errorMessage: '',
errorLogs: '',
})
const strings = useStrings()

React.useEffect(() => {
setErrorData({errorMessage: '', errorLogs: ''})
}, [spendingPassword])

const {signAndSubmitTx, isLoading} = useSignWithPasswordAndSubmitTx(
{wallet}, //
{submitTx: {onSuccess}},
Expand All @@ -50,11 +38,11 @@ export const ConfirmTxWithPassword = ({wallet, onSuccess, unsignedTx}: Props) =>
})
}

const onConfirm = async () => {
const onConfirm = async (password: string) => {
try {
const rootKey = await wallet.encryptedStorage.rootKey.read(spendingPassword)
const rootKey = await wallet.encryptedStorage.rootKey.read(password)
if (rootKey !== undefined) {
signAndSubmitTx({unsignedTx, password: spendingPassword})
signAndSubmitTx({unsignedTx, password})
}
} catch (err) {
if (err instanceof WrongPassword) {
Expand All @@ -71,58 +59,11 @@ export const ConfirmTxWithPassword = ({wallet, onSuccess, unsignedTx}: Props) =>
}
}

const isConfirmationDisabled = !wallet.isEasyConfirmationEnabled && isEmptyString(spendingPassword) && !wallet.isHW

return (
<>
<Text style={styles.modalText}>{strings.enterSpendingPassword}</Text>

<TextInput
secureTextEntry
ref={spendingPasswordRef}
enablesReturnKeyAutomatically
placeholder={strings.spendingPassword}
value={spendingPassword}
onChangeText={setSpendingPassword}
autoComplete="off"
/>

<Text style={styles.error}>{errorData.errorMessage}</Text>

<Spacer fill />

<Button
testID="swapButton"
shelleyTheme
title={strings.sign}
onPress={onConfirm}
disabled={isConfirmationDisabled || isLoading}
/>

{isLoading && (
<View style={styles.loading}>
<ActivityIndicator size="large" color="black" />
</View>
)}
</>
<ConfirmWithSpendingPassword
onSubmit={onConfirm}
isLoading={isLoading}
error={errorData.errorMessage.length > 0 ? new Error(errorData.errorMessage) : undefined}
/>
)
}

const styles = StyleSheet.create({
modalText: {
paddingHorizontal: 70,
textAlign: 'center',
paddingBottom: 8,
},
loading: {
position: 'absolute',
height: '100%',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
},
error: {
color: COLORS.ERROR_TEXT_COLOR,
textAlign: 'center',
},
})
Loading