diff --git a/src/base/credits/comfyCredits.ts b/src/base/credits/comfyCredits.ts
new file mode 100644
index 0000000000..b2407210ce
--- /dev/null
+++ b/src/base/credits/comfyCredits.ts
@@ -0,0 +1,115 @@
+const DEFAULT_NUMBER_FORMAT: Intl.NumberFormatOptions = {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2
+}
+
+const formatNumber = ({
+ value,
+ locale,
+ options
+}: {
+ value: number
+ locale?: string
+ options?: Intl.NumberFormatOptions
+}): string => {
+ const merged: Intl.NumberFormatOptions = {
+ ...DEFAULT_NUMBER_FORMAT,
+ ...options
+ }
+
+ if (
+ typeof merged.maximumFractionDigits === 'number' &&
+ typeof merged.minimumFractionDigits === 'number' &&
+ merged.maximumFractionDigits < merged.minimumFractionDigits
+ ) {
+ merged.minimumFractionDigits = merged.maximumFractionDigits
+ }
+
+ return new Intl.NumberFormat(locale, merged).format(value)
+}
+
+export const COMFY_CREDIT_RATE_CENTS = 210
+export const COMFY_CREDIT_RATE_USD = COMFY_CREDIT_RATE_CENTS / 100
+
+export const usdToCents = (usd: number): number => Math.round(usd * 100)
+
+export const centsToCredits = (cents: number): number =>
+ cents / COMFY_CREDIT_RATE_CENTS
+
+export const creditsToCents = (credits: number): number =>
+ Math.round(credits * COMFY_CREDIT_RATE_CENTS)
+
+export const usdToCredits = (usd: number): number =>
+ centsToCredits(usdToCents(usd))
+
+export const creditsToUsd = (credits: number): number =>
+ creditsToCents(credits) / 100
+
+export type FormatOptions = {
+ value: number
+ locale?: string
+ numberOptions?: Intl.NumberFormatOptions
+}
+
+export const formatCredits = ({
+ value,
+ locale,
+ numberOptions
+}: FormatOptions): string =>
+ formatNumber({ value, locale, options: numberOptions })
+
+export const formatCreditsFromCents = ({
+ cents,
+ locale,
+ numberOptions
+}: {
+ cents: number
+ locale?: string
+ numberOptions?: Intl.NumberFormatOptions
+}): string =>
+ formatCredits({
+ value: centsToCredits(cents),
+ locale,
+ numberOptions
+ })
+
+export const formatCreditsFromUsd = ({
+ usd,
+ locale,
+ numberOptions
+}: {
+ usd: number
+ locale?: string
+ numberOptions?: Intl.NumberFormatOptions
+}): string =>
+ formatCredits({
+ value: usdToCredits(usd),
+ locale,
+ numberOptions
+ })
+
+export const formatUsd = ({
+ value,
+ locale,
+ numberOptions
+}: FormatOptions): string =>
+ formatNumber({
+ value,
+ locale,
+ options: numberOptions
+ })
+
+export const formatUsdFromCents = ({
+ cents,
+ locale,
+ numberOptions
+}: {
+ cents: number
+ locale?: string
+ numberOptions?: Intl.NumberFormatOptions
+}): string =>
+ formatUsd({
+ value: cents / 100,
+ locale,
+ numberOptions
+ })
diff --git a/src/components/common/UserCredit.vue b/src/components/common/UserCredit.vue
index aac405b90c..825467dbe5 100644
--- a/src/components/common/UserCredit.vue
+++ b/src/components/common/UserCredit.vue
@@ -9,7 +9,7 @@
@@ -21,9 +21,10 @@
import Skeleton from 'primevue/skeleton'
import Tag from 'primevue/tag'
import { computed } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { formatCreditsFromCents } from '@/base/credits/comfyCredits'
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
-import { formatMetronomeCurrency } from '@/utils/formatUtil'
const { textClass } = defineProps<{
textClass?: string
@@ -31,9 +32,15 @@ const { textClass } = defineProps<{
const authStore = useFirebaseAuthStore()
const balanceLoading = computed(() => authStore.isFetchingBalance)
+const { t, locale } = useI18n()
const formattedBalance = computed(() => {
- if (!authStore.balance) return '0.00'
- return formatMetronomeCurrency(authStore.balance.amount_micros, 'usd')
+ // Backend returns cents despite the *_micros naming convention.
+ const cents = authStore.balance?.amount_micros ?? 0
+ const amount = formatCreditsFromCents({
+ cents,
+ locale: locale.value
+ })
+ return `${amount} ${t('credits.credits')}`
})
diff --git a/src/components/dialog/content/credit/CreditTopUpOption.vue b/src/components/dialog/content/credit/CreditTopUpOption.vue
index f134aba5e2..bdca252fec 100644
--- a/src/components/dialog/content/credit/CreditTopUpOption.vue
+++ b/src/components/dialog/content/credit/CreditTopUpOption.vue
@@ -2,24 +2,36 @@
-
(customAmount = Number(e.value))"
- @input="(e: InputNumberInputEvent) => (customAmount = Number(e.value))"
- />
- {{ amount }}
+
+
+ (customAmount = clampUsd(Number(e.value)))
+ "
+ @input="
+ (e: InputNumberInputEvent) =>
+ (customAmount = clampUsd(Number(e.value)))
+ "
+ />
+ {{ formattedCredits }}
+
+
+ {{ formattedCredits }}
+ {{ formattedUsd }}
+