From 727efb0eb99840128a9aa8fc8da45211fe2d3840 Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 9 Jul 2024 09:00:26 +0900 Subject: [PATCH 1/8] Remove redundant sliderXPosition update in debounced onTypedNumber --- .../screens/Swap/hooks/useSwapInputsController.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index c4aa47888d4..02f35d3af31 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -554,17 +554,6 @@ export function useSwapInputsController({ if (amount > 0) { const updateWorklet = () => { 'worklet'; - // If the user enters a new inputAmount, update the slider position ahead of the quote fetch, because - // we can derive the slider position directly from the entered amount. - if (inputKey === 'inputAmount') { - const inputAssetBalance = internalSelectedInputAsset.value?.maxSwappableAmount || '0'; - if (equalWorklet(inputAssetBalance, 0)) { - sliderXPosition.value = withSpring(0, snappySpringConfig); - } else { - const updatedSliderPosition = clamp(Number(divWorklet(amount, inputAssetBalance)) * SLIDER_WIDTH, 0, SLIDER_WIDTH); - sliderXPosition.value = withSpring(updatedSliderPosition, snappySpringConfig); - } - } fetchQuoteAndAssetPrices(); }; From 2d859ee9be0bfa8fbf6954622d4960f10b93743f Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 9 Jul 2024 09:25:55 +0900 Subject: [PATCH 2/8] Remove redundant preservedAmount argument in onTypedNumber as the default is true --- .../Swap/hooks/useSwapInputsController.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index 02f35d3af31..f17c3500386 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -548,7 +548,7 @@ export function useSwapInputsController({ ); const onTypedNumber = useDebouncedCallback( - (amount: number, inputKey: inputKeys, preserveAmount = true) => { + (amount: number, inputKey: inputKeys) => { lastTypedInput.value = inputKey; if (amount > 0) { @@ -569,7 +569,7 @@ export function useSwapInputsController({ const updatedValues = keysToReset.reduce( (acc, key) => { const castedKey = key as keyof typeof inputValues.value; - acc[castedKey] = castedKey === inputKey && preserveAmount ? inputValues.value[castedKey] : 0; + acc[castedKey] = castedKey === inputKey ? inputValues.value[castedKey] : 0; return acc; }, {} as Partial @@ -755,11 +755,7 @@ export function useSwapInputsController({ outputNativeValue: 0, }; }); - if (hasDecimal) { - runOnJS(onTypedNumber)(0, 'inputAmount', true); - } else { - runOnJS(onTypedNumber)(0, 'inputAmount'); - } + runOnJS(onTypedNumber)(0, 'inputAmount'); } else { // If the input amount was set to a non-zero value if (!internalSelectedInputAsset.value) return; @@ -787,7 +783,7 @@ export function useSwapInputsController({ sliderXPosition.value = withSpring(updatedSliderPosition, snappySpringConfig); } - runOnJS(onTypedNumber)(Number(current.values.inputAmount), 'inputAmount', true); + runOnJS(onTypedNumber)(Number(current.values.inputAmount), 'inputAmount'); } } if (inputMethod.value === 'outputAmount' && !equalWorklet(current.values.outputAmount, previous.values.outputAmount)) { @@ -811,11 +807,7 @@ export function useSwapInputsController({ }; }); - if (hasDecimal) { - runOnJS(onTypedNumber)(0, 'outputAmount', true); - } else { - runOnJS(onTypedNumber)(0, 'outputAmount'); - } + runOnJS(onTypedNumber)(0, 'outputAmount'); } else if (greaterThanWorklet(current.values.outputAmount, 0)) { // If the output amount was set to a non-zero value if (isQuoteStale.value !== 1) isQuoteStale.value = 1; From add51f276e5e3090cb7f4cd3fa1adb4318b0ffab Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 9 Jul 2024 09:06:46 -0400 Subject: [PATCH 3/8] Pull out resetToZero as its own worklet to reduce redundant code --- .../Swap/hooks/useSwapInputsController.ts | 121 +++++------------- 1 file changed, 35 insertions(+), 86 deletions(-) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index f17c3500386..77bfc0c9bcf 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -547,48 +547,43 @@ export function useSwapInputsController({ { leading: false, trailing: true } ); + const resetValuesToZeroWorklet = (inputKey?: inputKeys) => { + 'worklet'; + quoteFetchingInterval.stop(); + if (isFetching.value) isFetching.value = false; + if (isQuoteStale.value !== 0) isQuoteStale.value = 0; + if (inputKey) lastTypedInput.value = inputKey; + + const keysToReset = ['inputAmount', 'inputNativeValue', 'outputAmount', 'outputNativeValue']; + const inputKeyValue = inputKey ? inputValues.value[inputKey] : 0; + const hasDecimal = inputKeyValue.toString().includes('.'); + const updatedValues = keysToReset.reduce( + (acc, key) => { + const castedKey = key as keyof typeof inputValues.value; + acc[castedKey] = castedKey === inputKey && hasDecimal ? inputValues.value[castedKey] : 0; + return acc; + }, + {} as Partial + ); + + inputValues.modify(values => { + return { + ...values, + ...updatedValues, + }; + }); + + if (inputKey) { + sliderXPosition.value = withSpring(0, snappySpringConfig); + } + }; + const onTypedNumber = useDebouncedCallback( (amount: number, inputKey: inputKeys) => { lastTypedInput.value = inputKey; if (amount > 0) { - const updateWorklet = () => { - 'worklet'; - fetchQuoteAndAssetPrices(); - }; - - runOnUI(updateWorklet)(); - } else { - const resetValuesToZero = () => { - if (isFetching.value) isFetching.value = false; - if (isQuoteStale.value !== 0) isQuoteStale.value = 0; - - const updateWorklet = () => { - 'worklet'; - const keysToReset = ['inputAmount', 'inputNativeValue', 'outputAmount', 'outputNativeValue']; - const updatedValues = keysToReset.reduce( - (acc, key) => { - const castedKey = key as keyof typeof inputValues.value; - acc[castedKey] = castedKey === inputKey ? inputValues.value[castedKey] : 0; - return acc; - }, - {} as Partial - ); - inputValues.modify(values => { - return { - ...values, - ...updatedValues, - }; - }); - sliderXPosition.value = withSpring(0, snappySpringConfig); - isQuoteStale.value = 0; - quoteFetchingInterval.stop(); - }; - - runOnUI(updateWorklet)(); - }; - - resetValuesToZero(); + runOnUI(fetchQuoteAndAssetPrices)(); } }, 300, @@ -684,20 +679,7 @@ export function useSwapInputsController({ if (inputMethod.value === 'slider' && internalSelectedInputAsset.value && current.sliderXPosition !== previous.sliderXPosition) { // If the slider position changes if (percentageToSwap.value === 0) { - // If the change set the slider position to 0 - quoteFetchingInterval.stop(); - isQuoteStale.value = 0; - isFetching.value = false; - - inputValues.modify(values => { - return { - ...values, - inputAmount: 0, - inputNativeValue: 0, - outputAmount: 0, - outputNativeValue: 0, - }; - }); + resetValuesToZeroWorklet(); } else { // If the change set the slider position to > 0 if (!internalSelectedInputAsset.value) return; @@ -739,23 +721,7 @@ export function useSwapInputsController({ // If the number in the input field changes if (equalWorklet(current.values.inputAmount, 0)) { // If the input amount was set to 0 - quoteFetchingInterval.stop(); - isQuoteStale.value = 0; - isFetching.value = false; - - const hasDecimal = current.values.inputAmount.toString().includes('.'); - - sliderXPosition.value = withSpring(0, snappySpringConfig); - inputValues.modify(values => { - return { - ...values, - inputAmount: hasDecimal ? current.values.inputAmount : 0, - inputNativeValue: 0, - outputAmount: 0, - outputNativeValue: 0, - }; - }); - runOnJS(onTypedNumber)(0, 'inputAmount'); + resetValuesToZeroWorklet('inputAmount'); } else { // If the input amount was set to a non-zero value if (!internalSelectedInputAsset.value) return; @@ -790,24 +756,7 @@ export function useSwapInputsController({ // If the number in the output field changes if (equalWorklet(current.values.outputAmount, 0)) { // If the output amount was set to 0 - quoteFetchingInterval.stop(); - isQuoteStale.value = 0; - isFetching.value = false; - - const hasDecimal = current.values.outputAmount.toString().includes('.'); - - sliderXPosition.value = withSpring(0, snappySpringConfig); - inputValues.modify(values => { - return { - ...values, - inputAmount: 0, - inputNativeValue: 0, - outputAmount: hasDecimal ? current.values.outputAmount : 0, - outputNativeValue: 0, - }; - }); - - runOnJS(onTypedNumber)(0, 'outputAmount'); + resetValuesToZeroWorklet('outputAmount'); } else if (greaterThanWorklet(current.values.outputAmount, 0)) { // If the output amount was set to a non-zero value if (isQuoteStale.value !== 1) isQuoteStale.value = 1; From 4bffe7c20e5c0a1bc87049ffcf7f72b2b0dfc65c Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 9 Jul 2024 16:53:03 -0400 Subject: [PATCH 4/8] Remove unnecessary check for amount > 0 now that onTypedNumber is only used for when the amount is > 0 --- .../screens/Swap/hooks/useSwapInputsController.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index 77bfc0c9bcf..44d8224b132 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -579,12 +579,9 @@ export function useSwapInputsController({ }; const onTypedNumber = useDebouncedCallback( - (amount: number, inputKey: inputKeys) => { + (inputKey: inputKeys) => { lastTypedInput.value = inputKey; - - if (amount > 0) { - runOnUI(fetchQuoteAndAssetPrices)(); - } + runOnUI(fetchQuoteAndAssetPrices)(); }, 300, { leading: false, trailing: true } @@ -749,7 +746,7 @@ export function useSwapInputsController({ sliderXPosition.value = withSpring(updatedSliderPosition, snappySpringConfig); } - runOnJS(onTypedNumber)(Number(current.values.inputAmount), 'inputAmount'); + runOnJS(onTypedNumber)('inputAmount'); } } if (inputMethod.value === 'outputAmount' && !equalWorklet(current.values.outputAmount, previous.values.outputAmount)) { @@ -770,7 +767,7 @@ export function useSwapInputsController({ }; }); - runOnJS(onTypedNumber)(Number(current.values.outputAmount), 'outputAmount'); + runOnJS(onTypedNumber)('outputAmount'); } } } From 6fdbbd44babeb303ff9b1b3ebae2e9433c7fafb4 Mon Sep 17 00:00:00 2001 From: jinchung Date: Tue, 9 Jul 2024 17:02:16 -0400 Subject: [PATCH 5/8] Replace onTypedNumber with debouncedFetchQuote function --- .../Swap/hooks/useSwapInputsController.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index 44d8224b132..4401a1ad655 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -552,7 +552,6 @@ export function useSwapInputsController({ quoteFetchingInterval.stop(); if (isFetching.value) isFetching.value = false; if (isQuoteStale.value !== 0) isQuoteStale.value = 0; - if (inputKey) lastTypedInput.value = inputKey; const keysToReset = ['inputAmount', 'inputNativeValue', 'outputAmount', 'outputNativeValue']; const inputKeyValue = inputKey ? inputValues.value[inputKey] : 0; @@ -578,15 +577,6 @@ export function useSwapInputsController({ } }; - const onTypedNumber = useDebouncedCallback( - (inputKey: inputKeys) => { - lastTypedInput.value = inputKey; - runOnUI(fetchQuoteAndAssetPrices)(); - }, - 300, - { leading: false, trailing: true } - ); - const debouncedFetchQuote = useDebouncedCallback( () => { runOnUI(fetchQuoteAndAssetPrices)(); @@ -716,6 +706,7 @@ export function useSwapInputsController({ } if (inputMethod.value === 'inputAmount' && !equalWorklet(current.values.inputAmount, previous.values.inputAmount)) { // If the number in the input field changes + lastTypedInput.value = 'inputAmount'; if (equalWorklet(current.values.inputAmount, 0)) { // If the input amount was set to 0 resetValuesToZeroWorklet('inputAmount'); @@ -746,11 +737,12 @@ export function useSwapInputsController({ sliderXPosition.value = withSpring(updatedSliderPosition, snappySpringConfig); } - runOnJS(onTypedNumber)('inputAmount'); + runOnJS(debouncedFetchQuote)(); } } if (inputMethod.value === 'outputAmount' && !equalWorklet(current.values.outputAmount, previous.values.outputAmount)) { // If the number in the output field changes + lastTypedInput.value = 'outputAmount'; if (equalWorklet(current.values.outputAmount, 0)) { // If the output amount was set to 0 resetValuesToZeroWorklet('outputAmount'); @@ -767,7 +759,7 @@ export function useSwapInputsController({ }; }); - runOnJS(onTypedNumber)('outputAmount'); + runOnJS(debouncedFetchQuote)(); } } } From 2f5bd1132b46714ef0793088349f0674eff92e9e Mon Sep 17 00:00:00 2001 From: jinchung Date: Wed, 10 Jul 2024 07:19:15 -0400 Subject: [PATCH 6/8] Pull out variables for prev input / output native values for code readability --- .../screens/Swap/hooks/useSwapInputsController.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index 4401a1ad655..93d184d1efb 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -832,10 +832,13 @@ export function useSwapInputsController({ const inputNativePrice = internalSelectedInputAsset.value?.nativePrice || internalSelectedInputAsset.value?.price?.value || 0; const outputNativePrice = internalSelectedOutputAsset.value?.nativePrice || internalSelectedOutputAsset.value?.price?.value || 0; + const prevInputNativeValue = inputValues.value.inputNativeValue; + const prevOutputAmount = inputValues.value.outputAmount; + const newInputAmount = inputNativePrice > 0 ? divWorklet(prevInputNativeValue, inputNativePrice) : prevOutputAmount; + const inputAmount = Number( valueBasedDecimalFormatter({ - amount: - inputNativePrice > 0 ? divWorklet(inputValues.value.inputNativeValue, inputNativePrice) : inputValues.value.outputAmount, + amount: newInputAmount, nativePrice: inputNativePrice, roundingMode: 'up', isStablecoin: internalSelectedInputAsset.value?.type === 'stablecoin' ?? false, @@ -843,13 +846,16 @@ export function useSwapInputsController({ }) ); + const prevOutputNativeValue = inputValues.value.outputNativeValue; + const prevInputAmount = inputValues.value.inputAmount; + const newOutputAmount = outputNativePrice > 0 ? divWorklet(prevOutputNativeValue, outputNativePrice) : prevInputAmount; + inputValues.modify(values => { return { ...values, inputAmount, inputNativeValue: inputValues.value.inputNativeValue, - outputAmount: - outputNativePrice > 0 ? divWorklet(inputValues.value.outputNativeValue, outputNativePrice) : inputValues.value.inputAmount, + outputAmount: newOutputAmount, outputNativeValue: inputValues.value.outputNativeValue, }; }); From 8570f1f2da847cd803d49913db753b7488881a52 Mon Sep 17 00:00:00 2001 From: jinchung Date: Wed, 10 Jul 2024 07:21:03 -0400 Subject: [PATCH 7/8] Calculate native value based on the new amounts and native prices to be more accurate --- src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index 93d184d1efb..c0874bcfb57 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -854,9 +854,9 @@ export function useSwapInputsController({ return { ...values, inputAmount, - inputNativeValue: inputValues.value.inputNativeValue, + inputNativeValue: mulWorklet(newInputAmount, inputNativePrice), outputAmount: newOutputAmount, - outputNativeValue: inputValues.value.outputNativeValue, + outputNativeValue: mulWorklet(newOutputAmount, outputNativePrice), }; }); } From 0261b633bbde2ffdcec97e70537b6094aa5fc4db Mon Sep 17 00:00:00 2001 From: jinchung Date: Mon, 15 Jul 2024 11:59:08 -0400 Subject: [PATCH 8/8] Simplify resetToZeroValues logic --- .../Swap/hooks/useSwapInputsController.ts | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index c0874bcfb57..08e596ef6a1 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -553,28 +553,28 @@ export function useSwapInputsController({ if (isFetching.value) isFetching.value = false; if (isQuoteStale.value !== 0) isQuoteStale.value = 0; - const keysToReset = ['inputAmount', 'inputNativeValue', 'outputAmount', 'outputNativeValue']; - const inputKeyValue = inputKey ? inputValues.value[inputKey] : 0; + const resetValues = { + inputAmount: 0, + inputNativeValue: 0, + outputAmount: 0, + outputNativeValue: 0, + }; + + if (!inputKey) { + inputValues.modify(values => ({ ...values, ...resetValues })); + return; + } + + const inputKeyValue = inputValues.value[inputKey]; const hasDecimal = inputKeyValue.toString().includes('.'); - const updatedValues = keysToReset.reduce( - (acc, key) => { - const castedKey = key as keyof typeof inputValues.value; - acc[castedKey] = castedKey === inputKey && hasDecimal ? inputValues.value[castedKey] : 0; - return acc; - }, - {} as Partial - ); - - inputValues.modify(values => { - return { - ...values, - ...updatedValues, - }; - }); - if (inputKey) { - sliderXPosition.value = withSpring(0, snappySpringConfig); - } + inputValues.modify(values => ({ + ...values, + ...resetValues, + [inputKey]: hasDecimal ? inputKeyValue : 0, + })); + + sliderXPosition.value = withSpring(0, snappySpringConfig); }; const debouncedFetchQuote = useDebouncedCallback(