Skip to content

Commit

Permalink
fix(swap): Add swap cancellation easy-confirmation support (#2734)
Browse files Browse the repository at this point in the history
  • Loading branch information
stackchain authored Sep 29, 2023
2 parents 99643fd + d1e5339 commit 2a3a423
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 46 deletions.
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.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {storiesOf} from '@storybook/react-native'
import {mockSwapManager, mockSwapStateDefault, SwapProvider} from '@yoroi/swap'
import React from 'react'
import {StyleSheet, View} from 'react-native'

import {SelectedWalletProvider} from '../../../../SelectedWallet'
import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types'
import {mocks as walletMocks} from '../../../../yoroi-wallets/mocks'
import {mocks} from '../mocks'
import {SwapFormProvider} from '../SwapFormProvider'
import {ConfirmRawTx} from './ConfirmRawTx'

storiesOf('ConfirmRawTx', module)
.addDecorator((story) => <View style={styles.container}>{story()}</View>)
.add('ConfirmRawTxWithPassword', () => (
<Provider wallet={walletMocks.wallet}>
<ConfirmRawTx />
</Provider>
))
.add('ConfirmRawTxWithOs', () => (
<Provider wallet={{...walletMocks.wallet, isEasyConfirmationEnabled: true}}>
<ConfirmRawTx />
</Provider>
))
.add('ConfirmRawTxWithHw', () => (
<Provider wallet={{...walletMocks.wallet, isHW: true}}>
<ConfirmRawTx />
</Provider>
))

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
})

const Provider = ({children, wallet}: {children: React.ReactNode; wallet: YoroiWallet}) => {
return (
<SelectedWalletProvider wallet={wallet}>
<SwapProvider
initialState={{
...mockSwapStateDefault,
unsignedTx: walletMocks.yoroiUnsignedTx,
createOrder: {...mocks.confirmTx.createOrder},
}}
swapManager={{
...mockSwapManager,
}}
>
<SwapFormProvider>{children}</SwapFormProvider>
</SwapProvider>
</SelectedWalletProvider>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react'

import {useSelectedWallet} from '../../../../SelectedWallet'
import {ConfirmRawTxWithHW} from './ConfirmRawTxWithHW'
import {ConfirmRawTxWithOs} from './ConfirmRawTxWithOs'
import {ConfirmRawTxWithPassword} from './ConfirmRawTxWithPassword'

export const ConfirmRawTx = ({onConfirm}: {onConfirm?: (rootKey: string) => Promise<void>}) => {
const wallet = useSelectedWallet()

if (wallet.isHW) {
return <ConfirmRawTxWithHW />
}

if (wallet.isEasyConfirmationEnabled) {
return <ConfirmRawTxWithOs onConfirm={onConfirm} />
}

return <ConfirmRawTxWithPassword onConfirm={onConfirm} />
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const ConfirmRawTxWithHW = () => {
// TODO: Needs to be implemented
return null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, {useEffect} from 'react'
import {ActivityIndicator, StyleSheet, Text, View} from 'react-native'

import {useSelectedWallet} from '../../../../SelectedWallet'
import {COLORS} from '../../../../theme'
import {useAuthOsWithEasyConfirmation} from '../../../../yoroi-wallets/auth'

export const ConfirmRawTxWithOs = ({onConfirm}: {onConfirm?: (rootKey: string) => Promise<void>}) => {
const wallet = useSelectedWallet()

const {authWithOs, error} = useAuthOsWithEasyConfirmation(
{id: wallet.id},
{onSuccess: (rootKey) => onConfirm?.(rootKey)},
)

useEffect(() => {
if (!wallet.isEasyConfirmationEnabled) return
authWithOs()
}, [wallet.isEasyConfirmationEnabled, authWithOs])

if (error) {
return (
<View style={styles.center}>
<Text style={styles.errorMessage} numberOfLines={3}>
{error.message}
</Text>
</View>
)
}

return (
<View style={styles.center}>
<ActivityIndicator size="large" color="black" />
</View>
)
}

const styles = StyleSheet.create({
center: {
alignItems: 'center',
justifyContent: 'center',
},
errorMessage: {
color: COLORS.ERROR_TEXT_COLOR,
textAlign: 'center',
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, {useState} from 'react'

import {Spacer} from '../../../../components'
import {useSelectedWallet} from '../../../../SelectedWallet'
import {ConfirmWithSpendingPassword} from '../ConfirmWithSpendingPassword'

export const ConfirmRawTxWithPassword = ({onConfirm}: {onConfirm?: (rootKey: string) => Promise<void>}) => {
const wallet = useSelectedWallet()

const handlePasswordConfirm = async (password: string) => {
const rootKey = await wallet.encryptedStorage.rootKey.read(password)
return onConfirm?.(rootKey)
}

return <PasswordInput onConfirm={handlePasswordConfirm} />
}

const PasswordInput = ({onConfirm}: {onConfirm: (password: string) => Promise<void>}) => {
const [error, setError] = useState<Error | null>(null)
const [loading, setLoading] = useState(false)

const onConfirmPress = async (password: string) => {
setError(null)
setLoading(true)
try {
await onConfirm(password)
} catch (e: unknown) {
if (e instanceof Error) {
setError(e)
}
}
setLoading(false)
}

return (
<>
<ConfirmWithSpendingPassword onSubmit={onConfirmPress} isLoading={loading} error={error ?? undefined} />

<Spacer height={10} />
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ const styles = StyleSheet.create({
},
errorMessage: {
color: COLORS.ERROR_TEXT_COLOR,
textAlign: 'center',
},
loading: {
position: 'absolute',
height: '100%',
width: '100%',
left: 0,
right: 0,
alignItems: 'center',
justifyContent: 'center',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {useFocusEffect} from '@react-navigation/native'
import {useSwap, useSwapOrdersByStatusOpen} from '@yoroi/swap'
import {Buffer} from 'buffer'
import _ from 'lodash'
import React, {Suspense, useState} from 'react'
import React, {Suspense} from 'react'
import {useIntl} from 'react-intl'
import {ActivityIndicator, Alert, Linking, ScrollView, StyleSheet, TouchableOpacity, View} from 'react-native'

Expand All @@ -29,7 +29,7 @@ import {useSelectedWallet} from '../../../../../SelectedWallet'
import {COLORS} from '../../../../../theme'
import {createRawTxSigningKey, generateCIP30UtxoCbor} from '../../../../../yoroi-wallets/cardano/utils'
import {useTokenInfos, useTransactionInfos} from '../../../../../yoroi-wallets/hooks'
import {ConfirmWithSpendingPassword} from '../../../common/ConfirmWithSpendingPassword'
import {ConfirmRawTx} from '../../../common/ConfirmRawTx/ConfirmRawTx'
import {Counter} from '../../../common/Counter/Counter'
import {useNavigateTo} from '../../../common/navigation'
import {PoolIcon} from '../../../common/PoolIcon/PoolIcon'
Expand Down Expand Up @@ -107,10 +107,10 @@ export const OpenOrders = () => {
})
}

const handlePasswordConfirm = async (password: string, orderId: string) => {
const onRawTxConfirm = async (rootKey: string, orderId: string) => {
const order = normalizedOrders.find((o) => o.id === orderId)
if (!order || order.owner === undefined || order.utxo === undefined) return
const tx = await createCancellationTxAndSign(order.id, password)
const tx = await createCancellationTxAndSign(order.id, rootKey)
if (!tx) return
await wallet.submitTransaction(tx.txBase64)
trackCancellationSubmitted(order)
Expand All @@ -122,7 +122,7 @@ export const OpenOrders = () => {
setBottomSheetState({
openId: id,
title: strings.signTransaction,
content: wallet.isHW ? null : <PasswordModal onConfirm={(password) => handlePasswordConfirm(password, id)} />,
content: <ConfirmRawTx onConfirm={(rootKey) => onRawTxConfirm(rootKey, id)} />,
height: 350,
})
}
Expand All @@ -146,7 +146,7 @@ export const OpenOrders = () => {

const createCancellationTxAndSign = async (
orderId: string,
password: string,
rootKey: string,
): Promise<{txBase64: string} | undefined> => {
const order = normalizedOrders.find((o) => o.id === orderId)
if (!order || order.owner === undefined || order.utxo === undefined) return
Expand All @@ -157,7 +157,6 @@ export const OpenOrders = () => {
utxos: {collateral: collateralUtxo, order: utxo},
address: addressHex,
})
const rootKey = await wallet.encryptedStorage.rootKey.read(password)
const {cbor, signers} = await getMuesliSwapTransactionAndSigners(originalCbor, wallet)

const keys = await Promise.all(signers.map(async (signer) => createRawTxSigningKey(rootKey, signer)))
Expand Down Expand Up @@ -369,32 +368,6 @@ const HiddenInfo = ({
)
}

const PasswordModal = ({onConfirm}: {onConfirm: (password: string) => Promise<void>}) => {
const [error, setError] = useState<Error | null>(null)
const [loading, setLoading] = useState(false)

const onConfirmPress = async (password) => {
setError(null)
setLoading(true)
try {
await onConfirm(password)
} catch (e: unknown) {
if (e instanceof Error) {
setError(e)
}
}
setLoading(false)
}

return (
<>
<ConfirmWithSpendingPassword onSubmit={onConfirmPress} isLoading={loading} error={error ?? undefined} />

<Spacer height={10} />
</>
)
}

const MainInfo = ({tokenPrice, tokenAmount}: {tokenPrice: string; tokenAmount: string}) => {
const strings = useStrings()
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,44 @@
"defaultMessage": "!!!Authorize",
"file": "src/yoroi-wallets/auth/auth.ts",
"start": {
"line": 254,
"line": 255,
"column": 13,
"index": 8406
"index": 8429
},
"end": {
"line": 257,
"line": 258,
"column": 3,
"index": 8513
"index": 8536
}
},
{
"id": "components.send.biometricauthscreen.SENSOR_LOCKOUT",
"defaultMessage": "!!!Too many attempts",
"file": "src/yoroi-wallets/auth/auth.ts",
"start": {
"line": 258,
"line": 259,
"column": 19,
"index": 8534
"index": 8557
},
"end": {
"line": 261,
"line": 262,
"column": 3,
"index": 8645
"index": 8668
}
},
{
"id": "components.send.biometricauthscreen.UNKNOWN_ERROR",
"defaultMessage": "!!!Unknown error!",
"file": "src/yoroi-wallets/auth/auth.ts",
"start": {
"line": 262,
"line": 263,
"column": 16,
"index": 8663
"index": 8686
},
"end": {
"line": 265,
"line": 266,
"column": 3,
"index": 8770
"index": 8793
}
}
]

0 comments on commit 2a3a423

Please sign in to comment.