Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions .changeset/tricky-suns-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@cypherock/coin-support-btc': patch
'@cypherock/cysync-core': patch
'@cypherock/cysync-utils': patch
'@cypherock/cysync-ui': patch
'@cypherock/cysync-cli': patch
'@cypherock/cysync-desktop': patch
---

feat: use BigNumber in FeeInput & AmountInput with ux improvements
2 changes: 1 addition & 1 deletion apps/cli/src/services/send/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ const getTxnInputs = async (params: {
throw new Error('Invalid fees');
}

txn.userInputs.feeRate = feeRate;
txn.userInputs.feeRate = feeRate.toString(10);
}

if (coin.family === coinFamiliesMap.evm) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const broadcastTransaction = async (

const parsedTransaction: ITransaction = {
hash: txnHash,
fees: transaction.computedData.fee.toString(),
fees: transaction.computedData.fee,
amount: '0',
status: TransactionStatusMap.pending,
type: TransactionTypeMap.receive,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const initializeTransaction = async (
utxos,
},
computedData: {
fee: 0,
fee: '0',
inputs: [],
outputs: [],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const prepareTransaction = async (
result = coinselectSplit(
txn.staticData.utxos.map(mapUtxo),
outputList,
txn.userInputs.feeRate,
Number(txn.userInputs.feeRate),
3,
);
isNotOverDustThreshold = Boolean(result.isNotOverDustThreshold);
Expand Down Expand Up @@ -107,7 +107,7 @@ export const prepareTransaction = async (
result = coinselect(
txn.staticData.utxos.map(mapUtxo),
outputList,
txn.userInputs.feeRate,
Number(txn.userInputs.feeRate),
);
}

Expand Down Expand Up @@ -135,7 +135,7 @@ export const prepareTransaction = async (
},
computedData: {
inputs: result.inputs ?? [],
fee: result.fee,
fee: result.fee.toString(10),
outputs: (result.outputs ?? []).map((e: any) => {
if (e.address === undefined) {
return {
Expand Down
6 changes: 3 additions & 3 deletions packages/coin-support-btc/src/operations/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ export interface IPreparedBtcTransaction extends IPreparedTransaction {
};
userInputs: {
outputs: IPreparedTransactionOutput[];
feeRate: number;
feeRate: string;
isSendAll: boolean;
};
staticData: {
averageFee: number;
averageFee: string;
utxos: IUtxo[];
};
computedData: {
inputs: IPreparedBtcTransactionInput[];
outputs: IPreparedBtcTransactionOutput[];
fee: number;
fee: string;
};
}
4 changes: 2 additions & 2 deletions packages/coin-support-btc/src/services/fees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { config } from '../config';

const baseURL = `${config.API_CYPHEROCK}/transaction`;

export const getAverageFee = async (coin: IBtcCoinInfo): Promise<number> => {
export const getAverageFee = async (coin: IBtcCoinInfo): Promise<string> => {
const url = `${baseURL}/fees`;
const response = await axios.post(url, {
coinType: coin.apiCoinType,
Expand All @@ -17,5 +17,5 @@ export const getAverageFee = async (coin: IBtcCoinInfo): Promise<number> => {
new Error('Server: Invalid fees result from server'),
);

return Math.round(response.data.medium_fee_per_kb / 1024);
return Math.round(response.data.medium_fee_per_kb / 1024).toString(10);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface IInitializeTransactionTestCases {
txn: IPreparedBtcTransaction;
mocks: {
account: Partial<IBtcAccount>;
averageFee: number;
averageFee: string;
utxos: IUtxo[];
};
}
Expand All @@ -16,16 +16,16 @@ export const valid: IInitializeTransactionTestCases[] = [
txn: {
accountId: '1',
computedData: {
fee: 0,
fee: '0',
inputs: [],
outputs: [],
},
staticData: {
averageFee: 150,
averageFee: '150',
utxos: [],
},
userInputs: {
feeRate: 150,
feeRate: '150',
outputs: [],
isSendAll: false,
},
Expand All @@ -42,7 +42,7 @@ export const valid: IInitializeTransactionTestCases[] = [
parentAssetId: 'bitcoin',
familyId: 'bitcoin',
},
averageFee: 150,
averageFee: '150',
utxos: [],
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ export const valid: IPrepareTransactionTestCases[] = [
accountId: '1',
userInputs: {
outputs: [{ address: 'kajshd', amount: '' }],
feeRate: 150,
feeRate: '150',
isSendAll: false,
},
staticData: {
averageFee: 150,
averageFee: '150',
utxos: [
{
txid: '8b1720b139daa3231455348806a6d01f53bd6cb31f6068b4b206fc5a8bf46aba',
Expand All @@ -35,7 +35,7 @@ export const valid: IPrepareTransactionTestCases[] = [
],
},
computedData: {
fee: 0,
fee: '0',
inputs: [],
outputs: [],
},
Expand All @@ -61,11 +61,11 @@ export const valid: IPrepareTransactionTestCases[] = [
accountId: '1',
userInputs: {
outputs: [{ address: 'kajshd', amount: '' }],
feeRate: 150,
feeRate: '150',
isSendAll: false,
},
staticData: {
averageFee: 150,
averageFee: '150',
utxos: [
{
txid: '8b1720b139daa3231455348806a6d01f53bd6cb31f6068b4b206fc5a8bf46aba',
Expand All @@ -79,7 +79,7 @@ export const valid: IPrepareTransactionTestCases[] = [
],
},
computedData: {
fee: 33900,
fee: '33900',
inputs: [
{
address: 'LYzVffwKeuwnqeuwVikH59gk3iLvVaeZUN',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ export const valid: IPrepareTransactionTestCases[] = [
outputs: [
{ address: 'LPMmBEMdTVpoNYDKooGWjkFyQ2YduGZpyA', amount: '10000' },
],
feeRate: 150,
feeRate: '150',
isSendAll: false,
},
staticData: {
averageFee: 150,
averageFee: '150',
utxos: [
{
txid: '8b1720b139daa3231455348806a6d01f53bd6cb31f6068b4b206fc5a8bf46aba',
Expand All @@ -42,7 +42,7 @@ export const valid: IPrepareTransactionTestCases[] = [
],
},
computedData: {
fee: 33900,
fee: '33900',
inputs: [
{
address: 'LYzVffwKeuwnqeuwVikH59gk3iLvVaeZUN',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
Typography,
CustomInputSend,
} from '@cypherock/cysync-ui';
import { BigNumber } from '@cypherock/cysync-utils';
import { processNonNegativeNumericInput } from '@cypherock/cysync-utils';
import lodash from 'lodash';
import React, { useCallback, useEffect, useState } from 'react';

Expand Down Expand Up @@ -86,43 +86,30 @@ export const AmountInput: React.FC<AmountInputProps> = ({
debouncedOnSendMax(checked);
};

const filterNumericInput = (val: string) => {
let filteredValue = val.replace(/[^0-9.]/g, '');
const bigNum = new BigNumber(filteredValue);

if (filteredValue.includes('.')) {
const splitValue = filteredValue.split('.');
let firstValue = splitValue[0];
const secondValue = splitValue[1];

const firstValBigNumber = new BigNumber(firstValue);

if (firstValBigNumber.isNaN() || firstValBigNumber.isZero()) {
firstValue = '0';
}

filteredValue = `${firstValue}.${secondValue}`;
} else if (!bigNum.isNaN() && bigNum.isZero()) {
filteredValue = '0';
}

return filteredValue;
};

const updateValues = (amount: string, value: string, skipCall?: boolean) => {
setCoinAmount(amount);
setCoinValue(value);
if (!skipCall) debouncedOnValueChange(amount);
};

const handleCoinAmountChange = (val: string) => {
const filteredValue = filterNumericInput(val);
updateValues(filteredValue, converter(filteredValue));
const handleCoinAmountChange = (input: string, isPasted: boolean) => {
const result = processNonNegativeNumericInput({
input,
isBigNumber: true,
isPasted,
});
if (!result.isValid) return;
updateValues(result.inputValue, converter(result.inputValue));
};

const handleCoinValueChange = (val: string) => {
const filteredValue = filterNumericInput(val);
updateValues(converter(filteredValue, true), filteredValue);
const handleCoinValueChange = (input: string, isPasted: boolean) => {
const result = processNonNegativeNumericInput({
input,
isBigNumber: true,
isPasted,
});
if (!result.isValid) return;
updateValues(converter(result.inputValue, true), result.inputValue);
};

return (
Expand All @@ -146,7 +133,8 @@ export const AmountInput: React.FC<AmountInputProps> = ({
type="text"
name="address"
placeholder={placeholder}
onChange={handleCoinAmountChange}
onChange={val => handleCoinAmountChange(val, false)}
onPaste={val => handleCoinAmountChange(val, true)}
value={coinAmount}
disabled={isToggled || isDisabled}
$textColor="white"
Expand All @@ -166,7 +154,8 @@ export const AmountInput: React.FC<AmountInputProps> = ({
type="text"
name="address"
placeholder={placeholder}
onChange={handleCoinValueChange}
onChange={val => handleCoinValueChange(val, false)}
onPaste={val => handleCoinValueChange(val, true)}
value={coinValue}
disabled={isToggled || isDisabled}
$textColor="white"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import React, { useState } from 'react';

import { selectLanguage, useAppSelector } from '~/store';

interface BitcoinInputProps {
initialValue: number;
export interface BitcoinInputProps {
initialValue: string;
isTextInput: boolean;
unit: string;
onChange: (newValue: number) => void;
onChange: (newValue: string) => void;
}

export const BitcoinInput: React.FC<BitcoinInputProps> = ({
Expand All @@ -26,7 +26,7 @@ export const BitcoinInput: React.FC<BitcoinInputProps> = ({
const captions = lang.strings.send.fees.sliderLabels;
const [value, setValue] = useState(initialValue);

const handleChange = (val: number) => {
const handleChange = (val: string) => {
setValue(val);
onChange(val);
};
Expand All @@ -35,7 +35,7 @@ export const BitcoinInput: React.FC<BitcoinInputProps> = ({
<>
{isTextInput && (
<FeesInput
value={value.toString()}
value={value}
postfixText={unit}
onChange={handleChange}
valueType="integer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import React, { useEffect, useState } from 'react';
import { useSendDialog } from '~/dialogs/Send/context';
import { selectLanguage, useAppSelector } from '~/store';

interface EthereumInputProps {
initialGasPrice: number;
inputGasPrice: number;
export interface EthereumInputProps {
initialGasPrice: string;
inputGasPrice: string;
isTextInput: boolean;
unit: string;
onChange: (param: { gasLimit?: number; gasPrice?: number }) => void;
onChange: (param: { gasLimit?: string; gasPrice?: string }) => void;
}

export const EthereumInput: React.FC<EthereumInputProps> = ({
Expand All @@ -35,13 +35,13 @@ export const EthereumInput: React.FC<EthereumInputProps> = ({
const transaction = useSendDialog().transaction as IPreparedEvmTransaction;
const { getDefaultGasLimit } = useSendDialog();

const handlePriceChange = (val: number) => {
const handlePriceChange = (val: string) => {
setGasPrice(val);
// on change gas price, prepare EVM fee
onChange({ gasPrice: val });
};

const handleLimitChange = (val: number) => {
const handleLimitChange = (val: string) => {
// on change gas limit, prepare EVM fee
onChange({ gasLimit: val });
};
Expand All @@ -51,7 +51,7 @@ export const EthereumInput: React.FC<EthereumInputProps> = ({
transaction.userInputs.gasPrice = initialGasPrice.toString();
transaction.userInputs.gasLimit = getDefaultGasLimit();
onChange({
gasLimit: Number(transaction.userInputs.gasLimit),
gasLimit: transaction.userInputs.gasLimit,
gasPrice: initialGasPrice,
});
}, [isTextInput, transaction.computedData.gasLimitEstimate]);
Expand Down Expand Up @@ -95,7 +95,7 @@ export const EthereumInput: React.FC<EthereumInputProps> = ({
</Flex>
</Flex>
<FeesInput
value={gasPrice.toString()}
value={gasPrice}
postfixText={unit}
onChange={handlePriceChange}
/>
Expand Down
Loading