From a64a631d0de2b659cf657d8c787b6486bb3f9db1 Mon Sep 17 00:00:00 2001 From: Nouman Tahir Date: Wed, 9 Aug 2023 17:34:33 +0500 Subject: [PATCH 1/6] entry for order cancellation --- src/providers/hive-trade/hiveTrade.ts | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/providers/hive-trade/hiveTrade.ts b/src/providers/hive-trade/hiveTrade.ts index 073b670df4..c0aaefc0f6 100644 --- a/src/providers/hive-trade/hiveTrade.ts +++ b/src/providers/hive-trade/hiveTrade.ts @@ -70,6 +70,51 @@ export const limitOrderCreate = ( ); }; + +export const limitOrderCancel = ( + currentAccount: any, + pinHash:string, + orderid: number +) => { + + const digitPinCode = getDigitPinCode(pinHash); + const key = getAnyPrivateKey( + { + activeKey: currentAccount?.local?.activeKey, + }, + digitPinCode, + ); + + if (key) { + const privateKey = PrivateKey.fromString(key); + const ops:Operation[] = [ + [ + "limit_order_cancel", + { + owner: currentAccount.username, + orderid: orderid + } + ], + ]; + + return new Promise((resolve, reject) => { + sendHiveOperations(ops, privateKey) + .then((result) => { + resolve(result); + }) + .catch((err) => { + reject(err); + }); + }); + } + + return Promise.reject( + new Error('Check private key permission! Required private active key or above.'), + ); +}; + + + export const generateHsLimitOrderCreatePath = ( currentAccount: any, amountToSell: number, From e7257c37a0b968745549c915f64b9a5383362233 Mon Sep 17 00:00:00 2001 From: Nouman Tahir Date: Wed, 9 Aug 2023 18:30:31 +0500 Subject: [PATCH 2/6] cancel button support for transaction item --- .../walletLineItem/walletLineItemStyles.js | 3 ++ ...LineItemView.js => walletLineItemView.tsx} | 32 +++++++++++++++---- src/components/transaction/transactionView.js | 6 +++- 3 files changed, 34 insertions(+), 7 deletions(-) rename src/components/basicUIElements/view/walletLineItem/{walletLineItemView.js => walletLineItemView.tsx} (82%) diff --git a/src/components/basicUIElements/view/walletLineItem/walletLineItemStyles.js b/src/components/basicUIElements/view/walletLineItem/walletLineItemStyles.js index 2ae1e6cb66..81b7b06d1e 100644 --- a/src/components/basicUIElements/view/walletLineItem/walletLineItemStyles.js +++ b/src/components/basicUIElements/view/walletLineItem/walletLineItemStyles.js @@ -80,6 +80,9 @@ export default EStyleSheet.create({ justifyContent: 'center', alignSelf: 'center', }, + cancelIcon:{ + marginLeft:8, + }, dropdownWrapper: { flex: 1, }, diff --git a/src/components/basicUIElements/view/walletLineItem/walletLineItemView.js b/src/components/basicUIElements/view/walletLineItem/walletLineItemView.tsx similarity index 82% rename from src/components/basicUIElements/view/walletLineItem/walletLineItemView.js rename to src/components/basicUIElements/view/walletLineItem/walletLineItemView.tsx index ee820466ba..7010df54ac 100644 --- a/src/components/basicUIElements/view/walletLineItem/walletLineItemView.js +++ b/src/components/basicUIElements/view/walletLineItem/walletLineItemView.tsx @@ -3,7 +3,7 @@ import { View, Text, TouchableOpacity } from 'react-native'; import EStyleSheet from 'react-native-extended-stylesheet'; // Components -import { DropdownButton, PopoverWrapper, Icon, GrayWrapper } from '../../..'; +import { DropdownButton, PopoverWrapper, Icon, GrayWrapper, IconButton } from '../../..'; // Styles import styles from './walletLineItemStyles'; @@ -29,6 +29,9 @@ const WalletLineItem = ({ hintIconName, hintDescription, onPress, + cancelable, + cancelling, + onCancelPress, }) => ( @@ -40,11 +43,10 @@ const WalletLineItem = ({ styles.iconWrapper, isCircleIcon && styles.circleIcon, index && { - backgroundColor: `${ - index && index % 2 !== 0 - ? EStyleSheet.value('$white') - : EStyleSheet.value('$primaryLightBackground') - }`, + backgroundColor: `${index && index % 2 !== 0 + ? EStyleSheet.value('$white') + : EStyleSheet.value('$primaryLightBackground') + }`, }, ]} > @@ -76,6 +78,9 @@ const WalletLineItem = ({ /> )} + + + )} {!!description && ( @@ -83,6 +88,7 @@ const WalletLineItem = ({ )} + {!!rightText && ( )} + + {!!cancelable && ( {onCancelPress && onCancelPress()}} + color="#c1c5c7" + isLoading={cancelling} + /> + )} + + {isHasdropdown && ( { +const TransactionView = ({ item, index, cancelling, onCancelPress}) => { const intl = useIntl(); const [collapsed, setCollapsed] = useState(true); @@ -42,6 +42,10 @@ const TransactionView = ({ item, index }) => { onPress={() => { setCollapsed(!collapsed); }} + cancelable={item.cancelable} + cancelling={cancelling} + onCancelPress={onCancelPress} + /> ); From ff86b5b784214ca5c44577bb8ec0050c779776c2 Mon Sep 17 00:00:00 2001 From: Nouman Tahir Date: Wed, 9 Aug 2023 18:52:09 +0500 Subject: [PATCH 3/6] end to end open order cancel enabled --- src/redux/reducers/walletReducer.ts | 1 + .../assetDetails/children/activitiesList.tsx | 30 +++++++++++++++++-- src/screens/trade/screen/tradeScreen.tsx | 4 +++ src/utils/wallet.ts | 3 ++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/redux/reducers/walletReducer.ts b/src/redux/reducers/walletReducer.ts index 5d53f99a07..664a3cb59a 100644 --- a/src/redux/reducers/walletReducer.ts +++ b/src/redux/reducers/walletReducer.ts @@ -57,6 +57,7 @@ export interface CoinActivity { value: string; details: string | null; memo: string; + cancelable: boolean; } export interface QuoteItem { diff --git a/src/screens/assetDetails/children/activitiesList.tsx b/src/screens/assetDetails/children/activitiesList.tsx index a77a7f35a6..fd5c8ffd8b 100644 --- a/src/screens/assetDetails/children/activitiesList.tsx +++ b/src/screens/assetDetails/children/activitiesList.tsx @@ -1,4 +1,4 @@ -import React, { ComponentType, JSXElementConstructor, ReactElement } from 'react'; +import React, { ComponentType, JSXElementConstructor, ReactElement, useState } from 'react'; import { useIntl } from 'react-intl'; import { SectionList, Text, RefreshControl, ActivityIndicator } from 'react-native'; import EStyleSheet from 'react-native-extended-stylesheet'; @@ -6,6 +6,10 @@ import { Transaction } from '../../../components'; import { useAppSelector } from '../../../hooks'; import { CoinActivity } from '../../../redux/reducers/walletReducer'; import styles from './children.styles'; +import { limitOrderCancel } from '../../../providers/hive-trade/hiveTrade'; +import { walletQueries } from '../../../providers/queries'; +import { useQueryClient } from '@tanstack/react-query'; +import QUERIES from '../../../providers/queries/queryKeys'; interface ActivitiesListProps { header: ComponentType | ReactElement>; @@ -30,10 +34,32 @@ const ActivitiesList = ({ }: ActivitiesListProps) => { const intl = useIntl(); + const queryClient = useQueryClient(); const isDarkTheme = useAppSelector((state) => state.ui.isDarkTheme); + const currentAccount = useAppSelector((state) => state.account.currentAccount ); + const pinHash = useAppSelector((state) => state.application.pin); + + const [cancellingTrxIndex, setCancellingTrxIndex] = useState(-1); + + + const _onCancelPress = async (trxId:number) => { + try{ + if(trxId){ + setCancellingTrxIndex(trxId); + await limitOrderCancel(currentAccount, pinHash, trxId); + queryClient.invalidateQueries([QUERIES.WALLET.GET_PENDING_REQUESTS]); + setCancellingTrxIndex(-1); + } + } catch(err){ + setCancellingTrxIndex(-1); + } + + + } const _renderActivityItem = ({ item, index }) => { - return ; + + return {_onCancelPress(item.trxIndex)}}/>; }; const sections = []; diff --git a/src/screens/trade/screen/tradeScreen.tsx b/src/screens/trade/screen/tradeScreen.tsx index 992d1e220c..6e0d3b3b86 100644 --- a/src/screens/trade/screen/tradeScreen.tsx +++ b/src/screens/trade/screen/tradeScreen.tsx @@ -11,10 +11,13 @@ import TransferTypes from '../../../constants/transferTypes'; import { hsOptions } from '../../../constants/hsOptions'; import { walletQueries } from '../../../providers/queries'; import { delay } from '../../../utils/editor'; +import { useQueryClient } from '@tanstack/react-query'; +import QUERIES from '../../../providers/queries/queryKeys'; const TradeScreen = ({ route, navigation }) => { const intl = useIntl(); + const queryClient = useQueryClient(); const assetsQuery = walletQueries.useAssetsQuery(); const transferType = route?.params?.transferType; @@ -39,6 +42,7 @@ const TradeScreen = ({ route, navigation }) => { const _onSuccess = () => { _delayedRefreshCoinsData(); + queryClient.invalidateQueries([QUERIES.WALLET.GET_PENDING_REQUESTS]); }; const _handleHsTransfer = (_hsSignPath: string) => { diff --git a/src/utils/wallet.ts b/src/utils/wallet.ts index 3e5c930bef..d9223755aa 100644 --- a/src/utils/wallet.ts +++ b/src/utils/wallet.ts @@ -413,7 +413,9 @@ export const fetchPendingRequests = async ( .filter((request) => request.sell_price.base.includes(coinSymbol)) .map((request) => { const { base, quote } = request?.sell_price || {}; + const orderid = request.orderid return { + trxIndex: orderid, iconType: 'MaterialIcons', textKey: 'open_order', expires: request.expiration, @@ -421,6 +423,7 @@ export const fetchPendingRequests = async ( icon: 'reorder', value: base || '-- --', details: base && quote ? `@ ${base} = ${quote}` : '', + cancelable: true, } as CoinActivity; }); From a01c284e1c87147ce2045283b4e7881546e63964 Mon Sep 17 00:00:00 2001 From: Nouman Tahir Date: Wed, 9 Aug 2023 19:24:42 +0500 Subject: [PATCH 4/6] added dummy message if pending requests are detected after swap --- .../trade/children/swapTokenContent.tsx | 28 +++++++++++++------ src/screens/trade/screen/tradeScreen.tsx | 4 --- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/screens/trade/children/swapTokenContent.tsx b/src/screens/trade/children/swapTokenContent.tsx index a400abebf6..3760d37d2c 100644 --- a/src/screens/trade/children/swapTokenContent.tsx +++ b/src/screens/trade/children/swapTokenContent.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { View, Text, Alert, RefreshControl } from 'react-native'; import { useIntl } from 'react-intl'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; @@ -32,8 +32,6 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: const dispatch = useAppDispatch(); const navigation = useNavigation(); - // queres - const assetsQuery = walletQueries.useAssetsQuery(); const currentAccount = useAppSelector((state) => state.account.currentAccount); const currency = useAppSelector((state) => state.application.currency); @@ -55,6 +53,15 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: [fromAssetSymbol], ); + const _fromAssetId = fromAssetSymbol === MarketAsset.HBD ? ASSET_IDS.HBD : ASSET_IDS.HIVE; + const _toAssetId = _toAssetSymbol === MarketAsset.HBD ? ASSET_IDS.HBD : ASSET_IDS.HIVE; + + + // queres + const assetsQuery = walletQueries.useAssetsQuery(); + const pendingRequestsQuery = walletQueries.usePendingRequestsQuery(_fromAssetId); + + // this method makes sure amount is only updated when new order book is fetched after asset change // this avoid wrong from and to swap value on changing source asset const _onAssetChangeComplete = () => { @@ -83,12 +90,11 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: }, [tooMuchSlippage, offerUnavailable, isMoreThanBalance]); // accumulate asset data properties - const _fromAssetData = - assetsData[fromAssetSymbol === MarketAsset.HBD ? ASSET_IDS.HBD : ASSET_IDS.HIVE]; + const _fromAssetData = assetsData[_fromAssetId]; const _balance = _fromAssetData.balance; const _fromFiatPrice = _fromAssetData.currentPrice; const _toFiatPrice = - assetsData[_toAssetSymbol === MarketAsset.HBD ? ASSET_IDS.HBD : ASSET_IDS.HIVE].currentPrice; + assetsData[_toAssetId].currentPrice; const _marketFiatPrice = marketPrice * _toFiatPrice; const _toAmountStr = toAmount.toFixed(3); @@ -124,7 +130,7 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: setFromAmount('0'); }; - const _onSwapSuccess = () => { + const _onSwapSuccess = async (hasPending:boolean) => { const headerContent = ( navigation.goBack() }, @@ -173,9 +180,14 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: await swapToken(currentAccount, pinHash, data); + await delay(1000); + const _existingPedingCount = pendingRequestsQuery.data?.length || 0; + const pendingRequests = await pendingRequestsQuery.refetch(); + const _hasPending = pendingRequests.data?.length !== _existingPedingCount; + onSuccess(); setSwapping(false); - _onSwapSuccess(); + _onSwapSuccess(_hasPending); } catch (err) { Alert.alert('fail', err.message); setSwapping(false); diff --git a/src/screens/trade/screen/tradeScreen.tsx b/src/screens/trade/screen/tradeScreen.tsx index 6e0d3b3b86..992d1e220c 100644 --- a/src/screens/trade/screen/tradeScreen.tsx +++ b/src/screens/trade/screen/tradeScreen.tsx @@ -11,13 +11,10 @@ import TransferTypes from '../../../constants/transferTypes'; import { hsOptions } from '../../../constants/hsOptions'; import { walletQueries } from '../../../providers/queries'; import { delay } from '../../../utils/editor'; -import { useQueryClient } from '@tanstack/react-query'; -import QUERIES from '../../../providers/queries/queryKeys'; const TradeScreen = ({ route, navigation }) => { const intl = useIntl(); - const queryClient = useQueryClient(); const assetsQuery = walletQueries.useAssetsQuery(); const transferType = route?.params?.transferType; @@ -42,7 +39,6 @@ const TradeScreen = ({ route, navigation }) => { const _onSuccess = () => { _delayedRefreshCoinsData(); - queryClient.invalidateQueries([QUERIES.WALLET.GET_PENDING_REQUESTS]); }; const _handleHsTransfer = (_hsSignPath: string) => { From ee823ce6b5a28da0c26d4712bf22b69282dd0e51 Mon Sep 17 00:00:00 2001 From: Nouman Tahir Date: Fri, 18 Aug 2023 20:23:18 +0500 Subject: [PATCH 5/6] updated pending swap alert content --- src/config/locales/en-US.json | 4 +++- src/screens/trade/children/swapTokenContent.tsx | 16 +++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index 6ceab54b88..8b7c40fa0c 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -847,7 +847,9 @@ "free":"Free", "confirm_swap":"Confirm Swap", "swap_for" :"Swapping {fromAmount} for {toAmount}", - "swap_successful":"Successfully Swapped!", + "swap_successful":"Successfully Swapped", + "swap_pending":"Swap Pending!", + "swap_pending_body":"Swap requests may be pending, please check pending open orders in selected token details", "new_swap":"New Swap" }, "boost": { diff --git a/src/screens/trade/children/swapTokenContent.tsx b/src/screens/trade/children/swapTokenContent.tsx index 3760d37d2c..25247d175c 100644 --- a/src/screens/trade/children/swapTokenContent.tsx +++ b/src/screens/trade/children/swapTokenContent.tsx @@ -131,10 +131,16 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: }; const _onSwapSuccess = async (hasPending:boolean) => { + + const _badgeColor = hasPending ? EStyleSheet.value('$primaryBlue') : EStyleSheet.value('$primaryGreen'); + const _badgeIcon = hasPending ? "error-outline" : "check"; + const _titleId = hasPending ? 'trade.swap_pending' : 'trade.swap_successful' + const _body = hasPending ? intl.formatMessage({ id: 'trade.swap_pending_body' }) : undefined; + const headerContent = ( @@ -151,8 +157,8 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: dispatch( showActionModal({ headerContent, - title: intl.formatMessage({ id: 'trade.swap_successful' }), - body: hasPending ? "Some swap requests may be pending, checking pending reqeest for sleected token" : undefined, + title: intl.formatMessage({ id: _titleId }), + body: _body, buttons: [ { textId: 'trade.new_swap', onPress: _reset }, { textId: 'alert.done', onPress: () => navigation.goBack() }, @@ -168,7 +174,7 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: const data: SwapOptions = { fromAsset: fromAssetSymbol, fromAmount: _fromAmount, - toAmount, + toAmount: 1, }; if (currentAccount.local.authType === AUTH_TYPE.STEEM_CONNECT) { From a60d889af733042c31fc9874662160736bdfda03 Mon Sep 17 00:00:00 2001 From: Nouman Tahir Date: Fri, 18 Aug 2023 20:24:51 +0500 Subject: [PATCH 6/6] remove test code --- src/screens/trade/children/swapTokenContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/trade/children/swapTokenContent.tsx b/src/screens/trade/children/swapTokenContent.tsx index 25247d175c..d75e8a7e15 100644 --- a/src/screens/trade/children/swapTokenContent.tsx +++ b/src/screens/trade/children/swapTokenContent.tsx @@ -174,7 +174,7 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }: const data: SwapOptions = { fromAsset: fromAssetSymbol, fromAmount: _fromAmount, - toAmount: 1, + toAmount, }; if (currentAccount.local.authType === AUTH_TYPE.STEEM_CONNECT) {