Skip to content

Commit

Permalink
Merge branch 'develop' into swap/complete-orders
Browse files Browse the repository at this point in the history
  • Loading branch information
SorinC6 committed Oct 11, 2023
2 parents 956eb54 + 8967f20 commit fb8bd58
Show file tree
Hide file tree
Showing 28 changed files with 1,403 additions and 1,174 deletions.
6 changes: 3 additions & 3 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.

2 changes: 1 addition & 1 deletion apps/wallet-mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
"@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.9.8",
"@emurgo/yoroi-lib": "^0.10.1",
"@formatjs/intl-datetimeformat": "^6.7.0",
"@formatjs/intl-getcanonicallocales": "^2.1.0",
"@formatjs/intl-locale": "^3.2.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ import {ConfirmRawTxWithHW} from './ConfirmRawTxWithHW'
import {ConfirmRawTxWithOs} from './ConfirmRawTxWithOs'
import {ConfirmRawTxWithPassword} from './ConfirmRawTxWithPassword'

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

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

if (wallet.isEasyConfirmationEnabled) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,57 @@
export const ConfirmRawTxWithHW = () => {
// TODO: Needs to be implemented
return null
import React, {useState} from 'react'
import {ActivityIndicator, ScrollView} from 'react-native'

import {LedgerConnect} from '../../../../HW'
import {useSelectedWallet} from '../../../../SelectedWallet'
import {DeviceId, DeviceObj, withBLE, withUSB} from '../../../../yoroi-wallets/hw'
import {walletManager} from '../../../../yoroi-wallets/walletManager'
import {LedgerTransportSwitch} from '../../useCases/ConfirmTxScreen/LedgerTransportSwitch'

type TransportType = 'USB' | 'BLE'
type Step = 'select-transport' | 'connect-transport' | 'loading'

type Props = {
onConfirm?: (options: {useUSB: boolean}) => void
}

export const ConfirmRawTxWithHW = ({onConfirm}: Props) => {
const [transportType, setTransportType] = useState<TransportType>('USB')
const [step, setStep] = useState<Step>('select-transport')
const wallet = useSelectedWallet()

const onSelectTransport = (transportType: TransportType) => {
setTransportType(transportType)
setStep('connect-transport')
}

const onConnectBLE = async (deviceId: DeviceId) => {
await walletManager.updateHWDeviceInfo(wallet, withBLE(wallet, deviceId))
onConfirm?.({useUSB: false})
setStep('loading')
}

const onConnectUSB = async (deviceObj: DeviceObj) => {
await walletManager.updateHWDeviceInfo(wallet, withUSB(wallet, deviceObj))
onConfirm?.({useUSB: true})
setStep('loading')
}

if (step === 'select-transport') {
return (
<LedgerTransportSwitch
onSelectBLE={() => onSelectTransport('BLE')}
onSelectUSB={() => onSelectTransport('USB')}
/>
)
}

if (step === 'connect-transport') {
return (
<ScrollView>
<LedgerConnect useUSB={transportType === 'USB'} onConnectBLE={onConnectBLE} onConnectUSB={onConnectUSB} />
</ScrollView>
)
}

return <ActivityIndicator size="large" color="black" />
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import {getPairPriceInPtTerms, useSwap} from '@yoroi/swap'
import {Balance, Swap} from '@yoroi/types'
import {useSwap} from '@yoroi/swap'
import {Swap} from '@yoroi/types'
import React, {useState} from 'react'
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import LinearGradient from 'react-native-linear-gradient'

import {Boundary, Spacer} from '../../../../../components'
import {Spacer} from '../../../../../components'
import {useMetrics} from '../../../../../metrics/metricsManager'
import {useSelectedWallet} from '../../../../../SelectedWallet'
import {COLORS} from '../../../../../theme'
import {YoroiWallet} from '../../../../../yoroi-wallets/cardano/types'
import {useTokenInfo} from '../../../../../yoroi-wallets/hooks'
import {Quantities} from '../../../../../yoroi-wallets/utils'
import {useNavigateTo} from '../../navigation'
import {PoolIcon} from '../../PoolIcon/PoolIcon'
import {useStrings} from '../../strings'
import {useSwapTouched} from '../../SwapFormProvider'

const PRECISION = 14

type Props = {
pools?: ReadonlyArray<Swap.Pool>
}
Expand All @@ -28,6 +29,10 @@ export const SelectPoolFromList = ({pools = []}: Props) => {
const navigate = useNavigateTo()
const {track} = useMetrics()

const sellTokenInfo = useTokenInfo({wallet, tokenId: orderData.amounts.sell.tokenId})
const buyTokenInfo = useTokenInfo({wallet, tokenId: orderData.amounts.buy.tokenId})
const denomination = (sellTokenInfo.decimals ?? 0) - (buyTokenInfo.decimals ?? 0)

const handleOnPoolSelection = (pool: Swap.Pool) => {
track.swapPoolChanged()
selectedPoolChanged(pool.poolId)
Expand Down Expand Up @@ -69,9 +74,17 @@ export const SelectPoolFromList = ({pools = []}: Props) => {
<View>
<Spacer height={8} />

<Boundary>
<PriceInAda pool={pool} wallet={wallet} sell={orderData.amounts.sell} />
</Boundary>
<View style={styles.info}>
<Text style={styles.infoLabel}>{strings.price}</Text>

<Text style={styles.infoValue}>
{Quantities.format(
orderData.selectedPoolCalculation?.prices.market ?? Quantities.zero,
denomination,
PRECISION,
)}
</Text>
</View>
</View>

<View>
Expand Down Expand Up @@ -116,32 +129,6 @@ export const SelectPoolFromList = ({pools = []}: Props) => {
)
}

type PriceInAdaProps = {pool: Swap.Pool; wallet: YoroiWallet; sell: Balance.Amount}
const PriceInAda = ({pool, wallet, sell}: PriceInAdaProps) => {
const strings = useStrings()
const {ptPriceTokenA, ptPriceTokenB, tokenA, tokenB} = pool

const {decimals: decimalsA = 0} = useTokenInfo({wallet, tokenId: tokenA.tokenId})
const {decimals: decimalsB = 0} = useTokenInfo({wallet, tokenId: tokenB.tokenId})

const {ptPriceAB} = getPairPriceInPtTerms({
amountA: tokenA,
decimalsA,
decimalsB,
ptPriceTokenA,
ptPriceTokenB,
sell,
})

return (
<View style={styles.info}>
<Text style={styles.infoLabel}>{strings.price}</Text>

<Text style={styles.infoValue}>{ptPriceAB}</Text>
</View>
)
}

const styles = StyleSheet.create({
container: {
paddingHorizontal: 16,
Expand Down
1 change: 0 additions & 1 deletion apps/wallet-mobile/src/features/Swap/common/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {Swap} from '@yoroi/types'
import {YoroiWallet} from '../../../yoroi-wallets/cardano/types'
import {YoroiEntry} from '../../../yoroi-wallets/types'
import {Quantities} from '../../../yoroi-wallets/utils'

export const createYoroiEntry = (
createOrder: Swap.CreateOrderData,
address: string,
Expand Down
3 changes: 2 additions & 1 deletion apps/wallet-mobile/src/features/Swap/common/strings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {defineMessages, useIntl} from 'react-intl'

import globalMessages, {errorMessages} from '../../../i18n/global-messages'
import globalMessages, {errorMessages, ledgerMessages} from '../../../i18n/global-messages'

export const useStrings = () => {
const intl = useIntl()
Expand Down Expand Up @@ -91,6 +91,7 @@ export const useStrings = () => {
limitPriceWarningBack: intl.formatMessage(messages.limitPriceWarningBack),
limitPriceWarningConfirm: intl.formatMessage(messages.limitPriceWarningConfirm),
error: intl.formatMessage(globalMessages.error),
rejectedByUser: intl.formatMessage(ledgerMessages.rejectedByUserError),
usbExplanation: intl.formatMessage(messages.usbExplanation),
usbButton: intl.formatMessage(messages.usbButton),
usbConnectionIsBlocked: intl.formatMessage(messages.usbConnectionIsBlocked),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {useStrings} from '../../../common/strings'
import {useSwapTouched} from '../../../common/SwapFormProvider'

const BORDER_SIZE = 1
const PRECISION = 10
const PRECISION = 14

export const EditLimitPrice = () => {
const strings = useStrings()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,19 @@ import {useWalletNavigation} from '../../../../../navigation'
import {useSearch} from '../../../../../Search/SearchContext'
import {useSelectedWallet} from '../../../../../SelectedWallet'
import {COLORS} from '../../../../../theme'
import {
convertBech32ToHex,
getMuesliSwapTransactionAndSigners,
} from '../../../../../yoroi-wallets/cardano/common/signatureUtils'
import {createRawTxSigningKey, generateCIP30UtxoCbor} from '../../../../../yoroi-wallets/cardano/utils'
import {useTokenInfos, useTransactionInfos} from '../../../../../yoroi-wallets/hooks'
import {RejectedByUserError} from '../../../../../yoroi-wallets/hw'
import {ConfirmRawTx} from '../../../common/ConfirmRawTx/ConfirmRawTx'
import {Counter} from '../../../common/Counter/Counter'
import {useNavigateTo} from '../../../common/navigation'
import {PoolIcon} from '../../../common/PoolIcon/PoolIcon'
import {useStrings} from '../../../common/strings'
import {convertBech32ToHex, getMuesliSwapTransactionAndSigners, useCancellationOrderFee} from './helpers'
import {mapOpenOrders, MappedOpenOrder} from './mapOrders'
import {useCancellationOrderFee} from './helpers'
import {mapOrders, MappedOrder} from './mapOrders'

export const OpenOrders = () => {
const [bottomSheetState, setBottomSheetState] = React.useState<BottomSheetState & {height: number}>({
Expand All @@ -49,7 +53,7 @@ export const OpenOrders = () => {
const intl = useIntl()
const wallet = useSelectedWallet()
const {order: swapApiOrder} = useSwap()
const {navigateToCollateralSettings} = useWalletNavigation()
const {navigateToCollateralSettings, navigateToTxHistory} = useWalletNavigation()

const bottomSheetRef = React.useRef<null | BottomSheetRef>(null)
const orders = useSwapOrdersByStatusOpen()
Expand All @@ -58,12 +62,11 @@ export const OpenOrders = () => {
const transactionsInfos = useTransactionInfos(wallet)
const tokenInfos = useTokenInfos({wallet, tokenIds})
const normalizedOrders = React.useMemo(
() => mapOpenOrders(orders, tokenInfos, numberLocale, Object.values(transactionsInfos)),
() => mapOrders(orders, tokenInfos, numberLocale, Object.values(transactionsInfos)),
[orders, tokenInfos, numberLocale, transactionsInfos],
)

const {search} = useSearch()
const swapNavigation = useNavigateTo()

const filteredOrders = React.useMemo(
() =>
Expand All @@ -85,7 +88,7 @@ export const OpenOrders = () => {
}, [track]),
)

const trackCancellationSubmitted = (order: MappedOpenOrder) => {
const trackCancellationSubmitted = (order: MappedOrder) => {
track.swapCancelationSubmitted({
from_amount: Number(order.from.quantity) ?? 0,
to_amount: Number(order.to.quantity) ?? 0,
Expand Down Expand Up @@ -115,15 +118,50 @@ export const OpenOrders = () => {
await wallet.submitTransaction(tx.txBase64)
trackCancellationSubmitted(order)
closeBottomSheet()
swapNavigation.submittedTx()
navigateToTxHistory()
}

const onRawTxHwConfirm = async ({useUSB, orderId}: {useUSB: boolean; orderId: string}) => {
try {
const order = normalizedOrders.find((o) => o.id === orderId)
if (!order || order.owner === undefined || order.utxo === undefined) return

Check failure on line 127 in apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/ListOrders/OpenOrders.tsx

View workflow job for this annotation

GitHub Actions / check

Unexpected any value in conditional. An explicit comparison or type cast is required
const {utxo, owner: bech32Address} = order
const collateralUtxo = await getCollateralUtxo()
const addressHex = await convertBech32ToHex(bech32Address)
const originalCbor = await swapApiOrder.cancel({
utxos: {collateral: collateralUtxo, order: utxo},
address: addressHex,
})
const {cbor} = await getMuesliSwapTransactionAndSigners(originalCbor, wallet)
await wallet.signSwapCancellationWithLedger(cbor, useUSB)

closeBottomSheet()
navigateToTxHistory()
} catch (e) {
if (e instanceof RejectedByUserError) {
Alert.alert(strings.error, strings.rejectedByUser)
closeBottomSheet()
return
}

if (e instanceof Error) {
Alert.alert(strings.error, e.message)
closeBottomSheet()
}
}
}

const onOrderCancelConfirm = (id: string) => {
setBottomSheetState({
openId: id,
title: strings.signTransaction,
content: <ConfirmRawTx onConfirm={(rootKey) => onRawTxConfirm(rootKey, id)} />,
height: 350,
content: (
<ConfirmRawTx
onConfirm={(rootKey) => onRawTxConfirm(rootKey, id)}
onHWConfirm={({useUSB}) => onRawTxHwConfirm({useUSB, orderId: id})}
/>
),
height: 400,
})
}

Expand Down Expand Up @@ -166,7 +204,7 @@ export const OpenOrders = () => {
return {txBase64: hexBase64}
}

const openBottomSheet = async (order: MappedOpenOrder) => {
const openBottomSheet = async (order: MappedOrder) => {
if (order.owner === undefined || order.utxo === undefined) return
const {
utxo,
Expand Down Expand Up @@ -696,4 +734,4 @@ const styles = StyleSheet.create({
alignSelf: 'stretch',
paddingHorizontal: 16,
},
})
})
Loading

0 comments on commit fb8bd58

Please sign in to comment.