Skip to content

Commit dcaba70

Browse files
authored
Merge pull request #2966 from input-output-hk/fix/ddw-1086-fix-phrasing-of-insufficient-funds-for-tokens-message
[DDW-1086] Fix phrasing of insufficient funds for tokens message
2 parents 64edaae + 721d1ed commit dcaba70

File tree

12 files changed

+150
-37
lines changed

12 files changed

+150
-37
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## vNext
4+
5+
### Fixes
6+
7+
- Fixed phrasing of insufficient funds for tokens message ([PR 2966](https://github.com/input-output-hk/daedalus/pull/2966))
8+
39
## 4.10.0
410

511
### Features

source/renderer/app/api/api.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -906,13 +906,15 @@ export default class AdaApi {
906906

907907
const {
908908
requiresAdaToRemainToSupportNativeTokens,
909-
adaToRemain,
909+
adaToProceed,
910910
} = doesWalletRequireAdaToRemainToSupportTokens(
911911
error,
912912
hasAssetsRemainingAfterTransaction
913913
);
914914
if (requiresAdaToRemainToSupportNativeTokens) {
915-
apiError.set('cannotLeaveWalletEmpty', true, { adaToRemain });
915+
apiError.set('cannotLeaveWalletEmpty', true, {
916+
adaAmount: adaToProceed,
917+
});
916918
}
917919

918920
throw apiError.result();

source/renderer/app/api/errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export const messages = defineMessages({
114114
cannotLeaveWalletEmpty: {
115115
id: 'api.errors.NotEnoughFundsForTransactionFeesErrorWithTokens',
116116
defaultMessage:
117-
'!!!Insufficient funds to support tokens. A minimum of {adaToRemain} ADA must remain in the wallet after this transaction.',
117+
'!!!Insufficient funds to support tokens. You need at least an additional {adaAmount} ADA in your wallet to process this transaction.',
118118
description:
119119
'"Balance after transaction would not leave enough ada in the wallet to support tokens remaining in wallet',
120120
},

source/renderer/app/api/utils/apiHelpers.spec.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,8 @@ describe('throw error if not enough Ada to support tokens', () => {
4848
requiresAdaToRemainToSupportNativeTokens: false,
4949
});
5050
});
51-
it('should throw if there are tokens remaining in wallet after transaction and error is "cannot_cover_fee" and round to 2 minimum ada', () => {
52-
const error: ErrorType = {
53-
message:
54-
'I am unable to finalize the transaction, as there is not enough ada available to pay for the fee and also pay for the minimum ada quantities of all change outputs. I need approximately 0.629344 ada to proceed. Try increasing your wallet balance or sending a smaller amount.',
55-
code: 'cannot_cover_fee',
56-
};
57-
58-
expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
59-
requiresAdaToRemainToSupportNativeTokens: true,
60-
adaToRemain: 2,
61-
});
62-
});
6351

64-
it('should throw if there are tokens remaining in wallet after transaction and error is "cannot_cover_fee" and round to 2 nearest whole value provided by error', () => {
52+
it('should throw if there are tokens remaining in wallet after transaction and error is "cannot_cover_fee"', () => {
6553
const error: ErrorType = {
6654
message:
6755
'I am unable to finalize the transaction, as there is not enough ada available to pay for the fee and also pay for the minimum ada quantities of all change outputs. I need approximately 2.629344 ada to proceed. Try increasing your wallet balance or sending a smaller amount.',
@@ -70,7 +58,7 @@ describe('throw error if not enough Ada to support tokens', () => {
7058

7159
expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
7260
requiresAdaToRemainToSupportNativeTokens: true,
73-
adaToRemain: 3,
61+
adaToProceed: 3,
7462
});
7563
});
7664
});

source/renderer/app/api/utils/apiHelpers.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,21 @@ export const doesWalletRequireAdaToRemainToSupportTokens = (
2727
hasAssetsRemainingAfterTransaction?: boolean
2828
): {
2929
requiresAdaToRemainToSupportNativeTokens: boolean;
30-
adaToRemain?: number;
30+
adaToProceed?: number;
3131
} => {
32-
const adaToProceedRegex = new RegExp(
33-
/.*I need approximately([\s\d.,]+)ada to proceed.*/
34-
);
32+
const adaToProceedRegex = /I need approximately\s+([\d.,]+)\s+ada to proceed/;
33+
34+
const [, adaToProceed] = adaToProceedRegex.exec(error.message) ?? [];
3535

3636
if (
3737
error.code === 'cannot_cover_fee' &&
3838
hasAssetsRemainingAfterTransaction &&
39-
adaToProceedRegex.test(error.message)
39+
adaToProceed
4040
) {
41-
const roundedAda = Math.ceil(
42-
Number(error.message.replace(adaToProceedRegex, '$1'))
43-
);
44-
const adaToRemain = roundedAda > 2 ? roundedAda : 2;
45-
return { requiresAdaToRemainToSupportNativeTokens: true, adaToRemain };
41+
return {
42+
requiresAdaToRemainToSupportNativeTokens: true,
43+
adaToProceed: Math.ceil(Number(adaToProceed)),
44+
};
4645
}
4746
return { requiresAdaToRemainToSupportNativeTokens: false };
4847
};
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import BigNumber from 'bignumber.js';
2+
import { hasAssetsAfterTransaction } from './helpers';
3+
4+
const assetWithOneQuantity = {
5+
policyId: 'policyId1',
6+
assetName: '54657374636f696e',
7+
quantity: new BigNumber(1),
8+
fingerprint: 'policyId154657374636f696e',
9+
metadata: {
10+
name: 'Testcoin',
11+
description: 'Test coin',
12+
},
13+
uniqueId: 'uniqueId1',
14+
decimals: 1,
15+
recommendedDecimals: null,
16+
};
17+
18+
const assetWithTenQuantity = {
19+
policyId: 'policyId2',
20+
assetName: '436f696e74657374',
21+
quantity: new BigNumber(10),
22+
fingerprint: 'policyId2436f696e74657374',
23+
uniqueId: 'uniqueId2',
24+
decimals: 1,
25+
recommendedDecimals: null,
26+
};
27+
28+
describe('hasAssetsAfterTransaction', () => {
29+
test('Should be true when wallet has assets and tx sending no assets', () => {
30+
expect(
31+
hasAssetsAfterTransaction({
32+
assetTokens: [assetWithOneQuantity, assetWithTenQuantity],
33+
selectedAssets: [],
34+
assetsAmounts: [],
35+
})
36+
).toEqual(true);
37+
});
38+
39+
test('Should be true when wallet has assets and tx is not sending all asset types', () => {
40+
expect(
41+
hasAssetsAfterTransaction({
42+
assetTokens: [assetWithOneQuantity, assetWithTenQuantity],
43+
selectedAssets: [assetWithTenQuantity],
44+
assetsAmounts: ['5'],
45+
})
46+
).toEqual(true);
47+
});
48+
49+
test('Should be true when wallet has assets and tx is not sending all assets', () => {
50+
expect(
51+
hasAssetsAfterTransaction({
52+
assetTokens: [assetWithOneQuantity, assetWithTenQuantity],
53+
selectedAssets: [assetWithOneQuantity, assetWithTenQuantity],
54+
assetsAmounts: ['1', '5'],
55+
})
56+
).toEqual(true);
57+
});
58+
59+
test('Should be false when wallet has no assets', () => {
60+
expect(
61+
hasAssetsAfterTransaction({
62+
assetTokens: [],
63+
selectedAssets: [],
64+
assetsAmounts: [],
65+
})
66+
).toEqual(false);
67+
});
68+
69+
test('Should be false when tx is sending all assets (1 asset)', () => {
70+
expect(
71+
hasAssetsAfterTransaction({
72+
assetTokens: [assetWithOneQuantity],
73+
selectedAssets: [assetWithOneQuantity],
74+
assetsAmounts: ['1'],
75+
})
76+
).toEqual(false);
77+
});
78+
79+
test('Should be false when tx is sending all assets (2 assets)', () => {
80+
expect(
81+
hasAssetsAfterTransaction({
82+
assetTokens: [assetWithOneQuantity, assetWithTenQuantity],
83+
selectedAssets: [assetWithOneQuantity, assetWithTenQuantity],
84+
assetsAmounts: ['1', '10'],
85+
})
86+
).toEqual(false);
87+
});
88+
});

source/renderer/app/containers/wallet/dialogs/send-confirmation/helpers.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import { AssetToken } from '../../../../api/assets/types';
77
import { HwDeviceStatuses } from '../../../../domains/Wallet';
88
import { FORM_VALIDATION_DEBOUNCE_WAIT } from '../../../../config/timingConfig';
99
import { formattedTokenWalletAmount } from '../../../../utils/formatters';
10-
import { CreateForm, FormFields, HasAssetsAfterTransaction } from './types';
10+
import {
11+
CreateForm,
12+
FormFields,
13+
HasAssetsAfterTransaction,
14+
IsSendingAllFromSelected,
15+
} from './types';
1116

1217
export const doTermsNeedAcceptance = ({ isFlight, areTermsAccepted }) =>
1318
!areTermsAccepted && isFlight;
@@ -25,13 +30,32 @@ export const isNotEnoughFundsForTokenError = (errorId) =>
2530
export const isPasswordValid = ({ isHardwareWallet, isValid }) =>
2631
isHardwareWallet || isValid;
2732

33+
export const isSendingAllFromSelected = ({
34+
selectedAssets = [],
35+
assetsAmounts = [],
36+
}: IsSendingAllFromSelected) =>
37+
Boolean(selectedAssets.length) &&
38+
selectedAssets.every(({ quantity }, i) =>
39+
quantity.isEqualTo(assetsAmounts?.[i])
40+
);
41+
2842
export const hasAssetsAfterTransaction = ({
2943
selectedAssets = [],
3044
assetTokens = [],
31-
}: HasAssetsAfterTransaction) =>
32-
selectedAssets.length
33-
? selectedAssets.length < assetTokens.length
34-
: assetTokens.length > 0;
45+
assetsAmounts = [],
46+
}: HasAssetsAfterTransaction) => {
47+
const sendingTokens = Boolean(selectedAssets.length);
48+
const hasTokens = Boolean(assetTokens.length);
49+
const sendingAllTokenTypes = selectedAssets.length === assetTokens.length;
50+
const sendingAllFromSelected = isSendingAllFromSelected({
51+
assetsAmounts,
52+
selectedAssets,
53+
});
54+
55+
return sendingTokens
56+
? !(sendingAllTokenTypes && sendingAllFromSelected)
57+
: hasTokens;
58+
};
3559

3660
export const getFormattedAssetAmount = (
3761
{ metadata, decimals }: AssetToken,

source/renderer/app/containers/wallet/dialogs/send-confirmation/hooks.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const useForm = ({
3939
hasAssetsRemainingAfterTransaction: hasAssetsAfterTransaction({
4040
assetTokens,
4141
selectedAssets,
42+
assetsAmounts,
4243
}),
4344
...(selectedAssets.length
4445
? { assets: selectedAssets, assetsAmounts }

source/renderer/app/containers/wallet/dialogs/send-confirmation/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,10 @@ export type CreateForm = Pick<ViewProps, 'intl' | 'isHardwareWallet'>;
9494

9595
export type HasAssetsAfterTransaction = Pick<
9696
ViewProps,
97-
'assetTokens' | 'selectedAssets'
97+
'assetTokens' | 'selectedAssets' | 'assetsAmounts'
98+
>;
99+
100+
export type IsSendingAllFromSelected = Pick<
101+
ViewProps,
102+
'selectedAssets' | 'assetsAmounts'
98103
>;

source/renderer/app/i18n/locales/defaultMessages.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@
287287
}
288288
},
289289
{
290-
"defaultMessage": "!!!Insufficient funds to support tokens. A minimum of {adaToRemain} ADA must remain in the wallet after this transaction.",
290+
"defaultMessage": "!!!Insufficient funds to support tokens. You need at least an additional {adaAmount} ADA in your wallet to process this transaction.",
291291
"description": "\"Balance after transaction would not leave enough ada in the wallet to support tokens remaining in wallet",
292292
"end": {
293293
"column": 3,

0 commit comments

Comments
 (0)