From c786b794e5928c663a375a91863a290c70e5175b Mon Sep 17 00:00:00 2001 From: kcw-grunt Date: Sun, 24 May 2026 23:06:15 +0100 Subject: [PATCH 1/7] Working Route with Bitrefill Update remote config defaults Adding and unwrapping the JSON for the cards --- app/build.gradle.kts | 1 + .../com/brainwallet/constants/BWConstants.kt | 2 +- .../repository/ShopProxyRepositoryImpl.kt | 21 +- .../navigation/MainNavigationHost.kt | 4 +- .../java/com/brainwallet/navigation/Route.kt | 2 +- .../presenter/entities/ShopItems.kt | 41 + .../shopbento/GiftCardsComposable.kt | 17 +- .../shopbento/ShopBentoScreen.kt | 5 +- .../bentosections/shopbento/ShopBentoState.kt | 3 + .../shopbento/ShopBentoViewModel.kt | 9 +- .../cards/{Cards.kt => CardComposables.kt} | 43 + .../brainwallet/ui/screens/main/MainScreen.kt | 17 +- .../main/res/xml/remote_config_defaults.xml | 3202 ++++++++++++++++- 13 files changed, 3328 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/com/brainwallet/presenter/entities/ShopItems.kt rename app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/{Cards.kt => CardComposables.kt} (79%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 120a3900..db85f2c2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -258,6 +258,7 @@ dependencies { implementation(libs.android.installreferrer) implementation("androidx.compose.animation:animation:1.5.0") implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7") + implementation("io.coil-kt:coil-compose:2.0.0-rc01") testImplementation(libs.junit) testImplementation(libs.mockk) testImplementation(libs.turbine) diff --git a/app/src/main/java/com/brainwallet/constants/BWConstants.kt b/app/src/main/java/com/brainwallet/constants/BWConstants.kt index cb988a3b..77c4fef7 100644 --- a/app/src/main/java/com/brainwallet/constants/BWConstants.kt +++ b/app/src/main/java/com/brainwallet/constants/BWConstants.kt @@ -104,7 +104,7 @@ object BWConstants { const val SUPPORT_WEB_LINK: String = "https://www.brainwallet.co/support" const val TOS_LINK: String = "https://www.brainwallet.co/privacypolicy" const val LINKTREE_URL: String = "https://linktr.ee/brainwallet" - const val BITREFILL_URL: String = "https://www.bitrefill.com/?ref=2h186s7q" + const val BITREFILL_URL: String = "https://www.bitrefill.com/?ref=bw_tk_26" /** * API Hosts diff --git a/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt b/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt index ee3505db..13945270 100644 --- a/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt +++ b/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt @@ -1,5 +1,7 @@ package com.brainwallet.data.repository import com.brainwallet.data.source.RemoteConfigSource +import com.brainwallet.presenter.entities.ShopCard +import com.brainwallet.presenter.entities.ShopConfig import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -10,11 +12,13 @@ import timber.log.Timber @Serializable data class ShopProxy( - @SerialName("widget_url") val widget: String = "" + @SerialName("widget_url") val widget: String = "", + @SerialName("cards") val shopCards: List = emptyList() ) interface ShopProxyRepository { val shopProxy: StateFlow> + val shopCards: StateFlow> suspend fun refresh() } @@ -26,6 +30,9 @@ class ShopProxyRepositoryImpl( private val _shopProxy = MutableStateFlow>(emptyList()) override val shopProxy: StateFlow> = _shopProxy.asStateFlow() + private val _shopCards = MutableStateFlow>(emptyList()) + override val shopCards: StateFlow> = _shopCards.asStateFlow() + override suspend fun refresh() { runCatching { remoteConfigSource.fetchAndActivate() } .onFailure { Timber.e(it, "RemoteConfig fetch failed") } @@ -34,14 +41,10 @@ class ShopProxyRepositoryImpl( Timber.d("ShopProxy rawJson: '$rawJson'") runCatching { - val wrapper = json.decodeFromString(rawJson) - Timber.d("ShopProxy parsed: ${wrapper.shopProxy}") - _shopProxy.value = wrapper.shopProxy + val shopConfig = json.decodeFromString(rawJson) + Timber.d("ShopConfig parsed: ${shopConfig.shopData}") + _shopProxy.value = listOf(shopConfig.shopData.widgetUrl).map { ShopProxy(widget = it) } + _shopCards.value = shopConfig.shopData.cards }.onFailure { Timber.e(it, "RemoteConfig parse failed") } } - - @Serializable - private data class ShopProxyWrapper( - @SerialName("shop_data") val shopProxy: List = emptyList() - ) } diff --git a/app/src/main/java/com/brainwallet/navigation/MainNavigationHost.kt b/app/src/main/java/com/brainwallet/navigation/MainNavigationHost.kt index ef6f005c..e0883d71 100644 --- a/app/src/main/java/com/brainwallet/navigation/MainNavigationHost.kt +++ b/app/src/main/java/com/brainwallet/navigation/MainNavigationHost.kt @@ -148,10 +148,10 @@ fun NavGraphBuilder.mainNavGraph( } composable { navBackStackEntry -> - val route: Route.LinktreeWeb = navBackStackEntry.toRoute() + val route: Route.BitrefillWeb = navBackStackEntry.toRoute() WebModalScreen( onNavigate = onNavigate, - url = BWConstants.BITREFILL_URL + url = route.url ) } } diff --git a/app/src/main/java/com/brainwallet/navigation/Route.kt b/app/src/main/java/com/brainwallet/navigation/Route.kt index f17cdf26..3f2385e4 100644 --- a/app/src/main/java/com/brainwallet/navigation/Route.kt +++ b/app/src/main/java/com/brainwallet/navigation/Route.kt @@ -65,7 +65,7 @@ sealed class Route : JavaSerializable { object MoonPayBuy : Route() @Serializable - object BitrefillWeb : Route() + data class BitrefillWeb(val url: String) : Route() @Serializable object LinktreeWeb : Route() diff --git a/app/src/main/java/com/brainwallet/presenter/entities/ShopItems.kt b/app/src/main/java/com/brainwallet/presenter/entities/ShopItems.kt new file mode 100644 index 00000000..ac8048ff --- /dev/null +++ b/app/src/main/java/com/brainwallet/presenter/entities/ShopItems.kt @@ -0,0 +1,41 @@ +package com.brainwallet.presenter.entities + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ShopConfig( + @SerialName("shop_data") + val shopData: ShopData +) + +@Serializable +data class ShopData( + @SerialName("widget_url") + val widgetUrl: String, + val cards: List +) + +@Serializable +data class ShopCard( + @SerialName("country_code") + val countryCode: String, + + @SerialName("country_name") + val countryName: String, + + @SerialName("product_slug") + val productSlug: String, + + @SerialName("product_name") + val productName: String, + + @SerialName("product_url") + val productUrl: String, + + @SerialName("card_image_webp") + val cardImageWebP: String +) { + // Computed property — same as Swift's `var id` + val id: String get() = productSlug +} diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt index e09efb5d..7ed26641 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt @@ -12,23 +12,22 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.brainwallet.ui.bentosections.shopbento.cards.CardAmazonComposable -import com.brainwallet.ui.bentosections.shopbento.cards.CardJustEatComposable import com.brainwallet.ui.bentosections.shopbento.cards.CardVisaComposable import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue +import androidx.compose.ui.geometry.Offset +import com.brainwallet.ui.bentosections.shopbento.cards.SingleCardComposable @Composable fun GiftCardsComposable( state: ShopBentoState, - cardData: String, modifier: Modifier = Modifier, ) { - val cornerRadius = 4.dp var appeared by remember { mutableStateOf(false) } + var cards = state.cardData LaunchedEffect(Unit) { appeared = true } @@ -88,15 +87,7 @@ fun GiftCardsComposable( .offset(x = offsetJE.dp, y = 15.dp) ) { - CardJustEatComposable(rotation = -30f) + SingleCardComposable(rotation = -30f, modelString = "", offset = Offset(14f, 22f)) } } } - -@Preview -@Composable -private fun GiftCardsComposablePreview() { - Box(modifier = Modifier) { - GiftCardsComposable(state = ShopBentoState(), cardData = "acr") - } -} diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoScreen.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoScreen.kt index 037df567..ed60efa2 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoScreen.kt @@ -61,6 +61,7 @@ private fun ShopBentoScreen( val logotypeWhite = R.drawable.logotype_bitrefill_wht val logotypeBitrefill = if (state.darkMode) logotypeWhite else logotypeBlack + Box( modifier = Modifier .fillMaxSize() @@ -119,9 +120,7 @@ private fun ShopBentoScreen( ) { GiftCardsComposable( state = state, - modifier = - Modifier.fillMaxSize(), - cardData = "test-json" + modifier = Modifier.fillMaxSize() ) } } diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoState.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoState.kt index eeda54f7..f98be6c3 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoState.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoState.kt @@ -1,7 +1,10 @@ package com.brainwallet.ui.bentosections.shopbento +import com.brainwallet.presenter.entities.ShopCard + data class ShopBentoState( val cardData: String = "", + val shopCards: List = emptyList(), val regionData: String = "", val countryIso: String = "US", val darkMode: Boolean = true, diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt index 9fbef227..d6c0c82c 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt @@ -14,6 +14,7 @@ import java.util.Locale import android.telephony.TelephonyManager import com.brainwallet.data.repository.SettingRepository import com.brainwallet.data.repository.ShopProxyRepository +import com.brainwallet.presenter.entities.ShopCard @KoinViewModel class ShopBentoViewModel( @@ -31,7 +32,8 @@ class ShopBentoViewModel( _state.update { it.copy( darkMode = setting.isDarkMode, - countryIso = getCountryIso() + countryIso = getCountryIso(), + shopCards = loadCards() ) } } @@ -57,6 +59,11 @@ class ShopBentoViewModel( else -> Locale.getDefault().country.ifEmpty { "US" } } } + + private fun loadCards(): List { + return emptyList() + } + override fun onEvent(event: ShopBentoEvent) { when (event) { is ShopBentoEvent.OnLoad -> { diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/Cards.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt similarity index 79% rename from app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/Cards.kt rename to app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt index ba5fe454..aebefb15 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/Cards.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt @@ -21,9 +21,52 @@ import androidx.compose.foundation.layout.size import androidx.compose.ui.Alignment import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview +import coil.compose.rememberAsyncImagePainter import com.brainwallet.ui.theme.giftCardGradient1 import com.brainwallet.ui.theme.giftCardGradient3 +@Composable +fun SingleCardComposable( + rotation: Float, + modelString: String, + offset: Offset, + modifier: Modifier = Modifier, +) { + val cornerRadius = 4.dp + + Box(modifier = Modifier.fillMaxSize()) { + Canvas( + modifier = Modifier + .fillMaxSize() + .offset(x = offset.x.dp, y = offset.y.dp) + .clip(RoundedCornerShape(cornerRadius)) + ) { + rotate(degrees = 20f) { + val cardWidth = size.width * 0.7f + val cardHeight = cardWidth / 1.586f + drawRoundRect( + brush = giftCardGradient2(size), + size = Size(cardWidth, cardHeight), + topLeft = Offset( + x = (size.width - cardWidth) / 2f, + y = (size.height - cardHeight) / 2f + ), + cornerRadius = CornerRadius(cornerRadius.toPx()) + ) + } + } + Image( + painter = rememberAsyncImagePainter(modelString), + contentDescription = null, + modifier = Modifier + .size(50.dp) + .align(Alignment.Center) + .offset(x = 30.dp, y = -10.dp) + .rotate(rotation) + ) + } +} + @Composable fun CardAmazonComposable( rotation: Float, diff --git a/app/src/main/java/com/brainwallet/ui/screens/main/MainScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/main/MainScreen.kt index f5340c08..60779447 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/main/MainScreen.kt @@ -72,6 +72,7 @@ import com.brainwallet.ui.bentosections.buyreceivebento.receive.ReceiveDialog import com.brainwallet.ui.bentosections.gamehubbento.GameHubBentoPagerScreen import com.brainwallet.ui.bentosections.ltcpickerbento.LTCPickerBentoScreen import com.brainwallet.ui.bentosections.shopbento.ShopBentoScreen +import com.brainwallet.ui.bentosections.shopbento.ShopBentoViewModel import com.brainwallet.ui.bentosections.transactionbento.TransactionsBentoScreen import com.brainwallet.ui.bentosections.tutorials.TutorialsBentoScreen import com.brainwallet.ui.bentosections.tutorials.send.TutorialSendPagerScreen @@ -104,7 +105,8 @@ import timber.log.Timber fun MainScreen( onNavigate: OnNavigate, modifier: Modifier = Modifier, - viewModel: MainViewModel = koinViewModel() + viewModel: MainViewModel = koinViewModel(), + shopBentoViewModel: ShopBentoViewModel = koinViewModel() ) { val context = LocalContext.current var currentRoute by remember { mutableStateOf(Route.Main) } @@ -113,6 +115,7 @@ fun MainScreen( val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) var isSheetOpen by remember { mutableStateOf(false) } var modalContentRoute by remember { mutableStateOf(null) } + val shopBentoState by shopBentoViewModel.state.collectAsStateWithLifecycle() val appSetting by viewModel.appSetting.collectAsStateWithLifecycle() val isDarkMode = appSetting.isDarkMode val state by viewModel.state.collectAsStateWithLifecycle() @@ -329,7 +332,7 @@ fun MainScreen( } Box(modifier = Modifier.height(storeBentoHeight)) { ShopBentoScreen(onClick = { - modalContentRoute = Route.BitrefillWeb + modalContentRoute = Route.BitrefillWeb(url = shopBentoState.shopBaseUrl) isSheetOpen = true }) } @@ -390,7 +393,7 @@ fun MainScreen( .fillMaxHeight( if (modalContentRoute == Route.TutorialSend || modalContentRoute == Route.TutorialWalkthrough || - modalContentRoute == Route.BitrefillWeb || + modalContentRoute is Route.BitrefillWeb || modalContentRoute == Route.LinktreeWeb ) { 1f @@ -452,12 +455,10 @@ fun MainScreen( onNavigate = onNavigate, url = BWConstants.LINKTREE_URL ) - - Route.BitrefillWeb -> WebModalScreen( - modifier = Modifier - .fillMaxSize(), + is Route.BitrefillWeb -> WebModalScreen( + modifier = Modifier.fillMaxSize(), onNavigate = onNavigate, - url = BWConstants.BITREFILL_URL + url = (modalContentRoute as Route.BitrefillWeb).url ) else -> {} } diff --git a/app/src/main/res/xml/remote_config_defaults.xml b/app/src/main/res/xml/remote_config_defaults.xml index d41161a3..8ad710bb 100644 --- a/app/src/main/res/xml/remote_config_defaults.xml +++ b/app/src/main/res/xml/remote_config_defaults.xml @@ -22,7 +22,3207 @@ path_shop_content - {"shop_data":[{ "widget_url":"https://www.bitrefill.com/?ref=2h186s7q"}]} + { + "shop_data": { + "widget_url": "https://www.bitrefill.com/?ref=bw_tk_26", + "cards": [ + { + "country_code": "AD", + "country_name": "Andorra", + "product_slug": "carrefour-france", + "product_name": "Carrefour France", + "product_url": "https://www.bitrefill.com/carrefour-france/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/carrefour-france.webp" + }, + { + "country_code": "AD", + "country_name": "Andorra", + "product_slug": "amazon_fr-france", + "product_name": "Amazon.fr France", + "product_url": "https://www.bitrefill.com/amazon_fr-france/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/amazon_fr-france.webp" + }, + { + "country_code": "AD", + "country_name": "Andorra", + "product_slug": "orange-spain", + "product_name": "Orange Spain", + "product_url": "https://www.bitrefill.com/orange-spain/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-spain.webp" + }, + { + "country_code": "AE", + "country_name": "United Arab Emirates", + "product_slug": "noon-uae", + "product_name": "Noon.com UAE", + "product_url": "https://www.bitrefill.com/noon-uae/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/noon-uae.webp" + }, + { + "country_code": "AE", + "country_name": "United Arab Emirates", + "product_slug": "talabat-uae", + "product_name": "Talabat UAE", + "product_url": "https://www.bitrefill.com/talabat-uae/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/talabat-uae.webp" + }, + { + "country_code": "AE", + "country_name": "United Arab Emirates", + "product_slug": "lulu-hypermarket-uae", + "product_name": "LuLu Hypermarket UAE", + "product_url": "https://www.bitrefill.com/lulu-hypermarket-uae/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/lulu-hypermarket-uae.webp" + }, + { + "country_code": "AG", + "country_name": "Antigua and Barbuda", + "product_slug": "digicel-antigua-and-barbuda", + "product_name": "Digicel Antigua", + "product_url": "https://www.bitrefill.com/digicel-antigua-and-barbuda/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-antigua-and-barbuda.webp" + }, + { + "country_code": "AG", + "country_name": "Antigua and Barbuda", + "product_slug": "flow-antigua-and-barbuda", + "product_name": "Flow Antigua", + "product_url": "https://www.bitrefill.com/flow-antigua-and-barbuda/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-antigua-and-barbuda.webp" + }, + { + "country_code": "AG", + "country_name": "Antigua and Barbuda", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "AI", + "country_name": "Anguilla", + "product_slug": "digicel-anguilla", + "product_name": "Digicel Anguilla", + "product_url": "https://www.bitrefill.com/digicel-anguilla/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-anguilla.webp" + }, + { + "country_code": "AI", + "country_name": "Anguilla", + "product_slug": "flow-anguilla", + "product_name": "Flow Anguilla", + "product_url": "https://www.bitrefill.com/flow-anguilla/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-anguilla.webp" + }, + { + "country_code": "AI", + "country_name": "Anguilla", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "AL", + "country_name": "Albania", + "product_slug": "eneba-gift-card-eu", + "product_name": "Eneba EUR", + "product_url": "https://www.bitrefill.com/eneba-gift-card-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/eneba-gift-card-eu.webp" + }, + { + "country_code": "AL", + "country_name": "Albania", + "product_slug": "valorant-eu", + "product_name": "Valorant EU", + "product_url": "https://www.bitrefill.com/valorant-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/valorant-eu.webp" + }, + { + "country_code": "AL", + "country_name": "Albania", + "product_slug": "league-of-legends-eu", + "product_name": "League of Legends EU", + "product_url": "https://www.bitrefill.com/league-of-legends-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/league-of-legends-eu.webp" + }, + { + "country_code": "AM", + "country_name": "Armenia", + "product_slug": "ucom-armenia", + "product_name": "UCom Armenia", + "product_url": "https://www.bitrefill.com/ucom-armenia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ucom-armenia.webp" + }, + { + "country_code": "AM", + "country_name": "Armenia", + "product_slug": "vivacell-mts-armenia", + "product_name": "VivaCell-MTS Armenia", + "product_url": "https://www.bitrefill.com/vivacell-mts-armenia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vivacell-mts-armenia.webp" + }, + { + "country_code": "AM", + "country_name": "Armenia", + "product_slug": "bitrefill-esim-armenia", + "product_name": "eSIM Armenia", + "product_url": "https://www.bitrefill.com/bitrefill-esim-armenia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-armenia.webp" + }, + { + "country_code": "AN", + "country_name": "Netherlands Antilles", + "product_slug": "digicel-netherlands-antilles", + "product_name": "Digicel Netherlands Antilles", + "product_url": "https://www.bitrefill.com/digicel-netherlands-antilles/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-netherlands-antilles.webp" + }, + { + "country_code": "AN", + "country_name": "Netherlands Antilles", + "product_slug": "flow-netherlands-antilles", + "product_name": "Flow Netherlands Antilles", + "product_url": "https://www.bitrefill.com/flow-netherlands-antilles/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-netherlands-antilles.webp" + }, + { + "country_code": "AN", + "country_name": "Netherlands Antilles", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "AR", + "country_name": "Argentina", + "product_slug": "eneba-gift-card-ars-international", + "product_name": "Eneba ARS", + "product_url": "https://www.bitrefill.com/eneba-gift-card-ars-international/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/eneba-gift-card-ars-international.webp" + }, + { + "country_code": "AR", + "country_name": "Argentina", + "product_slug": "dia-argentina", + "product_name": "Día Argentina", + "product_url": "https://www.bitrefill.com/dia-argentina/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/dia-argentina.webp" + }, + { + "country_code": "AR", + "country_name": "Argentina", + "product_slug": "claro-argentina", + "product_name": "Claro Argentina", + "product_url": "https://www.bitrefill.com/claro-argentina/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-argentina.webp" + }, + { + "country_code": "AT", + "country_name": "Austria", + "product_slug": "interspar-austria", + "product_name": "INTERSPAR Austria", + "product_url": "https://www.bitrefill.com/interspar-austria/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/interspar-austria.webp" + }, + { + "country_code": "AT", + "country_name": "Austria", + "product_slug": "billa-austria", + "product_name": "Billa Austria", + "product_url": "https://www.bitrefill.com/billa-austria/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/billa-austria.webp" + }, + { + "country_code": "AT", + "country_name": "Austria", + "product_slug": "drei-austria", + "product_name": "Drei Austria", + "product_url": "https://www.bitrefill.com/drei-austria/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/drei-austria.webp" + }, + { + "country_code": "AU", + "country_name": "Australia", + "product_slug": "the-visa-digital-gift-card-australia", + "product_name": "Visa Gift Card AU", + "product_url": "https://www.bitrefill.com/the-visa-digital-gift-card-australia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/the-visa-digital-gift-card-australia.webp" + }, + { + "country_code": "AU", + "country_name": "Australia", + "product_slug": "woolworths-australia", + "product_name": "Woolworths Australia", + "product_url": "https://www.bitrefill.com/woolworths-australia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/woolworths-australia.webp" + }, + { + "country_code": "AU", + "country_name": "Australia", + "product_slug": "jb-hi-fi-australia", + "product_name": "JB Hi-Fi Australia", + "product_url": "https://www.bitrefill.com/jb-hi-fi-australia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/jb-hi-fi-australia.webp" + }, + { + "country_code": "AX", + "country_name": "Åland Islands", + "product_slug": "k-ruoka-finland", + "product_name": "K-Ruoka Finland", + "product_url": "https://www.bitrefill.com/k-ruoka-finland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/k-ruoka-finland.webp" + }, + { + "country_code": "AX", + "country_name": "Åland Islands", + "product_slug": "wolt-fi", + "product_name": "Wolt Finland", + "product_url": "https://www.bitrefill.com/wolt-fi/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/wolt-fi.webp" + }, + { + "country_code": "AX", + "country_name": "Åland Islands", + "product_slug": "s-group-finland", + "product_name": "S-Group Finland", + "product_url": "https://www.bitrefill.com/s-group-finland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/s-group-finland.webp" + }, + { + "country_code": "BA", + "country_name": "Bosnia and Herzegovina", + "product_slug": "league-of-legends-eu", + "product_name": "League of Legends EU", + "product_url": "https://www.bitrefill.com/league-of-legends-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/league-of-legends-eu.webp" + }, + { + "country_code": "BA", + "country_name": "Bosnia and Herzegovina", + "product_slug": "valorant-eu", + "product_name": "Valorant EU", + "product_url": "https://www.bitrefill.com/valorant-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/valorant-eu.webp" + }, + { + "country_code": "BA", + "country_name": "Bosnia and Herzegovina", + "product_slug": "eneba-gift-card-eu", + "product_name": "Eneba EUR", + "product_url": "https://www.bitrefill.com/eneba-gift-card-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/eneba-gift-card-eu.webp" + }, + { + "country_code": "BB", + "country_name": "Barbados", + "product_slug": "digicel-barbados", + "product_name": "Digicel Barbados", + "product_url": "https://www.bitrefill.com/digicel-barbados/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-barbados.webp" + }, + { + "country_code": "BB", + "country_name": "Barbados", + "product_slug": "flow-barbados", + "product_name": "Flow Barbados", + "product_url": "https://www.bitrefill.com/flow-barbados/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-barbados.webp" + }, + { + "country_code": "BB", + "country_name": "Barbados", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "BE", + "country_name": "Belgium", + "product_slug": "itunes-belgium", + "product_name": "Apple Belgium", + "product_url": "https://www.bitrefill.com/itunes-belgium/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/itunes-belgium.webp" + }, + { + "country_code": "BE", + "country_name": "Belgium", + "product_slug": "bol-eu", + "product_name": "Bol.com", + "product_url": "https://www.bitrefill.com/bol-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bol-eu.webp" + }, + { + "country_code": "BE", + "country_name": "Belgium", + "product_slug": "zalando-belgium", + "product_name": "Zalando Belgium", + "product_url": "https://www.bitrefill.com/zalando-belgium/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/zalando-belgium.webp" + }, + { + "country_code": "BG", + "country_name": "Bulgaria", + "product_slug": "ozone_bg", + "product_name": "Ozone.bg Bulgaria", + "product_url": "https://www.bitrefill.com/ozone_bg/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ozone_bg.webp" + }, + { + "country_code": "BG", + "country_name": "Bulgaria", + "product_slug": "eMAG-bulgaria", + "product_name": "eMAG Bulgaria", + "product_url": "https://www.bitrefill.com/eMAG-bulgaria/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/eMAG-bulgaria.webp" + }, + { + "country_code": "BG", + "country_name": "Bulgaria", + "product_slug": "decathlon-bulgaria", + "product_name": "Decathlon Bulgaria", + "product_url": "https://www.bitrefill.com/decathlon-bulgaria/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/decathlon-bulgaria.webp" + }, + { + "country_code": "BO", + "country_name": "Bolivia", + "product_slug": "tigo-bolivia", + "product_name": "Tigo Bolivia", + "product_url": "https://www.bitrefill.com/tigo-bolivia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tigo-bolivia.webp" + }, + { + "country_code": "BO", + "country_name": "Bolivia", + "product_slug": "entel-bolivia", + "product_name": "Entel Bolivia", + "product_url": "https://www.bitrefill.com/entel-bolivia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/entel-bolivia.webp" + }, + { + "country_code": "BO", + "country_name": "Bolivia", + "product_slug": "viva-bolivia", + "product_name": "Viva Bolivia", + "product_url": "https://www.bitrefill.com/viva-bolivia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/viva-bolivia.webp" + }, + { + "country_code": "BR", + "country_name": "Brazil", + "product_slug": "uber-brazil", + "product_name": "Uber Brazil", + "product_url": "https://www.bitrefill.com/uber-brazil/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/uber-brazil.webp" + }, + { + "country_code": "BR", + "country_name": "Brazil", + "product_slug": "ifood-br", + "product_name": "iFood Brazil", + "product_url": "https://www.bitrefill.com/ifood-br/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ifood-br.webp" + }, + { + "country_code": "BR", + "country_name": "Brazil", + "product_slug": "submarino-brazil", + "product_name": "Submarino Brazil", + "product_url": "https://www.bitrefill.com/submarino-brazil/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/submarino-brazil.webp" + }, + { + "country_code": "BS", + "country_name": "Bahamas", + "product_slug": "batelco-bahamas", + "product_name": "Batelco Bahamas", + "product_url": "https://www.bitrefill.com/batelco-bahamas/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/batelco-bahamas.webp" + }, + { + "country_code": "BS", + "country_name": "Bahamas", + "product_slug": "aliv-bahamas", + "product_name": "Aliv Bahamas", + "product_url": "https://www.bitrefill.com/aliv-bahamas/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/aliv-bahamas.webp" + }, + { + "country_code": "BS", + "country_name": "Bahamas", + "product_slug": "bitrefill-esim-bahamas", + "product_name": "eSIM Bahamas", + "product_url": "https://www.bitrefill.com/bitrefill-esim-bahamas/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-bahamas.webp" + }, + { + "country_code": "BZ", + "country_name": "Belize", + "product_slug": "digicel-belize", + "product_name": "Digicel Belize", + "product_url": "https://www.bitrefill.com/digicel-belize/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-belize.webp" + }, + { + "country_code": "BZ", + "country_name": "Belize", + "product_slug": "smart-belize", + "product_name": "Smart Belize", + "product_url": "https://www.bitrefill.com/smart-belize/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/smart-belize.webp" + }, + { + "country_code": "BZ", + "country_name": "Belize", + "product_slug": "bitrefill-esim-belize", + "product_name": "eSIM Belize", + "product_url": "https://www.bitrefill.com/bitrefill-esim-belize/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-belize.webp" + }, + { + "country_code": "CA", + "country_name": "Canada", + "product_slug": "tim-hortons-canada", + "product_name": "Tim Hortons Canada", + "product_url": "https://www.bitrefill.com/tim-hortons-canada/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tim-hortons-canada.webp" + }, + { + "country_code": "CA", + "country_name": "Canada", + "product_slug": "uber-eats-canada", + "product_name": "Uber Eats Canada", + "product_url": "https://www.bitrefill.com/uber-eats-canada/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/uber-eats-canada.webp" + }, + { + "country_code": "CA", + "country_name": "Canada", + "product_slug": "walmart-canada", + "product_name": "Walmart Canada", + "product_url": "https://www.bitrefill.com/walmart-canada/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/walmart-canada.webp" + }, + { + "country_code": "CH", + "country_name": "Switzerland", + "product_slug": "coop-switzerland", + "product_name": "Coop Switzerland", + "product_url": "https://www.bitrefill.com/coop-switzerland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/coop-switzerland.webp" + }, + { + "country_code": "CH", + "country_name": "Switzerland", + "product_slug": "migros-switzerland", + "product_name": "Migros Switzerland", + "product_url": "https://www.bitrefill.com/migros-switzerland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/migros-switzerland.webp" + }, + { + "country_code": "CH", + "country_name": "Switzerland", + "product_slug": "digitec-switzerland", + "product_name": "Digitec Switzerland", + "product_url": "https://www.bitrefill.com/digitec-switzerland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digitec-switzerland.webp" + }, + { + "country_code": "CL", + "country_name": "Chile", + "product_slug": "uber-and-uber-eats-voucher-chile", + "product_name": "Uber & Uber Eats CLP", + "product_url": "https://www.bitrefill.com/uber-and-uber-eats-voucher-chile/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/uber-and-uber-eats-voucher-chile.webp" + }, + { + "country_code": "CL", + "country_name": "Chile", + "product_slug": "entel-chile", + "product_name": "Entel Chile", + "product_url": "https://www.bitrefill.com/entel-chile/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/entel-chile.webp" + }, + { + "country_code": "CL", + "country_name": "Chile", + "product_slug": "falabella-chile", + "product_name": "Falabella Chile", + "product_url": "https://www.bitrefill.com/falabella-chile/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/falabella-chile.webp" + }, + { + "country_code": "CM", + "country_name": "Cameroon", + "product_slug": "mtn-cameroon", + "product_name": "MTN Cameroon", + "product_url": "https://www.bitrefill.com/mtn-cameroon/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mtn-cameroon.webp" + }, + { + "country_code": "CM", + "country_name": "Cameroon", + "product_slug": "orange-cameroon", + "product_name": "Orange Cameroon", + "product_url": "https://www.bitrefill.com/orange-cameroon/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-cameroon.webp" + }, + { + "country_code": "CM", + "country_name": "Cameroon", + "product_slug": "bitrefill-esim-cameroon", + "product_name": "eSIM Cameroon", + "product_url": "https://www.bitrefill.com/bitrefill-esim-cameroon/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-cameroon.webp" + }, + { + "country_code": "CN", + "country_name": "China", + "product_slug": "alipay-china", + "product_name": "Alipay China", + "product_url": "https://www.bitrefill.com/alipay-china/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/alipay-china.webp" + }, + { + "country_code": "CN", + "country_name": "China", + "product_slug": "jd-com-china", + "product_name": "JD.com China", + "product_url": "https://www.bitrefill.com/jd-com-china/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/jd-com-china.webp" + }, + { + "country_code": "CN", + "country_name": "China", + "product_slug": "bitrefill-esim-china", + "product_name": "eSIM China", + "product_url": "https://www.bitrefill.com/bitrefill-esim-china/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-china.webp" + }, + { + "country_code": "CO", + "country_name": "Colombia", + "product_slug": "tiendasd1-colombia", + "product_name": "Tiendas D1 Colombia", + "product_url": "https://www.bitrefill.com/tiendasd1-colombia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tiendasd1-colombia.webp" + }, + { + "country_code": "CO", + "country_name": "Colombia", + "product_slug": "claro-colombia", + "product_name": "Claro Colombia", + "product_url": "https://www.bitrefill.com/claro-colombia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-colombia.webp" + }, + { + "country_code": "CO", + "country_name": "Colombia", + "product_slug": "exito-colombia", + "product_name": "Éxito Colombia", + "product_url": "https://www.bitrefill.com/exito-colombia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/exito-colombia.webp" + }, + { + "country_code": "CR", + "country_name": "Costa Rica", + "product_slug": "kolbi-costa-rica", + "product_name": "Kolbi Costa Rica", + "product_url": "https://www.bitrefill.com/kolbi-costa-rica/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/kolbi-costa-rica.webp" + }, + { + "country_code": "CR", + "country_name": "Costa Rica", + "product_slug": "claro-costa-rica", + "product_name": "Claro Costa Rica", + "product_url": "https://www.bitrefill.com/claro-costa-rica/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-costa-rica.webp" + }, + { + "country_code": "CR", + "country_name": "Costa Rica", + "product_slug": "bitrefill-esim-costa-rica", + "product_name": "eSIM Costa Rica", + "product_url": "https://www.bitrefill.com/bitrefill-esim-costa-rica/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-costa-rica.webp" + }, + { + "country_code": "CU", + "country_name": "Cuba", + "product_slug": "bitrefill-esim-cuba", + "product_name": "eSIM Cuba", + "product_url": "https://www.bitrefill.com/bitrefill-esim-cuba/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-cuba.webp" + }, + { + "country_code": "CU", + "country_name": "Cuba", + "product_slug": "nauta-cuba", + "product_name": "Nauta Cuba", + "product_url": "https://www.bitrefill.com/nauta-cuba/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/nauta-cuba.webp" + }, + { + "country_code": "CU", + "country_name": "Cuba", + "product_slug": "cubacel-cuba", + "product_name": "Cubacel Cuba", + "product_url": "https://www.bitrefill.com/cubacel-cuba/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/cubacel-cuba.webp" + }, + { + "country_code": "CY", + "country_name": "Cyprus", + "product_slug": "wolt-cy", + "product_name": "Wolt Cyprus", + "product_url": "https://www.bitrefill.com/wolt-cy/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/wolt-cy.webp" + }, + { + "country_code": "CY", + "country_name": "Cyprus", + "product_slug": "ikea-cy", + "product_name": "IKEA Cyprus", + "product_url": "https://www.bitrefill.com/ikea-cy/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ikea-cy.webp" + }, + { + "country_code": "CY", + "country_name": "Cyprus", + "product_slug": "bitrefill-esim-cyprus", + "product_name": "eSIM Cyprus", + "product_url": "https://www.bitrefill.com/bitrefill-esim-cyprus/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-cyprus.webp" + }, + { + "country_code": "CZ", + "country_name": "Czech Republic", + "product_slug": "kaufland-czech-republic", + "product_name": "Kaufland CZ", + "product_url": "https://www.bitrefill.com/kaufland-czech-republic/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/kaufland-czech-republic.webp" + }, + { + "country_code": "CZ", + "country_name": "Czech Republic", + "product_slug": "alza-cz", + "product_name": "Alza CZ", + "product_url": "https://www.bitrefill.com/alza-cz/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/alza-cz.webp" + }, + { + "country_code": "CZ", + "country_name": "Czech Republic", + "product_slug": "wolt-cz", + "product_name": "Wolt CZ", + "product_url": "https://www.bitrefill.com/wolt-cz/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/wolt-cz.webp" + }, + { + "country_code": "DE", + "country_name": "Germany", + "product_slug": "rewe-germany", + "product_name": "Rewe Germany", + "product_url": "https://www.bitrefill.com/rewe-germany/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/rewe-germany.webp" + }, + { + "country_code": "DE", + "country_name": "Germany", + "product_slug": "kaufland-germany", + "product_name": "Kaufland Germany", + "product_url": "https://www.bitrefill.com/kaufland-germany/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/kaufland-germany.webp" + }, + { + "country_code": "DE", + "country_name": "Germany", + "product_slug": "media-markt-germany", + "product_name": "MediaMarkt Germany", + "product_url": "https://www.bitrefill.com/media-markt-germany/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/media-markt-germany.webp" + }, + { + "country_code": "DK", + "country_name": "Denmark", + "product_slug": "wolt-dk", + "product_name": "Wolt Denmark", + "product_url": "https://www.bitrefill.com/wolt-dk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/wolt-dk.webp" + }, + { + "country_code": "DK", + "country_name": "Denmark", + "product_slug": "zalando-denmark", + "product_name": "Zalando Denmark", + "product_url": "https://www.bitrefill.com/zalando-denmark/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/zalando-denmark.webp" + }, + { + "country_code": "DK", + "country_name": "Denmark", + "product_slug": "salling-denmark", + "product_name": "Salling Denmark", + "product_url": "https://www.bitrefill.com/salling-denmark/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/salling-denmark.webp" + }, + { + "country_code": "DO", + "country_name": "Dominican Republic", + "product_slug": "claro-dominicana", + "product_name": "Claro Dominicana", + "product_url": "https://www.bitrefill.com/claro-dominicana/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-dominicana.webp" + }, + { + "country_code": "DO", + "country_name": "Dominican Republic", + "product_slug": "altice-dominicana", + "product_name": "Altice Dominicana", + "product_url": "https://www.bitrefill.com/altice-dominicana/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/altice-dominicana.webp" + }, + { + "country_code": "DO", + "country_name": "Dominican Republic", + "product_slug": "bitrefill-esim-dominican-republic", + "product_name": "eSIM Dominican Republic", + "product_url": "https://www.bitrefill.com/bitrefill-esim-dominican-republic/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-dominican-republic.webp" + }, + { + "country_code": "EC", + "country_name": "Ecuador", + "product_slug": "digicel-ecuador", + "product_name": "Digicel Ecuador", + "product_url": "https://www.bitrefill.com/digicel-ecuador/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-ecuador.webp" + }, + { + "country_code": "EC", + "country_name": "Ecuador", + "product_slug": "claro-ecuador", + "product_name": "Claro Ecuador", + "product_url": "https://www.bitrefill.com/claro-ecuador/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-ecuador.webp" + }, + { + "country_code": "EC", + "country_name": "Ecuador", + "product_slug": "bitrefill-esim-ecuador", + "product_name": "eSIM Ecuador", + "product_url": "https://www.bitrefill.com/bitrefill-esim-ecuador/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-ecuador.webp" + }, + { + "country_code": "EE", + "country_name": "Estonia", + "product_slug": "circle-k-estonia", + "product_name": "Circle K Estonia", + "product_url": "https://www.bitrefill.com/circle-k-estonia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/circle-k-estonia.webp" + }, + { + "country_code": "EE", + "country_name": "Estonia", + "product_slug": "handm-estonia", + "product_name": "H&M Estonia", + "product_url": "https://www.bitrefill.com/handm-estonia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/handm-estonia.webp" + }, + { + "country_code": "EE", + "country_name": "Estonia", + "product_slug": "telia-estonia", + "product_name": "Telia Estonia", + "product_url": "https://www.bitrefill.com/telia-estonia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telia-estonia.webp" + }, + { + "country_code": "EG", + "country_name": "Egypt", + "product_slug": "vodafone-pin-egypt", + "product_name": "Vodafone Egypt", + "product_url": "https://www.bitrefill.com/vodafone-pin-egypt/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vodafone-pin-egypt.webp" + }, + { + "country_code": "EG", + "country_name": "Egypt", + "product_slug": "etisalat-egypt", + "product_name": "Etisalat Egypt", + "product_url": "https://www.bitrefill.com/etisalat-egypt/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/etisalat-egypt.webp" + }, + { + "country_code": "EG", + "country_name": "Egypt", + "product_slug": "jumia-egypt", + "product_name": "Jumia Egypt", + "product_url": "https://www.bitrefill.com/jumia-egypt/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/jumia-egypt.webp" + }, + { + "country_code": "ES", + "country_name": "Spain", + "product_slug": "carrefour-es", + "product_name": "Carrefour Spain", + "product_url": "https://www.bitrefill.com/carrefour-es/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/carrefour-es.webp" + }, + { + "country_code": "ES", + "country_name": "Spain", + "product_slug": "el-corte-ingles-spain", + "product_name": "El Corte Inglés", + "product_url": "https://www.bitrefill.com/el-corte-ingles-spain/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/el-corte-ingles-spain.webp" + }, + { + "country_code": "ES", + "country_name": "Spain", + "product_slug": "mercadona-spain", + "product_name": "Mercadona Spain", + "product_url": "https://www.bitrefill.com/mercadona-spain/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mercadona-spain.webp" + }, + { + "country_code": "ET", + "country_name": "Ethiopia", + "product_slug": "ethio-telecom-ethiopia", + "product_name": "Ethio Telecom", + "product_url": "https://www.bitrefill.com/ethio-telecom-ethiopia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ethio-telecom-ethiopia.webp" + }, + { + "country_code": "ET", + "country_name": "Ethiopia", + "product_slug": "bitrefill-esim-ethiopia", + "product_name": "eSIM Ethiopia", + "product_url": "https://www.bitrefill.com/bitrefill-esim-ethiopia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-ethiopia.webp" + }, + { + "country_code": "ET", + "country_name": "Ethiopia", + "product_slug": "cbe-birr-ethiopia", + "product_name": "CBE Birr Ethiopia", + "product_url": "https://www.bitrefill.com/cbe-birr-ethiopia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/cbe-birr-ethiopia.webp" + }, + { + "country_code": "FI", + "country_name": "Finland", + "product_slug": "wolt-fi", + "product_name": "Wolt Finland", + "product_url": "https://www.bitrefill.com/wolt-fi/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/wolt-fi.webp" + }, + { + "country_code": "FI", + "country_name": "Finland", + "product_slug": "k-ruoka-finland", + "product_name": "K-Ruoka Finland", + "product_url": "https://www.bitrefill.com/k-ruoka-finland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/k-ruoka-finland.webp" + }, + { + "country_code": "FI", + "country_name": "Finland", + "product_slug": "s-group-finland", + "product_name": "S-Group Finland", + "product_url": "https://www.bitrefill.com/s-group-finland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/s-group-finland.webp" + }, + { + "country_code": "FR", + "country_name": "France", + "product_slug": "carrefour-france", + "product_name": "Carrefour France", + "product_url": "https://www.bitrefill.com/carrefour-france/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/carrefour-france.webp" + }, + { + "country_code": "FR", + "country_name": "France", + "product_slug": "fnac-france", + "product_name": "Fnac France", + "product_url": "https://www.bitrefill.com/fnac-france/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/fnac-france.webp" + }, + { + "country_code": "FR", + "country_name": "France", + "product_slug": "leclerc-france", + "product_name": "E.Leclerc France", + "product_url": "https://www.bitrefill.com/leclerc-france/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/leclerc-france.webp" + }, + { + "country_code": "GB", + "country_name": "United Kingdom", + "product_slug": "uber-rides-uk", + "product_name": "Uber Money GBP", + "product_url": "https://www.bitrefill.com/uber-rides-uk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/uber-rides-uk.webp" + }, + { + "country_code": "GB", + "country_name": "United Kingdom", + "product_slug": "deliveroo-uk", + "product_name": "Deliveroo UK", + "product_url": "https://www.bitrefill.com/deliveroo-uk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/deliveroo-uk.webp" + }, + { + "country_code": "GB", + "country_name": "United Kingdom", + "product_slug": "sainsburys-in-store-digital-uk", + "product_name": "Sainsbury's UK", + "product_url": "https://www.bitrefill.com/sainsburys-in-store-digital-uk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/sainsburys-in-store-digital-uk.webp" + }, + { + "country_code": "GD", + "country_name": "Grenada", + "product_slug": "digicel-grenada", + "product_name": "Digicel Grenada", + "product_url": "https://www.bitrefill.com/digicel-grenada/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-grenada.webp" + }, + { + "country_code": "GD", + "country_name": "Grenada", + "product_slug": "flow-grenada", + "product_name": "Flow Grenada", + "product_url": "https://www.bitrefill.com/flow-grenada/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-grenada.webp" + }, + { + "country_code": "GD", + "country_name": "Grenada", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "GE", + "country_name": "Georgia", + "product_slug": "geocell-georgia", + "product_name": "Geocell Georgia", + "product_url": "https://www.bitrefill.com/geocell-georgia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/geocell-georgia.webp" + }, + { + "country_code": "GE", + "country_name": "Georgia", + "product_slug": "magti-georgia", + "product_name": "Magti Georgia", + "product_url": "https://www.bitrefill.com/magti-georgia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/magti-georgia.webp" + }, + { + "country_code": "GE", + "country_name": "Georgia", + "product_slug": "bitrefill-esim-georgia", + "product_name": "eSIM Georgia", + "product_url": "https://www.bitrefill.com/bitrefill-esim-georgia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-georgia.webp" + }, + { + "country_code": "GG", + "country_name": "Guernsey", + "product_slug": "deliveroo-uk", + "product_name": "Deliveroo UK", + "product_url": "https://www.bitrefill.com/deliveroo-uk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/deliveroo-uk.webp" + }, + { + "country_code": "GG", + "country_name": "Guernsey", + "product_slug": "o2-pin-united-kingdom", + "product_name": "O2 UK", + "product_url": "https://www.bitrefill.com/o2-pin-united-kingdom/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/o2-pin-united-kingdom.webp" + }, + { + "country_code": "GG", + "country_name": "Guernsey", + "product_slug": "ee-pin-united-kingdom", + "product_name": "EE UK", + "product_url": "https://www.bitrefill.com/ee-pin-united-kingdom/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ee-pin-united-kingdom.webp" + }, + { + "country_code": "GH", + "country_name": "Ghana", + "product_slug": "mtn-ghana", + "product_name": "MTN Ghana", + "product_url": "https://www.bitrefill.com/mtn-ghana/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mtn-ghana.webp" + }, + { + "country_code": "GH", + "country_name": "Ghana", + "product_slug": "vodafone-ghana", + "product_name": "Vodafone Ghana", + "product_url": "https://www.bitrefill.com/vodafone-ghana/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vodafone-ghana.webp" + }, + { + "country_code": "GH", + "country_name": "Ghana", + "product_slug": "bitrefill-esim-ghana", + "product_name": "eSIM Ghana", + "product_url": "https://www.bitrefill.com/bitrefill-esim-ghana/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-ghana.webp" + }, + { + "country_code": "GI", + "country_name": "Gibraltar", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "GI", + "country_name": "Gibraltar", + "product_slug": "gibtel-gibraltar", + "product_name": "Gibtel Gibraltar", + "product_url": "https://www.bitrefill.com/gibtel-gibraltar/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/gibtel-gibraltar.webp" + }, + { + "country_code": "GI", + "country_name": "Gibraltar", + "product_slug": "sure-gibraltar", + "product_name": "Sure Gibraltar", + "product_url": "https://www.bitrefill.com/sure-gibraltar/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/sure-gibraltar.webp" + }, + { + "country_code": "GM", + "country_name": "Gambia", + "product_slug": "africell-gambia", + "product_name": "Africell Gambia", + "product_url": "https://www.bitrefill.com/africell-gambia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/africell-gambia.webp" + }, + { + "country_code": "GM", + "country_name": "Gambia", + "product_slug": "qcell-gambia", + "product_name": "QCell Gambia", + "product_url": "https://www.bitrefill.com/qcell-gambia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/qcell-gambia.webp" + }, + { + "country_code": "GM", + "country_name": "Gambia", + "product_slug": "bitrefill-esim-gambia", + "product_name": "eSIM Gambia", + "product_url": "https://www.bitrefill.com/bitrefill-esim-gambia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-gambia.webp" + }, + { + "country_code": "GP", + "country_name": "Guadeloupe", + "product_slug": "orange-guadeloupe", + "product_name": "Orange Guadeloupe", + "product_url": "https://www.bitrefill.com/orange-guadeloupe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-guadeloupe.webp" + }, + { + "country_code": "GP", + "country_name": "Guadeloupe", + "product_slug": "digicel-guadeloupe", + "product_name": "Digicel Guadeloupe", + "product_url": "https://www.bitrefill.com/digicel-guadeloupe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-guadeloupe.webp" + }, + { + "country_code": "GP", + "country_name": "Guadeloupe", + "product_slug": "bitrefill-esim-guadeloupe", + "product_name": "eSIM Guadeloupe", + "product_url": "https://www.bitrefill.com/bitrefill-esim-guadeloupe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-guadeloupe.webp" + }, + { + "country_code": "GR", + "country_name": "Greece", + "product_slug": "cosmote-pin-greece", + "product_name": "Cosmote Greece", + "product_url": "https://www.bitrefill.com/cosmote-pin-greece/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/cosmote-pin-greece.webp" + }, + { + "country_code": "GR", + "country_name": "Greece", + "product_slug": "wind-greece", + "product_name": "Wind Hellas Greece", + "product_url": "https://www.bitrefill.com/wind-greece/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/wind-greece.webp" + }, + { + "country_code": "GR", + "country_name": "Greece", + "product_slug": "public-greece", + "product_name": "Public Greece", + "product_url": "https://www.bitrefill.com/public-greece/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/public-greece.webp" + }, + { + "country_code": "GT", + "country_name": "Guatemala", + "product_slug": "tigo-guatemala", + "product_name": "Tigo Guatemala", + "product_url": "https://www.bitrefill.com/tigo-guatemala/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tigo-guatemala.webp" + }, + { + "country_code": "GT", + "country_name": "Guatemala", + "product_slug": "claro-guatemala", + "product_name": "Claro Guatemala", + "product_url": "https://www.bitrefill.com/claro-guatemala/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-guatemala.webp" + }, + { + "country_code": "GT", + "country_name": "Guatemala", + "product_slug": "bitrefill-esim-guatemala", + "product_name": "eSIM Guatemala", + "product_url": "https://www.bitrefill.com/bitrefill-esim-guatemala/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-guatemala.webp" + }, + { + "country_code": "GU", + "country_name": "Guam", + "product_slug": "it-e-t-mobile-guam", + "product_name": "IT&E / T-Mobile Guam", + "product_url": "https://www.bitrefill.com/it-e-t-mobile-guam/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/it-e-t-mobile-guam.webp" + }, + { + "country_code": "GU", + "country_name": "Guam", + "product_slug": "docomo-guam", + "product_name": "Docomo Pacific Guam", + "product_url": "https://www.bitrefill.com/docomo-guam/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/docomo-guam.webp" + }, + { + "country_code": "GU", + "country_name": "Guam", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "HK", + "country_name": "Hong Kong", + "product_slug": "steam-hong-kong", + "product_name": "Steam HK", + "product_url": "https://www.bitrefill.com/steam-hong-kong/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/steam-hong-kong.webp" + }, + { + "country_code": "HK", + "country_name": "Hong Kong", + "product_slug": "itunes-hong-kong", + "product_name": "Apple HK", + "product_url": "https://www.bitrefill.com/itunes-hong-kong/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/itunes-hong-kong.webp" + }, + { + "country_code": "HK", + "country_name": "Hong Kong", + "product_slug": "watsons-hong-kong", + "product_name": "Watsons HK", + "product_url": "https://www.bitrefill.com/watsons-hong-kong/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/watsons-hong-kong.webp" + }, + { + "country_code": "HN", + "country_name": "Honduras", + "product_slug": "tigo-honduras", + "product_name": "Tigo Honduras", + "product_url": "https://www.bitrefill.com/tigo-honduras/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tigo-honduras.webp" + }, + { + "country_code": "HN", + "country_name": "Honduras", + "product_slug": "claro-honduras", + "product_name": "Claro Honduras", + "product_url": "https://www.bitrefill.com/claro-honduras/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-honduras.webp" + }, + { + "country_code": "HN", + "country_name": "Honduras", + "product_slug": "bitrefill-esim-honduras", + "product_name": "eSIM Honduras", + "product_url": "https://www.bitrefill.com/bitrefill-esim-honduras/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-honduras.webp" + }, + { + "country_code": "HR", + "country_name": "Croatia", + "product_slug": "wolthr-croatia", + "product_name": "Wolt Croatia", + "product_url": "https://www.bitrefill.com/wolthr-croatia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/wolthr-croatia.webp" + }, + { + "country_code": "HR", + "country_name": "Croatia", + "product_slug": "mall-hr-croatia", + "product_name": "MALL.HR Croatia", + "product_url": "https://www.bitrefill.com/mall-hr-croatia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mall-hr-croatia.webp" + }, + { + "country_code": "HR", + "country_name": "Croatia", + "product_slug": "playstation-croatia", + "product_name": "PlayStation Croatia", + "product_url": "https://www.bitrefill.com/playstation-croatia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/playstation-croatia.webp" + }, + { + "country_code": "HU", + "country_name": "Hungary", + "product_slug": "alza-hungary", + "product_name": "Alza Hungary", + "product_url": "https://www.bitrefill.com/alza-hungary/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/alza-hungary.webp" + }, + { + "country_code": "HU", + "country_name": "Hungary", + "product_slug": "tesco-hungary", + "product_name": "Tesco Hungary", + "product_url": "https://www.bitrefill.com/tesco-hungary/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tesco-hungary.webp" + }, + { + "country_code": "HU", + "country_name": "Hungary", + "product_slug": "telekom-hungary", + "product_name": "Telekom Hungary", + "product_url": "https://www.bitrefill.com/telekom-hungary/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telekom-hungary.webp" + }, + { + "country_code": "ID", + "country_name": "Indonesia", + "product_slug": "dana-cash-indonesia", + "product_name": "DANA Cash Indonesia", + "product_url": "https://www.bitrefill.com/dana-cash-indonesia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/dana-cash-indonesia.webp" + }, + { + "country_code": "ID", + "country_name": "Indonesia", + "product_slug": "gopay-indonesia", + "product_name": "GoPay Indonesia", + "product_url": "https://www.bitrefill.com/gopay-indonesia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/gopay-indonesia.webp" + }, + { + "country_code": "ID", + "country_name": "Indonesia", + "product_slug": "ovo-indonesia", + "product_name": "OVO Indonesia", + "product_url": "https://www.bitrefill.com/ovo-indonesia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ovo-indonesia.webp" + }, + { + "country_code": "IE", + "country_name": "Ireland", + "product_slug": "an-post-ireland", + "product_name": "An Post Ireland", + "product_url": "https://www.bitrefill.com/an-post-ireland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/an-post-ireland.webp" + }, + { + "country_code": "IE", + "country_name": "Ireland", + "product_slug": "tesco-ireland", + "product_name": "Tesco Ireland", + "product_url": "https://www.bitrefill.com/tesco-ireland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tesco-ireland.webp" + }, + { + "country_code": "IE", + "country_name": "Ireland", + "product_slug": "three-ireland", + "product_name": "Three Ireland", + "product_url": "https://www.bitrefill.com/three-ireland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/three-ireland.webp" + }, + { + "country_code": "IL", + "country_name": "Israel", + "product_slug": "cellcom-israel", + "product_name": "Cellcom Israel", + "product_url": "https://www.bitrefill.com/cellcom-israel/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/cellcom-israel.webp" + }, + { + "country_code": "IL", + "country_name": "Israel", + "product_slug": "partner-israel", + "product_name": "Partner Israel", + "product_url": "https://www.bitrefill.com/partner-israel/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/partner-israel.webp" + }, + { + "country_code": "IL", + "country_name": "Israel", + "product_slug": "bezeq-israel", + "product_name": "Bezeq Israel", + "product_url": "https://www.bitrefill.com/bezeq-israel/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bezeq-israel.webp" + }, + { + "country_code": "IM", + "country_name": "Isle of Man", + "product_slug": "deliveroo-uk", + "product_name": "Deliveroo UK", + "product_url": "https://www.bitrefill.com/deliveroo-uk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/deliveroo-uk.webp" + }, + { + "country_code": "IM", + "country_name": "Isle of Man", + "product_slug": "o2-pin-united-kingdom", + "product_name": "O2 UK", + "product_url": "https://www.bitrefill.com/o2-pin-united-kingdom/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/o2-pin-united-kingdom.webp" + }, + { + "country_code": "IM", + "country_name": "Isle of Man", + "product_slug": "ee-pin-united-kingdom", + "product_name": "EE UK", + "product_url": "https://www.bitrefill.com/ee-pin-united-kingdom/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ee-pin-united-kingdom.webp" + }, + { + "country_code": "IN", + "country_name": "India", + "product_slug": "phonepe-india", + "product_name": "PhonePe India", + "product_url": "https://www.bitrefill.com/phonepe-india/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/phonepe-india.webp" + }, + { + "country_code": "IN", + "country_name": "India", + "product_slug": "jio-india", + "product_name": "Jio India", + "product_url": "https://www.bitrefill.com/jio-india/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/jio-india.webp" + }, + { + "country_code": "IN", + "country_name": "India", + "product_slug": "airtel-india", + "product_name": "Airtel India", + "product_url": "https://www.bitrefill.com/airtel-india/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/airtel-india.webp" + }, + { + "country_code": "IQ", + "country_name": "Iraq", + "product_slug": "zain-iraq", + "product_name": "Zain Iraq", + "product_url": "https://www.bitrefill.com/zain-iraq/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/zain-iraq.webp" + }, + { + "country_code": "IQ", + "country_name": "Iraq", + "product_slug": "asia-cell-iraq", + "product_name": "Asia Cell Iraq", + "product_url": "https://www.bitrefill.com/asia-cell-iraq/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/asia-cell-iraq.webp" + }, + { + "country_code": "IQ", + "country_name": "Iraq", + "product_slug": "bitrefill-esim-iraq", + "product_name": "eSIM Iraq", + "product_url": "https://www.bitrefill.com/bitrefill-esim-iraq/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-iraq.webp" + }, + { + "country_code": "IS", + "country_name": "Iceland", + "product_slug": "siminn-iceland", + "product_name": "Síminn Iceland", + "product_url": "https://www.bitrefill.com/siminn-iceland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/siminn-iceland.webp" + }, + { + "country_code": "IS", + "country_name": "Iceland", + "product_slug": "nova-iceland", + "product_name": "Nova Iceland", + "product_url": "https://www.bitrefill.com/nova-iceland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/nova-iceland.webp" + }, + { + "country_code": "IS", + "country_name": "Iceland", + "product_slug": "bitrefill-esim-europe", + "product_name": "eSIM Europe", + "product_url": "https://www.bitrefill.com/bitrefill-esim-europe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-europe.webp" + }, + { + "country_code": "IT", + "country_name": "Italy", + "product_slug": "q8-italy", + "product_name": "Q8 Italy", + "product_url": "https://www.bitrefill.com/q8-italy/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/q8-italy.webp" + }, + { + "country_code": "IT", + "country_name": "Italy", + "product_slug": "esselunga-italy", + "product_name": "Esselunga Italy", + "product_url": "https://www.bitrefill.com/esselunga-italy/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/esselunga-italy.webp" + }, + { + "country_code": "IT", + "country_name": "Italy", + "product_slug": "trenitalia-italy", + "product_name": "Trenitalia Italy", + "product_url": "https://www.bitrefill.com/trenitalia-italy/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/trenitalia-italy.webp" + }, + { + "country_code": "JE", + "country_name": "Jersey", + "product_slug": "deliveroo-uk", + "product_name": "Deliveroo UK", + "product_url": "https://www.bitrefill.com/deliveroo-uk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/deliveroo-uk.webp" + }, + { + "country_code": "JE", + "country_name": "Jersey", + "product_slug": "o2-pin-united-kingdom", + "product_name": "O2 UK", + "product_url": "https://www.bitrefill.com/o2-pin-united-kingdom/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/o2-pin-united-kingdom.webp" + }, + { + "country_code": "JE", + "country_name": "Jersey", + "product_slug": "ee-pin-united-kingdom", + "product_name": "EE UK", + "product_url": "https://www.bitrefill.com/ee-pin-united-kingdom/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ee-pin-united-kingdom.webp" + }, + { + "country_code": "JM", + "country_name": "Jamaica", + "product_slug": "digicel-jamaica", + "product_name": "Digicel Jamaica", + "product_url": "https://www.bitrefill.com/digicel-jamaica/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-jamaica.webp" + }, + { + "country_code": "JM", + "country_name": "Jamaica", + "product_slug": "flow-jamaica", + "product_name": "Flow Jamaica", + "product_url": "https://www.bitrefill.com/flow-jamaica/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-jamaica.webp" + }, + { + "country_code": "JM", + "country_name": "Jamaica", + "product_slug": "bitrefill-esim-jamaica", + "product_name": "eSIM Jamaica", + "product_url": "https://www.bitrefill.com/bitrefill-esim-jamaica/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-jamaica.webp" + }, + { + "country_code": "JO", + "country_name": "Jordan", + "product_slug": "zain-jordan", + "product_name": "Zain Jordan", + "product_url": "https://www.bitrefill.com/zain-jordan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/zain-jordan.webp" + }, + { + "country_code": "JO", + "country_name": "Jordan", + "product_slug": "orange-jordan", + "product_name": "Orange Jordan", + "product_url": "https://www.bitrefill.com/orange-jordan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-jordan.webp" + }, + { + "country_code": "JO", + "country_name": "Jordan", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "JP", + "country_name": "Japan", + "product_slug": "au-pay-gift-card-japan", + "product_name": "au PAY Japan", + "product_url": "https://www.bitrefill.com/au-pay-gift-card-japan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/au-pay-gift-card-japan.webp" + }, + { + "country_code": "JP", + "country_name": "Japan", + "product_slug": "nintendo-japan", + "product_name": "Nintendo Japan", + "product_url": "https://www.bitrefill.com/nintendo-japan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/nintendo-japan.webp" + }, + { + "country_code": "JP", + "country_name": "Japan", + "product_slug": "starbucks-japan", + "product_name": "Starbucks Japan", + "product_url": "https://www.bitrefill.com/starbucks-japan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/starbucks-japan.webp" + }, + { + "country_code": "KE", + "country_name": "Kenya", + "product_slug": "naivas-pin-kenya", + "product_name": "Naivas Kenya", + "product_url": "https://www.bitrefill.com/naivas-pin-kenya/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/naivas-pin-kenya.webp" + }, + { + "country_code": "KE", + "country_name": "Kenya", + "product_slug": "safaricom-kenya", + "product_name": "Safaricom Kenya", + "product_url": "https://www.bitrefill.com/safaricom-kenya/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/safaricom-kenya.webp" + }, + { + "country_code": "KE", + "country_name": "Kenya", + "product_slug": "mtn-kenya", + "product_name": "MTN Kenya", + "product_url": "https://www.bitrefill.com/mtn-kenya/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mtn-kenya.webp" + }, + { + "country_code": "KN", + "country_name": "Saint Kitts and Nevis", + "product_slug": "digicel-st-kitts-and-nevis", + "product_name": "Digicel St Kitts", + "product_url": "https://www.bitrefill.com/digicel-st-kitts-and-nevis/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-st-kitts-and-nevis.webp" + }, + { + "country_code": "KN", + "country_name": "Saint Kitts and Nevis", + "product_slug": "flow-st-kitts", + "product_name": "Flow St Kitts", + "product_url": "https://www.bitrefill.com/flow-st-kitts/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-st-kitts.webp" + }, + { + "country_code": "KN", + "country_name": "Saint Kitts and Nevis", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "KR", + "country_name": "South Korea", + "product_slug": "naver-pay-korea", + "product_name": "Naver Pay", + "product_url": "https://www.bitrefill.com/naver-pay-korea/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/naver-pay-korea.webp" + }, + { + "country_code": "KR", + "country_name": "South Korea", + "product_slug": "kakao-korea", + "product_name": "Kakao Korea", + "product_url": "https://www.bitrefill.com/kakao-korea/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/kakao-korea.webp" + }, + { + "country_code": "KR", + "country_name": "South Korea", + "product_slug": "coupang-korea", + "product_name": "Coupang Korea", + "product_url": "https://www.bitrefill.com/coupang-korea/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/coupang-korea.webp" + }, + { + "country_code": "KW", + "country_name": "Kuwait", + "product_slug": "viva-kuwait", + "product_name": "Viva Kuwait", + "product_url": "https://www.bitrefill.com/viva-kuwait/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/viva-kuwait.webp" + }, + { + "country_code": "KW", + "country_name": "Kuwait", + "product_slug": "zain-kuwait", + "product_name": "Zain Kuwait", + "product_url": "https://www.bitrefill.com/zain-kuwait/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/zain-kuwait.webp" + }, + { + "country_code": "KW", + "country_name": "Kuwait", + "product_slug": "ooredoo-kuwait", + "product_name": "Ooredoo Kuwait", + "product_url": "https://www.bitrefill.com/ooredoo-kuwait/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ooredoo-kuwait.webp" + }, + { + "country_code": "KY", + "country_name": "Cayman Islands", + "product_slug": "digicel-cayman-islands", + "product_name": "Digicel Cayman Islands", + "product_url": "https://www.bitrefill.com/digicel-cayman-islands/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-cayman-islands.webp" + }, + { + "country_code": "KY", + "country_name": "Cayman Islands", + "product_slug": "flow-cayman", + "product_name": "Flow Cayman", + "product_url": "https://www.bitrefill.com/flow-cayman/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-cayman.webp" + }, + { + "country_code": "KY", + "country_name": "Cayman Islands", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "KZ", + "country_name": "Kazakhstan", + "product_slug": "beeline-kazakhstan", + "product_name": "Beeline Kazakhstan", + "product_url": "https://www.bitrefill.com/beeline-kazakhstan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/beeline-kazakhstan.webp" + }, + { + "country_code": "KZ", + "country_name": "Kazakhstan", + "product_slug": "kcell-kazakhstan", + "product_name": "Kcell Kazakhstan", + "product_url": "https://www.bitrefill.com/kcell-kazakhstan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/kcell-kazakhstan.webp" + }, + { + "country_code": "KZ", + "country_name": "Kazakhstan", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "LC", + "country_name": "Saint Lucia", + "product_slug": "digicel-saint-lucia", + "product_name": "Digicel Saint Lucia", + "product_url": "https://www.bitrefill.com/digicel-saint-lucia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-saint-lucia.webp" + }, + { + "country_code": "LC", + "country_name": "Saint Lucia", + "product_slug": "flow-saint-lucia", + "product_name": "Flow Saint Lucia", + "product_url": "https://www.bitrefill.com/flow-saint-lucia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-saint-lucia.webp" + }, + { + "country_code": "LC", + "country_name": "Saint Lucia", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "LI", + "country_name": "Liechtenstein", + "product_slug": "post-liechtenstein", + "product_name": "Post Liechtenstein", + "product_url": "https://www.bitrefill.com/post-liechtenstein/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/post-liechtenstein.webp" + }, + { + "country_code": "LI", + "country_name": "Liechtenstein", + "product_slug": "bitrefill-esim-europe", + "product_name": "eSIM Europe", + "product_url": "https://www.bitrefill.com/bitrefill-esim-europe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-europe.webp" + }, + { + "country_code": "LI", + "country_name": "Liechtenstein", + "product_slug": "digitec-switzerland", + "product_name": "Digitec Switzerland", + "product_url": "https://www.bitrefill.com/digitec-switzerland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digitec-switzerland.webp" + }, + { + "country_code": "LK", + "country_name": "Sri Lanka", + "product_slug": "dialog-sri-lanka", + "product_name": "Dialog Sri Lanka", + "product_url": "https://www.bitrefill.com/dialog-sri-lanka/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/dialog-sri-lanka.webp" + }, + { + "country_code": "LK", + "country_name": "Sri Lanka", + "product_slug": "mobitel-sri-lanka", + "product_name": "Mobitel Sri Lanka", + "product_url": "https://www.bitrefill.com/mobitel-sri-lanka/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mobitel-sri-lanka.webp" + }, + { + "country_code": "LK", + "country_name": "Sri Lanka", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "LT", + "country_name": "Lithuania", + "product_slug": "maxima-lithuania", + "product_name": "Maxima Lithuania", + "product_url": "https://www.bitrefill.com/maxima-lithuania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/maxima-lithuania.webp" + }, + { + "country_code": "LT", + "country_name": "Lithuania", + "product_slug": "telia-lithuania", + "product_name": "Telia Lithuania", + "product_url": "https://www.bitrefill.com/telia-lithuania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telia-lithuania.webp" + }, + { + "country_code": "LT", + "country_name": "Lithuania", + "product_slug": "bitrefill-esim-lithuania", + "product_name": "eSIM Lithuania", + "product_url": "https://www.bitrefill.com/bitrefill-esim-lithuania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-lithuania.webp" + }, + { + "country_code": "LU", + "country_name": "Luxembourg", + "product_slug": "deliveroo-be", + "product_name": "Deliveroo Belgium", + "product_url": "https://www.bitrefill.com/deliveroo-be/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/deliveroo-be.webp" + }, + { + "country_code": "LU", + "country_name": "Luxembourg", + "product_slug": "bol-eu", + "product_name": "Bol.com", + "product_url": "https://www.bitrefill.com/bol-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bol-eu.webp" + }, + { + "country_code": "LU", + "country_name": "Luxembourg", + "product_slug": "bitrefill-esim-europe", + "product_name": "eSIM Europe", + "product_url": "https://www.bitrefill.com/bitrefill-esim-europe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-europe.webp" + }, + { + "country_code": "LV", + "country_name": "Latvia", + "product_slug": "rimi-latvia", + "product_name": "Rimi Latvia", + "product_url": "https://www.bitrefill.com/rimi-latvia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/rimi-latvia.webp" + }, + { + "country_code": "LV", + "country_name": "Latvia", + "product_slug": "tele2-latvia", + "product_name": "Tele2 Latvia", + "product_url": "https://www.bitrefill.com/tele2-latvia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tele2-latvia.webp" + }, + { + "country_code": "LV", + "country_name": "Latvia", + "product_slug": "bitrefill-esim-latvia", + "product_name": "eSIM Latvia", + "product_url": "https://www.bitrefill.com/bitrefill-esim-latvia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-latvia.webp" + }, + { + "country_code": "MA", + "country_name": "Morocco", + "product_slug": "maroc-telecom-morocco", + "product_name": "Maroc Telecom", + "product_url": "https://www.bitrefill.com/maroc-telecom-morocco/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/maroc-telecom-morocco.webp" + }, + { + "country_code": "MA", + "country_name": "Morocco", + "product_slug": "orange-maroc", + "product_name": "Orange Maroc", + "product_url": "https://www.bitrefill.com/orange-maroc/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-maroc.webp" + }, + { + "country_code": "MA", + "country_name": "Morocco", + "product_slug": "bitrefill-esim-morocco", + "product_name": "eSIM Morocco", + "product_url": "https://www.bitrefill.com/bitrefill-esim-morocco/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-morocco.webp" + }, + { + "country_code": "MD", + "country_name": "Moldova", + "product_slug": "moldcell-moldova", + "product_name": "Moldcell Moldova", + "product_url": "https://www.bitrefill.com/moldcell-moldova/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/moldcell-moldova.webp" + }, + { + "country_code": "MD", + "country_name": "Moldova", + "product_slug": "orange-moldova", + "product_name": "Orange Moldova", + "product_url": "https://www.bitrefill.com/orange-moldova/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-moldova.webp" + }, + { + "country_code": "MD", + "country_name": "Moldova", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "ME", + "country_name": "Montenegro", + "product_slug": "telenor-montenegro", + "product_name": "Telenor Montenegro", + "product_url": "https://www.bitrefill.com/telenor-montenegro/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telenor-montenegro.webp" + }, + { + "country_code": "ME", + "country_name": "Montenegro", + "product_slug": "m-tel-montenegro", + "product_name": "m:tel Montenegro", + "product_url": "https://www.bitrefill.com/m-tel-montenegro/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/m-tel-montenegro.webp" + }, + { + "country_code": "ME", + "country_name": "Montenegro", + "product_slug": "bitrefill-esim-montenegro", + "product_name": "eSIM Montenegro", + "product_url": "https://www.bitrefill.com/bitrefill-esim-montenegro/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-montenegro.webp" + }, + { + "country_code": "MF", + "country_name": "Saint Martin", + "product_slug": "orange-saint-martin", + "product_name": "Orange Saint Martin", + "product_url": "https://www.bitrefill.com/orange-saint-martin/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-saint-martin.webp" + }, + { + "country_code": "MF", + "country_name": "Saint Martin", + "product_slug": "digicel-saint-martin", + "product_name": "Digicel Saint Martin", + "product_url": "https://www.bitrefill.com/digicel-saint-martin/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-saint-martin.webp" + }, + { + "country_code": "MF", + "country_name": "Saint Martin", + "product_slug": "bitrefill-esim-saint-martin", + "product_name": "eSIM Saint Martin", + "product_url": "https://www.bitrefill.com/bitrefill-esim-saint-martin/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-saint-martin.webp" + }, + { + "country_code": "MG", + "country_name": "Madagascar", + "product_slug": "airtel-madagascar", + "product_name": "Airtel Madagascar", + "product_url": "https://www.bitrefill.com/airtel-madagascar/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/airtel-madagascar.webp" + }, + { + "country_code": "MG", + "country_name": "Madagascar", + "product_slug": "telma-madagascar", + "product_name": "Telma Madagascar", + "product_url": "https://www.bitrefill.com/telma-madagascar/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telma-madagascar.webp" + }, + { + "country_code": "MG", + "country_name": "Madagascar", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "MH", + "country_name": "Marshall Islands", + "product_slug": "it-e-t-mobile-guam", + "product_name": "IT&E / T-Mobile", + "product_url": "https://www.bitrefill.com/it-e-t-mobile-guam/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/it-e-t-mobile-guam.webp" + }, + { + "country_code": "MH", + "country_name": "Marshall Islands", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "MH", + "country_name": "Marshall Islands", + "product_slug": "docomo-guam", + "product_name": "Docomo Pacific", + "product_url": "https://www.bitrefill.com/docomo-guam/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/docomo-guam.webp" + }, + { + "country_code": "MK", + "country_name": "North Macedonia", + "product_slug": "a1-north-macedonia", + "product_name": "A1 North Macedonia", + "product_url": "https://www.bitrefill.com/a1-north-macedonia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/a1-north-macedonia.webp" + }, + { + "country_code": "MK", + "country_name": "North Macedonia", + "product_slug": "telekom-mk", + "product_name": "Telekom MK", + "product_url": "https://www.bitrefill.com/telekom-mk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telekom-mk.webp" + }, + { + "country_code": "MK", + "country_name": "North Macedonia", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "MO", + "country_name": "Macau", + "product_slug": "ctm-macau", + "product_name": "CTM Macau", + "product_url": "https://www.bitrefill.com/ctm-macau/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ctm-macau.webp" + }, + { + "country_code": "MO", + "country_name": "Macau", + "product_slug": "three-macau", + "product_name": "3 Macau", + "product_url": "https://www.bitrefill.com/three-macau/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/three-macau.webp" + }, + { + "country_code": "MO", + "country_name": "Macau", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "MS", + "country_name": "Montserrat", + "product_slug": "digicel-montserrat", + "product_name": "Digicel Montserrat", + "product_url": "https://www.bitrefill.com/digicel-montserrat/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-montserrat.webp" + }, + { + "country_code": "MS", + "country_name": "Montserrat", + "product_slug": "flow-montserrat", + "product_name": "Flow Montserrat", + "product_url": "https://www.bitrefill.com/flow-montserrat/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-montserrat.webp" + }, + { + "country_code": "MS", + "country_name": "Montserrat", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "MT", + "country_name": "Malta", + "product_slug": "melita-malta", + "product_name": "Melita Malta", + "product_url": "https://www.bitrefill.com/melita-malta/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/melita-malta.webp" + }, + { + "country_code": "MT", + "country_name": "Malta", + "product_slug": "vodafone-malta", + "product_name": "Vodafone Malta", + "product_url": "https://www.bitrefill.com/vodafone-malta/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vodafone-malta.webp" + }, + { + "country_code": "MT", + "country_name": "Malta", + "product_slug": "bitrefill-esim-europe", + "product_name": "eSIM Europe", + "product_url": "https://www.bitrefill.com/bitrefill-esim-europe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-europe.webp" + }, + { + "country_code": "MU", + "country_name": "Mauritius", + "product_slug": "emtel-mauritius", + "product_name": "Emtel Mauritius", + "product_url": "https://www.bitrefill.com/emtel-mauritius/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/emtel-mauritius.webp" + }, + { + "country_code": "MU", + "country_name": "Mauritius", + "product_slug": "orange-mauritius", + "product_name": "Orange Mauritius", + "product_url": "https://www.bitrefill.com/orange-mauritius/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-mauritius.webp" + }, + { + "country_code": "MU", + "country_name": "Mauritius", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "MX", + "country_name": "Mexico", + "product_slug": "telcel-mexico", + "product_name": "Telcel Mexico", + "product_url": "https://www.bitrefill.com/telcel-mexico/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telcel-mexico.webp" + }, + { + "country_code": "MX", + "country_name": "Mexico", + "product_slug": "uber-mexico", + "product_name": "Uber Mexico", + "product_url": "https://www.bitrefill.com/uber-mexico/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/uber-mexico.webp" + }, + { + "country_code": "MX", + "country_name": "Mexico", + "product_slug": "cashi-walmart-mexico", + "product_name": "Cashi Walmart Mexico", + "product_url": "https://www.bitrefill.com/cashi-walmart-mexico/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/cashi-walmart-mexico.webp" + }, + { + "country_code": "MY", + "country_name": "Malaysia", + "product_slug": "digi-pin-malaysia", + "product_name": "Digi Malaysia", + "product_url": "https://www.bitrefill.com/digi-pin-malaysia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digi-pin-malaysia.webp" + }, + { + "country_code": "MY", + "country_name": "Malaysia", + "product_slug": "grabfood-my", + "product_name": "GrabFood Malaysia", + "product_url": "https://www.bitrefill.com/grabfood-my/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/grabfood-my.webp" + }, + { + "country_code": "MY", + "country_name": "Malaysia", + "product_slug": "touch-n-go-malaysia", + "product_name": "Touch 'n Go Malaysia", + "product_url": "https://www.bitrefill.com/touch-n-go-malaysia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/touch-n-go-malaysia.webp" + }, + { + "country_code": "NG", + "country_name": "Nigeria", + "product_slug": "mtn-nigeria", + "product_name": "MTN Nigeria", + "product_url": "https://www.bitrefill.com/mtn-nigeria/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mtn-nigeria.webp" + }, + { + "country_code": "NG", + "country_name": "Nigeria", + "product_slug": "airtel-nigeria", + "product_name": "Airtel Nigeria", + "product_url": "https://www.bitrefill.com/airtel-nigeria/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/airtel-nigeria.webp" + }, + { + "country_code": "NG", + "country_name": "Nigeria", + "product_slug": "glo-nigeria", + "product_name": "Glo Nigeria", + "product_url": "https://www.bitrefill.com/glo-nigeria/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/glo-nigeria.webp" + }, + { + "country_code": "NI", + "country_name": "Nicaragua", + "product_slug": "claro-nicaragua", + "product_name": "Claro Nicaragua", + "product_url": "https://www.bitrefill.com/claro-nicaragua/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-nicaragua.webp" + }, + { + "country_code": "NI", + "country_name": "Nicaragua", + "product_slug": "tigo-nicaragua", + "product_name": "Tigo Nicaragua", + "product_url": "https://www.bitrefill.com/tigo-nicaragua/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tigo-nicaragua.webp" + }, + { + "country_code": "NI", + "country_name": "Nicaragua", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "NL", + "country_name": "Netherlands", + "product_slug": "thuisbezorgd-netherlands", + "product_name": "Thuisbezorgd NL", + "product_url": "https://www.bitrefill.com/thuisbezorgd-netherlands/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/thuisbezorgd-netherlands.webp" + }, + { + "country_code": "NL", + "country_name": "Netherlands", + "product_slug": "bol-eu", + "product_name": "Bol.com", + "product_url": "https://www.bitrefill.com/bol-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bol-eu.webp" + }, + { + "country_code": "NL", + "country_name": "Netherlands", + "product_slug": "albert-heijn-netherlands", + "product_name": "Albert Heijn", + "product_url": "https://www.bitrefill.com/albert-heijn-netherlands/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/albert-heijn-netherlands.webp" + }, + { + "country_code": "NO", + "country_name": "Norway", + "product_slug": "wolt-no", + "product_name": "Wolt Norway", + "product_url": "https://www.bitrefill.com/wolt-no/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/wolt-no.webp" + }, + { + "country_code": "NO", + "country_name": "Norway", + "product_slug": "telenor-norway", + "product_name": "Telenor Norway", + "product_url": "https://www.bitrefill.com/telenor-norway/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telenor-norway.webp" + }, + { + "country_code": "NO", + "country_name": "Norway", + "product_slug": "norwegian-air", + "product_name": "Norwegian Air", + "product_url": "https://www.bitrefill.com/norwegian-air/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/norwegian-air.webp" + }, + { + "country_code": "NZ", + "country_name": "New Zealand", + "product_slug": "steam-new-zealand", + "product_name": "Steam NZ", + "product_url": "https://www.bitrefill.com/steam-new-zealand/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/steam-new-zealand.webp" + }, + { + "country_code": "NZ", + "country_name": "New Zealand", + "product_slug": "countdown-nz", + "product_name": "Countdown NZ", + "product_url": "https://www.bitrefill.com/countdown-nz/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/countdown-nz.webp" + }, + { + "country_code": "NZ", + "country_name": "New Zealand", + "product_slug": "vodafone-new-zealand", + "product_name": "Vodafone NZ", + "product_url": "https://www.bitrefill.com/vodafone-new-zealand/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vodafone-new-zealand.webp" + }, + { + "country_code": "OM", + "country_name": "Oman", + "product_slug": "omantel-oman", + "product_name": "Omantel Oman", + "product_url": "https://www.bitrefill.com/omantel-oman/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/omantel-oman.webp" + }, + { + "country_code": "OM", + "country_name": "Oman", + "product_slug": "ooredoo-oman", + "product_name": "Ooredoo Oman", + "product_url": "https://www.bitrefill.com/ooredoo-oman/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ooredoo-oman.webp" + }, + { + "country_code": "OM", + "country_name": "Oman", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "PA", + "country_name": "Panama", + "product_slug": "cable-onda-panama", + "product_name": "Cable Onda Panama", + "product_url": "https://www.bitrefill.com/cable-onda-panama/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/cable-onda-panama.webp" + }, + { + "country_code": "PA", + "country_name": "Panama", + "product_slug": "claro-panama", + "product_name": "Claro Panama", + "product_url": "https://www.bitrefill.com/claro-panama/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-panama.webp" + }, + { + "country_code": "PA", + "country_name": "Panama", + "product_slug": "bitrefill-esim-panama", + "product_name": "eSIM Panama", + "product_url": "https://www.bitrefill.com/bitrefill-esim-panama/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-panama.webp" + }, + { + "country_code": "PE", + "country_name": "Peru", + "product_slug": "claro-peru", + "product_name": "Claro Peru", + "product_url": "https://www.bitrefill.com/claro-peru/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-peru.webp" + }, + { + "country_code": "PE", + "country_name": "Peru", + "product_slug": "bcp-peru", + "product_name": "BCP Peru", + "product_url": "https://www.bitrefill.com/bcp-peru/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bcp-peru.webp" + }, + { + "country_code": "PE", + "country_name": "Peru", + "product_slug": "ripley-peru", + "product_name": "Ripley Peru", + "product_url": "https://www.bitrefill.com/ripley-peru/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ripley-peru.webp" + }, + { + "country_code": "PK", + "country_name": "Pakistan", + "product_slug": "jazz-pakistan", + "product_name": "Jazz Pakistan", + "product_url": "https://www.bitrefill.com/jazz-pakistan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/jazz-pakistan.webp" + }, + { + "country_code": "PK", + "country_name": "Pakistan", + "product_slug": "telenor-pakistan", + "product_name": "Telenor Pakistan", + "product_url": "https://www.bitrefill.com/telenor-pakistan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telenor-pakistan.webp" + }, + { + "country_code": "PK", + "country_name": "Pakistan", + "product_slug": "ufone-pakistan", + "product_name": "Ufone Pakistan", + "product_url": "https://www.bitrefill.com/ufone-pakistan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ufone-pakistan.webp" + }, + { + "country_code": "PL", + "country_name": "Poland", + "product_slug": "allegro-pl-egift", + "product_name": "Allegro Poland", + "product_url": "https://www.bitrefill.com/allegro-pl-egift/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/allegro-pl-egift.webp" + }, + { + "country_code": "PL", + "country_name": "Poland", + "product_slug": "biedronka-poland", + "product_name": "Biedronka Poland", + "product_url": "https://www.bitrefill.com/biedronka-poland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/biedronka-poland.webp" + }, + { + "country_code": "PL", + "country_name": "Poland", + "product_slug": "orlen-poland", + "product_name": "Orlen Poland", + "product_url": "https://www.bitrefill.com/orlen-poland/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orlen-poland.webp" + }, + { + "country_code": "PR", + "country_name": "Puerto Rico", + "product_slug": "virtual-prepaid-visa-usa", + "product_name": "Prepaid Visa USA", + "product_url": "https://www.bitrefill.com/virtual-prepaid-visa-usa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/virtual-prepaid-visa-usa.webp" + }, + { + "country_code": "PR", + "country_name": "Puerto Rico", + "product_slug": "doordash-usa", + "product_name": "DoorDash USA", + "product_url": "https://www.bitrefill.com/doordash-usa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/doordash-usa.webp" + }, + { + "country_code": "PR", + "country_name": "Puerto Rico", + "product_slug": "t-mobile-usa", + "product_name": "T-Mobile USA", + "product_url": "https://www.bitrefill.com/t-mobile-usa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/t-mobile-usa.webp" + }, + { + "country_code": "PT", + "country_name": "Portugal", + "product_slug": "cartao-da-portugal", + "product_name": "Cartão Dá Portugal", + "product_url": "https://www.bitrefill.com/cartao-da-portugal/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/cartao-da-portugal.webp" + }, + { + "country_code": "PT", + "country_name": "Portugal", + "product_slug": "continente-portugal", + "product_name": "Continente Portugal", + "product_url": "https://www.bitrefill.com/continente-portugal/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/continente-portugal.webp" + }, + { + "country_code": "PT", + "country_name": "Portugal", + "product_slug": "nos-portugal", + "product_name": "NOS Portugal", + "product_url": "https://www.bitrefill.com/nos-portugal/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/nos-portugal.webp" + }, + { + "country_code": "PY", + "country_name": "Paraguay", + "product_slug": "tigo-paraguay", + "product_name": "Tigo Paraguay", + "product_url": "https://www.bitrefill.com/tigo-paraguay/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tigo-paraguay.webp" + }, + { + "country_code": "PY", + "country_name": "Paraguay", + "product_slug": "personal-paraguay", + "product_name": "Personal Paraguay", + "product_url": "https://www.bitrefill.com/personal-paraguay/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/personal-paraguay.webp" + }, + { + "country_code": "PY", + "country_name": "Paraguay", + "product_slug": "bitrefill-esim-paraguay", + "product_name": "eSIM Paraguay", + "product_url": "https://www.bitrefill.com/bitrefill-esim-paraguay/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-paraguay.webp" + }, + { + "country_code": "QA", + "country_name": "Qatar", + "product_slug": "ooredoo-qatar", + "product_name": "Ooredoo Qatar", + "product_url": "https://www.bitrefill.com/ooredoo-qatar/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ooredoo-qatar.webp" + }, + { + "country_code": "QA", + "country_name": "Qatar", + "product_slug": "vodafone-qatar", + "product_name": "Vodafone Qatar", + "product_url": "https://www.bitrefill.com/vodafone-qatar/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vodafone-qatar.webp" + }, + { + "country_code": "QA", + "country_name": "Qatar", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "RO", + "country_name": "Romania", + "product_slug": "emagro-dir-romania", + "product_name": "eMAG Romania", + "product_url": "https://www.bitrefill.com/emagro-dir-romania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/emagro-dir-romania.webp" + }, + { + "country_code": "RO", + "country_name": "Romania", + "product_slug": "kaufland-romania", + "product_name": "Kaufland Romania", + "product_url": "https://www.bitrefill.com/kaufland-romania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/kaufland-romania.webp" + }, + { + "country_code": "RO", + "country_name": "Romania", + "product_slug": "digi-romania", + "product_name": "Digi Romania", + "product_url": "https://www.bitrefill.com/digi-romania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digi-romania.webp" + }, + { + "country_code": "RS", + "country_name": "Serbia", + "product_slug": "delfi-serbia", + "product_name": "Delfi Serbia", + "product_url": "https://www.bitrefill.com/delfi-serbia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/delfi-serbia.webp" + }, + { + "country_code": "RS", + "country_name": "Serbia", + "product_slug": "mts-serbia", + "product_name": "MTS Serbia", + "product_url": "https://www.bitrefill.com/mts-serbia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mts-serbia.webp" + }, + { + "country_code": "RS", + "country_name": "Serbia", + "product_slug": "bitrefill-esim-serbia", + "product_name": "eSIM Serbia", + "product_url": "https://www.bitrefill.com/bitrefill-esim-serbia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-serbia.webp" + }, + { + "country_code": "SA", + "country_name": "Saudi Arabia", + "product_slug": "hungerstation-sa", + "product_name": "HungerStation SA", + "product_url": "https://www.bitrefill.com/hungerstation-sa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/hungerstation-sa.webp" + }, + { + "country_code": "SA", + "country_name": "Saudi Arabia", + "product_slug": "stc-saudi-arabia", + "product_name": "STC Saudi Arabia", + "product_url": "https://www.bitrefill.com/stc-saudi-arabia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/stc-saudi-arabia.webp" + }, + { + "country_code": "SA", + "country_name": "Saudi Arabia", + "product_slug": "noon-saudi-arabia", + "product_name": "Noon.com Saudi Arabia", + "product_url": "https://www.bitrefill.com/noon-saudi-arabia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/noon-saudi-arabia.webp" + }, + { + "country_code": "SC", + "country_name": "Seychelles", + "product_slug": "airtel-seychelles", + "product_name": "Airtel Seychelles", + "product_url": "https://www.bitrefill.com/airtel-seychelles/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/airtel-seychelles.webp" + }, + { + "country_code": "SC", + "country_name": "Seychelles", + "product_slug": "cable-and-wireless-seychelles", + "product_name": "Cable & Wireless SC", + "product_url": "https://www.bitrefill.com/cable-and-wireless-seychelles/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/cable-and-wireless-seychelles.webp" + }, + { + "country_code": "SC", + "country_name": "Seychelles", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "SE", + "country_name": "Sweden", + "product_slug": "superpresentkortet-sweden", + "product_name": "SuperPresentkortet", + "product_url": "https://www.bitrefill.com/superpresentkortet-sweden/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/superpresentkortet-sweden.webp" + }, + { + "country_code": "SE", + "country_name": "Sweden", + "product_slug": "foodora-se", + "product_name": "Foodora SE", + "product_url": "https://www.bitrefill.com/foodora-se/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/foodora-se.webp" + }, + { + "country_code": "SE", + "country_name": "Sweden", + "product_slug": "zalando-sweden", + "product_name": "Zalando Sweden", + "product_url": "https://www.bitrefill.com/zalando-sweden/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/zalando-sweden.webp" + }, + { + "country_code": "SG", + "country_name": "Singapore", + "product_slug": "foodpanda-singapore", + "product_name": "Foodpanda Singapore", + "product_url": "https://www.bitrefill.com/foodpanda-singapore/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/foodpanda-singapore.webp" + }, + { + "country_code": "SG", + "country_name": "Singapore", + "product_slug": "grab-singapore", + "product_name": "Grab Singapore", + "product_url": "https://www.bitrefill.com/grab-singapore/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/grab-singapore.webp" + }, + { + "country_code": "SG", + "country_name": "Singapore", + "product_slug": "fairprice-singapore", + "product_name": "FairPrice Singapore", + "product_url": "https://www.bitrefill.com/fairprice-singapore/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/fairprice-singapore.webp" + }, + { + "country_code": "SI", + "country_name": "Slovenia", + "product_slug": "mercator-slovenia", + "product_name": "Mercator Slovenia", + "product_url": "https://www.bitrefill.com/mercator-slovenia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mercator-slovenia.webp" + }, + { + "country_code": "SI", + "country_name": "Slovenia", + "product_slug": "petrol-slovenia", + "product_name": "Petrol Slovenia", + "product_url": "https://www.bitrefill.com/petrol-slovenia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/petrol-slovenia.webp" + }, + { + "country_code": "SI", + "country_name": "Slovenia", + "product_slug": "bitrefill-esim-europe", + "product_name": "eSIM Europe", + "product_url": "https://www.bitrefill.com/bitrefill-esim-europe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-europe.webp" + }, + { + "country_code": "SK", + "country_name": "Slovakia", + "product_slug": "tesco-slovakia", + "product_name": "Tesco Slovakia", + "product_url": "https://www.bitrefill.com/tesco-slovakia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tesco-slovakia.webp" + }, + { + "country_code": "SK", + "country_name": "Slovakia", + "product_slug": "mall-sk", + "product_name": "MALL.SK Slovakia", + "product_url": "https://www.bitrefill.com/mall-sk/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mall-sk.webp" + }, + { + "country_code": "SK", + "country_name": "Slovakia", + "product_slug": "bitrefill-esim-europe", + "product_name": "eSIM Europe", + "product_url": "https://www.bitrefill.com/bitrefill-esim-europe/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-europe.webp" + }, + { + "country_code": "SR", + "country_name": "Suriname", + "product_slug": "telesur-suriname", + "product_name": "Telesur Suriname", + "product_url": "https://www.bitrefill.com/telesur-suriname/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/telesur-suriname.webp" + }, + { + "country_code": "SR", + "country_name": "Suriname", + "product_slug": "digicel-suriname", + "product_name": "Digicel Suriname", + "product_url": "https://www.bitrefill.com/digicel-suriname/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-suriname.webp" + }, + { + "country_code": "SR", + "country_name": "Suriname", + "product_slug": "bitrefill-esim-suriname", + "product_name": "eSIM Suriname", + "product_url": "https://www.bitrefill.com/bitrefill-esim-suriname/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-suriname.webp" + }, + { + "country_code": "SV", + "country_name": "El Salvador", + "product_slug": "tigo-el-salvador", + "product_name": "Tigo El Salvador", + "product_url": "https://www.bitrefill.com/tigo-el-salvador/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/tigo-el-salvador.webp" + }, + { + "country_code": "SV", + "country_name": "El Salvador", + "product_slug": "claro-el-salvador", + "product_name": "Claro El Salvador", + "product_url": "https://www.bitrefill.com/claro-el-salvador/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/claro-el-salvador.webp" + }, + { + "country_code": "SV", + "country_name": "El Salvador", + "product_slug": "bitrefill-esim-el-salvador", + "product_name": "eSIM El Salvador", + "product_url": "https://www.bitrefill.com/bitrefill-esim-el-salvador/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-el-salvador.webp" + }, + { + "country_code": "TC", + "country_name": "Turks and Caicos", + "product_slug": "digicel-turks-and-caicos", + "product_name": "Digicel T&C", + "product_url": "https://www.bitrefill.com/digicel-turks-and-caicos/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-turks-and-caicos.webp" + }, + { + "country_code": "TC", + "country_name": "Turks and Caicos", + "product_slug": "flow-turks-and-caicos", + "product_name": "Flow T&C", + "product_url": "https://www.bitrefill.com/flow-turks-and-caicos/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-turks-and-caicos.webp" + }, + { + "country_code": "TC", + "country_name": "Turks and Caicos", + "product_slug": "bitrefill-esim-turks-and-caicos", + "product_name": "eSIM T&C", + "product_url": "https://www.bitrefill.com/bitrefill-esim-turks-and-caicos/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-turks-and-caicos.webp" + }, + { + "country_code": "TH", + "country_name": "Thailand", + "product_slug": "grabfood-thailand", + "product_name": "GrabFood Thailand", + "product_url": "https://www.bitrefill.com/grabfood-thailand/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/grabfood-thailand.webp" + }, + { + "country_code": "TH", + "country_name": "Thailand", + "product_slug": "true-move-h-thailand", + "product_name": "True Move H Thailand", + "product_url": "https://www.bitrefill.com/true-move-h-thailand/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/true-move-h-thailand.webp" + }, + { + "country_code": "TH", + "country_name": "Thailand", + "product_slug": "central-gift-card-thailand", + "product_name": "Central Gift Card", + "product_url": "https://www.bitrefill.com/central-gift-card-thailand/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/central-gift-card-thailand.webp" + }, + { + "country_code": "TN", + "country_name": "Tunisia", + "product_slug": "ooredoo-tunisia", + "product_name": "Ooredoo Tunisia", + "product_url": "https://www.bitrefill.com/ooredoo-tunisia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ooredoo-tunisia.webp" + }, + { + "country_code": "TN", + "country_name": "Tunisia", + "product_slug": "orange-tunisia", + "product_name": "Orange Tunisia", + "product_url": "https://www.bitrefill.com/orange-tunisia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/orange-tunisia.webp" + }, + { + "country_code": "TN", + "country_name": "Tunisia", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "TR", + "country_name": "Turkey", + "product_slug": "google-play-turkey", + "product_name": "Google Play Turkey", + "product_url": "https://www.bitrefill.com/google-play-turkey/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/google-play-turkey.webp" + }, + { + "country_code": "TR", + "country_name": "Turkey", + "product_slug": "migros-turkey", + "product_name": "Migros Turkey", + "product_url": "https://www.bitrefill.com/migros-turkey/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/migros-turkey.webp" + }, + { + "country_code": "TR", + "country_name": "Turkey", + "product_slug": "getir-turkey", + "product_name": "Getir Turkey", + "product_url": "https://www.bitrefill.com/getir-turkey/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/getir-turkey.webp" + }, + { + "country_code": "TT", + "country_name": "Trinidad and Tobago", + "product_slug": "digicel-trinidad-tobago", + "product_name": "Digicel T&T", + "product_url": "https://www.bitrefill.com/digicel-trinidad-tobago/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-trinidad-tobago.webp" + }, + { + "country_code": "TT", + "country_name": "Trinidad and Tobago", + "product_slug": "bmobile-tt", + "product_name": "bmobile T&T", + "product_url": "https://www.bitrefill.com/bmobile-tt/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bmobile-tt.webp" + }, + { + "country_code": "TT", + "country_name": "Trinidad and Tobago", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "TW", + "country_name": "Taiwan", + "product_slug": "steam-taiwan", + "product_name": "Steam Taiwan", + "product_url": "https://www.bitrefill.com/steam-taiwan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/steam-taiwan.webp" + }, + { + "country_code": "TW", + "country_name": "Taiwan", + "product_slug": "7-eleven-taiwan", + "product_name": "7-Eleven Taiwan", + "product_url": "https://www.bitrefill.com/7-eleven-taiwan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/7-eleven-taiwan.webp" + }, + { + "country_code": "TW", + "country_name": "Taiwan", + "product_slug": "famiport-taiwan", + "product_name": "FamiPort Taiwan", + "product_url": "https://www.bitrefill.com/famiport-taiwan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/famiport-taiwan.webp" + }, + { + "country_code": "TZ", + "country_name": "Tanzania", + "product_slug": "vodacom-tanzania", + "product_name": "Vodacom Tanzania", + "product_url": "https://www.bitrefill.com/vodacom-tanzania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vodacom-tanzania.webp" + }, + { + "country_code": "TZ", + "country_name": "Tanzania", + "product_slug": "airtel-tanzania", + "product_name": "Airtel Tanzania", + "product_url": "https://www.bitrefill.com/airtel-tanzania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/airtel-tanzania.webp" + }, + { + "country_code": "TZ", + "country_name": "Tanzania", + "product_slug": "bitrefill-esim-tanzania", + "product_name": "eSIM Tanzania", + "product_url": "https://www.bitrefill.com/bitrefill-esim-tanzania/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-tanzania.webp" + }, + { + "country_code": "UA", + "country_name": "Ukraine", + "product_slug": "silpo-ukraine", + "product_name": "Сільпо Ukraine", + "product_url": "https://www.bitrefill.com/silpo-ukraine/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/silpo-ukraine.webp" + }, + { + "country_code": "UA", + "country_name": "Ukraine", + "product_slug": "lifecell-ukraine", + "product_name": "lifecell Ukraine", + "product_url": "https://www.bitrefill.com/lifecell-ukraine/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/lifecell-ukraine.webp" + }, + { + "country_code": "UA", + "country_name": "Ukraine", + "product_slug": "kyivstar-ukraine", + "product_name": "Kyivstar Ukraine", + "product_url": "https://www.bitrefill.com/kyivstar-ukraine/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/kyivstar-ukraine.webp" + }, + { + "country_code": "UG", + "country_name": "Uganda", + "product_slug": "mtn-uganda", + "product_name": "MTN Uganda", + "product_url": "https://www.bitrefill.com/mtn-uganda/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mtn-uganda.webp" + }, + { + "country_code": "UG", + "country_name": "Uganda", + "product_slug": "airtel-uganda", + "product_name": "Airtel Uganda", + "product_url": "https://www.bitrefill.com/airtel-uganda/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/airtel-uganda.webp" + }, + { + "country_code": "UG", + "country_name": "Uganda", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + }, + { + "country_code": "US", + "country_name": "United States", + "product_slug": "doordash-usa", + "product_name": "DoorDash USA", + "product_url": "https://www.bitrefill.com/doordash-usa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/doordash-usa.webp" + }, + { + "country_code": "US", + "country_name": "United States", + "product_slug": "target-usa", + "product_name": "Target USA", + "product_url": "https://www.bitrefill.com/target-usa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/target-usa.webp" + }, + { + "country_code": "US", + "country_name": "United States", + "product_slug": "dunkin-donuts-usa", + "product_name": "Dunkin USA", + "product_url": "https://www.bitrefill.com/dunkin-donuts-usa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w360h216/dunkin-donuts-usa.webp" + }, + { + "country_code": "UY", + "country_name": "Uruguay", + "product_slug": "abitab-uruguay", + "product_name": "Abitab Uruguay", + "product_url": "https://www.bitrefill.com/abitab-uruguay/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/abitab-uruguay.webp" + }, + { + "country_code": "UY", + "country_name": "Uruguay", + "product_slug": "antel-uruguay", + "product_name": "Antel Uruguay", + "product_url": "https://www.bitrefill.com/antel-uruguay/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/antel-uruguay.webp" + }, + { + "country_code": "UY", + "country_name": "Uruguay", + "product_slug": "bitrefill-esim-uruguay", + "product_name": "eSIM Uruguay", + "product_url": "https://www.bitrefill.com/bitrefill-esim-uruguay/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-uruguay.webp" + }, + { + "country_code": "UZ", + "country_name": "Uzbekistan", + "product_slug": "ucell-uzbekistan", + "product_name": "Ucell Uzbekistan", + "product_url": "https://www.bitrefill.com/ucell-uzbekistan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/ucell-uzbekistan.webp" + }, + { + "country_code": "UZ", + "country_name": "Uzbekistan", + "product_slug": "beeline-uzbekistan", + "product_name": "Beeline Uzbekistan", + "product_url": "https://www.bitrefill.com/beeline-uzbekistan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/beeline-uzbekistan.webp" + }, + { + "country_code": "UZ", + "country_name": "Uzbekistan", + "product_slug": "bitrefill-esim-uzbekistan", + "product_name": "eSIM Uzbekistan", + "product_url": "https://www.bitrefill.com/bitrefill-esim-uzbekistan/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-uzbekistan.webp" + }, + { + "country_code": "VA", + "country_name": "Vatican City", + "product_slug": "eneba-gift-card-eu", + "product_name": "Eneba EUR", + "product_url": "https://www.bitrefill.com/eneba-gift-card-eu/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/eneba-gift-card-eu.webp" + }, + { + "country_code": "VA", + "country_name": "Vatican City", + "product_slug": "trenitalia-italy", + "product_name": "Trenitalia Italy", + "product_url": "https://www.bitrefill.com/trenitalia-italy/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/trenitalia-italy.webp" + }, + { + "country_code": "VA", + "country_name": "Vatican City", + "product_slug": "esselunga-italy", + "product_name": "Esselunga Italy", + "product_url": "https://www.bitrefill.com/esselunga-italy/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/esselunga-italy.webp" + }, + { + "country_code": "VC", + "country_name": "Saint Vincent", + "product_slug": "digicel-st-vincent", + "product_name": "Digicel St Vincent", + "product_url": "https://www.bitrefill.com/digicel-st-vincent/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-st-vincent.webp" + }, + { + "country_code": "VC", + "country_name": "Saint Vincent", + "product_slug": "flow-st-vincent", + "product_name": "Flow St Vincent", + "product_url": "https://www.bitrefill.com/flow-st-vincent/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-st-vincent.webp" + }, + { + "country_code": "VC", + "country_name": "Saint Vincent", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "VG", + "country_name": "British Virgin Islands", + "product_slug": "digicel-british-virgin-islands", + "product_name": "Digicel BVI", + "product_url": "https://www.bitrefill.com/digicel-british-virgin-islands/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/digicel-british-virgin-islands.webp" + }, + { + "country_code": "VG", + "country_name": "British Virgin Islands", + "product_slug": "flow-british-virgin-islands", + "product_name": "Flow BVI", + "product_url": "https://www.bitrefill.com/flow-british-virgin-islands/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/flow-british-virgin-islands.webp" + }, + { + "country_code": "VG", + "country_name": "British Virgin Islands", + "product_slug": "bitrefill-esim-caribbean", + "product_name": "eSIM Caribbean", + "product_url": "https://www.bitrefill.com/bitrefill-esim-caribbean/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-caribbean.webp" + }, + { + "country_code": "VN", + "country_name": "Vietnam", + "product_slug": "viettel-mobile-vietnam", + "product_name": "Viettel Vietnam", + "product_url": "https://www.bitrefill.com/viettel-mobile-vietnam/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/viettel-mobile-vietnam.webp" + }, + { + "country_code": "VN", + "country_name": "Vietnam", + "product_slug": "momo-vietnam", + "product_name": "MoMo Vietnam", + "product_url": "https://www.bitrefill.com/momo-vietnam/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/momo-vietnam.webp" + }, + { + "country_code": "VN", + "country_name": "Vietnam", + "product_slug": "vinid-vietnam", + "product_name": "VinID Vietnam", + "product_url": "https://www.bitrefill.com/vinid-vietnam/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vinid-vietnam.webp" + }, + { + "country_code": "ZA", + "country_name": "South Africa", + "product_slug": "1voucher-south-africa", + "product_name": "1Voucher South Africa", + "product_url": "https://www.bitrefill.com/1voucher-south-africa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/1voucher-south-africa.webp" + }, + { + "country_code": "ZA", + "country_name": "South Africa", + "product_slug": "vodacom-south-africa", + "product_name": "Vodacom South Africa", + "product_url": "https://www.bitrefill.com/vodacom-south-africa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/vodacom-south-africa.webp" + }, + { + "country_code": "ZA", + "country_name": "South Africa", + "product_slug": "takealot-south-africa", + "product_name": "Takealot South Africa", + "product_url": "https://www.bitrefill.com/takealot-south-africa/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/takealot-south-africa.webp" + }, + { + "country_code": "ZM", + "country_name": "Zambia", + "product_slug": "mtn-zambia", + "product_name": "MTN Zambia", + "product_url": "https://www.bitrefill.com/mtn-zambia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/mtn-zambia.webp" + }, + { + "country_code": "ZM", + "country_name": "Zambia", + "product_slug": "airtel-zambia", + "product_name": "Airtel Zambia", + "product_url": "https://www.bitrefill.com/airtel-zambia/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/airtel-zambia.webp" + }, + { + "country_code": "ZM", + "country_name": "Zambia", + "product_slug": "bitrefill-esim-global", + "product_name": "eSIM Global", + "product_url": "https://www.bitrefill.com/bitrefill-esim-global/", + "card_image_webp": "https://cdn.bitrefill.com/primg/w720h432/bitrefill-esim-global.webp" + } + ] + } + } + + key_api_baseurl_prod_new_enabled From 2b22e2acc2b1d0c48c371fba0bcd6aa0586cdb8e Mon Sep 17 00:00:00 2001 From: kcw-grunt Date: Wed, 27 May 2026 11:05:54 +0100 Subject: [PATCH 2/7] Version bump Working version --- app/build.gradle.kts | 2 +- .../ui/bentosections/shopbento/GiftCardsComposable.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index db85f2c2..4e6dc7a4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -35,7 +35,7 @@ android { applicationId = "ltd.grunt.brainwallet" minSdk = 29 targetSdk = 35 - versionCode = 202506331 + versionCode = 202506333 versionName = "v4.9.2" multiDexEnabled = true base.archivesName.set("${defaultConfig.versionName}(${defaultConfig.versionCode})") diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt index 7ed26641..11069511 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt @@ -87,7 +87,7 @@ fun GiftCardsComposable( .offset(x = offsetJE.dp, y = 15.dp) ) { - SingleCardComposable(rotation = -30f, modelString = "", offset = Offset(14f, 22f)) + SingleCardComposable(rotation = -30f, modelString = "", offset = Offset(0F, 0F)) } } } From 497b2a0aa001c1f6763cc640cd9879392bef97ad Mon Sep 17 00:00:00 2001 From: kcw-grunt Date: Wed, 27 May 2026 12:41:28 +0100 Subject: [PATCH 3/7] Seriously refactoring the BreadActivity Remvoed more cruft of BreadActivity Able to debug crash which was calling the cards before they are filled --- .../presenter/activities/BreadActivity.java | 282 ------------------ .../customviews/BRNotificationBar.java | 3 +- .../shopbento/GiftCardsComposable.kt | 20 +- 3 files changed, 11 insertions(+), 294 deletions(-) diff --git a/app/src/main/java/com/brainwallet/presenter/activities/BreadActivity.java b/app/src/main/java/com/brainwallet/presenter/activities/BreadActivity.java index 39ee3517..51828632 100644 --- a/app/src/main/java/com/brainwallet/presenter/activities/BreadActivity.java +++ b/app/src/main/java/com/brainwallet/presenter/activities/BreadActivity.java @@ -117,82 +117,15 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bread); AnalyticsManager.logCustomEvent(BWConstants._HOME_OPEN); - app = this; getWindowManager().getDefaultDisplay().getSize(screenParametersPoint); - initializeViews(); - setPriceTags(BRSharedPrefs.getLTCViewingPreference(BreadActivity.this), false); setListeners(); - setUpBarFlipper(); - checkTransactionDatabase(); primaryPrice.setTextSize(PRIMARY_TEXT_SIZE); secondaryPrice.setTextSize(SECONDARY_TEXT_SIZE); - onConnectionChanged(InternetManager.getInstance().isConnected(this)); - - updateUI(); bottomNav.setSelectedItemId(R.id.nav_history); - - setupNotificationPermission(); - showInAppReviewDialogIfNeeded(); - } - - private void setupNotificationPermission() { - //https://developer.android.com/develop/ui/views/notifications/notification-permission - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { - return; - } - - if (!PermissionUtil.hasPermission(this, Manifest.permission.POST_NOTIFICATIONS)) { - if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.POST_NOTIFICATIONS)) { - new AlertDialog.Builder(this) - .setTitle(R.string.permission_info) - .setMessage(R.string.please_grant_notification_permission) - .setNegativeButton(R.string.cancel, (dialog, which) -> { - dialog.dismiss(); - }) - .setPositiveButton(R.string.ok, (dialog, which) -> { - PermissionUtil.requestPermission(requestNotificationPermissionLauncher, Manifest.permission.POST_NOTIFICATIONS); - }) - .show(); - } else { - PermissionUtil.requestPermission(requestNotificationPermissionLauncher, Manifest.permission.POST_NOTIFICATIONS); - } - } - } - - private void finishActivities(BRActivity... activities) { - for (BRActivity activity : activities) { - if (activity != null) activity.finish(); - } - } - - private void showInAppReviewDialogIfNeeded() { - if (!BRSharedPrefs.isInAppReviewDone(this) && BRSharedPrefs.getSendTransactionCount(this) > 2) { - ReviewManager manager = ReviewManagerFactory.create(this); - Task request = manager.requestReviewFlow(); - request.addOnCompleteListener(task -> { - AnalyticsManager.logCustomEvent(BWConstants._20241006_DRR); - if (task.isSuccessful()) { - ReviewInfo reviewInfo = task.getResult(); - Task flow = manager.launchReviewFlow(BreadActivity.this, reviewInfo); - flow.addOnCompleteListener(task1 -> { - // The flow has finished. The API does not indicate whether the user - // reviewed or not, or even whether the review dialog was shown. Thus, no - // matter the result, we continue our app flow. - Timber.i("timber: In-app LaunchReviewFlow completed successful (%s)", task1.isSuccessful()); - if (task1.isSuccessful()) { - BRSharedPrefs.inAppReviewDone(BreadActivity.this); - AnalyticsManager.logCustomEvent(BWConstants._20241006_UCR); - } - }); - } else { - Timber.e(task.getException(), "In-app request review flow failed"); - } - }); - } } private void addObservers() { @@ -222,8 +155,6 @@ protected void onNewIntent(Intent intent) { private void setListeners() { bottomNav.setOnNavigationItemSelectedListener(item -> handleNavigationItemSelected(item.getItemId())); - primaryPrice.setOnClickListener(v -> swap()); - secondaryPrice.setOnClickListener(v -> swap()); menuBut.setOnClickListener(v -> { if (BRAnimator.isClickAllowed()) { drawerLayout.open(); @@ -240,78 +171,6 @@ public boolean handleNavigationItemSelected(int menuItemId) { return true; } - private void swap() { - if (!BRAnimator.isClickAllowed()) return; - boolean b = !BRSharedPrefs.getLTCViewingPreference(this); - setPriceTags(b, true); - BRSharedPrefs.putLTCViewingPreference(this, b); - } - - private void setPriceTags(boolean ltcPreferred, boolean animate) { - ConstraintSet set = new ConstraintSet(); - set.clone(toolBarConstraintLayout); - - if (animate) { - TransitionSet textSizeTransition = new TransitionSet() - .setOrdering(TransitionSet.ORDERING_TOGETHER) - .addTransition(new TextSizeTransition()) - .addTransition(new ChangeBounds()); - - TransitionSet transition = new TransitionSet() - .setOrdering(TransitionSet.ORDERING_SEQUENTIAL) - .addTransition(new Fade(Fade.OUT)) - .addTransition(textSizeTransition) - .addTransition(new Fade(Fade.IN)); - TransitionManager.beginDelayedTransition(toolBarConstraintLayout, transition); - } - - primaryPrice.setTextSize(ltcPreferred ? PRIMARY_TEXT_SIZE : SECONDARY_TEXT_SIZE); - secondaryPrice.setTextSize(ltcPreferred ? SECONDARY_TEXT_SIZE : PRIMARY_TEXT_SIZE); - - int[] ids = {primaryPrice.getId(), secondaryPrice.getId(), equals.getId()}; - // Clear views constraints - for (int id : ids) { - set.clear(id); - set.constrainWidth(id, ConstraintSet.WRAP_CONTENT); - set.constrainHeight(id, ConstraintSet.WRAP_CONTENT); - } - - int dp16 = Utils.getPixelsFromDps(this, 16); - int dp8 = Utils.getPixelsFromDps(this, 4); - - int leftId = ltcPreferred ? primaryPrice.getId() : secondaryPrice.getId(); - int rightId = ltcPreferred ? secondaryPrice.getId() : primaryPrice.getId(); - - int[] chainViews = {leftId, equals.getId(), rightId}; - - set.connect(leftId, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, dp16); - set.connect(leftId, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP); - set.connect(leftId, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, dp16); - set.setVerticalBias(leftId, 1.0f); - - set.connect(rightId, ConstraintSet.BASELINE, leftId, ConstraintSet.BASELINE); - set.connect(equals.getId(), ConstraintSet.BASELINE, leftId, ConstraintSet.BASELINE); - - set.connect(equals.getId(), ConstraintSet.START, leftId, ConstraintSet.END, dp8); - set.connect(equals.getId(), ConstraintSet.END, rightId, ConstraintSet.START, dp8); - - set.createHorizontalChain(leftId, ConstraintSet.LEFT, equals.getId(), ConstraintSet.RIGHT, chainViews, null, ConstraintSet.CHAIN_PACKED); - - // Apply the changes - set.applyTo(toolBarConstraintLayout); - - mHandler.postDelayed(() -> updateUI(), toolBarConstraintLayout.getLayoutTransition().getDuration(LayoutTransition.CHANGING)); - } - - private void checkTransactionDatabase() { - - } - - private void setUpBarFlipper() { - barFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.flipper_enter)); - barFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.flipper_exit)); - } - @Override protected void onRestart() { super.onRestart(); @@ -325,23 +184,13 @@ protected void onResume() { app = this; addObservers(); - setupNetworking(); - if (!BRWalletManager.getInstance().isCreated()) { BRExecutor.getInstance().forBackgroundTasks().execute(() -> BRWalletManager.getInstance().initWallet(BreadActivity.this)); } - mHandler.postDelayed(() -> updateUI(), 1000); BRWalletManager.getInstance().refreshBalance(this); } - private void setupNetworking() { - if (mConnectionReceiver == null) mConnectionReceiver = InternetManager.getInstance(); - IntentFilter mNetworkStateFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); - registerReceiver(mConnectionReceiver, mNetworkStateFilter); - InternetManager.addConnectionListener(this); - } - @Override protected void onPause() { super.onPause(); @@ -355,87 +204,9 @@ protected void onDestroy() { unregisterReceiver(mConnectionReceiver); } - private void initializeViews() { - menuBut = findViewById(R.id.menuBut); - - navigationDrawer = findViewById(R.id.navigationDrawer); - drawerLayout = findViewById(R.id.drawerLayout); - homeSettingDrawerComposeView.observeBus(message -> { - drawerLayout.close(); - if (SettingsViewModel.LEGACY_EFFECT_ON_LOCK.equals(message.getMessage())) { - LegacyNavigation.startBrainwalletActivity(this, true); - } else if (SettingsViewModel.LEGACY_EFFECT_ON_TOGGLE_DARK_MODE.equals(message.getMessage())) { - LegacyNavigation.restartBreadActivity(this); - } else if (SettingsViewModel.LEGACY_EFFECT_ON_SEC_UPDATE_PIN.equals(message.getMessage())) { - Intent intent = BrainwalletActivity.createIntent(this, new Route.UnLock(true)); - intent.putExtra("noPin", true); - startActivity(intent); - } else if (SettingsViewModel.LEGACY_EFFECT_ON_SEED_PHRASE.equals(message.getMessage())) { - PostAuth.getInstance().onPhraseCheckAuth(this, true); - } else if (SettingsViewModel.LEGACY_EFFECT_ON_SHARE_ANALYTICS_DATA_TOGGLE.equals(message.getMessage())) { - boolean currentShareAnalyticsDataEnabled = BRSharedPrefs.getShareData(this); - BRSharedPrefs.putShareData(this, !currentShareAnalyticsDataEnabled); - } else if (SettingsViewModel.LEGACY_EFFECT_ON_SYNC.equals(message.getMessage())) { - Intent intent = new Intent(this, SyncBlockchainActivity.class); - startActivity(intent); - overridePendingTransition(R.anim.enter_from_right, R.anim.exit_to_left); - } - return null; - }); //since we are still using this BreadActivity, need to observe EventBus e.g. lock from [HomeSettingDrawerSheet] - - bottomNav = findViewById(R.id.bottomNav); - bottomNav.getMenu().clear(); - bottomNav.inflateMenu(R.menu.bottom_nav_menu); - balanceTxtV = findViewById(R.id.balanceTxtV); - - primaryPrice = findViewById(R.id.primary_price); - secondaryPrice = findViewById(R.id.secondary_price); - equals = findViewById(R.id.equals); - toolBarConstraintLayout = findViewById(R.id.bread_toolbar); - - barFlipper = findViewById(R.id.tool_bar_flipper); - - final ViewTreeObserver observer = primaryPrice.getViewTreeObserver(); - observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (observer.isAlive()) { - observer.removeOnGlobalLayoutListener(this); - } - if (uiIsDone) return; - uiIsDone = true; - setPriceTags(BRSharedPrefs.getLTCViewingPreference(BreadActivity.this), false); - } - }); - - balanceTxtV.append(":"); - } - @Override public void onBalanceChanged(final long balance) { - updateUI(); - } - - public void updateUI() { - BRExecutor.getInstance().forLightWeightBackgroundTasks().execute(() -> { - Thread.currentThread().setName(Thread.currentThread().getName() + ":updateUI"); - //sleep a little in order to make sure all the commits are finished (like SharePreferences commits) - String iso = BRSharedPrefs.getIsoSymbol(BreadActivity.this); - - //current amount in litoshis - final BigDecimal amount = new BigDecimal(BRSharedPrefs.getCachedBalance(BreadActivity.this)); - - //amount in LTC units - BigDecimal btcAmount = BRExchange.getLitecoinForLitoshis(BreadActivity.this, amount); - final String formattedBTCAmount = BRCurrency.getFormattedCurrencyString(BreadActivity.this, "LTC", btcAmount); - final BigDecimal curAmount = BRExchange.getAmountFromLitoshis(BreadActivity.this, iso, amount); - final String formattedCurAmount = BRCurrency.getFormattedCurrencyString(BreadActivity.this, iso, curAmount); - runOnUiThread(() -> { - primaryPrice.setText(formattedBTCAmount); - secondaryPrice.setText(String.format("%s", formattedCurAmount)); - }); - }); } @Override @@ -443,64 +214,11 @@ public void onTxAdded() { BRWalletManager.getInstance().refreshBalance(BreadActivity.this); } - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - - switch (requestCode) { - case BWConstants.CAMERA_REQUEST_ID: { - // If request is cancelled, the result arrays are empty. - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - BRAnimator.openScanner(this, BWConstants.SCANNER_REQUEST); - // permission was granted, yay! Do the - // contacts-related task you need to do. - } else { - // permission denied, boo! Disable the - // functionality that depends on this permission. - } - return; - } - // other 'case' lines to check for other - // permissions this app might request - } - } - @Override public void onConnectionChanged(boolean isConnected) { Context thisContext = BreadActivity.this; Context app = getApplicationContext(); - if (isConnected) { - if (barFlipper != null) { - if (barFlipper.getDisplayedChild() == 1) { - removeNotificationBar(); - } - } - BRExecutor.getInstance().forLightWeightBackgroundTasks().execute(() -> { - final double progress = BRPeerManager.syncProgress(BRSharedPrefs.getStartHeight(thisContext)); - if (progress > 0 && progress < 1) { - SyncManager.getInstance().startSyncingProgressThread(app); - } - }); - } else { - if (barFlipper != null) { - addNotificationBar(); - } - SyncManager.getInstance().stopSyncingProgressThread(app); - } - } - - public void removeNotificationBar() { - if (barFlipper.getChildCount() == 1) return; - barFlipper.removeViewAt(1); - barFlipper.setDisplayedChild(0); - } - public void addNotificationBar() { - if (barFlipper.getChildCount() == 2) return; - BRNotificationBar view = new BRNotificationBar(this); - barFlipper.addView(view); - barFlipper.setDisplayedChild(1); } } diff --git a/app/src/main/java/com/brainwallet/presenter/customviews/BRNotificationBar.java b/app/src/main/java/com/brainwallet/presenter/customviews/BRNotificationBar.java index 4eee8df8..48551db0 100644 --- a/app/src/main/java/com/brainwallet/presenter/customviews/BRNotificationBar.java +++ b/app/src/main/java/com/brainwallet/presenter/customviews/BRNotificationBar.java @@ -43,9 +43,8 @@ private void init() { @Override public void onClick(View v) { if (getContext() instanceof BreadActivity) { - ((BreadActivity) getContext()).removeNotificationBar(); } } }); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt index 11069511..d56cdcbc 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt @@ -27,36 +27,36 @@ fun GiftCardsComposable( ) { var appeared by remember { mutableStateOf(false) } - var cards = state.cardData + var cards = state.shopCards LaunchedEffect(Unit) { appeared = true } - val offsetVisa by animateFloatAsState( + val offsetCardOne by animateFloatAsState( targetValue = if (appeared) -10f else 100f, animationSpec = tween( 500, delayMillis = 200 ), - label = "visaSlide" + label = "cardOneSlide" ) - val offsetJE by animateFloatAsState( + val offsetCardTwo by animateFloatAsState( targetValue = if (appeared) 30f else 100f, animationSpec = tween( 600, delayMillis = 200 ), - label = "jeSlide" + label = "cardTwoSlide" ) - val offsetAmazon by animateFloatAsState( + val offsetCardThree by animateFloatAsState( targetValue = if (appeared) -12f else 50f, animationSpec = tween( 400, delayMillis = 200 ), - label = "amazonSlide" + label = "cardThreeSlide" ) Box( @@ -67,7 +67,7 @@ fun GiftCardsComposable( Column( modifier = Modifier .fillMaxHeight() - .offset(x = offsetVisa.dp, y = 5.dp) + .offset(x = offsetCardOne.dp, y = 5.dp) ) { CardVisaComposable(rotation = 20f) } @@ -75,7 +75,7 @@ fun GiftCardsComposable( Column( modifier = Modifier .fillMaxHeight() - .offset(x = offsetAmazon.dp, y = -15.dp) + .offset(x = offsetCardTwo.dp, y = -15.dp) ) { CardAmazonComposable(rotation = 20f) @@ -84,7 +84,7 @@ fun GiftCardsComposable( Column( modifier = Modifier .fillMaxHeight() - .offset(x = offsetJE.dp, y = 15.dp) + .offset(x = offsetCardThree.dp, y = 15.dp) ) { SingleCardComposable(rotation = -30f, modelString = "", offset = Offset(0F, 0F)) From 7c9f3aead7c4958ef8b5f200c66677d8b81e98ea Mon Sep 17 00:00:00 2001 From: kcw-grunt Date: Wed, 27 May 2026 14:56:12 +0100 Subject: [PATCH 4/7] Parsed remote data of the widget and cards --- .../data/repository/ShopProxyRepositoryImpl.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt b/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt index 13945270..ac51efbb 100644 --- a/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt +++ b/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt @@ -43,8 +43,12 @@ class ShopProxyRepositoryImpl( runCatching { val shopConfig = json.decodeFromString(rawJson) Timber.d("ShopConfig parsed: ${shopConfig.shopData}") - _shopProxy.value = listOf(shopConfig.shopData.widgetUrl).map { ShopProxy(widget = it) } - _shopCards.value = shopConfig.shopData.cards + _shopProxy.value = listOf(shopConfig.shopData).map { + ShopProxy( + widget = it.widgetUrl, + shopCards = it.cards + ) + } }.onFailure { Timber.e(it, "RemoteConfig parse failed") } } } From eb79f93b9f1e49a0527afaed08b356849d88db98 Mon Sep 17 00:00:00 2001 From: kcw-grunt Date: Wed, 27 May 2026 15:22:28 +0100 Subject: [PATCH 5/7] Close to layouts are well polished --- .../repository/ShopProxyRepositoryImpl.kt | 4 - .../shopbento/GiftCardsComposable.kt | 28 ++- .../shopbento/ShopBentoScreen.kt | 6 +- .../bentosections/shopbento/ShopBentoState.kt | 5 +- .../shopbento/ShopBentoViewModel.kt | 29 ++- .../shopbento/cards/CardComposables.kt | 183 +----------------- 6 files changed, 49 insertions(+), 206 deletions(-) diff --git a/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt b/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt index ac51efbb..5dbfe795 100644 --- a/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt +++ b/app/src/main/java/com/brainwallet/data/repository/ShopProxyRepositoryImpl.kt @@ -18,7 +18,6 @@ data class ShopProxy( interface ShopProxyRepository { val shopProxy: StateFlow> - val shopCards: StateFlow> suspend fun refresh() } @@ -30,9 +29,6 @@ class ShopProxyRepositoryImpl( private val _shopProxy = MutableStateFlow>(emptyList()) override val shopProxy: StateFlow> = _shopProxy.asStateFlow() - private val _shopCards = MutableStateFlow>(emptyList()) - override val shopCards: StateFlow> = _shopCards.asStateFlow() - override suspend fun refresh() { runCatching { remoteConfigSource.fetchAndActivate() } .onFailure { Timber.e(it, "RemoteConfig fetch failed") } diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt index d56cdcbc..cc0c15ee 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt @@ -13,30 +13,28 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.brainwallet.ui.bentosections.shopbento.cards.CardAmazonComposable -import com.brainwallet.ui.bentosections.shopbento.cards.CardVisaComposable import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue -import androidx.compose.ui.geometry.Offset import com.brainwallet.ui.bentosections.shopbento.cards.SingleCardComposable @Composable fun GiftCardsComposable( - state: ShopBentoState, + imageURLOne: String, + imageURLTwo: String, + imageURLThree: String, modifier: Modifier = Modifier, ) { var appeared by remember { mutableStateOf(false) } - var cards = state.shopCards LaunchedEffect(Unit) { appeared = true } val offsetCardOne by animateFloatAsState( - targetValue = if (appeared) -10f else 100f, + targetValue = if (appeared) 5f else 100f, animationSpec = tween( 500, - delayMillis = 200 + delayMillis = 400 ), label = "cardOneSlide" ) @@ -45,16 +43,16 @@ fun GiftCardsComposable( targetValue = if (appeared) 30f else 100f, animationSpec = tween( 600, - delayMillis = 200 + delayMillis = 400 ), label = "cardTwoSlide" ) val offsetCardThree by animateFloatAsState( - targetValue = if (appeared) -12f else 50f, + targetValue = if (appeared) 30f else 50f, animationSpec = tween( 400, - delayMillis = 200 + delayMillis = 400 ), label = "cardThreeSlide" ) @@ -69,25 +67,25 @@ fun GiftCardsComposable( .fillMaxHeight() .offset(x = offsetCardOne.dp, y = 5.dp) ) { - CardVisaComposable(rotation = 20f) + SingleCardComposable(rotation = 20f, modelString = imageURLOne) } Column( modifier = Modifier .fillMaxHeight() - .offset(x = offsetCardTwo.dp, y = -15.dp) + .offset(x = offsetCardTwo.dp, y = -20.dp) ) { - CardAmazonComposable(rotation = 20f) + SingleCardComposable(rotation = 20f, modelString = imageURLTwo) } Column( modifier = Modifier .fillMaxHeight() - .offset(x = offsetCardThree.dp, y = 15.dp) + .offset(x = offsetCardThree.dp, y = 35.dp) ) { - SingleCardComposable(rotation = -30f, modelString = "", offset = Offset(0F, 0F)) + SingleCardComposable(rotation = -30f, modelString = imageURLThree) } } } diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoScreen.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoScreen.kt index ed60efa2..4edc666a 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoScreen.kt @@ -34,6 +34,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.runtime.collectAsState import androidx.compose.ui.tooling.preview.Preview +import androidx.lifecycle.compose.collectAsStateWithLifecycle @Composable fun ShopBentoScreen( @@ -61,6 +62,7 @@ private fun ShopBentoScreen( val logotypeWhite = R.drawable.logotype_bitrefill_wht val logotypeBitrefill = if (state.darkMode) logotypeWhite else logotypeBlack + val shopBentoState by viewModel.state.collectAsStateWithLifecycle() Box( modifier = Modifier @@ -119,7 +121,9 @@ private fun ShopBentoScreen( ) { GiftCardsComposable( - state = state, + imageURLOne = shopBentoState.cardImageURL1, + imageURLTwo = shopBentoState.cardImageURL2, + imageURLThree = shopBentoState.cardImageURL3, modifier = Modifier.fillMaxSize() ) } diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoState.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoState.kt index f98be6c3..4040a562 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoState.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoState.kt @@ -9,5 +9,8 @@ data class ShopBentoState( val countryIso: String = "US", val darkMode: Boolean = true, val shouldSlide: Boolean = false, - val shopBaseUrl: String = "" + val shopBaseUrl: String = "", + val cardImageURL1: String = "", + val cardImageURL2: String = "", + val cardImageURL3: String = "" ) diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt index d6c0c82c..d09239f6 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt @@ -14,7 +14,6 @@ import java.util.Locale import android.telephony.TelephonyManager import com.brainwallet.data.repository.SettingRepository import com.brainwallet.data.repository.ShopProxyRepository -import com.brainwallet.presenter.entities.ShopCard @KoinViewModel class ShopBentoViewModel( @@ -25,15 +24,14 @@ class ShopBentoViewModel( private val _state = MutableStateFlow(ShopBentoState()) val state: StateFlow = _state.asStateFlow() - + val currentCountryISO = getCountryIso() init { viewModelScope.launch { settingRepository.settings.collect { setting -> _state.update { it.copy( darkMode = setting.isDarkMode, - countryIso = getCountryIso(), - shopCards = loadCards() + countryIso = currentCountryISO ) } } @@ -42,8 +40,25 @@ class ShopBentoViewModel( shopProxyRepository.refresh() shopProxyRepository.shopProxy.collect { shopList -> val widget = shopList.firstOrNull()?.widget.orEmpty() + val cards = shopList.firstOrNull()?.shopCards.orEmpty() + .filter { it.countryCode == currentCountryISO } + var imageUrl1 = "" + var imageUrl2 = "" + var imageUrl3 = "" + + if (cards.count() >= 3) { + imageUrl1 = cards[0].cardImageWebP + imageUrl2 = cards[1].cardImageWebP + imageUrl3 = cards[2].cardImageWebP + } _state.update { - it.copy(shopBaseUrl = widget) + it.copy( + shopBaseUrl = widget, + shopCards = cards, + cardImageURL1 = imageUrl1, + cardImageURL2 = imageUrl2, + cardImageURL3 = imageUrl3 + ) } } } @@ -60,10 +75,6 @@ class ShopBentoViewModel( } } - private fun loadCards(): List { - return emptyList() - } - override fun onEvent(event: ShopBentoEvent) { when (event) { is ShopBentoEvent.OnLoad -> { diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt index aebefb15..1aa0cf60 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt @@ -1,208 +1,39 @@ package com.brainwallet.ui.bentosections.shopbento.cards import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.offset import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.CornerRadius -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.drawscope.rotate import androidx.compose.ui.unit.dp -import com.brainwallet.ui.theme.giftCardGradient2 -import com.brainwallet.R import androidx.compose.ui.draw.rotate -import androidx.compose.foundation.Canvas import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.size import androidx.compose.ui.Alignment -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview import coil.compose.rememberAsyncImagePainter -import com.brainwallet.ui.theme.giftCardGradient1 -import com.brainwallet.ui.theme.giftCardGradient3 @Composable fun SingleCardComposable( rotation: Float, modelString: String, - offset: Offset, modifier: Modifier = Modifier, ) { - val cornerRadius = 4.dp + val cornerRadius = 6.dp - Box(modifier = Modifier.fillMaxSize()) { - Canvas( - modifier = Modifier - .fillMaxSize() - .offset(x = offset.x.dp, y = offset.y.dp) - .clip(RoundedCornerShape(cornerRadius)) - ) { - rotate(degrees = 20f) { - val cardWidth = size.width * 0.7f - val cardHeight = cardWidth / 1.586f - drawRoundRect( - brush = giftCardGradient2(size), - size = Size(cardWidth, cardHeight), - topLeft = Offset( - x = (size.width - cardWidth) / 2f, - y = (size.height - cardHeight) / 2f - ), - cornerRadius = CornerRadius(cornerRadius.toPx()) - ) - } - } - Image( - painter = rememberAsyncImagePainter(modelString), - contentDescription = null, - modifier = Modifier - .size(50.dp) - .align(Alignment.Center) - .offset(x = 30.dp, y = -10.dp) - .rotate(rotation) - ) - } -} + BoxWithConstraints(modifier = Modifier.fillMaxSize().rotate(rotation)) { + val cardWidth = maxWidth * 0.7f + val cardHeight = cardWidth / 1.586f -@Composable -fun CardAmazonComposable( - rotation: Float, - modifier: Modifier = Modifier, -) { - val cornerRadius = 4.dp - Box(modifier = Modifier.fillMaxSize()) { - Canvas( - modifier = Modifier - .fillMaxSize() - .offset(x = 30.dp, y = -10.dp) - .clip(RoundedCornerShape(cornerRadius)) - ) { - rotate(degrees = 20f) { - val cardWidth = size.width * 0.7f - val cardHeight = cardWidth / 1.586f - drawRoundRect( - brush = giftCardGradient2(size), - size = Size(cardWidth, cardHeight), - topLeft = Offset( - x = (size.width - cardWidth) / 2f, - y = (size.height - cardHeight) / 2f - ), - cornerRadius = CornerRadius(cornerRadius.toPx()) - ) - } - } Image( - painter = painterResource(R.drawable.amazon_logo), + painter = rememberAsyncImagePainter(modelString), contentDescription = null, modifier = Modifier - .size(50.dp) + .size(width = cardWidth, height = cardHeight) .align(Alignment.Center) - .offset(x = 30.dp, y = -10.dp) - .rotate(20f) - ) - } -} - -@Composable -fun CardVisaComposable( - rotation: Float, - modifier: Modifier = Modifier, -) { - val cornerRadius = 4.dp - Box(modifier = Modifier.fillMaxSize()) { - Canvas( - modifier = Modifier - .fillMaxSize() .clip(RoundedCornerShape(cornerRadius)) - ) { - rotate(degrees = rotation) { - val cardWidth = size.width * 0.7f - val cardHeight = cardWidth / 1.586f - drawRoundRect( - brush = giftCardGradient1(size), - size = Size(cardWidth, cardHeight), - topLeft = Offset( - x = (size.width - cardWidth) / 2f, - y = (size.height - cardHeight) / 2f - ), - cornerRadius = CornerRadius(cornerRadius.toPx()) - ) - } - } - - Image( - painter = painterResource(R.drawable.visa_logo), - contentDescription = null, - modifier = Modifier - .size(40.dp) - .align(Alignment.Center) - .rotate(rotation) ) } } - -@Composable -fun CardJustEatComposable( - rotation: Float, - modifier: Modifier = Modifier, -) { - val cornerRadius = 4.dp - - Box(modifier = Modifier.fillMaxSize()) { - Canvas( - modifier = Modifier - .fillMaxSize() - .clip(RoundedCornerShape(cornerRadius)) - ) { - rotate(degrees = rotation) { - val cardWidth = size.width * 0.7f - val cardHeight = cardWidth / 1.586f - drawRoundRect( - brush = giftCardGradient3(size), - size = Size(cardWidth, cardHeight), - topLeft = Offset( - x = (size.width - cardWidth) / 2f, - y = (size.height - cardHeight) / 2f - ), - cornerRadius = CornerRadius(cornerRadius.toPx()) - ) - } - } - Image( - painter = painterResource(R.drawable.just_eat_logo), - contentDescription = null, - modifier = Modifier - .size(50.dp) - .align(Alignment.Center) - .rotate(rotation) - ) - } -} - -@Preview -@Composable -private fun CardJustEatComposablePreview() { - Box(modifier = Modifier) { - CardJustEatComposable(rotation = -30f) - } -} - -@Preview -@Composable -private fun CardAmazonComposablePreview() { - Box(modifier = Modifier) { - CardAmazonComposable(rotation = -30f) - } -} - -@Preview -@Composable -private fun CardVisaComposablePreview() { - Box(modifier = Modifier) { - CardVisaComposable(rotation = -30f) - } -} From c92a64bf41c9edaa9ccd8c69ed95d13aee69afeb Mon Sep 17 00:00:00 2001 From: kcw-grunt Date: Thu, 28 May 2026 14:00:57 +0100 Subject: [PATCH 6/7] Working the cards with polish --- .../com/brainwallet/tools/util/Extension.kt | 15 +++++++++ .../shopbento/GiftCardsComposable.kt | 2 +- .../shopbento/ShopBentoViewModel.kt | 16 ++------- .../shopbento/cards/CardComposables.kt | 31 +++++++++++++++--- .../brainwallet/ui/screens/main/MainScreen.kt | 5 ++- app/src/main/res/drawable/amazon_logo.png | Bin 3993 -> 0 bytes app/src/main/res/drawable/just_eat_logo.png | Bin 2882 -> 0 bytes app/src/main/res/drawable/visa_logo.png | Bin 2184 -> 0 bytes 8 files changed, 48 insertions(+), 21 deletions(-) delete mode 100644 app/src/main/res/drawable/amazon_logo.png delete mode 100644 app/src/main/res/drawable/just_eat_logo.png delete mode 100644 app/src/main/res/drawable/visa_logo.png diff --git a/app/src/main/java/com/brainwallet/tools/util/Extension.kt b/app/src/main/java/com/brainwallet/tools/util/Extension.kt index 89a6dc58..16935946 100644 --- a/app/src/main/java/com/brainwallet/tools/util/Extension.kt +++ b/app/src/main/java/com/brainwallet/tools/util/Extension.kt @@ -1,6 +1,7 @@ package com.brainwallet.tools.util import android.content.res.Configuration +import android.net.Uri import android.os.Build import androidx.annotation.StringRes import androidx.fragment.app.Fragment @@ -59,6 +60,20 @@ fun String.Companion.join( return stringBuilder.toString() } +fun String.withTheme(theme: String): String { + val uri = Uri.parse(this) + return uri.buildUpon() + .clearQuery() + .apply { + uri.queryParameterNames.forEach { key -> + val value = if (key == "theme") theme else uri.getQueryParameter(key) + appendQueryParameter(key, value) + } + } + .build() + .toString() +} + /** * TextInputLayout extension */ diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt index cc0c15ee..9d40e5d0 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/GiftCardsComposable.kt @@ -65,7 +65,7 @@ fun GiftCardsComposable( Column( modifier = Modifier .fillMaxHeight() - .offset(x = offsetCardOne.dp, y = 5.dp) + .offset(x = offsetCardOne.dp, y = 10.dp) ) { SingleCardComposable(rotation = 20f, modelString = imageURLOne) } diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt index d09239f6..695cb260 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModel.kt @@ -1,7 +1,6 @@ package com.brainwallet.ui.bentosections.shopbento import android.app.Application -import android.content.Context import androidx.lifecycle.viewModelScope import com.brainwallet.ui.BrainwalletViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -11,7 +10,6 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.koin.android.annotation.KoinViewModel import java.util.Locale -import android.telephony.TelephonyManager import com.brainwallet.data.repository.SettingRepository import com.brainwallet.data.repository.ShopProxyRepository @@ -24,7 +22,8 @@ class ShopBentoViewModel( private val _state = MutableStateFlow(ShopBentoState()) val state: StateFlow = _state.asStateFlow() - val currentCountryISO = getCountryIso() + + val currentCountryISO: String = Locale.getDefault().country.ifEmpty { "US" } init { viewModelScope.launch { settingRepository.settings.collect { setting -> @@ -63,17 +62,6 @@ class ShopBentoViewModel( } } } - private fun getCountryIso(): String { - val telephonyManager = app.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager - val simCountry = telephonyManager.simCountryIso - val networkCountry = telephonyManager.networkCountryIso - - return when { - simCountry.isNotEmpty() -> simCountry.uppercase() - networkCountry.isNotEmpty() -> networkCountry.uppercase() - else -> Locale.getDefault().country.ifEmpty { "US" } - } - } override fun onEvent(event: ShopBentoEvent) { when (event) { diff --git a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt index 1aa0cf60..92e77dc1 100644 --- a/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt +++ b/app/src/main/java/com/brainwallet/ui/bentosections/shopbento/cards/CardComposables.kt @@ -9,9 +9,14 @@ import androidx.compose.ui.graphics.drawscope.rotate import androidx.compose.ui.unit.dp import androidx.compose.ui.draw.rotate import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.size import androidx.compose.ui.Alignment +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import coil.compose.rememberAsyncImagePainter @Composable @@ -26,14 +31,30 @@ fun SingleCardComposable( val cardWidth = maxWidth * 0.7f val cardHeight = cardWidth / 1.586f - Image( - painter = rememberAsyncImagePainter(modelString), - contentDescription = null, + Box( modifier = Modifier .size(width = cardWidth, height = cardHeight) .align(Alignment.Center) .clip(RoundedCornerShape(cornerRadius)) - - ) + ) { + Image( + painter = rememberAsyncImagePainter(modelString), + contentDescription = "card_image", + modifier = Modifier.fillMaxSize(), + contentScale = ContentScale.Crop + ) + Box( + modifier = Modifier + .fillMaxSize() + .background( + brush = Brush.verticalGradient( + colors = listOf( + Color.Transparent, + Color.Black.copy(alpha = 0.15f) + ) + ) + ) + ) + } } } diff --git a/app/src/main/java/com/brainwallet/ui/screens/main/MainScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/main/MainScreen.kt index 60779447..fbdfda51 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/main/MainScreen.kt @@ -67,6 +67,7 @@ import com.brainwallet.navigation.Route import com.brainwallet.navigation.UiEffect import com.brainwallet.tools.animation.BRAnimator import com.brainwallet.tools.manager.AnalyticsManager +import com.brainwallet.tools.util.withTheme import com.brainwallet.ui.bentosections.balancebento.BalanceBentoScreen import com.brainwallet.ui.bentosections.buyreceivebento.receive.ReceiveDialog import com.brainwallet.ui.bentosections.gamehubbento.GameHubBentoPagerScreen @@ -458,7 +459,9 @@ fun MainScreen( is Route.BitrefillWeb -> WebModalScreen( modifier = Modifier.fillMaxSize(), onNavigate = onNavigate, - url = (modalContentRoute as Route.BitrefillWeb).url + url = (modalContentRoute as Route.BitrefillWeb).url.withTheme( + if (isDarkMode) "dark" else "light" + ) ) else -> {} } diff --git a/app/src/main/res/drawable/amazon_logo.png b/app/src/main/res/drawable/amazon_logo.png deleted file mode 100644 index b5c7a734557777047a39aa249f1e3945c4ac3d58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3993 zcmV;K4`%R*P)!1WL~({>Hwn&gX7E+flqC=Z z0W{EPG=KyYAmWH_$8S&G zIHv0bxC*O<6Y-W3F@u&+8h!%zah30&_}`SC;dH;I>l7YmN|_m5=S>Za&)_qt&jU-> zToRuK|L#}d8qJaNaju}3UDD(QVG7HQL})BsCvDPMDDN@I(mAK=U6*?4-`i*1Y$rSP zf-|~4VHg&4jX?=Lb1aPisPIgxO!tD{Q}O;0T~pMtsESYd?fe~A7>+4AA=IX0g6m_V zOdFTa8Md#d3v5v@{kx@g(-fXD{+$}8=!Cs7K^*xt_QOx0fWnW3@utemtc;`ZZmtwv z^5G0xg03?5!2*@Sivty0Y$pU&Oi>~nkKZq?nOw~{6`j&ovO4mEk@dJdzKsZ9T=8fO!8%_f< zSXj@&<$qQN{4-rApcCR$sP)WYJ=nT;c}-{xGV(m)divDgHT5&3M)(@Sk{Dpk6z}(-Z_t|Nz0169n8TH7Bo)9{@V7AUZK zqMQGf(ua|-&9vMU!hO@YAueg1;<6tFh^I(-<|2t@ACy*V1F}NXe2@tk7jsk- z*A?nm)TK`uUtPM6gmH*1)F`hA69^3I=PNm^X^3+wjZ2tDY5ttn#G$R5?`z_ccAm^- zKE|Da>$>Z>QMjT>!-Zx>X{`H>bI{S`Ca8(8P93t~)YT>C43p*h`n43m#{`5G1OT)5HSpJQV+`@JuDGUoT!%bscT$tEAOjqG6NRS3$-S|ddGo@ugX8cJ( zNQ1^zM3cwd+s~jIk{({1rUTd=ZiTJlN04CyhucUGxMs8~h@K0}Oge3-5k{*BE49$q zAxWFKjvPWu3MyT0&i>Bd^Z&0K3t{;c!V+9?@nPL*UKSfG19YyMsp1jMGD9N_C(dK9 zElGz>2D%~bRKg3cA7^mOcLWcMl!wGl_h|UAi9xXp27zxtCW=SwDqnyaj4<41&>y4PU$O$^q>l_D$)%X4X9)UDR}1Uf9p8U;z1wX#xheT8Aw z=M*9v0o}p`UdCl$z<3qeC?3(M$N&TR{y>)HU@QqPI!A%fPWBNYzR_fX9mBx!!>5Vj zk(r;b+(x)uhAFsI5WLV}29b^6g|^R441$3V`%p=-pm%_YR8U;jXXvJF4J|mw40ayK zR;W;mn)sh1dRP!NLYplt0Oygz4m3{_5A?sHr*9QGQbV!F)hteCE7_Z554Zm83v@dq z94j8--s@r$9 z=!v0e3%RPSS?4Gb+BkKjBL#WG`DRl>>*>ooY9&g6`37`I>*?S+sRM5rG{W%b!a|6G zt3$d&f=xPZ;N69uy`$=|!f*z3XoiM^f_q%exN0s87X?=cJ{&6|;RDDq5Rf%^N7eC* zFq{D$Mi@@&-@Z0@j4O5Ly6wTYG@`R2i(3AIA9+YL-cgK2xA31ew9oLcshw@1>T`I} zo@m^_Na`upY;3TCISdRI+&=Vt&EjLuKnweef$(T5Wurl-g?AK_*2KrRIXDgCQXpt^ zki#0JWLk5p1(#K2so;vjp>E?jX7J7iTZm@I&e|n&EmUMFDL4~I})lF+P#5?xVP_6k!;qqvt7{IV8OMD@U=qboe0LD!(dN44Q>gV*8CXjcOA@KCbiU^x72k>n+5~b zM}SDw-<-3Kf6v*d6~7J^T+M>>+pLmza zD&aM-URD~`yt*pw{Z6ssq(uLnV~{ae-)c5a%|WNG&b(@sPfZx;zFw3Ii!G4ib(*^Z z8)g(cF)%5(Q{~u4oQ2+i>lMe)Z5oa%`-g$Ju~vP@1YBK{eCNb3jbvfx{N+62{~M4o z*xr_5!Mz0KiE`j7$r!@IW0Ru|dj)L@>F$0x2D%+5S_KbT<}grvBgYMvRMkC#_QuZ> z7%&G)6-0|>{AOXtx1Xuu68b@#pM!5Sy;H{=`sIA+3uyAyK@*UxAX0dIFbA2jge%O; zeO>nD_j~5XGo*#xf*X3UHkAs(pLATo!)3_!lHAcEXXLME{+>d2xHoJ&o^Rr9K##B9 z$Tvi16@&#Xl=^jlFql_u>eN84u%~ggQKqKybdQ1V+&6@j|6IxI4!LTx+9=o3=FnoE z)7wZ`g?$ArR9XLB+$e<>UKZNzo8drrxK$TEt(p_W>N9pGf;5d$hG-fD<>w?#gz+te z@fkr}+B0`nae*bPGgjx}0-Mk5xhjO`pHm13J{-ulD7;4`%-HQPw<26`)dGv*>t-s9 zZ&8&Q3)Hc6qFpIYp5(tSJtN8}#m7i9=Rz3YSQy_z7@yShY@|qIkt?hbDqOB)TpmV{ z9zXwPU|+K-pgfqGZQh-Wye@;|BdJuIDBl)#*> z^W-nXb$s7-r~$psj81O)>4wVVHZwHw|L^EJ@b_g5{Vjz$Z!juf8t3laim(t2$~Z-1 zC@$>f);$XFRzn&TH^|3Je@I|Pf;;F{I74L^s_@KP)MJr(NmR6#DlaSXg&Bo*5u-9-(mErS!>oaFDBTOyxA zw|e|kFk)pYc4T9)6Gm-0Bo*$5Uq?rbwhUHq8Jgp}pjMfWkF*s*G6ANqU;&;+HF~{d z(?m3Up=rENg>o1#1-x51?Q;|7?AtSF!DX^>?^hM7a}lHpldI7`!)fe=`yuOHX^M#Q z_)|7bv^=l7>>!`4*eNm*A1e}B!B)9EW}Z6-iUXCCYz*}dzR~{mSPcp5v7l!yJxIftKf`3znAMll z<6T4(IH7!>L8LWXy*eoC75+!o=L7YzCq*nckDw3x)*JgJdF&X$D}DGb+NGla&%2-0 zsl1u->Tx4ry_#$x(wd!E*4J8nUX6u(XO9E2eD099R@S5bURaXX-v5}#vTtcR=c3Ls zyi!fRgL4wv2}C-vQ|oc5qNH9eGY}Hz$#p}O{UZxA91eRbq?6lzKWGeI%5@3v;RYJItxg>#o*LJRzJ=rp+7)Ml*1G5)` zn^Q1ig+6X&R}dMUBxE~gIL#mmZ4c~~;O6*gq~pN*Cv7V%pmP@3P@YWLRz#4k!Hq)O z6MHGRMSL&J6^+j~GO#b?PAFf|*fX$&Jj>H3G{63ZdhRH+y|DL!Tf}dlld3(3wu8K9 z{XnYlWn7uF-9*8yz^^V!8~05bGR`8*t8nJgp?|lCf-A(U)a=lZ0%T4NDGUn>xyRQX z-M^0OU3Zx%xE=7SwE^e!@QiZP_&L}*lOg4+X`)%w3#5AB>K4*aR? zZVQ*qlmB0Jg1{5hnc!t6Xgxuc3G7Z_ zd4f6<*qI>C1X3o5Gl7r^qE3L~Ot6L-9B?2&S=EEj^U#t({340N9S$G_>;YrUg*~>W zXKfFKMx(J`NbsBhhWN`Ki%8mqOTR#)(I~@d#UCclHl!_`ApQu%U6UZA(P+qUn(dRx z<7$-0G74b5OmlcXOj%*wq*#dbW!iWPXztN~pmOvhmFcPoPXdD@0fjlr_B$~6LQd4A8pv<%g2x{LjPdn>rt506s6AKOCWs~ruW>E za7*Snscux}eIosLs-MKHcF*AdqcXnPw0Ds-R2G#xnD~oGeRr-tcmBN!lv~Qq=Km)$ z@#?X_^ttAZE&Ey$(U#Yte_n(do!0jFVvqarvvZ2$0(IxZKR+uVLmL?{&A{4)t-P?M z3tJ1a+?w$IIyoA4jY4c5UriqCQTjC#uM?EL;0lSvzcT6fM?+AWVQ8StJSb#f<9DVG zBL9bx4~bTRw6~@{xBj#TO>rnp=kGvRj-%z8(Qbc34n5G){dP*{Hakp5T(;>2oEqK= z(|YN}lyY;JV6D`e#?r!gpM>#3!=X9u+4o0*GS+4i=%1qq% z)l6Gx@J*OrGBtB1N$biX&0JzG?L0HALw%-9Mb+9X>02s->(CTrgtjA{Lm(f1agFyX zGof~$$_xAMK0}Qp)o^0=ey%`LSyR2P3i)V3`kioEMsewfFYb9sd-fQ73Tz2Y$m7X}AcSVE8>gnRN=~eDuEO zc6t)N9PA<;BR6UxCo^o{rZf{CNid%pE}?B+Fg<$`wp>L&aBJYwcA5!NQ;5xiv5>?S-@ zwllMNy+K_#?MTm`EWOY@{w75^PY;o60?Ph@>gHFAr;kTU&?o8SVvFFO9nVHg`ErJ1&{iALtKhJ{wQt=MIAA zd=~;!oV#D&A>dWyoJJlR`Futpdk{uKG2vPeM>?M3dSL%S#`2+tu(gfm4*h-Il#b0~ zj+PnTuwhNs#57jUc$L$R+Fxyjz7te|cvQy?;wUCubibzV%c>)V=a^L+lu>nj5kaE8 zN;MoiRvW&!hPOeSCHiR*T8XnR^fpVJOvNNTtTctSjU2-&r6uBJDDc{GJnhCUMu}NL z14Sl&%^%xYj6NTU^llG@b92P(0%_t)-uB^P9Y08NJV>v*LvPA%CkiH4r<~POCFSIh zQUo#WcsB~;ghw)8TV&#w3gpIpJ~~p|_rYs=mq;tJsSkjdm$8wq&AbA%GE zZi8T|jC7nCy+K`S2&CptWNOD)UeS8iF!757(m8`@KIU{7%hB5%?*I3RDK40(_qR(Fq2ZP|aIpEv6uL!lp+y%ogW%iJK!r*kx?ffCwLqhHkpVSUKcsv_;X z$iqq$3uFNrKFArjs{?R{5F9O;8lh3N;4c}IsQoUwJvDHpy% zVVxwz#?SVeKA?bvcAScua87*B*fC`39F|9^Ir5UQrl?R$s8j^kXe3%#3<;+<&g7nB z%41mMEzCeM;WY%mL;Vi@Y{EGWAyb_?T}E7mGGdF>HReS+w&NOo=smhIvDbi#8f9YM zGGz*uPUA=^9(P5^eZ@*b@V+E8eYu8oXeL}4`8#31ql}l-u+p(z?1ulvop27BC3E_7 zg_SlP__y#i;wUD(_V{s@wX$yBRiQpyC##tFS=UkG)S=$zJQg8g!`BeB+7r}cIwpMM z|KncAA>j#K)6xkBjfaMZqtLthm*Bbg|8ZNBkT-RQr#Cl-j$sHJphkX%xFwTnC{pX7 z6vc$U&Roo}8F@e1g#eIwm=*Z7+;nbyALi8bJtn<5)m0>IYSXNxunw_Jr&gE=6W;*o zED(QX>aj)MeJIXfc8B>o-FVAHp-cnevMNS@u-;8aA3{oa*%4DKO_|tY0rq_(A zU(C8NGP5_PNozTtLa;9aGh>1q)Em==dT{9wLBe(7ykf%V@UYfGd*5@G$pvx41JNvtdjvCkXh-bCL76RNM53U1xc7F`N z6ft`d#Z)irGfdjGFJ(7VzEMoSK`&`V8e3gPqF$$#1$shBPMm052VFC1-P4HX+PGs% z2e}dCFXbL}(Wrx8FHTb>pIstf9}OAVCjLq6q*MQrrA4QsZRtsnrZ@n``6$GHh3oXB z;00xuKV4rZh)$bvog)+Tw8I(QlVMJkh5{PBXE5ubnWsHlhEL$RWue_C<*TPmotW^x zGm`CAvN2CTgD{oHvEFcEfQ>v%C zs1dQ-3DX<21;Jb=@$IYJ%o=f6Z;FvFNIV|iqZ9deT{mRqAvm_jTqNQC#`a2FbhsK6IT;;b&PXS(8e_%k4LJ6ZOo}VY5^y~ zLzkg}DqDk<&caN6YX&K3<2ODoTdE*lzhWDT1pgg@#HHyfe*77W#x3_$$6thVJ#%bP zTOAPQ4#rOZ8b7MFI7rbFKf@QY;hYOhCRpHvY!6)%jx5dEEd>`pI>HGP^+`KWftwuM z+`cP1K7o|vHhZ$eFP)$gI3Wt%4e7L;BORV_HZz;FsIUoP=2-RCgpvo+^ObB_?9<<< zjvs_CbDngar0JaNg?6Bfwwu%Dt0x^YX}{;XAL!*Ic9gtm8OV?HIvUYyqaOT!q{EUA z)DqTtc{ku~w9dkIq0U>Zx@n`B^Q&{BPHA}vZOIpnl>Do1+0rK>>AX0HBr|EfA9#(N+WF8@?qOB3Eq3j@zW= zquV##!S!3<+R3pn(Qw(0Gh63b=PZ=E?~X7+!8sB=v2rS0Eb9h>hh~Kw_9v2+GMS`d zwWJE@ew>>**2Gz0;|!63JmEf*Esm1lNpVyG1 z7{oTU-}Z_37mc7v*;=BbWZ!wx;|XI-c?4>EPaMYWI5$#kjb+uI1f#HSn~AEw!X~Zl#PmTp0Cq53l3=4(cU34(}v;sUJJGb_o{Z{M(Vu> z>U-5jYa31ogfYwlbT*c5g$$fJL*!`%$d6fy#;djOWO1TO7Qq+ebo+nNhp)(SmviD(|wlac`o zr6;p)(-if%VfMV)o^*`bNXiMkE?FZ9e;m^9e`%rN1SHHQ#&1U$=#IX|cx|TP_Q}hb zby&>mX?hD@m@=&dE&%7EhPh}^(>(jJdo1PES(3GNPdKk^%xw6Vc(BL9?|*p<0*7*^ zFym-2HPcMw@>Kl?eX0Itu&la`&OSZ zN?rGTT4aa}(SwfbQ-?%&HG%F|+cs?TV!;+1Mc`07tAvsVWDfC!v$Uj&P3S0jY$ABK zS@_`BHc)y?rX!p&FZ!)5rvrZY#~C#ucfQ2ttd^fXhltR2i1zTnC5!jr6mxVFhliKa zh=%Ve*;zvwmUr>oR#c~r-tTMsEWGVgf^MRC4DTO9{iRzHxsyw?8kYsArJ`bUK$-1j<*)3C3-rTe5^}+=&3HsfjVPy zZgYXN+FsZwoCTr9hOej7ay`-)9pQXNqBV!)$&9=S%TpV>{w1t`0rftP6mWwK5kAh} zU6|r(qD?!-FnN0uD^ku|dZ`0}>Ih2hCZG|9k_-_~r{Owhn!JE@TOomLKvuA))#exi zR~rPcN#jA6)TP%%oWg#S3Giu5*fJVt!7B9~*=v1DIX{NL)vVin&ZvOlHW?zGj*IL& zzMrzSSoaq4zQ%StAP|OcE^vyp^L;cMy#p;AhCoR>Xn#)$Qul_ER=ZqS;x!w+=mYC> zyuFljf$_BS0Y^&M@TJic^-IRBI3-)I=P}oF$%WAh*8h<^(?MsX*g( Date: Thu, 28 May 2026 14:23:26 +0100 Subject: [PATCH 7/7] Refactored the tests --- .../shopbento/ShopBentoViewModelTest.kt | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/app/src/test/kotlin/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModelTest.kt b/app/src/test/kotlin/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModelTest.kt index 4f5e9fc3..cd85b224 100644 --- a/app/src/test/kotlin/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModelTest.kt +++ b/app/src/test/kotlin/com/brainwallet/ui/bentosections/shopbento/ShopBentoViewModelTest.kt @@ -1,12 +1,10 @@ package com.brainwallet.ui.bentosections.shopbento import android.app.Application -import android.content.Context -import android.telephony.TelephonyManager -import app.cash.turbine.testIn import app.cash.turbine.turbineScope import com.brainwallet.data.model.AppSetting import com.brainwallet.data.repository.SettingRepository +import com.brainwallet.data.repository.ShopProxy import com.brainwallet.data.repository.ShopProxyRepository import com.brainwallet.testing.FlakyTest import io.mockk.every @@ -17,15 +15,15 @@ import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test +import io.mockk.coEvery class ShopBentoViewModelTest { private lateinit var app: Application private lateinit var settingRepository: SettingRepository private lateinit var shopProxyRepository: ShopProxyRepository - - private lateinit var telephonyManager: TelephonyManager private lateinit var settingsFlow: MutableStateFlow + private lateinit var shopProxyFlow: MutableStateFlow> private fun buildViewModel() = ShopBentoViewModel( app = app, @@ -37,36 +35,34 @@ class ShopBentoViewModelTest { fun setup() { app = mockk() settingRepository = mockk() - telephonyManager = mockk() + shopProxyRepository = mockk() settingsFlow = MutableStateFlow(AppSetting()) + shopProxyFlow = MutableStateFlow(emptyList()) every { settingRepository.settings } returns settingsFlow - every { app.getSystemService(Context.TELEPHONY_SERVICE) } returns telephonyManager - every { telephonyManager.simCountryIso } returns "gb" - every { telephonyManager.networkCountryIso } returns "" + coEvery { shopProxyRepository.refresh() } returns Unit + every { shopProxyRepository.shopProxy } returns shopProxyFlow } @Test - fun `init - uses simCountryIso when available`() = runTest { + fun `init - countryIso defaults to Locale`() = runTest { turbineScope { - every { telephonyManager.simCountryIso } returns "us" - val viewModel = buildViewModel() val turbine = viewModel.state.testIn(backgroundScope) settingsFlow.emit(AppSetting()) advanceTimeBy(100) - assertEquals("US", turbine.expectMostRecentItem().countryIso) + val countryIso = turbine.expectMostRecentItem().countryIso + assert(countryIso.isNotEmpty()) turbine.cancelAndIgnoreRemainingEvents() } } @Test - fun `init - falls back to Locale default when both sim and network are empty`() = runTest { + fun `init - sets shopBaseUrl from widget`() = runTest { turbineScope { - every { telephonyManager.simCountryIso } returns "" - every { telephonyManager.networkCountryIso } returns "" + shopProxyFlow.emit(listOf(ShopProxy(widget = "https://shop.example.com", shopCards = emptyList()))) val viewModel = buildViewModel() val turbine = viewModel.state.testIn(backgroundScope) @@ -74,8 +70,8 @@ class ShopBentoViewModelTest { settingsFlow.emit(AppSetting()) advanceTimeBy(100) - val countryIso = turbine.expectMostRecentItem().countryIso - assert(countryIso.isNotEmpty()) + val state = turbine.expectMostRecentItem() + assertEquals("https://shop.example.com", state.shopBaseUrl) turbine.cancelAndIgnoreRemainingEvents() } } @@ -104,19 +100,15 @@ class ShopBentoViewModelTest { val viewModel = buildViewModel() val turbine = viewModel.state.testIn(backgroundScope) - turbine.awaitItem() - settingsFlow.emit(AppSetting(isDarkMode = true)) advanceTimeBy(100) - val stateBefore = turbine.awaitItem() + val stateBefore = turbine.expectMostRecentItem() viewModel.onEvent(ShopBentoEvent.OnLoad) advanceTimeBy(100) - turbine.expectNoEvents() assertEquals(stateBefore, viewModel.state.value) - turbine.cancelAndIgnoreRemainingEvents() } }