Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

feat: network switch #121

Merged
merged 5 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions app.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { RouteLocationNormalized, NavigationGuardNext } from 'vue-router'
import { isAddress } from 'web3-utils'
import { isAddress, numberToHex } from 'web3-utils'

import { assertString } from '@/utils/validators'

Expand All @@ -9,8 +9,8 @@ if (typeof window !== 'undefined') {
}

const web3Store = useWeb3Store()
const { getNetwork, selectedNetwork, modal } = useAppStore()
const { isLoadedApp } = storeToRefs(useAppStore())
const { getNetwork } = useAppStore()
const { isLoadedApp, selectedChainId, modal } = storeToRefs(useAppStore())
const { addProviderEvents, removeProviderEvents, disconnect } =
useBrowserExtension()
const router = useRouter()
Expand All @@ -33,7 +33,7 @@ const setupWeb3Instances = () => {
}

// for chain interactions through RPC endpoint
web3Store.addWeb3(PROVIDERS.RPC, getNetwork(selectedNetwork).rpcHttp)
web3Store.addWeb3(PROVIDERS.RPC, getNetwork(selectedChainId.value).rpcHttp)
}

const routerBackProfileLoad = async () => {
Expand Down Expand Up @@ -96,19 +96,28 @@ const setupViewedProfile = async () => {
if (isAddress(profileAddress)) {
await fetchProfile(profileAddress)
await fetchAssets(profileAddress)
} else {
navigateTo(notFoundRoute())
}
}
} catch (error) {
} catch (error: unknown) {
console.error(error)

if (error instanceof EoAError) {
navigateTo(notFoundRoute())
}
}
}

const setupNetwork = async () => {
const { getChainId } = useWeb3(PROVIDERS.INJECTED)

selectedChainId.value = numberToHex(await getChainId()) as string
}

onMounted(async () => {
setupTranslations()
setupWeb3Instances()
checkConnectionExpiry()
await setupNetwork()
await routerBackProfileLoad()
await setupViewedProfile()

Expand All @@ -125,7 +134,7 @@ onUnmounted(() => {
useHead({
bodyAttrs: {
class: computed(() => {
if (modal?.isOpen) {
if (modal.value?.isOpen) {
return 'overflow-hidden'
}

Expand Down
4 changes: 2 additions & 2 deletions components/AppNavbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { connect, disconnect, isUniversalProfileExtension } =
useBrowserExtension()
const { viewedProfile } = useViewedProfile()
const { connectedProfile } = useConnectedProfile()
const { isConnecting, isConnected } = storeToRefs(useAppStore())
const { isConnecting, isConnected, isTestnet } = storeToRefs(useAppStore())

const handleNavigateProfile = async () => {
try {
Expand Down Expand Up @@ -59,7 +59,7 @@ const browserSupportExtension = extensionStore.url !== ''
<lukso-navbar
is-sticky
:title="$formatMessage('header_title')"
:is-testnet="IS_TESTNET"
:is-testnet="isTestnet ? true : undefined"
icon="wallet-outline"
has-menu
@on-brand-click="handleNavigationDiscovery"
Expand Down
5 changes: 4 additions & 1 deletion components/SendCardProfileSearch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import { IndexedProfile } from '@/models/profile'

const SEARCH_COMPONENT_TAG_NAME = 'LUKSO-SEARCH'

const { search } = useAlgoliaSearch<IndexedProfile>(INDEX_NAME)
const { currentNetwork } = storeToRefs(useAppStore())
const { search } = useAlgoliaSearch<IndexedProfile>(
currentNetwork.value.indexName
)
const { receiver, receiverError } = storeToRefs(useSendStore())
const { isEoA } = useWeb3(PROVIDERS.RPC)
const isSearchingReceiver = ref<boolean>(false)
Expand Down
20 changes: 16 additions & 4 deletions composables/useBrowserExtension.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ProviderAPI } from '@/types/provider'

const openStoreLink = () => {
const storeLink = browserInfo().storeLink

Expand Down Expand Up @@ -100,18 +102,28 @@ const handleAccountsChanged = async (accounts: string[]) => {
}
}

const handleChainChanged = (network: { chainId: string }) => {
const { selectedChainId } = storeToRefs(useAppStore())

selectedChainId.value = network.chainId
disconnect()
navigateTo(homeRoute())
}

const handleDisconnect = () => {
location.reload()
}

const addProviderEvents = async (provider: any) => {
const addProviderEvents = async (provider: ProviderAPI) => {
provider?.on?.('accountsChanged', handleAccountsChanged)
provider?.on?.('disconnect', handleDisconnect)
provider?.on?.('chainChanged', handleChainChanged)
doubleppereira marked this conversation as resolved.
Show resolved Hide resolved
}

const removeProviderEvents = async (provider: any) => {
provider?.removeListener?.('accountsChanged', handleAccountsChanged)
provider?.removeListener?.('disconnect', handleAccountsChanged)
const removeProviderEvents = async (provider: ProviderAPI) => {
provider?.off?.('accountsChanged', handleAccountsChanged)
provider?.off?.('disconnect', handleDisconnect)
provider?.off?.('chainChanged', handleChainChanged)
}

const isUniversalProfileExtension = () => {
Expand Down
3 changes: 3 additions & 0 deletions composables/useWeb3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,8 @@ export default function useWeb3(providerName: string) {
console.log(JSON.stringify(payload, null, 2))
})
},
getChainId: async () => {
return await getWeb3().eth.getChainId()
},
}
}
6 changes: 4 additions & 2 deletions models/asset.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { Item, Model } from 'pinia-orm'
import { Item } from 'pinia-orm'
import { LinkMetadata } from '@lukso/lsp-smart-contracts'

import { Profile } from '@/models/profile'
import { InterfaceId } from '@/types/assets'
import { Image } from '@/models/image'
import { BaseModel } from '@/models/base'

export class AssetModel extends Model {
export class AssetModel extends BaseModel {
static entity = 'assets'
static primaryKey = ['address', 'tokenId']

static fields() {
return {
...super.fields(),
address: this.attr(null),
name: this.string(''),
symbol: this.string(''),
Expand Down
16 changes: 16 additions & 0 deletions models/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Model } from 'pinia-orm'

export class BaseModel extends Model {
static fields() {
return {
chainId: this.attr(null),
}
}

declare chainId?: string

static creating(model: Model) {
const { selectedChainId } = storeToRefs(useAppStore())
model.chainId = selectedChainId.value
}
}
6 changes: 4 additions & 2 deletions models/creator.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { Item, Model } from 'pinia-orm'
import { Item } from 'pinia-orm'

import { Profile } from '@/models/profile'
import { Asset } from '@/models/asset'
import { BaseModel } from '@/models/base'

export class CreatorModel extends Model {
export class CreatorModel extends BaseModel {
static entity = 'creators'
static primaryKey = ['profileId', 'assetId', 'tokenId']

static fields() {
return {
...super.fields(),
isVerified: this.attr(false),

// foreign keys
Expand Down
7 changes: 5 additions & 2 deletions models/image.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Item, Model } from 'pinia-orm'
import { Item } from 'pinia-orm'

export class ImageModel extends Model {
import { BaseModel } from '@/models/base'

export class ImageModel extends BaseModel {
static entity = 'images'
static primaryKey = 'hash'

static fields() {
return {
...super.fields(),
width: this.number(0),
height: this.number(0),
hashFunction: this.string(''),
Expand Down
6 changes: 4 additions & 2 deletions models/profile.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { Item, Model } from 'pinia-orm'
import { Item } from 'pinia-orm'
import { LSP3ProfileMetadata, LinkMetadata } from '@lukso/lsp-smart-contracts'

import { Image } from '@/models/image'
import { BaseModel } from '@/models/base'

export class ProfileModel extends Model {
export class ProfileModel extends BaseModel {
static entity = 'profiles'
static primaryKey = 'address'

static fields() {
return {
...super.fields(),
address: this.attr(null),
name: this.string(''),
balance: this.string(''),
Expand Down
1 change: 0 additions & 1 deletion pages/[profileAddress]/send.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ const updateLyxBalance = async () => {
useRepo(ProfileModel)
.where('address', connectedProfile.value.address)
.update({ balance })
// TODO check if this update is needed
}
</script>

Expand Down
41 changes: 36 additions & 5 deletions repositories/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import { InterfaceId } from '@/types/assets'

export class AssetRepository extends Repository<AssetModel> {
async loadAssets(addresses: Address[], profileAddress: Address) {
const { selectedChainId } = storeToRefs(useAppStore())

await Promise.all(
addresses.map(async assetAddress => {
const storageAsset = this.repo(AssetModel)
.where('address', assetAddress)
.where('chainId', selectedChainId.value)
.get()

if (storageAsset && storageAsset.length > 0) {
Expand Down Expand Up @@ -42,6 +45,7 @@ export class AssetRepository extends Repository<AssetModel> {

async getOwnedTokens() {
const { viewedProfile } = useViewedProfile()
const { selectedChainId } = storeToRefs(useAppStore())

if (!viewedProfile.value?.receivedAssetIds) {
return []
Expand All @@ -50,11 +54,13 @@ export class AssetRepository extends Repository<AssetModel> {
return this.repo(AssetModel)
.where('standard', 'LSP7DigitalAsset')
.where('address', viewedProfile.value.receivedAssetIds)
.where('chainId', selectedChainId.value)
.get()
}

async getIssuedTokens() {
const { viewedProfile } = useViewedProfile()
const { selectedChainId } = storeToRefs(useAppStore())

if (!viewedProfile.value?.issuedAssetIds) {
return []
Expand All @@ -63,11 +69,13 @@ export class AssetRepository extends Repository<AssetModel> {
return this.repo(AssetModel)
.where('standard', 'LSP7DigitalAsset')
.where('address', viewedProfile.value.issuedAssetIds)
.where('chainId', selectedChainId.value)
.get()
}

async getOwnedNfts() {
const { viewedProfile } = useViewedProfile()
const { selectedChainId } = storeToRefs(useAppStore())

if (!viewedProfile.value?.receivedAssetIds) {
return []
Expand All @@ -76,11 +84,13 @@ export class AssetRepository extends Repository<AssetModel> {
return this.repo(AssetModel)
.where('standard', 'LSP8IdentifiableDigitalAsset')
.where('address', viewedProfile.value.receivedAssetIds)
.where('chainId', selectedChainId.value)
.get()
}

async getIssuedNfts() {
const { viewedProfile } = useViewedProfile()
const { selectedChainId } = storeToRefs(useAppStore())

if (!viewedProfile.value?.issuedAssetIds) {
return []
Expand All @@ -89,11 +99,13 @@ export class AssetRepository extends Repository<AssetModel> {
return this.repo(AssetModel)
.where('standard', 'LSP8IdentifiableDigitalAsset')
.where('address', viewedProfile.value.issuedAssetIds)
.where('chainId', selectedChainId.value)
.get()
}

getOwnedAssets() {
const { viewedProfile } = useViewedProfile()
const { selectedChainId } = storeToRefs(useAppStore())

if (!viewedProfile.value?.receivedAssetIds) {
return []
Expand All @@ -102,6 +114,7 @@ export class AssetRepository extends Repository<AssetModel> {
return this.repo(AssetModel)
.where('address', viewedProfile.value.receivedAssetIds)
.where('standard', (standard: InterfaceId) => standard)
.where('chainId', selectedChainId.value)
.get()
}

Expand All @@ -124,18 +137,27 @@ export class AssetRepository extends Repository<AssetModel> {
}

getAssetAndImages(address: Address, tokenId = '') {
const { selectedChainId } = storeToRefs(useAppStore())
const primaryKey = this.primaryKey(address, tokenId)
const asset = this.repo(AssetModel).find(primaryKey)
const asset = this.repo(AssetModel)
.where('chainId', selectedChainId.value)
.find(primaryKey)

if (!asset) {
return
}

const icon = asset?.iconId && this.repo(ImageModel).find(asset.iconId)
const icon =
asset?.iconId &&
this.repo(ImageModel)
.where('chainId', selectedChainId.value)
.find(asset.iconId)
const images =
asset?.imageIds &&
asset.imageIds.length &&
this.repo(ImageModel).find(asset.imageIds)
this.repo(ImageModel)
.where('chainId', selectedChainId.value)
.find(asset.imageIds)

return {
...asset,
Expand All @@ -145,12 +167,21 @@ export class AssetRepository extends Repository<AssetModel> {
}

setBalance(address: Address, balance: string) {
this.repo(AssetModel).where('address', address).update({ balance })
const { selectedChainId } = storeToRefs(useAppStore())

this.repo(AssetModel)
.where('address', address)
.where('chainId', selectedChainId.value)
.update({ balance })
}

removeAsset(address: Address, tokenId = '') {
const { selectedChainId } = storeToRefs(useAppStore())
const primaryKey = this.primaryKey(address, tokenId)
this.repo(AssetModel).destroy(primaryKey)

this.repo(AssetModel)
.where('chainId', selectedChainId.value)
.destroy(primaryKey)
}

private primaryKey(address: Address, tokenId = '') {
Expand Down
Loading