Skip to content

Commit 242e0ff

Browse files
authored
fix: improve hasEnoughAda check when setting collateral (#1578)
* fix: improve hasEnoughAda check when setting collateral * fix: resolve e2e lint issue
1 parent 1435a4d commit 242e0ff

File tree

8 files changed

+70
-35
lines changed

8 files changed

+70
-35
lines changed

apps/browser-extension-wallet/src/hooks/__tests__/useCollateral.test.tsx

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/* eslint-disable sonarjs/no-identical-functions */
44
/* eslint-disable @typescript-eslint/no-explicit-any */
55
/* eslint-disable import/imports-first */
6-
const mockUseMaxAda = jest.fn();
6+
const mockUseHasEnoughCollateral = jest.fn();
77
const mockUseBuitTxState = jest.fn();
88
const mockUseSyncingTheFirstTime = jest.fn();
99
const mockCreateTxBuilder = jest.fn();
@@ -13,11 +13,10 @@ import { BehaviorSubject } from 'rxjs';
1313
import { cleanup, renderHook } from '@testing-library/react-hooks';
1414
import { AppSettingsProvider } from '@providers';
1515
import { StoreProvider } from '@src/stores';
16-
import { COLLATERAL_ADA_AMOUNT, COLLATERAL_AMOUNT_LOVELACES, useCollateral } from '@hooks';
17-
import { APP_MODE_BROWSER } from '@src/utils/constants';
16+
import { useCollateral } from '@hooks';
17+
import { APP_MODE_BROWSER, COLLATERAL_AMOUNT_LOVELACES } from '@src/utils/constants';
1818
import { I18nextProvider } from 'react-i18next';
1919
import { i18n } from '@lace/translation';
20-
import { Wallet } from '@lace/cardano';
2120
import { act } from 'react-dom/test-utils';
2221
import { waitFor } from '@testing-library/react';
2322
import { TxInspection } from '@cardano-sdk/tx-construction';
@@ -59,9 +58,9 @@ jest.mock('@src/views/browser-view/features/send-transaction', () => {
5958
};
6059
});
6160

62-
jest.mock('@hooks/useMaxAda', () => ({
63-
...jest.requireActual<any>('@hooks/useMaxAda'),
64-
useMaxAda: mockUseMaxAda
61+
jest.mock('@hooks/useHasEnoughCollateral', () => ({
62+
...jest.requireActual<any>('@hooks/useHasEnoughCollateral'),
63+
useHasEnoughCollateral: mockUseHasEnoughCollateral
6564
}));
6665

6766
jest.mock('@hooks/useSyncingTheFirstTime', () => ({
@@ -91,7 +90,7 @@ describe('Testing useCollateral hook', () => {
9190
});
9291
test('should return proper initial states', async () => {
9392
mockUseBuitTxState.mockReturnValue({});
94-
mockUseMaxAda.mockReturnValue('');
93+
mockUseHasEnoughCollateral.mockReturnValue(false);
9594
const hook = renderHook(() => useCollateral(), { wrapper: getWrapper() });
9695
await waitFor(() => {
9796
expect(hook.result.current.isInitializing).toBe(false);
@@ -106,21 +105,21 @@ describe('Testing useCollateral hook', () => {
106105

107106
test('should return proper hasEnoughAda value', async () => {
108107
mockUseBuitTxState.mockReturnValue({});
109-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT + 1))));
108+
mockUseHasEnoughCollateral.mockReturnValue(true);
110109

111110
const hook = renderHook(() => useCollateral(), { wrapper: getWrapper() });
112111

113112
expect(hook.result.current.hasEnoughAda).toBe(true);
114113

115-
mockUseMaxAda.mockReset();
116-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT - 1))));
114+
mockUseHasEnoughCollateral.mockReset();
115+
mockUseHasEnoughCollateral.mockReturnValue(false);
117116
hook.rerender();
118117
await waitFor(() => {
119118
expect(hook.result.current.hasEnoughAda).toBe(false);
120119
});
121120

122-
mockUseMaxAda.mockReset();
123-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT))));
121+
mockUseHasEnoughCollateral.mockReset();
122+
mockUseHasEnoughCollateral.mockReturnValue(true);
124123
hook.rerender();
125124
await waitFor(() => {
126125
expect(hook.result.current.hasEnoughAda).toBe(true);
@@ -181,7 +180,7 @@ describe('Testing useCollateral hook', () => {
181180

182181
describe('testing initializeCollateralTx', () => {
183182
test('should exit early in case there is not enough ada or the wallet is syncing for the first time', async () => {
184-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT - 1))));
183+
mockUseHasEnoughCollateral.mockReturnValue(false);
185184
mockUseSyncingTheFirstTime.mockReturnValue(false);
186185
const hook = renderHook(() => useCollateral(), { wrapper: getWrapper() });
187186

@@ -196,8 +195,8 @@ describe('Testing useCollateral hook', () => {
196195
expect(inspect).not.toHaveBeenCalled();
197196
});
198197

199-
mockUseMaxAda.mockReset();
200-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT))));
198+
mockUseHasEnoughCollateral.mockReset();
199+
mockUseHasEnoughCollateral.mockReturnValue(true);
201200
mockUseSyncingTheFirstTime.mockReturnValue(true);
202201
hook.rerender();
203202
act(() => {
@@ -220,7 +219,7 @@ describe('Testing useCollateral hook', () => {
220219
coins: COLLATERAL_AMOUNT_LOVELACES
221220
}
222221
};
223-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT + 1))));
222+
mockUseHasEnoughCollateral.mockReturnValue(true);
224223
mockUseSyncingTheFirstTime.mockReturnValue(false);
225224
const hook = renderHook(() => useCollateral(), { wrapper: getWrapper() });
226225
act(() => {
@@ -239,7 +238,7 @@ describe('Testing useCollateral hook', () => {
239238
});
240239
describe('testing submitCollateralTx', () => {
241240
test('should exit early in case txBuilder is not set', async () => {
242-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT - 1))));
241+
mockUseHasEnoughCollateral.mockReturnValue(false);
243242
mockUseSyncingTheFirstTime.mockReturnValue(false);
244243
const hook = renderHook(() => useCollateral(), { wrapper: getWrapper() });
245244

@@ -256,8 +255,8 @@ describe('Testing useCollateral hook', () => {
256255
expect(mockSetBuiltTxData).not.toHaveBeenCalled();
257256
});
258257

259-
mockUseMaxAda.mockReset();
260-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT))));
258+
mockUseHasEnoughCollateral.mockReset();
259+
mockUseHasEnoughCollateral.mockReturnValue(true);
261260
mockUseSyncingTheFirstTime.mockReturnValue(true);
262261
hook.rerender();
263262
await act(async () => {
@@ -290,7 +289,7 @@ describe('Testing useCollateral hook', () => {
290289
isInMemoryWallet: true
291290
});
292291

293-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT + 1))));
292+
mockUseHasEnoughCollateral.mockReturnValue(true);
294293
mockUseSyncingTheFirstTime.mockReturnValue(false);
295294
const hook = renderHook(() => useCollateral(), { wrapper: getWrapper() });
296295

@@ -309,8 +308,8 @@ describe('Testing useCollateral hook', () => {
309308
test('should submit the tx and set the colateral for HW (not in memory wallet)', async () => {
310309
mockSubmitTx.mockReset();
311310

312-
mockUseMaxAda.mockReset();
313-
mockUseMaxAda.mockReturnValue(BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT + 1))));
311+
mockUseHasEnoughCollateral.mockReset();
312+
mockUseHasEnoughCollateral.mockReturnValue(true);
314313
mockUseSyncingTheFirstTime.mockReset();
315314
mockUseSyncingTheFirstTime.mockReturnValue(false);
316315
const hook = renderHook(() => useCollateral(), { wrapper: getWrapper() });

apps/browser-extension-wallet/src/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ export * from './useWalletAvatar';
2525
export * from './useActionExecution';
2626
export * from './useCustomSubmitApi';
2727
export * from './useSharedWalletData';
28+
export * from './useHasEnoughCollateral';

apps/browser-extension-wallet/src/hooks/useCollateral.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
/* eslint-disable unicorn/no-useless-undefined */
22
import { useCallback, useMemo, useState } from 'react';
33
import { useObservable } from '@lace/common';
4-
import { useMaxAda } from '@hooks/useMaxAda';
54
import { firstValueFrom } from 'rxjs';
65
import { map, take, filter } from 'rxjs/operators';
76
import { TxBuilder } from '@cardano-sdk/tx-construction';
87
import { Cardano } from '@cardano-sdk/core';
98
import { isNotNil } from '@cardano-sdk/util';
10-
import { Wallet } from '@lace/cardano';
119
import { useWalletStore } from '@src/stores';
1210
import { useSyncingTheFirstTime } from '@hooks/useSyncingTheFirstTime';
1311
import { useBuiltTxState } from '@src/views/browser-view/features/send-transaction';
14-
15-
export const COLLATERAL_ADA_AMOUNT = 5;
16-
export const COLLATERAL_AMOUNT_LOVELACES = BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT)));
12+
import { COLLATERAL_AMOUNT_LOVELACES } from '@utils/constants';
13+
import { useHasEnoughCollateral } from '@hooks/useHasEnoughCollateral';
1714

1815
export type UseCollateralReturn = {
1916
initializeCollateralTx: () => Promise<void>;
@@ -34,8 +31,7 @@ export const useCollateral = (): UseCollateralReturn => {
3431
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
3532
const addresses = useObservable(inMemoryWallet?.addresses$);
3633
const walletAddress = addresses?.[0]?.address;
37-
const maxAvailableAda = useMaxAda();
38-
const hasEnoughAda = useMemo(() => maxAvailableAda >= COLLATERAL_AMOUNT_LOVELACES, [maxAvailableAda]);
34+
const hasEnoughAda = useHasEnoughCollateral();
3935
const isSyncingForTheFirstTime = useSyncingTheFirstTime(); // here we check wallet is syncing for the first time
4036
const output: Cardano.TxOut = useMemo(
4137
() => ({
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { useEffect, useState } from 'react';
2+
import { Cardano } from '@cardano-sdk/core';
3+
import { useWalletStore } from '@stores';
4+
import { useObservable } from '@lace/common';
5+
import { COLLATERAL_AMOUNT_LOVELACES } from '@utils/constants';
6+
7+
export const useHasEnoughCollateral = (): boolean => {
8+
const [hasEnoughAda, setHasEnoughAda] = useState<boolean>(false);
9+
const { inMemoryWallet } = useWalletStore();
10+
const addresses = useObservable(inMemoryWallet?.addresses$);
11+
12+
useEffect(() => {
13+
(async () => {
14+
const walletAddress = addresses?.[0]?.address;
15+
const output = {
16+
address: walletAddress && Cardano.PaymentAddress(walletAddress),
17+
value: {
18+
coins: COLLATERAL_AMOUNT_LOVELACES
19+
}
20+
};
21+
22+
try {
23+
await inMemoryWallet.createTxBuilder().addOutput(output).build().inspect();
24+
setHasEnoughAda(true);
25+
} catch {
26+
setHasEnoughAda(false);
27+
}
28+
})();
29+
}, [addresses, inMemoryWallet]);
30+
31+
return hasEnoughAda;
32+
};

apps/browser-extension-wallet/src/utils/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ export const EPOCH_DURATION_DAYS = 5;
2020

2121
export const MIN_COIN_TO_SEND = 1;
2222

23+
export const COLLATERAL_ADA_AMOUNT = 5;
24+
export const COLLATERAL_AMOUNT_LOVELACES = BigInt(Wallet.util.adaToLovelacesString(String(COLLATERAL_ADA_AMOUNT)));
25+
2326
type StaticBalanceTracker = {
2427
rewardAccounts: {
2528
rewards$: Wallet.Cardano.Lovelace;

apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsWalletBase.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { NetworkChoiceDrawer } from './NetworkChoiceDrawer';
99
import { useWalletStore } from '@src/stores';
1010
import { AboutDrawer } from './AboutDrawer';
1111
import { config } from '@src/config';
12-
import { COLLATERAL_AMOUNT_LOVELACES, useCustomSubmitApi, useRedirection } from '@hooks';
12+
import { useCustomSubmitApi, useRedirection } from '@hooks';
1313
import { BrowserViewSections, MessageTypes } from '@lib/scripts/types';
1414
import { useAnalyticsContext, useBackgroundServiceAPIContext } from '@providers';
1515
import { useSearchParams, useObservable, Button } from '@lace/common';
@@ -19,6 +19,7 @@ import uniq from 'lodash/uniq';
1919
import { isKeyHashAddress } from '@cardano-sdk/wallet';
2020
import { AddressesDiscoveryStatus } from '@lib/communication/addresses-discoverer';
2121
import { CustomSubmitApiDrawer } from './CustomSubmitApiDrawer';
22+
import { COLLATERAL_AMOUNT_LOVELACES } from '@utils/constants';
2223

2324
const { Title } = Typography;
2425

apps/browser-extension-wallet/src/views/browser-view/features/settings/components/__tests__/SettingsWallet.test.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { SettingsWallet } from '../SettingsWallet';
1313
import '@testing-library/jest-dom';
1414
import { I18nextProvider } from 'react-i18next';
1515
import { StoreProvider } from '@src/stores';
16-
import { APP_MODE_BROWSER } from '@src/utils/constants';
16+
import { APP_MODE_BROWSER, COLLATERAL_AMOUNT_LOVELACES } from '@src/utils/constants';
1717
import { i18n } from '@lace/translation';
1818
import {
1919
AnalyticsProvider,
@@ -25,7 +25,6 @@ import {
2525
} from '@providers';
2626
import { BehaviorSubject } from 'rxjs';
2727
import { act } from 'react-dom/test-utils';
28-
import { COLLATERAL_AMOUNT_LOVELACES } from '@hooks';
2928
import { BrowserViewSections, MessageTypes } from '@lib/scripts/types';
3029
import * as hooks from '@hooks';
3130
import * as common from '@lace/common';

packages/e2e-tests/src/steps/analyticsSteps.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ export const validateEventProperty = async (event: string, property: string, pro
1616
interval: 1000,
1717
timeout: 6000,
1818
timeoutMsg: `Failed while waiting for event '${event}' contains property '${property}' equal to ${propertyValue}. Actual event property value = '${
19-
(await getEventPayload(event)).properties[property]
19+
(
20+
await getEventPayload(event)
21+
).properties[property]
2022
}'`
2123
}
2224
);
@@ -62,7 +64,9 @@ When(/^I validate that (\d+) analytics event\(s\) have been sent$/, async (numbe
6264
interval: 1000,
6365
timeout: 6000,
6466
timeoutMsg: `Failed while waiting for amount events sent: ${Number(numberOfRequests)}. Actual events amount sent: ${
65-
(await getAllEventsNames()).length
67+
(
68+
await getAllEventsNames()
69+
).length
6670
}\n
6771
Actual events:\n ${(await getAllEventsNames()).toString()}`
6872
});

0 commit comments

Comments
 (0)