@@ -14,13 +14,13 @@ import { fetcher } from '@/lib/fetcher'
1414import { STABLE_SWR_OPTIONS , useUpdateSetting } from '@/lib/hooks/useUpdateSetting'
1515import { createCheckoutSession } from '@/lib/stripe'
1616import {
17- calculateSavings ,
18- getPriceId ,
19- gracePeriodPrettyDate ,
20- isSubscriptionActive ,
21- type PricePeriod ,
22- SUBSCRIPTION_TIERS ,
23- type SubscriptionRow ,
17+ calculateSavings ,
18+ getPriceId ,
19+ gracePeriodPrettyDate ,
20+ isSubscriptionActive ,
21+ type PricePeriod ,
22+ SUBSCRIPTION_TIERS ,
23+ type SubscriptionRow ,
2424} from '@/utils/subscription'
2525import CryptoToggle from '../CryptoToggle'
2626import ErrorBoundary from '../ErrorBoundary'
@@ -128,20 +128,47 @@ function Plan({
128128 formattedCreditBalance,
129129 } = useSubscriptionContext ( )
130130
131- // Check if the current subscription was paid with crypto by comparing price IDs
131+ // Check if the current subscription was paid with crypto.
132+ // Prefer explicit subscription metadata and only fall back to price IDs when
133+ // crypto price IDs are distinct from regular price IDs.
132134 const isPaidWithCrypto = useMemo ( ( ) => {
133- // Only check for crypto payments on Pro tier subscriptions
134- if ( ! subscription ?. stripePriceId || tier === SUBSCRIPTION_TIERS . FREE ) return false
135-
136- // Check if the subscription's price ID matches one with crypto payment
137- const monthlyPriceWithCrypto = getPriceId ( SUBSCRIPTION_TIERS . PRO , 'monthly' , true )
138- const annualPriceWithCrypto = getPriceId ( SUBSCRIPTION_TIERS . PRO , 'annual' , true )
139- const lifetimePriceWithCrypto = getPriceId ( SUBSCRIPTION_TIERS . PRO , 'lifetime' , true )
140-
141- return [ monthlyPriceWithCrypto , annualPriceWithCrypto , lifetimePriceWithCrypto ] . includes (
142- subscription . stripePriceId ,
143- )
144- } , [ subscription ?. stripePriceId , tier ] )
135+ if ( tier === SUBSCRIPTION_TIERS . FREE ) return false
136+
137+ const metadata =
138+ subscription ?. metadata &&
139+ typeof subscription . metadata === 'object' &&
140+ ! Array . isArray ( subscription . metadata )
141+ ? ( subscription . metadata as Record < string , unknown > )
142+ : null
143+
144+ // Strong signal: crypto subscriptions set this metadata flag server-side
145+ const isCryptoFromMetadata =
146+ metadata ?. isCryptoPayment === true || metadata ?. isCryptoPayment === 'true'
147+
148+ if ( isCryptoFromMetadata ) return true
149+
150+ if ( ! subscription ?. stripePriceId ) return false
151+
152+ const regularPriceIds = [
153+ getPriceId ( SUBSCRIPTION_TIERS . PRO , 'monthly' , false ) ,
154+ getPriceId ( SUBSCRIPTION_TIERS . PRO , 'annual' , false ) ,
155+ getPriceId ( SUBSCRIPTION_TIERS . PRO , 'lifetime' , false ) ,
156+ ]
157+
158+ const cryptoPriceIds = [
159+ getPriceId ( SUBSCRIPTION_TIERS . PRO , 'monthly' , true ) ,
160+ getPriceId ( SUBSCRIPTION_TIERS . PRO , 'annual' , true ) ,
161+ getPriceId ( SUBSCRIPTION_TIERS . PRO , 'lifetime' , true ) ,
162+ ]
163+
164+ // If crypto IDs overlap with regular IDs in config, treat price ID matching
165+ // as ambiguous and avoid forcing crypto state in the UI.
166+ const hasDistinctCryptoPrice =
167+ cryptoPriceIds . includes ( subscription . stripePriceId ) &&
168+ ! regularPriceIds . includes ( subscription . stripePriceId )
169+
170+ return hasDistinctCryptoPrice
171+ } , [ subscription ?. metadata , subscription ?. stripePriceId , tier ] )
145172
146173 // Check if crypto payments feature is enabled
147174 const isCryptoPaymentsEnabled = isFeatureEnabled ( 'enableCryptoPayments' )
0 commit comments