Skip to content

Commit

Permalink
Merge pull request #2966 from input-output-hk/fix/ddw-1086-fix-phrasi…
Browse files Browse the repository at this point in the history
…ng-of-insufficient-funds-for-tokens-message

[DDW-1086] Fix phrasing of insufficient funds for tokens message
  • Loading branch information
DominikGuzei committed May 17, 2022
2 parents 64edaae + 721d1ed commit dcaba70
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 37 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## vNext

### Fixes

- Fixed phrasing of insufficient funds for tokens message ([PR 2966](https://github.com/input-output-hk/daedalus/pull/2966))

## 4.10.0

### Features
Expand Down
6 changes: 4 additions & 2 deletions source/renderer/app/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -906,13 +906,15 @@ export default class AdaApi {

const {
requiresAdaToRemainToSupportNativeTokens,
adaToRemain,
adaToProceed,
} = doesWalletRequireAdaToRemainToSupportTokens(
error,
hasAssetsRemainingAfterTransaction
);
if (requiresAdaToRemainToSupportNativeTokens) {
apiError.set('cannotLeaveWalletEmpty', true, { adaToRemain });
apiError.set('cannotLeaveWalletEmpty', true, {
adaAmount: adaToProceed,
});
}

throw apiError.result();
Expand Down
2 changes: 1 addition & 1 deletion source/renderer/app/api/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export const messages = defineMessages({
cannotLeaveWalletEmpty: {
id: 'api.errors.NotEnoughFundsForTransactionFeesErrorWithTokens',
defaultMessage:
'!!!Insufficient funds to support tokens. A minimum of {adaToRemain} ADA must remain in the wallet after this transaction.',
'!!!Insufficient funds to support tokens. You need at least an additional {adaAmount} ADA in your wallet to process this transaction.',
description:
'"Balance after transaction would not leave enough ada in the wallet to support tokens remaining in wallet',
},
Expand Down
16 changes: 2 additions & 14 deletions source/renderer/app/api/utils/apiHelpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,8 @@ describe('throw error if not enough Ada to support tokens', () => {
requiresAdaToRemainToSupportNativeTokens: false,
});
});
it('should throw if there are tokens remaining in wallet after transaction and error is "cannot_cover_fee" and round to 2 minimum ada', () => {
const error: ErrorType = {
message:
'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.',
code: 'cannot_cover_fee',
};

expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
requiresAdaToRemainToSupportNativeTokens: true,
adaToRemain: 2,
});
});

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', () => {
it('should throw if there are tokens remaining in wallet after transaction and error is "cannot_cover_fee"', () => {
const error: ErrorType = {
message:
'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.',
Expand All @@ -70,7 +58,7 @@ describe('throw error if not enough Ada to support tokens', () => {

expect(doesWalletRequireAdaToRemainToSupportTokens(error, true)).toEqual({
requiresAdaToRemainToSupportNativeTokens: true,
adaToRemain: 3,
adaToProceed: 3,
});
});
});
19 changes: 9 additions & 10 deletions source/renderer/app/api/utils/apiHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,21 @@ export const doesWalletRequireAdaToRemainToSupportTokens = (
hasAssetsRemainingAfterTransaction?: boolean
): {
requiresAdaToRemainToSupportNativeTokens: boolean;
adaToRemain?: number;
adaToProceed?: number;
} => {
const adaToProceedRegex = new RegExp(
/.*I need approximately([\s\d.,]+)ada to proceed.*/
);
const adaToProceedRegex = /I need approximately\s+([\d.,]+)\s+ada to proceed/;

const [, adaToProceed] = adaToProceedRegex.exec(error.message) ?? [];

if (
error.code === 'cannot_cover_fee' &&
hasAssetsRemainingAfterTransaction &&
adaToProceedRegex.test(error.message)
adaToProceed
) {
const roundedAda = Math.ceil(
Number(error.message.replace(adaToProceedRegex, '$1'))
);
const adaToRemain = roundedAda > 2 ? roundedAda : 2;
return { requiresAdaToRemainToSupportNativeTokens: true, adaToRemain };
return {
requiresAdaToRemainToSupportNativeTokens: true,
adaToProceed: Math.ceil(Number(adaToProceed)),
};
}
return { requiresAdaToRemainToSupportNativeTokens: false };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import BigNumber from 'bignumber.js';
import { hasAssetsAfterTransaction } from './helpers';

const assetWithOneQuantity = {
policyId: 'policyId1',
assetName: '54657374636f696e',
quantity: new BigNumber(1),
fingerprint: 'policyId154657374636f696e',
metadata: {
name: 'Testcoin',
description: 'Test coin',
},
uniqueId: 'uniqueId1',
decimals: 1,
recommendedDecimals: null,
};

const assetWithTenQuantity = {
policyId: 'policyId2',
assetName: '436f696e74657374',
quantity: new BigNumber(10),
fingerprint: 'policyId2436f696e74657374',
uniqueId: 'uniqueId2',
decimals: 1,
recommendedDecimals: null,
};

describe('hasAssetsAfterTransaction', () => {
test('Should be true when wallet has assets and tx sending no assets', () => {
expect(
hasAssetsAfterTransaction({
assetTokens: [assetWithOneQuantity, assetWithTenQuantity],
selectedAssets: [],
assetsAmounts: [],
})
).toEqual(true);
});

test('Should be true when wallet has assets and tx is not sending all asset types', () => {
expect(
hasAssetsAfterTransaction({
assetTokens: [assetWithOneQuantity, assetWithTenQuantity],
selectedAssets: [assetWithTenQuantity],
assetsAmounts: ['5'],
})
).toEqual(true);
});

test('Should be true when wallet has assets and tx is not sending all assets', () => {
expect(
hasAssetsAfterTransaction({
assetTokens: [assetWithOneQuantity, assetWithTenQuantity],
selectedAssets: [assetWithOneQuantity, assetWithTenQuantity],
assetsAmounts: ['1', '5'],
})
).toEqual(true);
});

test('Should be false when wallet has no assets', () => {
expect(
hasAssetsAfterTransaction({
assetTokens: [],
selectedAssets: [],
assetsAmounts: [],
})
).toEqual(false);
});

test('Should be false when tx is sending all assets (1 asset)', () => {
expect(
hasAssetsAfterTransaction({
assetTokens: [assetWithOneQuantity],
selectedAssets: [assetWithOneQuantity],
assetsAmounts: ['1'],
})
).toEqual(false);
});

test('Should be false when tx is sending all assets (2 assets)', () => {
expect(
hasAssetsAfterTransaction({
assetTokens: [assetWithOneQuantity, assetWithTenQuantity],
selectedAssets: [assetWithOneQuantity, assetWithTenQuantity],
assetsAmounts: ['1', '10'],
})
).toEqual(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import { AssetToken } from '../../../../api/assets/types';
import { HwDeviceStatuses } from '../../../../domains/Wallet';
import { FORM_VALIDATION_DEBOUNCE_WAIT } from '../../../../config/timingConfig';
import { formattedTokenWalletAmount } from '../../../../utils/formatters';
import { CreateForm, FormFields, HasAssetsAfterTransaction } from './types';
import {
CreateForm,
FormFields,
HasAssetsAfterTransaction,
IsSendingAllFromSelected,
} from './types';

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

export const isSendingAllFromSelected = ({
selectedAssets = [],
assetsAmounts = [],
}: IsSendingAllFromSelected) =>
Boolean(selectedAssets.length) &&
selectedAssets.every(({ quantity }, i) =>
quantity.isEqualTo(assetsAmounts?.[i])
);

export const hasAssetsAfterTransaction = ({
selectedAssets = [],
assetTokens = [],
}: HasAssetsAfterTransaction) =>
selectedAssets.length
? selectedAssets.length < assetTokens.length
: assetTokens.length > 0;
assetsAmounts = [],
}: HasAssetsAfterTransaction) => {
const sendingTokens = Boolean(selectedAssets.length);
const hasTokens = Boolean(assetTokens.length);
const sendingAllTokenTypes = selectedAssets.length === assetTokens.length;
const sendingAllFromSelected = isSendingAllFromSelected({
assetsAmounts,
selectedAssets,
});

return sendingTokens
? !(sendingAllTokenTypes && sendingAllFromSelected)
: hasTokens;
};

export const getFormattedAssetAmount = (
{ metadata, decimals }: AssetToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const useForm = ({
hasAssetsRemainingAfterTransaction: hasAssetsAfterTransaction({
assetTokens,
selectedAssets,
assetsAmounts,
}),
...(selectedAssets.length
? { assets: selectedAssets, assetsAmounts }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,10 @@ export type CreateForm = Pick<ViewProps, 'intl' | 'isHardwareWallet'>;

export type HasAssetsAfterTransaction = Pick<
ViewProps,
'assetTokens' | 'selectedAssets'
'assetTokens' | 'selectedAssets' | 'assetsAmounts'
>;

export type IsSendingAllFromSelected = Pick<
ViewProps,
'selectedAssets' | 'assetsAmounts'
>;
2 changes: 1 addition & 1 deletion source/renderer/app/i18n/locales/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@
}
},
{
"defaultMessage": "!!!Insufficient funds to support tokens. A minimum of {adaToRemain} ADA must remain in the wallet after this transaction.",
"defaultMessage": "!!!Insufficient funds to support tokens. You need at least an additional {adaAmount} ADA in your wallet to process this transaction.",
"description": "\"Balance after transaction would not leave enough ada in the wallet to support tokens remaining in wallet",
"end": {
"column": 3,
Expand Down
2 changes: 1 addition & 1 deletion source/renderer/app/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"api.errors.IncorrectPasswordError": "Incorrect wallet password.",
"api.errors.NotEnoughFundsForTransactionError": "Not enough ada. Try sending a smaller amount.",
"api.errors.NotEnoughFundsForTransactionFeesError": "Not enough ada for fees. Try sending a smaller amount.",
"api.errors.NotEnoughFundsForTransactionFeesErrorWithTokens": "Insufficient funds to support tokens. A minimum of {adaToRemain} ADA must remain in the wallet after this transaction.",
"api.errors.NotEnoughFundsForTransactionFeesErrorWithTokens": "Insufficient funds to support tokens. You need at least an additional {adaAmount} ADA in your wallet to process this transaction.",
"api.errors.NotEnoughMoneyToSendError": "Not enough money to make this transaction.",
"api.errors.TooBigTransactionError": "Transaction too big due to too many inputs.",
"api.errors.TooBigTransactionErrorLinkLabel": "Learn more.",
Expand Down
4 changes: 2 additions & 2 deletions source/renderer/app/i18n/locales/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"api.errors.IncorrectPasswordError": "ウォレットパスワードが間違っています",
"api.errors.NotEnoughFundsForTransactionError": "ADAが不足しています。送金額を減らしてください。",
"api.errors.NotEnoughFundsForTransactionFeesError": "手数料分のADAが不足しています。送金額を減らしてください。",
"api.errors.NotEnoughFundsForTransactionFeesErrorWithTokens": "トークンをサポートする資金が不足しています。このトランザクションの後に、ウォレットに{adaToRemain} ADA以上残るようにしてください",
"api.errors.NotEnoughFundsForTransactionFeesErrorWithTokens": "トークンをサポートする資金が不足しています。このトランザクションを処理するためには、ウォレットに少なくともあと{adaAmount} ADAが必要です",
"api.errors.NotEnoughMoneyToSendError": "このトランザクションに必要な資金が不足しています。",
"api.errors.TooBigTransactionError": "入力過多によりトランザクションサイズが超過しています。",
"api.errors.TooBigTransactionErrorLinkLabel": "もっと知る。",
Expand Down Expand Up @@ -232,7 +232,7 @@
"loading.screen.updatingCardanoMessage": "Cardanoノードを更新しています",
"loading.screen.validatingChunk": "ディスクのブロックチェーンステータスの検証",
"loading.screen.validatingChunkDescription": "ブロックチェーンのハッシュ計算の整合性を検証します",
"news.newsfeed.empty": "Newsfeed is empty",
"news.newsfeed.empty": "ニュースフィードは空です",
"news.newsfeed.iconTooltip": "ニュースフィード",
"news.newsfeed.noFetch": "ニュースフィードを読み込んでいます...",
"news.newsfeed.title": "ニュースフィード",
Expand Down

0 comments on commit dcaba70

Please sign in to comment.