From 8665596ea95bb6c5dcbb0da50bdcf187e5d93eea Mon Sep 17 00:00:00 2001
From: evavirseda <evirseda@boxfish.studio>
Date: Wed, 29 Nov 2023 15:50:16 +0100
Subject: [PATCH 1/6] feat: add getIpfsUri function

---
 .../shared/lib/core/nfts/utils/getIpfsUri.ts  | 149 ++++++++++++++++++
 packages/shared/lib/core/nfts/utils/index.ts  |   5 +-
 2 files changed, 152 insertions(+), 2 deletions(-)
 create mode 100644 packages/shared/lib/core/nfts/utils/getIpfsUri.ts

diff --git a/packages/shared/lib/core/nfts/utils/getIpfsUri.ts b/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
new file mode 100644
index 00000000000..b313f87a2cd
--- /dev/null
+++ b/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
@@ -0,0 +1,149 @@
+interface IIpfsLink {
+    Hash: string
+    Name: string
+    Size: number
+    Target: string
+    Type: number
+    Mode?: string
+    Mtime?: number
+    MtimeNsecs?: number
+}
+
+interface IIPfsEntry {
+    readonly type: 'dir' | 'file'
+    readonly cid: string
+    readonly name: string
+    readonly path: string
+    mode?: number
+    mtime?: {
+        secs: number
+        nsecs?: number
+    }
+    size: number
+}
+
+interface IIpfsObject {
+    Hash: string
+    Links: IIpfsLink[]
+}
+
+enum typeOfLink {
+    Dir = 'dir',
+    File = 'file',
+}
+
+const IPFS_ENDPOINT = 'https://ipfs.io'
+const IPFS_PATH = '/api/v0/ls'
+const IPFS_PREFIX = '/ipfs/'
+
+export async function getIpfsUri(link: { path?: string; hash: string }): Promise<string | undefined> {
+    try {
+        const slicedLink = link.hash.slice('https://ipfs.io/'.length)
+        const ipfsEntry = await ls(slicedLink)
+        if (ipfsEntry) {
+            if (ipfsEntry.type === 'dir') {
+                const path = `${link.path ?? ''}/${ipfsEntry.name}`
+                return await getIpfsUri({ hash: link.hash, path })
+            }
+            return `${link.hash}/${encodeURIComponent(ipfsEntry.name)}`
+        }
+    } catch (error) {
+        console.error('error', error)
+    }
+}
+
+async function ls(path: string): Promise<IIPfsEntry | undefined> {
+    let ipfsEntry: IIPfsEntry | undefined
+
+    try {
+        const baseUrl = IPFS_ENDPOINT
+        const method = 'get'
+        const payload = undefined
+        let headers = {}
+        const timeout = undefined
+
+        headers ??= {}
+
+        let controller: AbortController | undefined
+        let timerId: NodeJS.Timeout | undefined
+
+        if (timeout !== undefined) {
+            controller = new AbortController()
+            timerId = setTimeout(() => {
+                if (controller) {
+                    controller.abort()
+                }
+            }, timeout)
+        }
+
+        try {
+            if (path.includes('ipfs')) {
+                const response = await fetch(`${baseUrl}${IPFS_PATH}?arg=/${path}`, {
+                    method,
+                    headers,
+                    body: payload ? JSON.stringify(payload) : undefined,
+                    signal: controller ? controller.signal : undefined,
+                })
+                const lsResponse = (await response.json()) as { Objects: IIpfsObject[] }
+                const result = lsResponse.Objects[0]
+                if (result) {
+                    const links = result.Links
+                    if (links.length > 0) {
+                        ipfsEntry = mapLinkToIpfsEntry(links[0], path)
+                    }
+                }
+            }
+        } catch (error) {
+            console.error('error', error)
+        } finally {
+            if (timerId) {
+                clearTimeout(timerId)
+            }
+        }
+    } catch (error) {
+        console.error('error', error)
+    }
+
+    return ipfsEntry
+}
+
+function mapLinkToIpfsEntry(link: IIpfsLink, path: string): IIPfsEntry {
+    const hash = link.Hash.startsWith(IPFS_PREFIX) ? link.Hash.slice(IPFS_PREFIX.length) : link.Hash
+    const entry: IIPfsEntry = {
+        name: link.Name,
+        path: path + (link.Name ? `/${link.Name}` : ''),
+        size: link.Size,
+        cid: hash,
+        type: typeOf(link),
+    }
+    if (link.Mode) {
+        entry.mode = Number.parseInt(link.Mode, 8)
+    }
+
+    if (link.Mtime !== undefined && link.Mtime !== null) {
+        entry.mtime = {
+            secs: link.Mtime,
+        }
+
+        if (link.MtimeNsecs !== undefined && link.MtimeNsecs !== null) {
+            entry.mtime.nsecs = link.MtimeNsecs
+        }
+    }
+
+    return entry
+}
+
+function typeOf(link: IIpfsLink): typeOfLink {
+    switch (link.Type) {
+        case 1:
+        case 5: {
+            return typeOfLink.Dir
+        }
+        case 2: {
+            return typeOfLink.File
+        }
+        default: {
+            return typeOfLink.File
+        }
+    }
+}
diff --git a/packages/shared/lib/core/nfts/utils/index.ts b/packages/shared/lib/core/nfts/utils/index.ts
index ea8bd888dc2..250a101e79b 100644
--- a/packages/shared/lib/core/nfts/utils/index.ts
+++ b/packages/shared/lib/core/nfts/utils/index.ts
@@ -2,9 +2,10 @@ export * from './buildNftFromNftOutput'
 export * from './checkIfNftShouldBeDownloaded'
 export * from './composeUrlFromNftUri'
 export * from './convertAndFormatNftMetadata'
-export * from './getSpendableStatusFromUnspentNftOutput'
 export * from './fetchWithTimeout'
+export * from './getIpfsUri'
+export * from './getParentMimeType'
+export * from './getSpendableStatusFromUnspentNftOutput'
 export * from './isNftOwnedByAnyAccount'
 export * from './parseNftMetadata'
 export * from './rewriteIpfsUri'
-export * from './getParentMimeType'

From 885abaedc079630a7c6182b870555f5f8f027ce0 Mon Sep 17 00:00:00 2001
From: evavirseda <evirseda@boxfish.studio>
Date: Wed, 29 Nov 2023 15:52:26 +0100
Subject: [PATCH 2/6] feat: display ipfs media

---
 packages/shared/components/MediaDisplay.svelte       |  2 +-
 packages/shared/components/NftImageOrIconBox.svelte  |  7 +++----
 .../lib/core/nfts/actions/downloadNextNftInQueue.ts  | 10 +++++++++-
 .../core/nfts/actions/updateNftInAllAccountNfts.ts   | 12 +++++++++---
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/packages/shared/components/MediaDisplay.svelte b/packages/shared/components/MediaDisplay.svelte
index 8df73db2c8a..d08e9111b20 100644
--- a/packages/shared/components/MediaDisplay.svelte
+++ b/packages/shared/components/MediaDisplay.svelte
@@ -31,7 +31,7 @@
 </script>
 
 <div class="h-full w-full object-cover">
-    {#if htmlTag === ParentMimeType.Image}
+    {#if htmlTag === ParentMimeType.Image || htmlTag === ParentMimeType.Text}
         <img {src} {alt} loading="lazy" class="w-full h-full object-cover" />
     {:else if htmlTag === ParentMimeType.Video}
         <video
diff --git a/packages/shared/components/NftImageOrIconBox.svelte b/packages/shared/components/NftImageOrIconBox.svelte
index c821731dc24..a1c9b5dd1ad 100644
--- a/packages/shared/components/NftImageOrIconBox.svelte
+++ b/packages/shared/components/NftImageOrIconBox.svelte
@@ -1,8 +1,7 @@
 <script lang="ts">
-    import { INft } from '@core/nfts'
-    import { NftSize } from 'shared/components/enums'
+    import { INft, ParentMimeType } from '@core/nfts'
     import { MediaPlaceholder, NftMedia } from 'shared/components'
-    import { ParentMimeType } from '@core/nfts'
+    import { NftSize } from 'shared/components/enums'
 
     export let nft: INft | null = null
     export let size: NftSize = NftSize.Medium
@@ -18,7 +17,7 @@
     class:medium={size === NftSize.Medium}
     class:large={size === NftSize.Large}
 >
-    {#if parentType === ParentMimeType.Image && nft}
+    {#if (parentType === ParentMimeType.Image && nft) || (parentType === ParentMimeType.Text && nft)}
         <NftMedia {nft} {useCaching}>
             <placeholder-wrapper
                 slot="placeholder"
diff --git a/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts b/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
index e67fa150a36..9d926972604 100644
--- a/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
+++ b/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
@@ -1,6 +1,7 @@
 import { Platform } from '@core/app'
 import { get } from 'svelte/store'
 import { downloadingNftId, nftDownloadQueue, removeNftFromDownloadQueue } from '../stores'
+import { getIpfsUri } from '../utils'
 
 export async function downloadNextNftInQueue(): Promise<void> {
     const nextDownload = get(nftDownloadQueue)?.[0]
@@ -9,8 +10,15 @@ export async function downloadNextNftInQueue(): Promise<void> {
     }
 
     try {
-        const { downloadUrl, path, nft, accountIndex } = nextDownload
+        // eslint-disable-next-line prefer-const
+        let { downloadUrl, path, nft, accountIndex } = nextDownload
         downloadingNftId.set(nft.id)
+        const ipfsUri = await getIpfsUri({ hash: downloadUrl })
+
+        if (ipfsUri) {
+            downloadUrl = ipfsUri
+        }
+
         await Platform.downloadNft(downloadUrl, path, nft.id, accountIndex)
     } catch (error) {
         downloadingNftId.set(undefined)
diff --git a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
index 62f63dd2936..6caaf437e99 100644
--- a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
+++ b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
@@ -1,14 +1,20 @@
 import { allAccountNfts } from '../stores'
-import { INft } from '../interfaces'
+import { getIpfsUri } from '../utils'
 
-export function updateNftInAllAccountNfts(accountIndex: number, nftId: string, partialNft: Partial<INft>): void {
+export function updateNftInAllAccountNfts(accountIndex: number, nftId: string): void {
     allAccountNfts.update((state) => {
         if (!state[accountIndex]) {
             state[accountIndex] = []
         }
         const nft = state[accountIndex].find((_nft) => _nft.id === nftId)
         if (nft) {
-            Object.assign(nft, { ...nft, ...partialNft })
+            const downloadUrl = nft.downloadUrl
+            void getIpfsUri({ hash: downloadUrl }).then((ipfsUri) => {
+                if (ipfsUri) {
+                    nft.downloadUrl = ipfsUri
+                    nft.composedUrl = ipfsUri
+                }
+            })
         }
         return state
     })

From 10d673511ede4e2a1bdf8ba538f9a9a76edaa472 Mon Sep 17 00:00:00 2001
From: evavirseda <evirseda@boxfish.studio>
Date: Wed, 29 Nov 2023 16:08:09 +0100
Subject: [PATCH 3/6] fix types

---
 .../shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
index 6caaf437e99..80009e7a414 100644
--- a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
+++ b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
@@ -1,7 +1,8 @@
+import { INft } from '../interfaces'
 import { allAccountNfts } from '../stores'
 import { getIpfsUri } from '../utils'
 
-export function updateNftInAllAccountNfts(accountIndex: number, nftId: string): void {
+export function updateNftInAllAccountNfts(accountIndex: number, nftId: string, partialNft: Partial<INft>): void {
     allAccountNfts.update((state) => {
         if (!state[accountIndex]) {
             state[accountIndex] = []
@@ -15,6 +16,7 @@ export function updateNftInAllAccountNfts(accountIndex: number, nftId: string):
                     nft.composedUrl = ipfsUri
                 }
             })
+            Object.assign(nft, { ...nft, ...partialNft })
         }
         return state
     })

From 2edca0ef768d97cfdc3f74a2bf3d62f0e0bdc5de Mon Sep 17 00:00:00 2001
From: evavirseda <evirseda@boxfish.studio>
Date: Mon, 4 Dec 2023 13:46:38 +0100
Subject: [PATCH 4/6] fix: check dowloadUrl and replace with constant

---
 .../core/nfts/actions/updateNftInAllAccountNfts.ts | 14 ++++++++------
 packages/shared/lib/core/nfts/utils/getIpfsUri.ts  |  2 +-
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
index 80009e7a414..07ab4890733 100644
--- a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
+++ b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
@@ -10,12 +10,14 @@ export function updateNftInAllAccountNfts(accountIndex: number, nftId: string, p
         const nft = state[accountIndex].find((_nft) => _nft.id === nftId)
         if (nft) {
             const downloadUrl = nft.downloadUrl
-            void getIpfsUri({ hash: downloadUrl }).then((ipfsUri) => {
-                if (ipfsUri) {
-                    nft.downloadUrl = ipfsUri
-                    nft.composedUrl = ipfsUri
-                }
-            })
+            if (downloadUrl) {
+                void getIpfsUri({ hash: downloadUrl }).then((ipfsUri) => {
+                    if (ipfsUri) {
+                        nft.downloadUrl = ipfsUri
+                        nft.composedUrl = ipfsUri
+                    }
+                })
+            }
             Object.assign(nft, { ...nft, ...partialNft })
         }
         return state
diff --git a/packages/shared/lib/core/nfts/utils/getIpfsUri.ts b/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
index b313f87a2cd..4ab4c091557 100644
--- a/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
+++ b/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
@@ -38,7 +38,7 @@ const IPFS_PREFIX = '/ipfs/'
 
 export async function getIpfsUri(link: { path?: string; hash: string }): Promise<string | undefined> {
     try {
-        const slicedLink = link.hash.slice('https://ipfs.io/'.length)
+        const slicedLink = link.hash.slice(IPFS_ENDPOINT.length)
         const ipfsEntry = await ls(slicedLink)
         if (ipfsEntry) {
             if (ipfsEntry.type === 'dir') {

From 14db8a8aa0c527bc089c1ec7b696e178421bddba Mon Sep 17 00:00:00 2001
From: evavirseda <evirseda@boxfish.studio>
Date: Tue, 12 Dec 2023 17:43:32 +0100
Subject: [PATCH 5/6] fix: check if ipfsHash exists

---
 .../lib/core/nfts/actions/downloadNextNftInQueue.ts  | 12 +++++++-----
 .../core/nfts/actions/updateNftInAllAccountNfts.ts   |  5 +++--
 packages/shared/lib/core/nfts/utils/getIpfsHash.ts   |  7 +++++++
 packages/shared/lib/core/nfts/utils/index.ts         |  1 +
 4 files changed, 18 insertions(+), 7 deletions(-)
 create mode 100644 packages/shared/lib/core/nfts/utils/getIpfsHash.ts

diff --git a/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts b/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
index 9d926972604..2194d600644 100644
--- a/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
+++ b/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
@@ -1,7 +1,7 @@
 import { Platform } from '@core/app'
 import { get } from 'svelte/store'
 import { downloadingNftId, nftDownloadQueue, removeNftFromDownloadQueue } from '../stores'
-import { getIpfsUri } from '../utils'
+import { getIpfsUri, getIPFSHash } from '../utils'
 
 export async function downloadNextNftInQueue(): Promise<void> {
     const nextDownload = get(nftDownloadQueue)?.[0]
@@ -13,10 +13,12 @@ export async function downloadNextNftInQueue(): Promise<void> {
         // eslint-disable-next-line prefer-const
         let { downloadUrl, path, nft, accountIndex } = nextDownload
         downloadingNftId.set(nft.id)
-        const ipfsUri = await getIpfsUri({ hash: downloadUrl })
-
-        if (ipfsUri) {
-            downloadUrl = ipfsUri
+        const ipfsHash = getIPFSHash(downloadUrl)
+        if (ipfsHash) {
+            const ipfsUri = await getIpfsUri({ hash: downloadUrl })
+            if (ipfsUri) {
+                downloadUrl = ipfsUri
+            }
         }
 
         await Platform.downloadNft(downloadUrl, path, nft.id, accountIndex)
diff --git a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
index 07ab4890733..264a2ca5e53 100644
--- a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
+++ b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
@@ -1,6 +1,6 @@
 import { INft } from '../interfaces'
 import { allAccountNfts } from '../stores'
-import { getIpfsUri } from '../utils'
+import { getIpfsUri, getIPFSHash } from '../utils'
 
 export function updateNftInAllAccountNfts(accountIndex: number, nftId: string, partialNft: Partial<INft>): void {
     allAccountNfts.update((state) => {
@@ -10,7 +10,8 @@ export function updateNftInAllAccountNfts(accountIndex: number, nftId: string, p
         const nft = state[accountIndex].find((_nft) => _nft.id === nftId)
         if (nft) {
             const downloadUrl = nft.downloadUrl
-            if (downloadUrl) {
+            const ipfsHash = getIPFSHash(downloadUrl)
+            if (ipfsHash) {
                 void getIpfsUri({ hash: downloadUrl }).then((ipfsUri) => {
                     if (ipfsUri) {
                         nft.downloadUrl = ipfsUri
diff --git a/packages/shared/lib/core/nfts/utils/getIpfsHash.ts b/packages/shared/lib/core/nfts/utils/getIpfsHash.ts
new file mode 100644
index 00000000000..d7d832f0681
--- /dev/null
+++ b/packages/shared/lib/core/nfts/utils/getIpfsHash.ts
@@ -0,0 +1,7 @@
+export function getIPFSHash(url?: string): string | undefined {
+    const ipfsPrefix = 'ipfs'
+
+    if (url?.includes(ipfsPrefix)) {
+        return url.slice(ipfsPrefix.length)
+    }
+}
diff --git a/packages/shared/lib/core/nfts/utils/index.ts b/packages/shared/lib/core/nfts/utils/index.ts
index 250a101e79b..717cbfe65c5 100644
--- a/packages/shared/lib/core/nfts/utils/index.ts
+++ b/packages/shared/lib/core/nfts/utils/index.ts
@@ -3,6 +3,7 @@ export * from './checkIfNftShouldBeDownloaded'
 export * from './composeUrlFromNftUri'
 export * from './convertAndFormatNftMetadata'
 export * from './fetchWithTimeout'
+export * from './getIpfsHash'
 export * from './getIpfsUri'
 export * from './getParentMimeType'
 export * from './getSpendableStatusFromUnspentNftOutput'

From 085399e2f943177d0b540c594ec6b2339c14632e Mon Sep 17 00:00:00 2001
From: Branko Bosnic <brankobosnic1@gmail.com>
Date: Wed, 13 Dec 2023 10:52:14 +0100
Subject: [PATCH 6/6] fix: ipfs hash and ipfs uri

---
 .../lib/core/nfts/actions/downloadNextNftInQueue.ts      | 2 +-
 .../lib/core/nfts/actions/updateNftInAllAccountNfts.ts   | 2 +-
 packages/shared/lib/core/nfts/utils/getIpfsHash.ts       | 2 +-
 packages/shared/lib/core/nfts/utils/getIpfsUri.ts        | 9 ++++++---
 4 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts b/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
index 2194d600644..33a18312c13 100644
--- a/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
+++ b/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
@@ -15,7 +15,7 @@ export async function downloadNextNftInQueue(): Promise<void> {
         downloadingNftId.set(nft.id)
         const ipfsHash = getIPFSHash(downloadUrl)
         if (ipfsHash) {
-            const ipfsUri = await getIpfsUri({ hash: downloadUrl })
+            const ipfsUri = await getIpfsUri({ hash: ipfsHash })
             if (ipfsUri) {
                 downloadUrl = ipfsUri
             }
diff --git a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
index 264a2ca5e53..bd4214c2655 100644
--- a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
+++ b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
@@ -12,7 +12,7 @@ export function updateNftInAllAccountNfts(accountIndex: number, nftId: string, p
             const downloadUrl = nft.downloadUrl
             const ipfsHash = getIPFSHash(downloadUrl)
             if (ipfsHash) {
-                void getIpfsUri({ hash: downloadUrl }).then((ipfsUri) => {
+                void getIpfsUri({ hash: ipfsHash }).then((ipfsUri) => {
                     if (ipfsUri) {
                         nft.downloadUrl = ipfsUri
                         nft.composedUrl = ipfsUri
diff --git a/packages/shared/lib/core/nfts/utils/getIpfsHash.ts b/packages/shared/lib/core/nfts/utils/getIpfsHash.ts
index d7d832f0681..44997e4cca8 100644
--- a/packages/shared/lib/core/nfts/utils/getIpfsHash.ts
+++ b/packages/shared/lib/core/nfts/utils/getIpfsHash.ts
@@ -1,5 +1,5 @@
 export function getIPFSHash(url?: string): string | undefined {
-    const ipfsPrefix = 'ipfs'
+    const ipfsPrefix = 'https://ipfs.io'
 
     if (url?.includes(ipfsPrefix)) {
         return url.slice(ipfsPrefix.length)
diff --git a/packages/shared/lib/core/nfts/utils/getIpfsUri.ts b/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
index 4ab4c091557..3d094ea6a87 100644
--- a/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
+++ b/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
@@ -37,19 +37,22 @@ const IPFS_PATH = '/api/v0/ls'
 const IPFS_PREFIX = '/ipfs/'
 
 export async function getIpfsUri(link: { path?: string; hash: string }): Promise<string | undefined> {
+    let ipfsLink = `${link.hash}${link.path ?? ''}`
     try {
-        const slicedLink = link.hash.slice(IPFS_ENDPOINT.length)
-        const ipfsEntry = await ls(slicedLink)
+        const ipfsEntry = await ls(ipfsLink)
+
         if (ipfsEntry) {
             if (ipfsEntry.type === 'dir') {
                 const path = `${link.path ?? ''}/${ipfsEntry.name}`
                 return await getIpfsUri({ hash: link.hash, path })
             }
-            return `${link.hash}/${encodeURIComponent(ipfsEntry.name)}`
+            ipfsLink = `${ipfsLink}/${encodeURIComponent(ipfsEntry.name)}`
         }
     } catch (error) {
         console.error('error', error)
     }
+
+    return `${IPFS_ENDPOINT}${ipfsLink}`
 }
 
 async function ls(path: string): Promise<IIPfsEntry | undefined> {