diff --git a/packages/frontend-main/src/components/popups/DislikePostDialog.vue b/packages/frontend-main/src/components/popups/DislikePostDialog.vue index 9260e308..a73b0ee8 100644 --- a/packages/frontend-main/src/components/popups/DislikePostDialog.vue +++ b/packages/frontend-main/src/components/popups/DislikePostDialog.vue @@ -9,9 +9,9 @@ import { Button } from '@/components/ui/button'; import { Dialog, DialogTitle, ResponsiveDialogContent } from '@/components/ui/dialog'; import InputPhoton from '@/components/ui/input/InputPhoton.vue'; import { useDislikePost } from '@/composables/useDislikePost'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useTxDialog } from '@/composables/useTxDialog'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { shorten } from '@/utility/text'; import { showBroadcastingToast } from '@/utility/toast'; @@ -21,11 +21,14 @@ const isBalanceInputValid = ref(false); const { dislikePost, txError, txSuccess } = useDislikePost(); const { isShown, inputPhotonModel, handleClose, popupState: dislike } = useTxDialog('dislike', txSuccess, txError); const configStore = useConfigStore(); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const fractionalDigits = useFractionalDigits(); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); -const canSubmit = computed(() => { - return isBalanceInputValid.value; -}); +const canSubmit = computed(() => isBalanceInputValid.value); function handleInputValidity(value: boolean) { isBalanceInputValid.value = value; diff --git a/packages/frontend-main/src/components/popups/FlagPostDialog.vue b/packages/frontend-main/src/components/popups/FlagPostDialog.vue index 465433e6..d1608674 100644 --- a/packages/frontend-main/src/components/popups/FlagPostDialog.vue +++ b/packages/frontend-main/src/components/popups/FlagPostDialog.vue @@ -9,9 +9,9 @@ import { Button } from '@/components/ui/button'; import { Dialog, DialogTitle, ResponsiveDialogContent } from '@/components/ui/dialog'; import InputPhoton from '@/components/ui/input/InputPhoton.vue'; import { useFlagPost } from '@/composables/useFlagPost'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useTxDialog } from '@/composables/useTxDialog'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { showBroadcastingToast } from '@/utility/toast'; import PostMessage from '../posts/PostMessage.vue'; @@ -28,11 +28,14 @@ const { handleClose, } = useTxDialog('flag', txSuccess, txError); const configStore = useConfigStore(); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const fractionalDigits = useFractionalDigits(); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); -const canSubmit = computed(() => { - return isBalanceInputValid.value; -}); +const canSubmit = computed(() => isBalanceInputValid.value); function handleInputValidity(value: boolean) { isBalanceInputValid.value = value; diff --git a/packages/frontend-main/src/components/popups/FollowUserDialog.vue b/packages/frontend-main/src/components/popups/FollowUserDialog.vue index dc2c8f0b..7f30c3cf 100644 --- a/packages/frontend-main/src/components/popups/FollowUserDialog.vue +++ b/packages/frontend-main/src/components/popups/FollowUserDialog.vue @@ -7,9 +7,9 @@ import { Button } from '@/components/ui/button'; import { Dialog, DialogTitle, ResponsiveDialogContent } from '@/components/ui/dialog'; import InputPhoton from '@/components/ui/input/InputPhoton.vue'; import { useFollowUser } from '@/composables/useFollowUser'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useTxDialog } from '@/composables/useTxDialog'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { showBroadcastingToast } from '@/utility/toast'; import DialogDescription from '../ui/dialog/DialogDescription.vue'; @@ -24,11 +24,14 @@ const { handleClose, } = useTxDialog('follow', txSuccess, txError); const configStore = useConfigStore(); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const fractionalDigits = useFractionalDigits(); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); -const canSubmit = computed(() => { - return isBalanceInputValid.value; -}); +const canSubmit = computed(() => isBalanceInputValid.value); function handleInputValidity(value: boolean) { isBalanceInputValid.value = value; diff --git a/packages/frontend-main/src/components/popups/LikePostDialog.vue b/packages/frontend-main/src/components/popups/LikePostDialog.vue index d5677fb6..5a9c4d6c 100644 --- a/packages/frontend-main/src/components/popups/LikePostDialog.vue +++ b/packages/frontend-main/src/components/popups/LikePostDialog.vue @@ -8,10 +8,10 @@ import { toast } from 'vue-sonner'; import { Button } from '@/components/ui/button'; import { Dialog, DialogDescription, DialogTitle, ResponsiveDialogContent } from '@/components/ui/dialog'; import InputPhoton from '@/components/ui/input/InputPhoton.vue'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useLikePost } from '@/composables/useLikePost'; import { useTxDialog } from '@/composables/useTxDialog'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { shorten } from '@/utility/text'; import { showBroadcastingToast } from '@/utility/toast'; @@ -19,11 +19,14 @@ const isBalanceInputValid = ref(false); const { likePost, txError, txSuccess } = useLikePost(); const { isShown, inputPhotonModel, handleClose, popupState: like } = useTxDialog('like', txSuccess, txError); const configStore = useConfigStore(); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const fractionalDigits = useFractionalDigits(); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); -const canSubmit = computed(() => { - return isBalanceInputValid.value; -}); +const canSubmit = computed(() => isBalanceInputValid.value); function handleInputValidity(value: boolean) { isBalanceInputValid.value = value; @@ -33,9 +36,11 @@ async function handleSubmit() { if (!canSubmit.value || !like.value) { return; } + const post = ref(like.value); handleClose(); const toastId = showBroadcastingToast('Like'); + try { await likePost({ post, amountAtomics: amountAtomics.value }); } finally { diff --git a/packages/frontend-main/src/components/popups/NewPostDialog.vue b/packages/frontend-main/src/components/popups/NewPostDialog.vue index 787edc3d..4314801a 100644 --- a/packages/frontend-main/src/components/popups/NewPostDialog.vue +++ b/packages/frontend-main/src/components/popups/NewPostDialog.vue @@ -5,9 +5,7 @@ import { toast } from 'vue-sonner'; import PostEditorToolbar from '@/components/posts/PostEditorToolbar.vue'; import PostMediaThumbnail from '@/components/posts/PostMediaThumbnail.vue'; -import -{ Button } - from '@/components/ui/button'; +import { Button } from '@/components/ui/button'; import { Dialog, DialogTitle, @@ -17,9 +15,9 @@ import InputPhoton from '@/components/ui/input/InputPhoton.vue'; import { Textarea } from '@/components/ui/textarea'; import { useConfirmDialog } from '@/composables/useConfirmDialog'; import { useCreatePost } from '@/composables/useCreatePost'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useTxDialog } from '@/composables/useTxDialog'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { showBroadcastingToast } from '@/utility/toast'; const MAX_CHARS = 512 - 'dither.Post("")'.length; @@ -31,15 +29,18 @@ const { showConfirmDialog } = useConfirmDialog(); const { isShown, inputPhotonModel, handleClose } = useTxDialog('newPost', txSuccess, txError); const configStore = useConfigStore(); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const fractionalDigits = useFractionalDigits(); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); function handleInputValidity(value: boolean) { isBalanceInputValid.value = value; } -const canSubmit = computed(() => { - return isBalanceInputValid.value && message.value.length > 0; -}); +const canSubmit = computed(() => isBalanceInputValid.value && message.value.length > 0); function handleCloseWithSaveDraft() { handleClose(); diff --git a/packages/frontend-main/src/components/popups/ReplyDialog.vue b/packages/frontend-main/src/components/popups/ReplyDialog.vue index 45fe967f..e461e7dc 100644 --- a/packages/frontend-main/src/components/popups/ReplyDialog.vue +++ b/packages/frontend-main/src/components/popups/ReplyDialog.vue @@ -14,9 +14,9 @@ import { Textarea } from '@/components/ui/textarea'; import UserAvatar from '@/components/users/UserAvatar.vue'; import Username from '@/components/users/Username.vue'; import { useCreateReply } from '@/composables/useCreateReply'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useTxDialog } from '@/composables/useTxDialog'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { showBroadcastingToast } from '@/utility/toast'; const POST_HASH_LEN = 64; @@ -32,7 +32,12 @@ const { popupState: reply, handleClose, } = useTxDialog('reply', txSuccess, txError); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const fractionalDigits = useFractionalDigits(); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); const canSubmit = computed(() => configStore.config.defaultAmountEnabled || (isBalanceInputValid.value && message.value.length > 0)); async function handleSubmit() { diff --git a/packages/frontend-main/src/components/popups/TipUserDialog.vue b/packages/frontend-main/src/components/popups/TipUserDialog.vue index 195114c9..d3ec9f5a 100644 --- a/packages/frontend-main/src/components/popups/TipUserDialog.vue +++ b/packages/frontend-main/src/components/popups/TipUserDialog.vue @@ -6,10 +6,10 @@ import { toast } from 'vue-sonner'; import { Button } from '@/components/ui/button'; import { Dialog, DialogTitle, ResponsiveDialogContent } from '@/components/ui/dialog'; import InputPhoton from '@/components/ui/input/InputPhoton.vue'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useTipUser } from '@/composables/useTipUser'; import { useTxDialog } from '@/composables/useTxDialog'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { showBroadcastingToast } from '@/utility/toast'; import DialogDescription from '../ui/dialog/DialogDescription.vue'; @@ -25,11 +25,14 @@ const { handleClose, } = useTxDialog('tipUser', txSuccess, txError); const configStore = useConfigStore(); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const fractionalDigits = useFractionalDigits(); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); -const canSubmit = computed(() => { - return isBalanceInputValid.value; -}); +const canSubmit = computed(() => isBalanceInputValid.value); function handleInputValidity(value: boolean) { isBalanceInputValid.value = value; diff --git a/packages/frontend-main/src/components/popups/UnfollowUserDialog.vue b/packages/frontend-main/src/components/popups/UnfollowUserDialog.vue index 4ac9478a..fb0408b4 100644 --- a/packages/frontend-main/src/components/popups/UnfollowUserDialog.vue +++ b/packages/frontend-main/src/components/popups/UnfollowUserDialog.vue @@ -3,18 +3,17 @@ import { Decimal } from '@cosmjs/math'; import { computed, ref } from 'vue'; import { toast } from 'vue-sonner'; -import { Button } - from '@/components/ui/button'; +import { Button } from '@/components/ui/button'; import { Dialog, DialogTitle, ResponsiveDialogContent, } from '@/components/ui/dialog'; import InputPhoton from '@/components/ui/input/InputPhoton.vue'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useTxDialog } from '@/composables/useTxDialog'; import { useUnfollowUser } from '@/composables/useUnfollowUser'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { showBroadcastingToast } from '@/utility/toast'; import DialogDescription from '../ui/dialog/DialogDescription.vue'; @@ -30,11 +29,14 @@ const { handleClose, } = useTxDialog('unfollow', txSuccess, txError); const configStore = useConfigStore(); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const fractionalDigits = useFractionalDigits(); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); -const canSubmit = computed(() => { - return isBalanceInputValid.value; -}); +const canSubmit = computed(() => isBalanceInputValid.value); function handleInputValidity(value: boolean) { isBalanceInputValid.value = value; diff --git a/packages/frontend-main/src/components/posts/PostActions.vue b/packages/frontend-main/src/components/posts/PostActions.vue index f4d8b3f8..cdefcfca 100644 --- a/packages/frontend-main/src/components/posts/PostActions.vue +++ b/packages/frontend-main/src/components/posts/PostActions.vue @@ -11,13 +11,13 @@ import { toast } from 'vue-sonner'; import { useDefaultAmount } from '@/composables/useDefaultAmount'; import { useDislikePost } from '@/composables/useDislikePost'; import { useFlagPost } from '@/composables/useFlagPost'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useLikePost } from '@/composables/useLikePost'; import { usePopups } from '@/composables/usePopups'; import { useWallet } from '@/composables/useWallet'; import { useConfigStore } from '@/stores/useConfigStore'; import { useWalletDialogStore } from '@/stores/useWalletDialogStore'; import { cn } from '@/utility'; -import { fractionalDigits } from '@/utility/atomics'; import { formatCompactAtomics, formatCompactNumber } from '@/utility/text'; import { showBroadcastingToast } from '@/utility/toast'; @@ -36,6 +36,7 @@ const wallet = useWallet(); const popups = usePopups(); const walletDialogStore = useWalletDialogStore(); const configStore = useConfigStore(); +const fractionalDigits = useFractionalDigits(); const { isDefaultAmountInvalid } = useDefaultAmount(); const { likePost } = useLikePost(); diff --git a/packages/frontend-main/src/components/tma/TMAInfo.vue b/packages/frontend-main/src/components/tma/TMAInfo.vue index e4a41ccb..239652ef 100644 --- a/packages/frontend-main/src/components/tma/TMAInfo.vue +++ b/packages/frontend-main/src/components/tma/TMAInfo.vue @@ -18,7 +18,7 @@ onMounted(async () => { const tmaInfo = computed(() => { const params = tmaStore.launchParams; const initData = tmaStore.initData; - const user = initData?.user(); + const user = initData?.user; if (!user) { return { diff --git a/packages/frontend-main/src/components/ui/filter/FilterPhoton.vue b/packages/frontend-main/src/components/ui/filter/FilterPhoton.vue index 222abdd5..a254a6dc 100644 --- a/packages/frontend-main/src/components/ui/filter/FilterPhoton.vue +++ b/packages/frontend-main/src/components/ui/filter/FilterPhoton.vue @@ -3,11 +3,12 @@ import { Decimal } from '@cosmjs/math'; import { computed } from 'vue'; import { Slider } from '@/components/ui/slider'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useFiltersStore } from '@/stores/useFiltersStore'; -import { fractionalDigits } from '@/utility/atomics'; const store = useFiltersStore(); +const fractionalDigits = useFractionalDigits(); const minDecimal = Decimal.fromAtomics('1', fractionalDigits); const maxDecimal = Decimal.fromUserInput('99', fractionalDigits); const stepDecimal = Decimal.fromAtomics('1', fractionalDigits); diff --git a/packages/frontend-main/src/components/ui/input/InputPhoton.vue b/packages/frontend-main/src/components/ui/input/InputPhoton.vue index 7775d97c..5f15a79d 100644 --- a/packages/frontend-main/src/components/ui/input/InputPhoton.vue +++ b/packages/frontend-main/src/components/ui/input/InputPhoton.vue @@ -3,16 +3,23 @@ import { Decimal } from '@cosmjs/math'; import { computed, watchEffect } from 'vue'; import { useBalanceFetcher } from '@/composables/useBalanceFetcher'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useWallet } from '@/composables/useWallet'; -import { fractionalDigits } from '@/utility/atomics'; import Input from './Input.vue'; const emit = defineEmits(['update:modelValue', 'onValidityChange']); +const fractionalDigits = useFractionalDigits(); +const model = defineModel(); +function getModelValue() { + if (model.value === undefined || model.value === null || model.value === '') { + model.value = Decimal.fromAtomics('1', fractionalDigits).toFloatApproximation(); + } + return model.value; +} const min = computed(() => Decimal.fromAtomics('1', fractionalDigits).toFloatApproximation()); const step = computed(() => Decimal.fromAtomics('1', fractionalDigits).toFloatApproximation()); -const model = defineModel({ default: Decimal.fromAtomics('1', fractionalDigits).toFloatApproximation() }); const wallet = useWallet(); const balanceFetcher = useBalanceFetcher(); @@ -26,11 +33,11 @@ const balanceAtomics = computed(() => { const balanceDecimal = computed(() => Decimal.fromAtomics(balanceAtomics.value, fractionalDigits)); const hasEnoughBalance = computed(() => balanceDecimal.value.isGreaterThanOrEqual( - Decimal.fromUserInput(model.value.toString(), fractionalDigits), + Decimal.fromUserInput(getModelValue().toString(), fractionalDigits), ), ); const balanceDiffDisplay = computed(() => - balanceDecimal.value.minus(Decimal.fromUserInput(model.value.toString(), fractionalDigits)).toString(), + balanceDecimal.value.minus(Decimal.fromUserInput(getModelValue().toString(), fractionalDigits)).toString(), ); // Truncate the input value to respect fractionalDigits diff --git a/packages/frontend-main/src/components/users/UserBalance.vue b/packages/frontend-main/src/components/users/UserBalance.vue index 6372eaf5..fa55ea1f 100644 --- a/packages/frontend-main/src/components/users/UserBalance.vue +++ b/packages/frontend-main/src/components/users/UserBalance.vue @@ -2,17 +2,18 @@ import { computed } from 'vue'; import { useBalanceFetcher } from '@/composables/useBalanceFetcher'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { useWallet } from '@/composables/useWallet'; -import { fractionalDigits } from '@/utility/atomics'; import { formatCompactAtomics } from '@/utility/text'; const wallet = useWallet(); - +const fractionalDigits = useFractionalDigits(); const balanceFetcher = useBalanceFetcher(); const balanceAtomics = computed(() => { - if (!wallet.loggedIn.value) + if (!wallet.loggedIn.value) { return '0'; + } const balances = balanceFetcher.balances.value[wallet.address.value]; return balances?.find(x => x.denom === 'uphoton')?.amount ?? '0'; }); diff --git a/packages/frontend-main/src/composables/useCreatePost.ts b/packages/frontend-main/src/composables/useCreatePost.ts index 2e4d60b5..a94c3bfa 100644 --- a/packages/frontend-main/src/composables/useCreatePost.ts +++ b/packages/frontend-main/src/composables/useCreatePost.ts @@ -5,10 +5,10 @@ import { Decimal } from '@cosmjs/math'; import { useMutation, useQueryClient } from '@tanstack/vue-query'; import { ref } from 'vue'; -import { fractionalDigits } from '@/utility/atomics'; import { infiniteDataWithNewItem, newPost } from '@/utility/optimisticBuilders'; import { feed } from './useFeed'; +import { useFractionalDigits } from './useFractionalDigits'; import { useTxNotification } from './useTxNotification'; import { userPosts } from './useUserPosts'; import { useWallet } from './useWallet'; @@ -18,10 +18,10 @@ interface CreatePostRequestMutation { amountAtomics: string; } -export function useCreatePost( -) { +export function useCreatePost() { const queryClient = useQueryClient(); const wallet = useWallet(); + const fractionalDigits = useFractionalDigits(); const txError = ref(); const txSuccess = ref(); const isToastShown = ref(false); @@ -35,7 +35,7 @@ export function useCreatePost( txSuccess.value = undefined; isToastShown.value = true; - const msg = message.replace(/&/g, '&') + const sanitizedMessage = message.replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') @@ -43,7 +43,7 @@ export function useCreatePost( const result = await wallet.dither.send( 'Post', - { args: [msg], amount: amountAtomics }, + { args: [sanitizedMessage], amount: amountAtomics }, ); if (!result.broadcast) { @@ -81,7 +81,13 @@ export function useCreatePost( const userPostsOpts = userPosts({ userAddress: wallet.address }); // Created Post - const optimisticNewPost: Post = newPost({ message: variables.message, quantity: Decimal.fromAtomics(variables.amountAtomics, fractionalDigits).atomics, hash, author: wallet.address.value, postHash: null }); + const optimisticNewPost: Post = newPost({ + message: variables.message, + quantity: Decimal.fromAtomics(variables.amountAtomics, fractionalDigits).atomics, + hash, + author: wallet.address.value, + postHash: null, + }); const newFeedData = infiniteDataWithNewItem({ previousItems: context.previousFeed, newItem: optimisticNewPost }); const newUserPostsData = infiniteDataWithNewItem({ previousItems: context.previousUserPosts, newItem: optimisticNewPost }); diff --git a/packages/frontend-main/src/composables/useCreateReply.ts b/packages/frontend-main/src/composables/useCreateReply.ts index fca70fc3..fee63aee 100644 --- a/packages/frontend-main/src/composables/useCreateReply.ts +++ b/packages/frontend-main/src/composables/useCreateReply.ts @@ -6,9 +6,9 @@ import { Decimal } from '@cosmjs/math'; import { useMutation, useQueryClient } from '@tanstack/vue-query'; import { ref } from 'vue'; -import { fractionalDigits } from '@/utility/atomics'; import { infiniteDataWithNewItem, newPost } from '@/utility/optimisticBuilders'; +import { useFractionalDigits } from './useFractionalDigits'; import { post } from './usePost'; import { replies } from './useReplies'; import { useTxNotification } from './useTxNotification'; @@ -21,10 +21,10 @@ interface CreateReplyRequestMutation { amountAtomics: string; } -export function useCreateReply( -) { +export function useCreateReply() { const queryClient = useQueryClient(); const wallet = useWallet(); + const fractionalDigits = useFractionalDigits(); const txError = ref(); const txSuccess = ref(); const isToastShown = ref(false); @@ -38,7 +38,7 @@ export function useCreateReply( txSuccess.value = undefined; isToastShown.value = true; - const msg = message.replace(/&/g, '&') + const sanitizedMessage = message.replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') @@ -46,7 +46,7 @@ export function useCreateReply( const result = await wallet.dither.send( 'Reply', - { args: [parentPost.value.hash, msg], amount: amountAtomics }, + { args: [parentPost.value.hash, sanitizedMessage], amount: amountAtomics }, ); if (!result.broadcast) { @@ -96,12 +96,22 @@ export function useCreateReply( ? { ...context.previousParentPost, replies: (context.previousParentPost.replies || 0) + 1 } : { ...variables.parentPost.value, replies: (variables.parentPost.value.replies || 0) + 1 }; // Created Post with parent hash as post_hash - const optimisticNewReply: Post = newPost({ message: variables.message, quantity: Decimal.fromAtomics(variables.amountAtomics, fractionalDigits).atomics, hash: createdHash, postHash: variables.parentPost.value.hash, author: wallet.address.value }); + const optimisticNewReply: Post = newPost({ + message: variables.message, + quantity: Decimal.fromAtomics(variables.amountAtomics, fractionalDigits).atomics, + hash: createdHash, + postHash: variables.parentPost.value.hash, + author: wallet.address.value, + }); // Created Post in ReplyWithParent const optimisticNewUserReply: ReplyWithParent = { - reply: newPost( - { message: variables.message, quantity: Decimal.fromAtomics(variables.amountAtomics, fractionalDigits).atomics, hash: createdHash, postHash: variables.parentPost.value.hash, author: wallet.address.value }, - ), + reply: newPost({ + message: variables.message, + quantity: Decimal.fromAtomics(variables.amountAtomics, fractionalDigits).atomics, + hash: createdHash, + postHash: variables.parentPost.value.hash, + author: wallet.address.value, + }), parent: optimisticParentPost, }; diff --git a/packages/frontend-main/src/composables/useDefaultAmount.ts b/packages/frontend-main/src/composables/useDefaultAmount.ts index a9abe3ce..4c5ccaae 100644 --- a/packages/frontend-main/src/composables/useDefaultAmount.ts +++ b/packages/frontend-main/src/composables/useDefaultAmount.ts @@ -2,24 +2,27 @@ import { Decimal } from '@cosmjs/math'; import { computed } from 'vue'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { useBalanceFetcher } from './useBalanceFetcher'; +import { useFractionalDigits } from './useFractionalDigits'; import { useWallet } from './useWallet'; export function useDefaultAmount() { const wallet = useWallet(); const balanceFetcher = useBalanceFetcher(); + const fractionalDigits = useFractionalDigits(); const balanceAtomics = computed(() => { - if (!wallet.loggedIn.value) + if (!wallet.loggedIn.value) { return '0'; + } const balances = balanceFetcher.balances.value[wallet.address.value]; return balances?.find(x => x.denom === 'uphoton')?.amount ?? '0'; }); const configStore = useConfigStore(); const balanceDecimal = computed(() => Decimal.fromAtomics(balanceAtomics.value, fractionalDigits)); const isDefaultAmountInvalid = computed(() => - configStore.config.defaultAmountEnabled && balanceDecimal.value.isLessThan( + configStore.config.defaultAmountEnabled + && balanceDecimal.value.isLessThan( Decimal.fromAtomics(configStore.config.defaultAmountAtomics, fractionalDigits), ), ); diff --git a/packages/frontend-main/src/composables/useFractionalDigits.ts b/packages/frontend-main/src/composables/useFractionalDigits.ts new file mode 100644 index 00000000..9cad7396 --- /dev/null +++ b/packages/frontend-main/src/composables/useFractionalDigits.ts @@ -0,0 +1,7 @@ +import { defaultMinimalCoinDenom, getFractionalDigitsFromChainConfig } from '@/utility/atomics'; +import { getChainConfigLazy } from '@/utility/getChainConfigLazy'; + +export function useFractionalDigits(coinMinimalDenom = defaultMinimalCoinDenom) { + const chainConfig = getChainConfigLazy(); + return getFractionalDigitsFromChainConfig(chainConfig.value, coinMinimalDenom); +} diff --git a/packages/frontend-main/src/composables/useTxDialog.ts b/packages/frontend-main/src/composables/useTxDialog.ts index 4a4d168c..652491bf 100644 --- a/packages/frontend-main/src/composables/useTxDialog.ts +++ b/packages/frontend-main/src/composables/useTxDialog.ts @@ -5,13 +5,13 @@ import type { PopupState } from './usePopups'; import { Decimal } from '@cosmjs/math'; import { computed, ref, watch } from 'vue'; -import { fractionalDigits } from '@/utility/atomics'; - import { useBalanceFetcher } from './useBalanceFetcher'; +import { useFractionalDigits } from './useFractionalDigits'; import { usePopups } from './usePopups'; import { useWallet } from './useWallet'; export function useTxDialog(dialogType: keyof PopupState, txSuccess: Ref, txError: Ref) { + const fractionalDigits = useFractionalDigits(); const inputPhotonModel = ref(Decimal.fromAtomics('1', fractionalDigits).toFloatApproximation()); const wallet = useWallet(); const balanceFetcher = useBalanceFetcher(); @@ -23,6 +23,7 @@ export function useTxDialog(dialogType: keyof PopupState, txSuccess: Ref { diff --git a/packages/frontend-main/src/stores/useConfigStore.ts b/packages/frontend-main/src/stores/useConfigStore.ts index 72c74267..1fe13fbd 100644 --- a/packages/frontend-main/src/stores/useConfigStore.ts +++ b/packages/frontend-main/src/stores/useConfigStore.ts @@ -3,7 +3,7 @@ import { defineStore } from 'pinia'; import { computed, reactive } from 'vue'; import { envConfigs } from '@/env-config'; -import { fractionalDigits } from '@/utility/atomics'; +import { defaultMinimalCoinDenom, getFractionalDigitsFromChainConfig } from '@/utility/atomics'; interface Config { selectedChain: keyof typeof envConfigs; @@ -12,10 +12,14 @@ interface Config { defaultAmountEnabled: boolean; } +const initialSelectedChain = (import.meta.env.VITE_ENVIRONMENT_TYPE as keyof typeof envConfigs | undefined) ?? 'mainnet'; +const initialChainConfig = envConfigs[initialSelectedChain].chainConfig; +const initialFractionalDigits = getFractionalDigitsFromChainConfig(initialChainConfig, defaultMinimalCoinDenom); + const defaultConfig: Config = { envConfigs, - selectedChain: import.meta.env.VITE_ENVIRONMENT_TYPE ?? 'mainnet', - defaultAmountAtomics: Decimal.fromUserInput('0.1', fractionalDigits).atomics, + selectedChain: initialSelectedChain, + defaultAmountAtomics: Decimal.fromUserInput('0.1', initialFractionalDigits).atomics, defaultAmountEnabled: false, }; diff --git a/packages/frontend-main/src/stores/useFiltersStore.ts b/packages/frontend-main/src/stores/useFiltersStore.ts index 68a5168a..8d10e9ac 100644 --- a/packages/frontend-main/src/stores/useFiltersStore.ts +++ b/packages/frontend-main/src/stores/useFiltersStore.ts @@ -2,11 +2,12 @@ import { Decimal } from '@cosmjs/math'; import { defineStore } from 'pinia'; import { ref } from 'vue'; -import { fractionalDigits } from '@/utility/atomics'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; export const useFiltersStore = defineStore( 'filtersStateStore', () => { + const fractionalDigits = useFractionalDigits(); const filterAmountAtomics = ref(Decimal.fromAtomics('1', fractionalDigits).atomics); const setFilterAmountAtomics = (newAmount: string) => { diff --git a/packages/frontend-main/src/stores/useTMAStore.ts b/packages/frontend-main/src/stores/useTMAStore.ts index f728bc1e..b58eabfe 100644 --- a/packages/frontend-main/src/stores/useTMAStore.ts +++ b/packages/frontend-main/src/stores/useTMAStore.ts @@ -1,4 +1,5 @@ -import type { InitData, RetrieveLaunchParamsError, RetrieveLaunchParamsResult } from '@tma.js/sdk-vue'; +import type { RetrieveLaunchParamsResult } from '@tma.js/sdk-vue'; +import type { InitData as TelegramInitData } from '@tma.js/types'; import { initData, @@ -22,7 +23,7 @@ declare global { export const useTMAStore = defineStore('tmaStore', () => { const isInitialized = ref(false); const launchParams = ref(null); - const initDataRef = ref>(); + const initDataRef = ref(null); const error = ref(null); const debugLogs = ref([]); @@ -40,9 +41,7 @@ export const useTMAStore = defineStore('tmaStore', () => { // Get init data using the signal const initDataSignal = useSignal(initData.state); - if (initDataSignal.value) { - initDataRef.value = initDataSignal.value as unknown as InitData; - } + initDataRef.value = initDataSignal.value ?? null; isInitialized.value = true; error.value = null; diff --git a/packages/frontend-main/src/utility/atomics.ts b/packages/frontend-main/src/utility/atomics.ts index f661fc1c..8aeddf11 100644 --- a/packages/frontend-main/src/utility/atomics.ts +++ b/packages/frontend-main/src/utility/atomics.ts @@ -1,9 +1,31 @@ import { Decimal } from '@cosmjs/math'; -export const fractionalDigits = 6; +export const defaultFractionalDigits = 0; +export const defaultMinimalCoinDenom = 'uphoton'; export function addAtomics(firstAtomicsAmount: string, secondAtomicsAmount: string) { return Decimal.fromAtomics(firstAtomicsAmount, 0) .plus(Decimal.fromAtomics(secondAtomicsAmount, 0)) .toString(); } + +interface ChainCurrency { + coinMinimalDenom: string; + coinDecimals: number; +} + +interface ChainConfigLike { + currencies?: ChainCurrency[]; +} + +export function getFractionalDigitsFromChainConfig( + chainConfig: ChainConfigLike | undefined, + coinMinimalDenom = defaultMinimalCoinDenom, +) { + if (!chainConfig?.currencies?.length) { + return defaultFractionalDigits; + } + + const currency = chainConfig.currencies.find(c => c.coinMinimalDenom === coinMinimalDenom); + return currency?.coinDecimals ?? defaultFractionalDigits; +} diff --git a/packages/frontend-main/src/views/PostView.vue b/packages/frontend-main/src/views/PostView.vue index 4eff3179..e00ec356 100644 --- a/packages/frontend-main/src/views/PostView.vue +++ b/packages/frontend-main/src/views/PostView.vue @@ -17,13 +17,13 @@ import UserAvatar from '@/components/users/UserAvatar.vue'; import UserAvatarUsername from '@/components/users/UserAvatarUsername.vue'; import { useCreateReply } from '@/composables/useCreateReply'; import { useDefaultAmount } from '@/composables/useDefaultAmount'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import { usePost } from '@/composables/usePost'; import { useReplies } from '@/composables/useReplies'; import { useWallet } from '@/composables/useWallet'; import MainLayout from '@/layouts/MainLayout.vue'; import { routesNames } from '@/router'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { showBroadcastingToast } from '@/utility/toast'; import ViewHeading from './ViewHeading.vue'; @@ -44,9 +44,14 @@ const MAX_CHARS = 512 - ('dither.Reply("", "")'.length + POST_HASH_LEN); const reply = ref(''); const showReply = ref(false); const isBalanceInputValid = ref(false); +const fractionalDigits = useFractionalDigits(); const inputPhotonModel = ref(Decimal.fromAtomics('1', fractionalDigits).toFloatApproximation()); const configStore = useConfigStore(); -const amountAtomics = computed(() => configStore.config.defaultAmountEnabled ? configStore.config.defaultAmountAtomics : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics); +const amountAtomics = computed(() => + configStore.config.defaultAmountEnabled + ? configStore.config.defaultAmountAtomics + : Decimal.fromUserInput(inputPhotonModel.value.toString(), fractionalDigits).atomics, +); const { createReply } = useCreateReply(); const canReply = computed(() => { diff --git a/packages/frontend-main/src/views/SettingsDefaultAmount.vue b/packages/frontend-main/src/views/SettingsDefaultAmount.vue index 1945a252..b414e926 100644 --- a/packages/frontend-main/src/views/SettingsDefaultAmount.vue +++ b/packages/frontend-main/src/views/SettingsDefaultAmount.vue @@ -5,13 +5,14 @@ import { ref, watch } from 'vue'; import InputPhoton from '@/components/ui/input/InputPhoton.vue'; import Switch from '@/components/ui/switch/Switch.vue'; +import { useFractionalDigits } from '@/composables/useFractionalDigits'; import MainLayout from '@/layouts/MainLayout.vue'; import { useConfigStore } from '@/stores/useConfigStore'; -import { fractionalDigits } from '@/utility/atomics'; import { showInfoToast } from '@/utility/toast'; import ViewHeading from '@/views/ViewHeading.vue'; const configStore = useConfigStore(); +const fractionalDigits = useFractionalDigits(); const inputPhotonModel = ref(Decimal.fromAtomics(configStore.config.defaultAmountAtomics, fractionalDigits).toFloatApproximation()); const hasEnoughBalance = ref(false);