Skip to content
Merged
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
2 changes: 1 addition & 1 deletion packages/product-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@trezor/utils": "workspace:*",
"framer-motion": "^12.9.1",
"react": "18.2.0",
"react-hook-form": "^7.54.2",
"react-hook-form": "^7.56.1",
"react-intl": "^7.1.11",
"react-svg": "16.3.0",
"styled-components": "^6.1.17",
Expand Down
4 changes: 2 additions & 2 deletions packages/suite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@everstake/wallet-sdk": "1.0.14",
"@floating-ui/react": "^0.27.8",
"@formatjs/intl": "3.1.6",
"@hookform/resolvers": "^4.1.3",
"@hookform/resolvers": "^5.0.1",
"@mobily/ts-belt": "^3.13.1",
"@reduxjs/toolkit": "2.6.0",
"@sentry/core": "8.55.0",
Expand Down Expand Up @@ -102,7 +102,7 @@
"react-dom": "18.2.0",
"react-focus-lock": "^2.13.6",
"react-helmet-async": "^2.0.5",
"react-hook-form": "^7.54.2",
"react-hook-form": "^7.56.1",
"react-intl": "^7.1.11",
"react-qr-reader": "^2.2.1",
"react-redux": "9.2.0",
Expand Down
14 changes: 11 additions & 3 deletions packages/suite/src/hooks/wallet/sign-verify/useSignVerifyForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,17 @@ type SignVerifyContext = {
symbol: NetworkSymbol;
};

const signVerifySchema = yup.object({
// yup doesn't type properly conditionally required fields → need to declare type rather than infer it
export type SignVerifyFields = {
message: string;
address: string;
hex: boolean;
path?: string;
signature?: string;
isElectrum?: boolean;
};

const signVerifySchema: yup.ObjectSchema<SignVerifyFields> = yup.object({
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solve TS error at L76 (string | undefined not assignable to string for path, signature)

The problem arose when bumping @hookform/resolvers + react-hook-form, and then bumping yup did not help.
It took me a while to realize that the former two are not at fault, it's yup that was insufficiently typed (in both versions I tried!), and react-hook-form merely tightened its types to catch that.

message: yup
.string()
.max(MAX_LENGTH_MESSAGE, 'TR_TOO_LONG')
Expand Down Expand Up @@ -48,8 +58,6 @@ const signVerifySchema = yup.object({
isElectrum: yup.boolean(),
});

export type SignVerifyFields = yup.InferType<typeof signVerifySchema>;

const DEFAULT_VALUES: SignVerifyFields = {
message: '',
address: '',
Expand Down
2 changes: 1 addition & 1 deletion suite-common/validators/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"@suite-common/wallet-config": "workspace:*",
"@suite-common/wallet-utils": "workspace:*",
"@trezor/utils": "workspace:*",
"yup": "^1.4.0"
"yup": "^1.6.1"
}
}
2 changes: 1 addition & 1 deletion suite-common/wallet-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@trezor/type-utils": "workspace:*",
"@trezor/utils": "workspace:*",
"date-fns": "^4.1.0",
"react-hook-form": "^7.54.2",
"react-hook-form": "^7.56.1",
"web3-utils": "^4.3.1"
}
}
2 changes: 1 addition & 1 deletion suite-common/wallet-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@trezor/utils": "workspace:*",
"date-fns": "^4.1.0",
"react": "18.2.0",
"react-hook-form": "^7.54.2",
"react-hook-form": "^7.56.1",
"web3-utils": "^4.3.1"
}
}
2 changes: 1 addition & 1 deletion suite-native/accounts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@trezor/styles": "workspace:*",
"jotai": "1.9.1",
"react": "18.2.0",
"react-hook-form": "^7.54.2",
"react-hook-form": "^7.56.1",
"react-native": "0.76.9",
"react-native-reanimated": "^3.16.7",
"react-redux": "9.2.0"
Expand Down
6 changes: 3 additions & 3 deletions suite-native/forms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
"type-check": "yarn g:tsc --build"
},
"dependencies": {
"@hookform/resolvers": "^4.1.3",
"@hookform/resolvers": "^5.0.1",
"@mobily/ts-belt": "^3.13.1",
"@suite-native/atoms": "workspace:*",
"@suite-native/icons": "workspace:*",
"react": "18.2.0",
"react-hook-form": "^7.54.2",
"react-hook-form": "^7.56.1",
"react-native": "0.76.9",
"yup": "^1.4.0"
"yup": "^1.6.1"
}
}
2 changes: 1 addition & 1 deletion suite-native/module-accounts-import/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"@trezor/utils": "workspace:*",
"@trezor/utxo-lib": "workspace:*",
"react": "18.2.0",
"react-hook-form": "^7.54.2",
"react-hook-form": "^7.56.1",
"react-native": "0.76.9",
"react-native-reanimated": "^3.16.7",
"react-redux": "9.2.0"
Expand Down
2 changes: 1 addition & 1 deletion suite-native/module-send/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"expo-linear-gradient": "^14.0.1",
"jotai": "1.9.1",
"react": "18.2.0",
"react-hook-form": "^7.54.2",
"react-hook-form": "^7.56.1",
"react-native": "0.76.9",
"react-native-reanimated": "^3.16.7",
"react-native-svg": "^15.9.0",
Expand Down
83 changes: 44 additions & 39 deletions suite-native/module-trading/src/hooks/useTradingBuyForm.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { BuyTrade } from 'invity-api';
import { BuyTrade, CryptoId, FiatCurrencyCode } from 'invity-api';

import { useFormatters } from '@suite-common/formatters';
import {
Expand Down Expand Up @@ -34,53 +34,58 @@ const useReceiveAccountChangeEffect = ({ setValue }: TradingBuyForm) => {
}, [selectedReceiveAccount, setValue]);
};

const useAmountAndCurrencyFieldsChangeEffect = ({ setValue, watch }: TradingBuyForm) => {
const useAmountAndCurrencyFieldsChangeEffect = ({ setValue, getValues, watch }: TradingBuyForm) => {
const dispatch = useDispatch();
const prevNetworkId = useRef<string | undefined>(undefined);
const prevCryptoId = useRef<CryptoId | undefined>(undefined);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using cryptoId I can distinguish tokens of the same network and solve #18677 (review)

const prevFiatCurrency = useRef<FiatCurrencyCode | undefined>(getValues('fiatCurrency'));

useEffect(() => {
const { unsubscribe } = watch(({ focusedValue, asset, amountInCrypto }, { name, type }) => {
switch (name) {
case 'fiatValue':
if (focusedValue === 'fiatValue' && type === 'change') {
setValue('cryptoValue', undefined, { shouldValidate: true });
if (amountInCrypto) {
setValue('amountInCrypto', false);
const { unsubscribe } = watch(
({ focusedValue, asset, amountInCrypto, fiatCurrency }, { name, type }) => {
switch (name) {
case 'fiatValue':
if (focusedValue === 'fiatValue' && type === 'change') {
setValue('cryptoValue', undefined, { shouldValidate: true });
if (amountInCrypto) {
setValue('amountInCrypto', false);
}
}
}
break;
break;

case 'cryptoValue':
if (focusedValue === 'cryptoValue' && type === 'change') {
setValue('fiatValue', undefined, { shouldValidate: true });
if (!amountInCrypto) {
setValue('amountInCrypto', true);
}
}
break;

case 'cryptoValue':
if (focusedValue === 'cryptoValue' && type === 'change') {
setValue('fiatValue', undefined, { shouldValidate: true });
if (!amountInCrypto) {
setValue('amountInCrypto', true);
case 'fiatCurrency':
if (fiatCurrency !== prevFiatCurrency.current) {
prevFiatCurrency.current = fiatCurrency;
setValue('fiatValue', undefined, { shouldValidate: true });
setValue('cryptoValue', undefined, { shouldValidate: true });
}
break;

case 'asset': {
if (asset?.cryptoId !== prevCryptoId.current) {
prevCryptoId.current = asset?.cryptoId as CryptoId | undefined;
setValue('cryptoValue', undefined, { shouldValidate: true });
dispatch(
setBuySelectedReceiveAccount({ selectedReceiveAccount: undefined }),
);
}
Copy link
Copy Markdown
Contributor Author

@Lemonexe Lemonexe May 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only clear the cryptoValue | fiatValue field when you really selected a different asset, or different fiatCurrency.

This fixes an infinite render loop, that only manifested in @testing-library/react-native unit tests
(the app worked fine)

Note: I spend considerably time debugging this, trying to find the real root cause why this started happening after bumping react-hook-form to 7.55. I did not succeed 😞
This whole form is very complex, with a lot of watch→setValue interactions that are rather difficult to trace. I tried disabling many such interactions, and validations, to at least see if I can break the cycle, but to no avail. I also tried:

  • wrapping the hook in renderHookWithStoreProviderAsync in a FormProvider
  • mocking useDebounce
  • any of the three setValues here in cases 'fiatCurrency' and 'asset' are enough to crash
  • in the useQuotes.test, this line is enough to crash (without the other setValues)

This issue sounds relevant, but I reproduced the same crash even in 7.55, not just 7.56

break;
}
break;

case 'fiatCurrency':
setValue('fiatValue', undefined, { shouldValidate: true });
setValue('cryptoValue', undefined, { shouldValidate: true });
break;

case 'asset': {
setValue('cryptoValue', undefined, { shouldValidate: true });

if (asset?.networkId !== prevNetworkId.current) {
prevNetworkId.current = asset?.networkId;
dispatch(
setBuySelectedReceiveAccount({ selectedReceiveAccount: undefined }),
);
}
break;
default:
// do nothing
break;
}

default:
// do nothing
break;
}
});
},
);

return unsubscribe;
}, [dispatch, setValue, watch]);
Expand Down
50 changes: 25 additions & 25 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3930,14 +3930,14 @@ __metadata:
languageName: node
linkType: hard

"@hookform/resolvers@npm:^4.1.3":
version: 4.1.3
resolution: "@hookform/resolvers@npm:4.1.3"
"@hookform/resolvers@npm:^5.0.1":
version: 5.0.1
resolution: "@hookform/resolvers@npm:5.0.1"
dependencies:
"@standard-schema/utils": "npm:^0.3.0"
peerDependencies:
react-hook-form: ^7.0.0
checksum: 10/7cd4a872509c79053fd3a377bc2831348453b60f1af41564442b574d4f36b6303f751e715d01c2d9291b484581ae0152045e779aefafdd66802055e24eff7762
react-hook-form: ^7.55.0
checksum: 10/a54904e90ea7c600ed59f6c5b9dd1d8039dcf99b32f285602fcb14e915ea1a7568133debceb7801cec5f8f3f06d9cf5d285fe8d1fb5e3c844f3f9b47dc7e91d6
languageName: node
linkType: hard

Expand Down Expand Up @@ -9546,7 +9546,7 @@ __metadata:
"@suite-common/wallet-config": "workspace:*"
"@suite-common/wallet-utils": "workspace:*"
"@trezor/utils": "workspace:*"
yup: "npm:^1.4.0"
yup: "npm:^1.6.1"
languageName: unknown
linkType: soft

Expand Down Expand Up @@ -9594,7 +9594,7 @@ __metadata:
"@trezor/type-utils": "workspace:*"
"@trezor/utils": "workspace:*"
date-fns: "npm:^4.1.0"
react-hook-form: "npm:^7.54.2"
react-hook-form: "npm:^7.56.1"
web3-utils: "npm:^4.3.1"
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -9637,7 +9637,7 @@ __metadata:
"@trezor/utils": "workspace:*"
date-fns: "npm:^4.1.0"
react: "npm:18.2.0"
react-hook-form: "npm:^7.54.2"
react-hook-form: "npm:^7.56.1"
web3-utils: "npm:^4.3.1"
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -9691,7 +9691,7 @@ __metadata:
"@trezor/styles": "workspace:*"
jotai: "npm:1.9.1"
react: "npm:18.2.0"
react-hook-form: "npm:^7.54.2"
react-hook-form: "npm:^7.56.1"
react-native: "npm:0.76.9"
react-native-reanimated: "npm:^3.16.7"
react-redux: "npm:9.2.0"
Expand Down Expand Up @@ -10202,14 +10202,14 @@ __metadata:
version: 0.0.0-use.local
resolution: "@suite-native/forms@workspace:suite-native/forms"
dependencies:
"@hookform/resolvers": "npm:^4.1.3"
"@hookform/resolvers": "npm:^5.0.1"
"@mobily/ts-belt": "npm:^3.13.1"
"@suite-native/atoms": "workspace:*"
"@suite-native/icons": "workspace:*"
react: "npm:18.2.0"
react-hook-form: "npm:^7.54.2"
react-hook-form: "npm:^7.56.1"
react-native: "npm:0.76.9"
yup: "npm:^1.4.0"
yup: "npm:^1.6.1"
languageName: unknown
linkType: soft

Expand Down Expand Up @@ -10375,7 +10375,7 @@ __metadata:
"@trezor/utils": "workspace:*"
"@trezor/utxo-lib": "workspace:*"
react: "npm:18.2.0"
react-hook-form: "npm:^7.54.2"
react-hook-form: "npm:^7.56.1"
react-native: "npm:0.76.9"
react-native-reanimated: "npm:^3.16.7"
react-redux: "npm:9.2.0"
Expand Down Expand Up @@ -10724,7 +10724,7 @@ __metadata:
expo-linear-gradient: "npm:^14.0.1"
jotai: "npm:1.9.1"
react: "npm:18.2.0"
react-hook-form: "npm:^7.54.2"
react-hook-form: "npm:^7.56.1"
react-native: "npm:0.76.9"
react-native-reanimated: "npm:^3.16.7"
react-native-svg: "npm:^15.9.0"
Expand Down Expand Up @@ -12063,7 +12063,7 @@ __metadata:
"@types/react": "npm:18.2.55"
framer-motion: "npm:^12.9.1"
react: "npm:18.2.0"
react-hook-form: "npm:^7.54.2"
react-hook-form: "npm:^7.56.1"
react-intl: "npm:^7.1.11"
react-svg: "npm:16.3.0"
storybook: "npm:^8.6.12"
Expand Down Expand Up @@ -12450,7 +12450,7 @@ __metadata:
"@floating-ui/react": "npm:^0.27.8"
"@formatjs/cli": "npm:6.6.4"
"@formatjs/intl": "npm:3.1.6"
"@hookform/resolvers": "npm:^4.1.3"
"@hookform/resolvers": "npm:^5.0.1"
"@mobily/ts-belt": "npm:^3.13.1"
"@reduxjs/toolkit": "npm:2.6.0"
"@sentry/core": "npm:8.55.0"
Expand Down Expand Up @@ -12549,7 +12549,7 @@ __metadata:
react-dom: "npm:18.2.0"
react-focus-lock: "npm:^2.13.6"
react-helmet-async: "npm:^2.0.5"
react-hook-form: "npm:^7.54.2"
react-hook-form: "npm:^7.56.1"
react-intl: "npm:^7.1.11"
react-qr-reader: "npm:^2.2.1"
react-redux: "npm:9.2.0"
Expand Down Expand Up @@ -35080,12 +35080,12 @@ __metadata:
languageName: node
linkType: hard

"react-hook-form@npm:^7.54.2":
version: 7.54.2
resolution: "react-hook-form@npm:7.54.2"
"react-hook-form@npm:^7.56.1":
version: 7.56.1
resolution: "react-hook-form@npm:7.56.1"
peerDependencies:
react: ^16.8.0 || ^17 || ^18 || ^19
checksum: 10/b156d15b6246c76d0275e5722d9056014693e014d0e3dec06e44bf2672ee549aaba4366de5144d18c4cab29e631f3b2b84269d4fd5727ca17aad9b970fde6960
checksum: 10/42f9b5a78c9cc0c0f4eaff0eedbe9f019c1c2c8bbacdc9d3fdead7a1b652b4a34f5f6a2d0c7923c5edaf54a5a4c246d4ac6650c80cb91bc9ff4247100e725169
languageName: node
linkType: hard

Expand Down Expand Up @@ -43012,15 +43012,15 @@ __metadata:
languageName: node
linkType: hard

"yup@npm:^1.4.0":
version: 1.4.0
resolution: "yup@npm:1.4.0"
"yup@npm:^1.6.1":
version: 1.6.1
resolution: "yup@npm:1.6.1"
dependencies:
property-expr: "npm:^2.0.5"
tiny-case: "npm:^1.0.3"
toposort: "npm:^2.0.2"
type-fest: "npm:^2.19.0"
checksum: 10/3d1277e5e1fff4d8130e525c7361f54874ca848ebd427a0aa66606952e3370b9947d84a1ea0b943f389649e886d26b1349930889727489460d6f2f86c2a26e77
checksum: 10/19dba13403160a8739a9e57c8b816254842f3a9e01672846a980d8230cee8763783c089ded88662b30158d1479cf6bce0b51dce7f19ae7d0477be0c981024bc0
languageName: node
linkType: hard

Expand Down