more no enough balance description
This commit is contained in:
parent
378cc9125d
commit
6f24b5a05e
@ -17,6 +17,7 @@
|
|||||||
import {
|
import {
|
||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
|
PayMerchantInsufficientBalanceDetails,
|
||||||
PreparePayResult,
|
PreparePayResult,
|
||||||
PreparePayResultType,
|
PreparePayResultType,
|
||||||
TranslatedString,
|
TranslatedString,
|
||||||
@ -35,7 +36,6 @@ import { assertUnreachable } from "../utils/index.js";
|
|||||||
interface Props {
|
interface Props {
|
||||||
payStatus: PreparePayResult;
|
payStatus: PreparePayResult;
|
||||||
payHandler: ButtonHandler | undefined;
|
payHandler: ButtonHandler | undefined;
|
||||||
balance: AmountJson | undefined;
|
|
||||||
uri: string;
|
uri: string;
|
||||||
amount: AmountJson;
|
amount: AmountJson;
|
||||||
goToWalletManualWithdraw: (currency: string) => Promise<void>;
|
goToWalletManualWithdraw: (currency: string) => Promise<void>;
|
||||||
@ -45,7 +45,6 @@ export function PaymentButtons({
|
|||||||
payStatus,
|
payStatus,
|
||||||
uri,
|
uri,
|
||||||
payHandler,
|
payHandler,
|
||||||
balance,
|
|
||||||
amount,
|
amount,
|
||||||
goToWalletManualWithdraw,
|
goToWalletManualWithdraw,
|
||||||
}: Props): VNode {
|
}: Props): VNode {
|
||||||
@ -73,16 +72,58 @@ export function PaymentButtons({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (payStatus.status === PreparePayResultType.InsufficientBalance) {
|
if (payStatus.status === PreparePayResultType.InsufficientBalance) {
|
||||||
|
const reason = getReason(payStatus.balanceDetails);
|
||||||
|
|
||||||
let BalanceMessage = "";
|
let BalanceMessage = "";
|
||||||
if (!balance) {
|
switch (reason) {
|
||||||
BalanceMessage = i18n.str`You have no balance for this currency. Withdraw digital cash first.`;
|
case "age-acceptable": {
|
||||||
} else {
|
BalanceMessage = i18n.str`Balance is not enough because you have ${Amounts.stringifyValue(
|
||||||
const balanceShouldBeEnough = Amounts.cmp(balance, amount) !== -1;
|
payStatus.balanceDetails.balanceAgeAcceptable,
|
||||||
if (balanceShouldBeEnough) {
|
)} ${amount.currency} to pay for contracts restricted for age above ${
|
||||||
BalanceMessage = i18n.str`Could not find enough coins to pay. Even if you have enough ${balance.currency} some restriction may apply.`;
|
payStatus.contractTerms.minimum_age
|
||||||
} else {
|
} years old`;
|
||||||
BalanceMessage = i18n.str`Your current balance is not enough.`;
|
break;
|
||||||
}
|
}
|
||||||
|
case "available": {
|
||||||
|
BalanceMessage = i18n.str`Balance is not enough because you have ${Amounts.stringifyValue(
|
||||||
|
payStatus.balanceDetails.balanceAvailable,
|
||||||
|
)} ${amount.currency} available.`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "merchant-acceptable": {
|
||||||
|
BalanceMessage = i18n.str`Balance is not enough because merchant will just accept ${Amounts.stringifyValue(
|
||||||
|
payStatus.balanceDetails.balanceMerchantAcceptable,
|
||||||
|
)} ${
|
||||||
|
amount.currency
|
||||||
|
} . To know more you can check which exchange and auditors the merchant trust.`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "merchant-depositable": {
|
||||||
|
BalanceMessage = i18n.str`Balance is not enough because merchant will just accept ${Amounts.stringifyValue(
|
||||||
|
payStatus.balanceDetails.balanceMerchantDepositable,
|
||||||
|
)} ${
|
||||||
|
amount.currency
|
||||||
|
} . To know more you can check which wire methods the merchant accepts.`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "material": {
|
||||||
|
BalanceMessage = i18n.str`Balance is not enough because you have ${Amounts.stringifyValue(
|
||||||
|
payStatus.balanceDetails.balanceMaterial,
|
||||||
|
)} ${
|
||||||
|
amount.currency
|
||||||
|
} to spend right know. There are some coins that need to be refreshed.`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "fee-gap": {
|
||||||
|
BalanceMessage = i18n.str`Balance looks like it should be enough, but doesn't cover all fees requested by the merchant and payment processor. Please ensure there is at least ${Amounts.stringifyValue(
|
||||||
|
payStatus.balanceDetails.feeGapEstimate,
|
||||||
|
)} ${
|
||||||
|
amount.currency
|
||||||
|
} more balance in your wallet or ask your merchant to cover more of the fees.`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assertUnreachable(reason);
|
||||||
}
|
}
|
||||||
const uriPrivate = `${uri}&n=${payStatus.noncePriv}`;
|
const uriPrivate = `${uri}&n=${payStatus.noncePriv}`;
|
||||||
|
|
||||||
@ -150,3 +191,32 @@ function PayWithMobile({ uri }: { uri: string }): VNode {
|
|||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NoEnoughBalanceReason =
|
||||||
|
| "available"
|
||||||
|
| "material"
|
||||||
|
| "age-acceptable"
|
||||||
|
| "merchant-acceptable"
|
||||||
|
| "merchant-depositable"
|
||||||
|
| "fee-gap";
|
||||||
|
|
||||||
|
function getReason(
|
||||||
|
info: PayMerchantInsufficientBalanceDetails,
|
||||||
|
): NoEnoughBalanceReason {
|
||||||
|
if (Amounts.cmp(info.amountRequested, info.balanceAvailable)) {
|
||||||
|
return "available";
|
||||||
|
}
|
||||||
|
if (Amounts.cmp(info.amountRequested, info.balanceMaterial)) {
|
||||||
|
return "material";
|
||||||
|
}
|
||||||
|
if (Amounts.cmp(info.amountRequested, info.balanceAgeAcceptable)) {
|
||||||
|
return "age-acceptable";
|
||||||
|
}
|
||||||
|
if (Amounts.cmp(info.amountRequested, info.balanceMerchantAcceptable)) {
|
||||||
|
return "merchant-acceptable";
|
||||||
|
}
|
||||||
|
if (Amounts.cmp(info.amountRequested, info.balanceMerchantDepositable)) {
|
||||||
|
return "merchant-depositable";
|
||||||
|
}
|
||||||
|
return "fee-gap";
|
||||||
|
}
|
||||||
|
@ -28,8 +28,7 @@ export function ReadyView(
|
|||||||
state: State.Ready | State.NoBalanceForCurrency | State.NoEnoughBalance,
|
state: State.Ready | State.NoBalanceForCurrency | State.NoEnoughBalance,
|
||||||
): VNode {
|
): VNode {
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
const { summary, amount, expiration, uri, status, balance, payStatus } =
|
const { summary, amount, expiration, uri, status, payStatus } = state;
|
||||||
state;
|
|
||||||
return (
|
return (
|
||||||
<WalletAction>
|
<WalletAction>
|
||||||
<LogoHeader />
|
<LogoHeader />
|
||||||
@ -47,7 +46,6 @@ export function ReadyView(
|
|||||||
</section>
|
</section>
|
||||||
<PaymentButtons
|
<PaymentButtons
|
||||||
amount={amount}
|
amount={amount}
|
||||||
balance={balance}
|
|
||||||
payStatus={payStatus}
|
payStatus={payStatus}
|
||||||
uri={uri}
|
uri={uri}
|
||||||
payHandler={status === "ready" ? state.accept : undefined}
|
payHandler={status === "ready" ? state.accept : undefined}
|
||||||
|
@ -36,16 +36,28 @@ export default {
|
|||||||
argTypes: {},
|
argTypes: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NoBalance = tests.createExample(BaseView, {
|
export const NoEnoughBalanceAvailable = tests.createExample(BaseView, {
|
||||||
status: "no-balance-for-currency",
|
status: "no-enough-balance",
|
||||||
error: undefined,
|
error: undefined,
|
||||||
amount: Amounts.parseOrThrow("USD:10"),
|
amount: Amounts.parseOrThrow("USD:10"),
|
||||||
balance: undefined,
|
balance: {
|
||||||
|
currency: "USD",
|
||||||
|
fraction: 40000000,
|
||||||
|
value: 12,
|
||||||
|
},
|
||||||
|
|
||||||
uri: "",
|
uri: "",
|
||||||
payStatus: {
|
payStatus: {
|
||||||
status: PreparePayResultType.InsufficientBalance,
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
balanceDetails: {} as any,
|
balanceDetails: {
|
||||||
|
amountRequested: "USD:10",
|
||||||
|
balanceAvailable: "USD:9",
|
||||||
|
balanceMaterial: "USD:9",
|
||||||
|
balanceAgeAcceptable: "USD:9",
|
||||||
|
balanceMerchantAcceptable: "USD:9",
|
||||||
|
balanceMerchantDepositable: "USD:9",
|
||||||
|
feeGapEstimate: "USD:1",
|
||||||
|
},
|
||||||
talerUri: "taler://pay/..",
|
talerUri: "taler://pay/..",
|
||||||
noncePriv: "",
|
noncePriv: "",
|
||||||
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||||
@ -63,20 +75,28 @@ export const NoBalance = tests.createExample(BaseView, {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const NoEnoughBalance = tests.createExample(BaseView, {
|
export const NoEnoughBalanceMaterial = tests.createExample(BaseView, {
|
||||||
status: "no-enough-balance",
|
status: "no-enough-balance",
|
||||||
error: undefined,
|
error: undefined,
|
||||||
amount: Amounts.parseOrThrow("USD:10"),
|
amount: Amounts.parseOrThrow("USD:10"),
|
||||||
balance: {
|
balance: {
|
||||||
currency: "USD",
|
currency: "USD",
|
||||||
fraction: 40000000,
|
fraction: 40000000,
|
||||||
value: 9,
|
value: 12,
|
||||||
},
|
},
|
||||||
|
|
||||||
uri: "",
|
uri: "",
|
||||||
payStatus: {
|
payStatus: {
|
||||||
status: PreparePayResultType.InsufficientBalance,
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
balanceDetails: {} as any,
|
balanceDetails: {
|
||||||
|
amountRequested: "USD:10",
|
||||||
|
balanceAvailable: "USD:10",
|
||||||
|
balanceMaterial: "USD:9",
|
||||||
|
balanceAgeAcceptable: "USD:9",
|
||||||
|
balanceMerchantAcceptable: "USD:9",
|
||||||
|
balanceMerchantDepositable: "USD:0",
|
||||||
|
feeGapEstimate: "USD:1",
|
||||||
|
},
|
||||||
talerUri: "taler://pay/..",
|
talerUri: "taler://pay/..",
|
||||||
noncePriv: "",
|
noncePriv: "",
|
||||||
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||||
@ -94,20 +114,28 @@ export const NoEnoughBalance = tests.createExample(BaseView, {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const EnoughBalanceButRestricted = tests.createExample(BaseView, {
|
export const NoEnoughBalanceAgeAcceptable = tests.createExample(BaseView, {
|
||||||
status: "no-enough-balance",
|
status: "no-enough-balance",
|
||||||
error: undefined,
|
error: undefined,
|
||||||
amount: Amounts.parseOrThrow("USD:10"),
|
amount: Amounts.parseOrThrow("USD:10"),
|
||||||
balance: {
|
balance: {
|
||||||
currency: "USD",
|
currency: "USD",
|
||||||
fraction: 40000000,
|
fraction: 40000000,
|
||||||
value: 19,
|
value: 12,
|
||||||
},
|
},
|
||||||
|
|
||||||
uri: "",
|
uri: "",
|
||||||
payStatus: {
|
payStatus: {
|
||||||
status: PreparePayResultType.InsufficientBalance,
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
balanceDetails: {} as any,
|
balanceDetails: {
|
||||||
|
amountRequested: "USD:10",
|
||||||
|
balanceAvailable: "USD:10",
|
||||||
|
balanceMaterial: "USD:10",
|
||||||
|
balanceAgeAcceptable: "USD:9",
|
||||||
|
balanceMerchantAcceptable: "USD:9",
|
||||||
|
balanceMerchantDepositable: "USD:9",
|
||||||
|
feeGapEstimate: "USD:1",
|
||||||
|
},
|
||||||
talerUri: "taler://pay/..",
|
talerUri: "taler://pay/..",
|
||||||
noncePriv: "",
|
noncePriv: "",
|
||||||
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||||
@ -118,6 +146,128 @@ export const EnoughBalanceButRestricted = tests.createExample(BaseView, {
|
|||||||
website: "https://www.themerchant.taler",
|
website: "https://www.themerchant.taler",
|
||||||
email: "contact@merchant.taler",
|
email: "contact@merchant.taler",
|
||||||
},
|
},
|
||||||
|
minimum_age: 18,
|
||||||
|
summary: "some beers",
|
||||||
|
amount: "USD:10",
|
||||||
|
} as Partial<ContractTerms> as any,
|
||||||
|
amountRaw: "USD:10",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const NoEnoughBalanceMerchantAcceptable = tests.createExample(BaseView, {
|
||||||
|
status: "no-enough-balance",
|
||||||
|
error: undefined,
|
||||||
|
amount: Amounts.parseOrThrow("USD:10"),
|
||||||
|
balance: {
|
||||||
|
currency: "USD",
|
||||||
|
fraction: 40000000,
|
||||||
|
value: 12,
|
||||||
|
},
|
||||||
|
|
||||||
|
uri: "",
|
||||||
|
payStatus: {
|
||||||
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
|
balanceDetails: {
|
||||||
|
amountRequested: "USD:10",
|
||||||
|
balanceAvailable: "USD:10",
|
||||||
|
balanceMaterial: "USD:10",
|
||||||
|
balanceAgeAcceptable: "USD:10",
|
||||||
|
balanceMerchantAcceptable: "USD:9",
|
||||||
|
balanceMerchantDepositable: "USD:9",
|
||||||
|
feeGapEstimate: "USD:1",
|
||||||
|
},
|
||||||
|
talerUri: "taler://pay/..",
|
||||||
|
noncePriv: "",
|
||||||
|
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||||
|
contractTerms: {
|
||||||
|
merchant: {
|
||||||
|
name: "the merchant",
|
||||||
|
logo: merchantIcon,
|
||||||
|
website: "https://www.themerchant.taler",
|
||||||
|
email: "contact@merchant.taler",
|
||||||
|
},
|
||||||
|
summary: "some beers",
|
||||||
|
amount: "USD:10",
|
||||||
|
} as Partial<ContractTerms> as any,
|
||||||
|
amountRaw: "USD:10",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const NoEnoughBalanceMerchantDepositable = tests.createExample(
|
||||||
|
BaseView,
|
||||||
|
{
|
||||||
|
status: "no-enough-balance",
|
||||||
|
error: undefined,
|
||||||
|
amount: Amounts.parseOrThrow("USD:10"),
|
||||||
|
balance: {
|
||||||
|
currency: "USD",
|
||||||
|
fraction: 40000000,
|
||||||
|
value: 12,
|
||||||
|
},
|
||||||
|
|
||||||
|
uri: "",
|
||||||
|
payStatus: {
|
||||||
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
|
balanceDetails: {
|
||||||
|
amountRequested: "USD:10",
|
||||||
|
balanceAvailable: "USD:10",
|
||||||
|
balanceMaterial: "USD:10",
|
||||||
|
balanceAgeAcceptable: "USD:10",
|
||||||
|
balanceMerchantAcceptable: "USD:10",
|
||||||
|
balanceMerchantDepositable: "USD:9",
|
||||||
|
feeGapEstimate: "USD:1",
|
||||||
|
},
|
||||||
|
talerUri: "taler://pay/..",
|
||||||
|
noncePriv: "",
|
||||||
|
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||||
|
contractTerms: {
|
||||||
|
merchant: {
|
||||||
|
name: "the merchant",
|
||||||
|
logo: merchantIcon,
|
||||||
|
website: "https://www.themerchant.taler",
|
||||||
|
email: "contact@merchant.taler",
|
||||||
|
},
|
||||||
|
summary: "some beers",
|
||||||
|
amount: "USD:10",
|
||||||
|
} as Partial<ContractTerms> as any,
|
||||||
|
amountRaw: "USD:10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export const NoEnoughBalanceFeeGap = tests.createExample(BaseView, {
|
||||||
|
status: "no-enough-balance",
|
||||||
|
error: undefined,
|
||||||
|
amount: Amounts.parseOrThrow("USD:10"),
|
||||||
|
balance: {
|
||||||
|
currency: "USD",
|
||||||
|
fraction: 40000000,
|
||||||
|
value: 12,
|
||||||
|
},
|
||||||
|
|
||||||
|
uri: "",
|
||||||
|
payStatus: {
|
||||||
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
|
balanceDetails: {
|
||||||
|
amountRequested: "USD:10",
|
||||||
|
balanceAvailable: "USD:10",
|
||||||
|
balanceMaterial: "USD:10",
|
||||||
|
balanceAgeAcceptable: "USD:10",
|
||||||
|
balanceMerchantAcceptable: "USD:10",
|
||||||
|
balanceMerchantDepositable: "USD:10",
|
||||||
|
feeGapEstimate: "USD:1",
|
||||||
|
},
|
||||||
|
talerUri: "taler://pay/..",
|
||||||
|
noncePriv: "",
|
||||||
|
proposalId: "96YY92RQZGF3V7TJSPN4SF9549QX7BRF88Q5PYFCSBNQ0YK4RPK0",
|
||||||
|
contractTerms: {
|
||||||
|
merchant: {
|
||||||
|
name: "the merchant",
|
||||||
|
logo: merchantIcon,
|
||||||
|
website: "https://www.themerchant.taler",
|
||||||
|
email: "contact@merchant.taler",
|
||||||
|
},
|
||||||
|
minimum_age: 18,
|
||||||
summary: "some beers",
|
summary: "some beers",
|
||||||
amount: "USD:10",
|
amount: "USD:10",
|
||||||
} as Partial<ContractTerms> as any,
|
} as Partial<ContractTerms> as any,
|
||||||
|
@ -105,7 +105,6 @@ export function BaseView(state: SupportedStates): VNode {
|
|||||||
</section>
|
</section>
|
||||||
<PaymentButtons
|
<PaymentButtons
|
||||||
amount={state.amount}
|
amount={state.amount}
|
||||||
balance={state.balance}
|
|
||||||
payStatus={state.payStatus}
|
payStatus={state.payStatus}
|
||||||
uri={state.uri}
|
uri={state.uri}
|
||||||
payHandler={state.status === "ready" ? state.payHandler : undefined}
|
payHandler={state.status === "ready" ? state.payHandler : undefined}
|
||||||
|
Loading…
Reference in New Issue
Block a user