Skip to content

Commit

Permalink
Merge pull request #967 from tonwhales/fix/hub-1250
Browse files Browse the repository at this point in the history
fix: fixing limits change preview formatting for USDT
  • Loading branch information
vzhovnitsky authored Jun 21, 2024
2 parents 0f971d6 + a97d621 commit 41a2122
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 69 deletions.
40 changes: 29 additions & 11 deletions app/components/transfer/HoldersOpView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,32 @@ import { Typography } from "../styles";
import { t } from "../../i18n/t";
import { ItemDivider } from "../ItemDivider";
import { ItemGroup } from "../ItemGroup";
import { ContractKind } from "../../engine/api/fetchContractInfo";
import { toNano } from "@ton/core";
import { fromBnWithDecimals } from "../../utils/withDecimals";

export type HoldersOpType = {
export type HoldersOp = {
type: 'topUp';
amount: string;
} | {
type: 'jettonTopUp';
} | {
type: 'limitsChange';
onetime: string | null;
daily: string | null;
monthly: string | null;
onetime?: string | null;
daily?: string | null;
monthly?: string | null;
}

export const HoldersOpView = memo(({ theme, op }: { theme: ThemeType, op: HoldersOpType }) => {
function formatAmount(amount: string | null | undefined, type: 'USDT' | 'TON'): string | null {
if (!amount) {
return null;
}

// convert back to nano and format with decimals
return `${fromBnWithDecimals(toNano(amount), type === 'USDT' ? 6 : 9)} ${type}`;
}

export const HoldersOpView = memo(({ theme, op, targetKind }: { theme: ThemeType, op: HoldersOp, targetKind?: ContractKind }) => {
if (op.type === 'jettonTopUp') { // Jetton account top up (amount is shown in the Tx preview title)
return null;
}
Expand All @@ -41,49 +53,55 @@ export const HoldersOpView = memo(({ theme, op }: { theme: ThemeType, op: Holder
);
}

// We have no jetton address so are forced to use built-in decimals
const type = targetKind === 'jetton-card' ? 'USDT' : 'TON'
const onetime = formatAmount(op.onetime, type);
const daily = formatAmount(op.daily, type);
const monthly = formatAmount(op.monthly, type);

return (
<ItemGroup style={{ marginTop: 16 }}>
<PerfView style={{ paddingHorizontal: 10, justifyContent: 'center' }}>
<PerfText style={[{ color: theme.textSecondary, marginBottom: 8 }, Typography.regular17_24]}>
{t('known.holders.limitsTitle')}
</PerfText>
{!!op.onetime && (
{!!onetime && (
<>
<PerfView style={{ justifyContent: 'space-between', flexDirection: 'row', width: '100%' }}>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular15_20]}>
{t('known.holders.limitsOneTime')}
</PerfText>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular17_24]}>
{`${op.onetime} TON`}
{onetime}
</PerfText>
</PerfView>
{(!!op.daily || !!op.monthly) && (
<ItemDivider marginHorizontal={0} />
)}
</>
)}
{!!op.daily && (
{!!daily && (
<>
<PerfView style={{ justifyContent: 'space-between', flexDirection: 'row', width: '100%' }}>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular15_20]}>
{t('known.holders.limitsDaily')}
</PerfText>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular17_24]}>
{`${op.daily} TON`}
{daily}
</PerfText>
</PerfView>
{!!op.monthly && (
<ItemDivider marginHorizontal={0} />
)}
</>
)}
{!!op.monthly && (
{!!monthly && (
<PerfView style={{ justifyContent: 'space-between', flexDirection: 'row', width: '100%' }}>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular15_20]}>
{t('known.holders.limitsMonthly')}
</PerfText>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular17_24]}>
{`${op.monthly} TON`}
{monthly}
</PerfText>
</PerfView>
)}
Expand Down
2 changes: 2 additions & 0 deletions app/engine/api/fetchContractInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const contractKindCodec = z.enum([
'dedust-vault'
]);

export type ContractKind = z.infer<typeof contractKindCodec>;

const contractInfoCodec = z.object({
name: z.string(),
kind: contractKindCodec.optional(),
Expand Down
4 changes: 2 additions & 2 deletions app/engine/hooks/metadata/useContractInfo.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useQuery } from "@tanstack/react-query";
import { Queries } from "../../queries";
import { fetchContractInfo } from "../../api/fetchContractInfo";
import { ContractInfo, fetchContractInfo } from "../../api/fetchContractInfo";

export function useContractInfo(addressString: string | null) {
export function useContractInfo(addressString: string | null): ContractInfo {
const query = useQuery({
queryKey: Queries.ContractInfo(addressString ?? ''),
queryFn: async () => {
Expand Down
2 changes: 1 addition & 1 deletion app/engine/transactions/formatSupportedBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function formatSupportedBody(supportedMessage: SupportedMessage): { res:
const monthly = supportedMessage.data.monthly;

return {
res: 'known.holders.limitsChange',
res: 'known.holders.accountLimitsChange',
options: {
onetime: onetime === 0n ? undefined : fromNano(onetime),
daily: daily === 0n ? undefined : fromNano(daily),
Expand Down
85 changes: 35 additions & 50 deletions app/fragments/secure/components/TransferSingleView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ import { toBnWithDecimals } from "../../../utils/withDecimals";
import { avatarHash } from "../../../utils/avatarHash";
import { ContractMetadata } from "../../../engine/metadata/Metadata";
import { Typography } from "../../../components/styles";
import { ItemDivider } from "../../../components/ItemDivider";
import { PerfText } from "../../../components/basic/PerfText";
import { PerfView } from "../../../components/basic/PerfView";
import { useContractInfo } from "../../../engine/hooks/metadata/useContractInfo";
import { copyText } from "../../../utils/copyText";
import { ToastDuration, useToaster } from "../../../components/toast/ToastProvider";
import { ThemeType } from "../../../engine/state/theme";
import { ForcedAvatar, ForcedAvatarType } from "../../../components/avatar/ForcedAvatar";
import { HoldersOp, HoldersOpView } from "../../../components/transfer/HoldersOpView";

import WithStateInit from '@assets/ic_sign_contract.svg';
import IcAlert from '@assets/ic-alert.svg';
Expand Down Expand Up @@ -178,7 +176,7 @@ export const TransferSingleView = memo(({
if (isTargetLedger) {
return 'ledger';
}

if (targetContract?.kind === 'dedust-vault') {
return 'dedust';
}
Expand Down Expand Up @@ -247,6 +245,29 @@ export const TransferSingleView = memo(({
master: jetton?.master?.toString({ testOnly: isTestnet })
});

const holdersOp = useMemo<null | HoldersOp>(() => {
if (!operation?.op) {
return null;
}

if (operation.op.res === 'known.holders.accountTopUp') {
return {
type: 'topUp',
amount: operation.op.options.amount
};
} else if (operation.op.res === 'known.holders.accountJettonTopUp') {
return { type: 'jettonTopUp' };
} else if (operation.op.res === 'known.holders.accountLimitsChange') {
const onetime = operation.op.options.onetime === '0' ? null : operation.op.options.onetime;
const daily = operation.op.options.daily === '0' ? null : operation.op.options.daily;
const monthly = operation.op.options.monthly === '0' ? null : operation.op.options.monthly;

return { type: 'limitsChange', onetime, daily, monthly };
}

return null;
}, [operation?.op]);

return (
<View style={{ flexGrow: 1 }}>
<ScrollView
Expand Down Expand Up @@ -291,7 +312,7 @@ export const TransferSingleView = memo(({
</View>
</View>
)}
<ItemGroup style={{ marginBottom: 16, marginTop: 16, paddingTop: 27 }}>
<ItemGroup style={{ marginBottom: holdersOp ? 0 : 16, marginTop: 16, paddingTop: 27 }}>
<View style={{
backgroundColor: theme.divider,
height: 54,
Expand Down Expand Up @@ -372,7 +393,15 @@ export const TransferSingleView = memo(({
)}
</ItemGroup>

<ItemGroup style={{ marginBottom: 16 }}>
{!!holdersOp && (
<HoldersOpView
theme={theme}
op={holdersOp}
targetKind={targetContract?.kind}
/>
)}

<ItemGroup style={{ marginBottom: 16, marginTop: holdersOp ? 16 : 0 }}>
<View style={{ paddingHorizontal: 10, justifyContent: 'center' }}>
<Text style={{
fontSize: 13, lineHeight: 18, fontWeight: '400',
Expand Down Expand Up @@ -557,50 +586,6 @@ export const TransferSingleView = memo(({
{t(operation.op.res, operation.op.options)}
</Text>
</View>
{operation.op.res === 'known.holders.limitsChange' && (
<>
{!!operation.op.options.onetime && (
<>
<PerfView style={{ justifyContent: 'space-between', flexDirection: 'row', width: '100%' }}>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular15_20]}>
{t('known.holders.limitsOneTime')}
</PerfText>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular17_24]}>
{`${operation.op.options.onetime} TON`}
</PerfText>
</PerfView>
{(!!operation.op.options.daily || !!operation.op.options.monthly) && (
<ItemDivider marginHorizontal={0} />
)}
</>
)}
{!!operation.op.options.daily && (
<>
<PerfView style={{ justifyContent: 'space-between', flexDirection: 'row', width: '100%' }}>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular15_20]}>
{t('known.holders.limitsDaily')}
</PerfText>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular17_24]}>
{`${operation.op.options.daily} TON`}
</PerfText>
</PerfView>
{!!operation.op.options.monthly && (
<ItemDivider marginHorizontal={0} />
)}
</>
)}
{!!operation.op.options.monthly && (
<PerfView style={{ justifyContent: 'space-between', flexDirection: 'row', width: '100%' }}>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular15_20]}>
{t('known.holders.limitsMonthly')}
</PerfText>
<PerfText style={[{ color: theme.textPrimary }, Typography.regular17_24]}>
{`${operation.op.options.monthly} TON`}
</PerfText>
</PerfView>
)}
</>
)}
</View>
</>
)}
Expand Down
7 changes: 5 additions & 2 deletions app/fragments/wallet/PendingTxPreviewFragment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ import { parseBody } from "../../engine/transactions/parseWalletTransaction";
import { resolveOperation } from "../../engine/transactions/resolveOperation";
import { RoundButton } from "../../components/RoundButton";
import { pendingTxToTransferParams } from "../../utils/toTransferParams";
import { HoldersOpType, HoldersOpView } from "../../components/transfer/HoldersOpView";
import { HoldersOp, HoldersOpView } from "../../components/transfer/HoldersOpView";
import { ForcedAvatar, ForcedAvatarType } from "../../components/avatar/ForcedAvatar";
import { useContractInfo } from "../../engine/hooks/metadata/useContractInfo";

export type PendingTxPreviewParams = {
transaction: PendingTransaction;
Expand Down Expand Up @@ -89,6 +90,7 @@ const PendingTxPreview = () => {
const isOwn = appState.addresses.findIndex((a) => a.address.toString({ testOnly: isTestnet }) === opAddress) >= 0;

const { verified } = useVerifyJetton({ master: opAddress });
const targetContract = useContractInfo(opAddress || '');
const knownWallet = knownWallets[opAddress ?? ''];
const contact = addressBook.asContact(opAddress);
const isSpam = addressBook.isDenyAddress(opAddress);
Expand Down Expand Up @@ -169,7 +171,7 @@ const PendingTxPreview = () => {
decimals: tx.body?.type === 'token' && jetton ? jetton.decimals : undefined,
});

const holdersOp = useMemo<null | HoldersOpType>(() => {
const holdersOp = useMemo<null | HoldersOp>(() => {
if (params.forceAvatar !== 'holders') {
return null;
}
Expand Down Expand Up @@ -331,6 +333,7 @@ const PendingTxPreview = () => {
<HoldersOpView
theme={theme}
op={holdersOp}
targetKind={targetContract?.kind}
/>
)}
{!(dontShowComments && isSpam) && !!comment && (
Expand Down
7 changes: 4 additions & 3 deletions app/fragments/wallet/TransactionPreviewFragment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { AddressComponent } from "../../components/address/AddressComponent";
import { avatarHash } from "../../utils/avatarHash";
import { PreviewMessages } from "./views/preview/PreviewMessages";
import { BatchAvatars } from "../../components/avatar/BatchAvatars";
import { HoldersOpType, HoldersOpView } from "../../components/transfer/HoldersOpView";
import { HoldersOp, HoldersOpView } from "../../components/transfer/HoldersOpView";
import { previewToTransferParams } from "../../utils/toTransferParams";
import { useContractInfo } from "../../engine/hooks/metadata/useContractInfo";
import { ForcedAvatar, ForcedAvatarType } from "../../components/avatar/ForcedAvatar";
Expand Down Expand Up @@ -150,12 +150,12 @@ const TransactionPreview = () => {
const forceAvatar: ForcedAvatarType | undefined = useMemo(() => {
if (targetContract?.kind === 'dedust-vault') {
return 'dedust';
} else if (targetContract?.kind === 'card' || targetContract?.kind === 'jetton-card') {
} else if (targetContract?.kind === 'card' || targetContract?.kind === 'jetton-card') {
return 'holders';
}
}, [targetContract]);

const holdersOp = useMemo<null | HoldersOpType>(
const holdersOp = useMemo<null | HoldersOp>(
() => {
if (!operation.op) {
return null;
Expand Down Expand Up @@ -465,6 +465,7 @@ const TransactionPreview = () => {
<HoldersOpView
theme={theme}
op={holdersOp}
targetKind={targetContract?.kind}
/>
)}
{
Expand Down

0 comments on commit 41a2122

Please sign in to comment.