diff --git a/packages/desktop/App.svelte b/packages/desktop/App.svelte
index 2e93160630..826cdd3801 100644
--- a/packages/desktop/App.svelte
+++ b/packages/desktop/App.svelte
@@ -32,6 +32,7 @@
import { _ } from '@core/i18n'
import { getAndUpdateShimmerEvmTokensMetadata } from '@core/market/actions'
import { initializeWalletConnect } from '@auxiliary/wallet-connect/actions'
+ import { getAndUpdateCountryCode } from '@auxiliary/country/actions'
$: $activeProfile, saveActiveProfile()
@@ -50,6 +51,7 @@
let splash = true
void setupI18n({ fallbackLocale: 'en', initialLocale: $appSettings.language })
+ void getAndUpdateCountryCode()
onMount(async () => {
if (features.analytics.appStart.enabled) {
diff --git a/packages/desktop/features/onboarding.features.ts b/packages/desktop/features/onboarding.features.ts
index 8ff9b0b705..e4611e3145 100644
--- a/packages/desktop/features/onboarding.features.ts
+++ b/packages/desktop/features/onboarding.features.ts
@@ -42,7 +42,7 @@ const onboardingFeaturesForIota: IOnboardingFeaturesForNetwork = {
},
},
defaultIscChains: {
- enabled: false,
+ enabled: true,
},
defaultEvmChains: {
enabled: false,
diff --git a/packages/desktop/package.json b/packages/desktop/package.json
index 78f93a0720..fb922eb060 100644
--- a/packages/desktop/package.json
+++ b/packages/desktop/package.json
@@ -1,7 +1,7 @@
{
"name": "desktop",
"productName": "Bloom",
- "version": "1.0.3",
+ "version": "1.0.4",
"description": "Simple and secure web3 wallet for the IOTA and Shimmer ecosystem",
"main": "public/build/main.process.js",
"repository": "git@github.com:bloomwalletio/bloom.git",
diff --git a/packages/desktop/views/dashboard/components/DashboardSidebar.svelte b/packages/desktop/views/dashboard/components/DashboardSidebar.svelte
index 5b039ffc1f..146e879e3b 100644
--- a/packages/desktop/views/dashboard/components/DashboardSidebar.svelte
+++ b/packages/desktop/views/dashboard/components/DashboardSidebar.svelte
@@ -16,12 +16,12 @@
} from '@core/router'
import { isDashboardSideBarExpanded } from '@core/ui'
import { IDashboardSidebarTab } from '@desktop/routers'
- import features from '@features/features'
import { Logo } from '@ui'
import { campaignsRouter } from '../campaigns'
import LedgerStatusTile from './LedgerStatusTile.svelte'
import StrongholdStatusTile from './StrongholdStatusTile.svelte'
import { BackupToast, VersionToast } from './toasts'
+ import { isFeatureEnabled, isFeatureNotGeoFenced } from '@lib/features/utils'
let expanded = true
function toggleExpand(): void {
@@ -38,7 +38,7 @@
route: DashboardRoute.Wallet,
onClick: openWallet,
},
- ...(features?.collectibles?.enabled && profileFeatures?.collectibles
+ ...(isFeatureEnabled(DashboardRoute.Collectibles) && profileFeatures?.collectibles
? [
{
icon: IconName.Image,
@@ -48,7 +48,7 @@
},
]
: []),
- ...(features?.governance?.enabled && profileFeatures?.governance
+ ...(isFeatureEnabled(DashboardRoute.Governance) && profileFeatures?.governance
? [
{
icon: IconName.Bank,
@@ -58,7 +58,7 @@
},
]
: []),
- ...(features?.campaigns?.enabled && profileFeatures?.campaigns
+ ...(isFeatureEnabled(DashboardRoute.Campaigns) && profileFeatures?.campaigns
? [
{
icon: IconName.Trophy,
@@ -68,7 +68,9 @@
},
]
: []),
- ...(features?.buySell?.enabled && profileFeatures?.buySell
+ ...(isFeatureEnabled(DashboardRoute.BuySell) &&
+ isFeatureNotGeoFenced(DashboardRoute.BuySell) &&
+ profileFeatures?.buySell
? [
{
icon: IconName.ArrowDownUp,
@@ -83,7 +85,7 @@
},
]
: []),
- ...(features?.developerTools?.enabled && profileFeatures?.developer
+ ...(isFeatureEnabled('developerTools') && profileFeatures?.developer
? [
{
icon: IconName.Developer,
diff --git a/packages/desktop/views/settings/views/advanced/ToggleFeatures.svelte b/packages/desktop/views/settings/views/advanced/ToggleFeatures.svelte
index c17f2dee8c..2e7a3415bf 100644
--- a/packages/desktop/views/settings/views/advanced/ToggleFeatures.svelte
+++ b/packages/desktop/views/settings/views/advanced/ToggleFeatures.svelte
@@ -4,6 +4,7 @@
import { activeProfile, updateActiveProfile } from '@core/profile/stores'
import { DashboardRoute } from '@core/router'
import SettingsSection from '../SettingsSection.svelte'
+ import { isFeatureNotGeoFenced, isFeatureNotGeoFenced } from '@lib/features/utils'
const features = $activeProfile?.features ?? {
[DashboardRoute.Wallet]: true,
@@ -47,12 +48,14 @@
label={localize('tabs.campaigns')}
bind:checked={features[DashboardRoute.Campaigns]}
/>
-
+ {#if isFeatureNotGeoFenced(DashboardRoute.BuySell)}
+
+ {/if}
{
+ const api = new CountryApi()
+ const countryCode = await api.getCountryCode()
+ updateCountryCode(countryCode)
+}
diff --git a/packages/shared/src/lib/auxiliary/country/actions/index.ts b/packages/shared/src/lib/auxiliary/country/actions/index.ts
new file mode 100644
index 0000000000..a1b5ecf498
--- /dev/null
+++ b/packages/shared/src/lib/auxiliary/country/actions/index.ts
@@ -0,0 +1 @@
+export * from './getAndUpdateCountryCode'
diff --git a/packages/shared/src/lib/auxiliary/country/api/country.api.ts b/packages/shared/src/lib/auxiliary/country/api/country.api.ts
new file mode 100644
index 0000000000..aa159cb0ca
--- /dev/null
+++ b/packages/shared/src/lib/auxiliary/country/api/country.api.ts
@@ -0,0 +1,42 @@
+import { BaseApi } from '@core/utils'
+
+interface IIpApiResponse {
+ ip: string
+ network: string
+ version: string
+ city: string
+ region: string
+ region_code: string
+ country: string
+ country_name: string
+ country_code: string
+ country_code_iso3: string
+ country_capital: string
+ country_tld: string
+ continent_code: string
+ in_eu: boolean
+ postal: string
+ latitude: number
+ longitude: number
+ timezone: string
+ utc_offset: string
+ country_calling_code: string
+ currency: string
+ currency_name: string
+ languages: string
+ country_area: number
+ country_population: number
+ asn: string
+ org: string
+}
+
+export class CountryApi extends BaseApi {
+ constructor() {
+ super('https://ipapi.co')
+ }
+
+ async getCountryCode(): Promise {
+ const ipData = await this.get('json')
+ return ipData?.country_code
+ }
+}
diff --git a/packages/shared/src/lib/auxiliary/country/api/index.ts b/packages/shared/src/lib/auxiliary/country/api/index.ts
new file mode 100644
index 0000000000..836019fd1c
--- /dev/null
+++ b/packages/shared/src/lib/auxiliary/country/api/index.ts
@@ -0,0 +1 @@
+export * from './country.api'
diff --git a/packages/shared/src/lib/auxiliary/country/index.ts b/packages/shared/src/lib/auxiliary/country/index.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/shared/src/lib/auxiliary/country/stores/country-code.store.ts b/packages/shared/src/lib/auxiliary/country/stores/country-code.store.ts
new file mode 100644
index 0000000000..c40c032b26
--- /dev/null
+++ b/packages/shared/src/lib/auxiliary/country/stores/country-code.store.ts
@@ -0,0 +1,9 @@
+import { writable } from 'svelte/store'
+
+export const countryCode = writable(undefined)
+
+export function updateCountryCode(_countryCode: string | undefined): void {
+ if (_countryCode) {
+ countryCode?.set(_countryCode)
+ }
+}
diff --git a/packages/shared/src/lib/auxiliary/country/stores/index.ts b/packages/shared/src/lib/auxiliary/country/stores/index.ts
new file mode 100644
index 0000000000..2cdc6e5d88
--- /dev/null
+++ b/packages/shared/src/lib/auxiliary/country/stores/index.ts
@@ -0,0 +1 @@
+export * from './country-code.store'
diff --git a/packages/shared/src/lib/core/app/interfaces/app-parameters.interface.ts b/packages/shared/src/lib/core/app/interfaces/app-parameters.interface.ts
index 85177303a1..56d74cbab0 100644
--- a/packages/shared/src/lib/core/app/interfaces/app-parameters.interface.ts
+++ b/packages/shared/src/lib/core/app/interfaces/app-parameters.interface.ts
@@ -6,4 +6,7 @@ export interface IAppParameters {
allowlists: {
urls: string[]
}
+ geoFence: {
+ buySell: string[]
+ }
}
diff --git a/packages/shared/src/lib/core/app/json/configurable-app-parameters.json b/packages/shared/src/lib/core/app/json/configurable-app-parameters.json
index 6fc1f916d0..dd557bc87d 100644
--- a/packages/shared/src/lib/core/app/json/configurable-app-parameters.json
+++ b/packages/shared/src/lib/core/app/json/configurable-app-parameters.json
@@ -5,5 +5,8 @@
},
"allowlists": {
"urls": ["https://tideprotocol.infura-ipfs.io"]
+ },
+ "geoFence": {
+ "buySell": ["GB"]
}
}
diff --git a/packages/shared/src/lib/core/profile/constants/profile-version.constant.ts b/packages/shared/src/lib/core/profile/constants/profile-version.constant.ts
index daa1c6ad40..6276523770 100644
--- a/packages/shared/src/lib/core/profile/constants/profile-version.constant.ts
+++ b/packages/shared/src/lib/core/profile/constants/profile-version.constant.ts
@@ -1,7 +1,7 @@
import { AppStage } from '@core/app/enums'
export const PROFILE_VERSION: Record = {
- [AppStage.ALPHA]: 20,
+ [AppStage.ALPHA]: 21,
[AppStage.BETA]: 1,
[AppStage.PROD]: 11,
}
diff --git a/packages/shared/src/lib/core/profile/migrations/actions/addDefaultIscChainsToIotaProfiles.ts b/packages/shared/src/lib/core/profile/migrations/actions/addDefaultIscChainsToIotaProfiles.ts
new file mode 100644
index 0000000000..1e071ed41d
--- /dev/null
+++ b/packages/shared/src/lib/core/profile/migrations/actions/addDefaultIscChainsToIotaProfiles.ts
@@ -0,0 +1,15 @@
+import { DEFAULT_ISC_CHAINS_CONFIGURATIONS, SupportedStardustNetworkId } from '@core/network'
+import { IPersistedProfile } from '@core/profile/interfaces'
+
+export function addDefaultIscChainsToIotaProfiles(profile: IPersistedProfile): void {
+ if (profile.network.id !== SupportedStardustNetworkId.Iota) {
+ return
+ }
+
+ const chainConfiguration = DEFAULT_ISC_CHAINS_CONFIGURATIONS[SupportedStardustNetworkId.Iota]
+
+ profile.network = {
+ ...profile.network,
+ chainConfigurations: chainConfiguration ? [chainConfiguration] : [],
+ }
+}
diff --git a/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-19-to-20.ts b/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-19-to-20.ts
index eb60ffe498..f02cc5c5a8 100644
--- a/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-19-to-20.ts
+++ b/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-19-to-20.ts
@@ -1,10 +1,10 @@
-import { IPersistedProfile } from '../../interfaces'
-import { migrateEvmContacts } from '../../migrations/actions/migrateEvmContacts'
+import { IPersistedProfile } from '@core/profile/interfaces'
+import { addDefaultIscChainsToIotaProfiles } from '../actions/addDefaultIscChainsToIotaProfiles'
export function alphaProfileMigration19To20(existingProfile: unknown): Promise {
const profile = existingProfile as IPersistedProfile
- migrateEvmContacts(profile)
+ addDefaultIscChainsToIotaProfiles(profile)
return Promise.resolve()
}
diff --git a/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-20-to-21.ts b/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-20-to-21.ts
new file mode 100644
index 0000000000..973c9ed653
--- /dev/null
+++ b/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-20-to-21.ts
@@ -0,0 +1,10 @@
+import { IPersistedProfile } from '@core/profile/interfaces'
+import { migrateEvmContacts } from '../../migrations/actions/migrateEvmContacts'
+
+export function alphaProfileMigration20To21(existingProfile: unknown): Promise {
+ const profile = existingProfile as IPersistedProfile
+
+ migrateEvmContacts(profile)
+
+ return Promise.resolve()
+}
diff --git a/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-map.ts b/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-map.ts
index 97b22be1df..2ef5dc7dff 100644
--- a/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-map.ts
+++ b/packages/shared/src/lib/core/profile/migrations/alpha/alpha-profile-migration-map.ts
@@ -12,6 +12,7 @@ import { alphaProfileMigration17To18 } from './alpha-profile-migration-17-to-18'
import { alphaProfileMigration18To19 } from './alpha-profile-migration-18-to-19'
import { alphaProfileMigration19To20 } from './alpha-profile-migration-19-to-20'
import { alphaProfileMigration2To3 } from './alpha-profile-migration-2-to-3'
+import { alphaProfileMigration20To21 } from './alpha-profile-migration-20-to-21'
import { alphaProfileMigration3To4 } from './alpha-profile-migration-3-to-4'
import { alphaProfileMigration4To5 } from './alpha-profile-migration-4-to-5'
import { alphaProfileMigration5To6 } from './alpha-profile-migration-5-to-6'
@@ -43,4 +44,6 @@ export const ALPHA_PROFILE_MIGRATION_MAP: ProfileMigrationMap = {
18: alphaProfileMigration18To19,
// ^^^ release 1.0.3 ^^^
19: alphaProfileMigration19To20,
+ // ^^^ release 1.0.4 ^^^
+ 20: alphaProfileMigration20To21,
}
diff --git a/packages/shared/src/lib/core/profile/migrations/prod/prod-profile-migration-9-to-10.ts b/packages/shared/src/lib/core/profile/migrations/prod/prod-profile-migration-9-to-10.ts
index cd00960248..c57bc648b8 100644
--- a/packages/shared/src/lib/core/profile/migrations/prod/prod-profile-migration-9-to-10.ts
+++ b/packages/shared/src/lib/core/profile/migrations/prod/prod-profile-migration-9-to-10.ts
@@ -6,6 +6,7 @@ import { prodProfileMigration6To7 } from './prod-profile-migration-6-to-7'
import { prodProfileMigration7To8 } from './prod-profile-migration-7-to-8'
import { prodProfileMigration4To5 } from './prod-profile-migration-4-to-5'
import { prodProfileMigration8To9 } from './prod-profile-migration-8-to-9'
+import { addDefaultIscChainsToIotaProfiles } from '../actions/addDefaultIscChainsToIotaProfiles'
export async function prodProfileMigration9To10(existingProfile: unknown): Promise {
const profile = existingProfile as IPersistedProfile
@@ -37,5 +38,7 @@ export async function prodProfileMigration9To10(existingProfile: unknown): Promi
// prodProfileMigration8To9 recovery
await prodProfileMigration8To9(profile)
+ addDefaultIscChainsToIotaProfiles(profile)
+
return Promise.resolve()
}
diff --git a/packages/shared/src/lib/core/profile/migrations/prod/prod-profile-migration-map.ts b/packages/shared/src/lib/core/profile/migrations/prod/prod-profile-migration-map.ts
index 4313a0cdd1..ce1e78cff4 100644
--- a/packages/shared/src/lib/core/profile/migrations/prod/prod-profile-migration-map.ts
+++ b/packages/shared/src/lib/core/profile/migrations/prod/prod-profile-migration-map.ts
@@ -22,8 +22,9 @@ export const PROD_PROFILE_MIGRATION_MAP: ProfileMigrationMap = {
6: prodProfileMigration6To7,
7: prodProfileMigration7To8,
// ^^^ release 1.0.2 ^^^
- 8: prodProfileMigration8To9, // Migration was removed and replaced with 10To11 after 9To10
+ 8: prodProfileMigration8To9,
// ^^^ release 1.0.3 ^^^
9: prodProfileMigration9To10, // rechecking some previous migrations due to a bug during migrations
10: prodProfileMigration10To11,
+ // ^^^ release 1.0.4 ^^^
}
diff --git a/packages/shared/src/lib/features/utils/index.ts b/packages/shared/src/lib/features/utils/index.ts
index 29563dad5d..10cb189989 100644
--- a/packages/shared/src/lib/features/utils/index.ts
+++ b/packages/shared/src/lib/features/utils/index.ts
@@ -1 +1,2 @@
export * from './isFeatureEnabled'
+export * from './isFeatureGeoFenced'
diff --git a/packages/shared/src/lib/features/utils/isFeatureGeoFenced.ts b/packages/shared/src/lib/features/utils/isFeatureGeoFenced.ts
new file mode 100644
index 0000000000..c00d640ad0
--- /dev/null
+++ b/packages/shared/src/lib/features/utils/isFeatureGeoFenced.ts
@@ -0,0 +1,21 @@
+import { countryCode } from '@auxiliary/country/stores'
+import { appParameters } from '@core/app/stores'
+import { get } from 'svelte/store'
+
+export function isFeatureNotGeoFenced(featureString: string): boolean {
+ const currentCountryCode = get(countryCode)
+ const featurePathToCheck = featureString.split('.')
+ const geoFence = get(appParameters)?.geoFence
+ let previousFeatures = geoFence
+ for (let i = 0; i < featurePathToCheck.length; i++) {
+ const currentFeature = previousFeatures?.[featurePathToCheck[i]]
+ if (!currentFeature) {
+ return true
+ }
+ if (i === featurePathToCheck.length - 1) {
+ return !currentFeature?.some((blockedCountry) => blockedCountry === currentCountryCode)
+ }
+ previousFeatures = currentFeature
+ }
+ return true
+}