Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storing data on the network not possible with helia in the browser? #159

Closed
AlexCherrypi opened this issue Jun 18, 2023 · 10 comments
Closed
Labels
kind/bug A bug in existing code (including security flaws) need/maintainers-input Needs input from the current maintainer(s)

Comments

@AlexCherrypi
Copy link

AlexCherrypi commented Jun 18, 2023

I was trying to get some sort of "hello world" project going in helia.
Retrieving data is no issue, but storing my own does not seem to work.

This is my test file: helia_.html

looking for the file on https://ipfs.io/ipfs/CID or trying to get the data via cid in another ipfs client does not work.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>IPFS in the Browser via Helia</title>
    <link rel="icon favicon" href="https://unpkg.com/@helia/[email protected]/logos/favicon.ico" />
    <link href="https://cdn.jsdelivr.net/npm/prismjs/themes/prism.css" rel="stylesheet" />
  </head>
  <body>
    <h1>IPFS in the Browser via Helia</h1>
    
      This is testing if you can successfully store data on the network, using helia.
    </p>
    <hr />
    <div>
	  <button onclick="logging = true">Enable Logging</button>
      <button onclick="logging = false">Disable Logging</button>
    </div>
    <h1 id="status">Node status: <span id="statusValue">Not Started</span></h1>
    <div id="nodeInfo">
      <h3>ID: <span id="nodeId">unknown</span></h3>
      <h3>Discovered Peers: <span id="discoveredPeerCount">0</span></h3>
      <h3>Connected Peers: <span id="connectedPeerCount">0</span></h3>
      <ul id="connectedPeersList"></ul>
    </div>
    <hr />
	<h1 id="testStatus">Test data status: <span id="testStatusValue">Not Added</span></h1>
    <div>
      <h3>Hash: <span id="testHash">-</span></h3>
      <h3>Content: <span id="testContent">-</span></h3>
    </div>

    <hr />

    
    <h2>Event Log:</h2>
    <article id="runningLog"></article>
  </body>
  <style>
    #runningLog span {
      display: block;
    }
  </style>
  <script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-core.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/prismjs/plugins/autoloader/prism-autoloader.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/helia@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/@helia/unixfs@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/libp2p@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/@chainsafe/libp2p-yamux@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/@chainsafe/libp2p-noise@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/@libp2p/websockets@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/@libp2p/bootstrap@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/blockstore-core@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/datastore-core@latest/dist/index.min.js" defer></script>
  <script src="https://cdn.jsdelivr.net/npm/@libp2p/kad-dht@latest/dist/index.min.js" defer></script>
  <script src="https://unpkg.com/@helia/strings/dist/index.min.js"></script>
  <script>
  var logging = false
  </script>
  <script type="module" defer>
  /* global Helia, BlockstoreCore, DatastoreCore, HeliaUnixfs */

const statusValueEl = document.getElementById('statusValue')
const discoveredPeerCountEl = document.getElementById('discoveredPeerCount')
const connectedPeerCountEl = document.getElementById('connectedPeerCount')
const connectedPeersListEl = document.getElementById('connectedPeersList')
const logEl = document.getElementById('runningLog')
const nodeIdEl = document.getElementById('nodeId')

document.addEventListener('DOMContentLoaded', async () => {
  const helia = window.helia = await instantiateHeliaNode()
  window.heliaFs = await HeliaUnixfs.unixfs(helia)

  helia.libp2p.addEventListener('peer:discovery', (evt) => {
    window.discoveredPeers.set(evt.detail.id.toString(), evt.detail)
    addToLog(`Discovered peer ${evt.detail.id.toString()}`)
  })

  helia.libp2p.addEventListener('peer:connect', (evt) => {
    addToLog(`Connected to ${evt.detail.toString()}`)
  })
  helia.libp2p.addEventListener('peer:disconnect', (evt) => {
    addToLog(`Disconnected from ${evt.detail.toString()}`)
  })

  setInterval(() => {
    statusValueEl.innerHTML = helia.libp2p.isStarted() ? 'Online' : 'Offline'
    updateConnectedPeers()
    updateDiscoveredPeers()
  }, 500)

  const id = await helia.libp2p.peerId.toString()

  nodeIdEl.innerHTML = id

  /**
   * You can write more code here to use it.
   *
   * https://github.com/ipfs/helia
   * - helia.start
   * - helia.stop
   *
   * https://github.com/ipfs/helia-unixfs
   * - heliaFs.addBytes
   * - heliaFs.addFile
   * - heliaFs.ls
   * - heliaFs.cat
   */
})

function ms2TimeString (a) {
  const k = a % 1e3
  const s = a / 1e3 % 60 | 0
  const m = a / 6e4 % 60 | 0
  const h = a / 36e5 % 24 | 0

  return (h ? (h < 10 ? '0' + h : h) + ':' : '00:') +
    (m < 10 ? 0 : '') + m + ':' +
    (s < 10 ? 0 : '') + s + ':' +
    (k < 100 ? k < 10 ? '00' : 0 : '') + k
}

const getLogLineEl = (msg) => {
  const logLine = document.createElement('span')
  logLine.innerHTML = `${ms2TimeString(performance.now())} - ${msg}`

  return logLine
}
const addToLog = (msg) => {
if(logging) {
logEl.appendChild(getLogLineEl(msg))
}
}

let heliaInstance = null
const instantiateHeliaNode = async () => {

  heliaInstance = await Helia.createHelia()
  addToLog('Created Helia instance')

  return heliaInstance
}

window.discoveredPeers = new Map()

const updateConnectedPeers = () => {
  const peers = window.helia.libp2p.getPeers()
  connectedPeerCountEl.innerHTML = peers.length
  connectedPeersListEl.innerHTML = ''
  for (const peer of peers) {
    const peerEl = document.createElement('li')
    peerEl.innerText = peer.toString()
    connectedPeersListEl.appendChild(peerEl)
  }
}

const updateDiscoveredPeers = () => {
  discoveredPeerCountEl.innerHTML = window.discoveredPeers.size
}

  </script>
  <script>
async function testdata(){
if ((window.helia.libp2p.getPeers()).length > 5) {
const s = HeliaStrings.strings(helia)
const myImmutableAddress = await s.add('hello world ' + Math.random())
document.getElementById('testStatusValue').innerText = 'Added to local IPFS'
console.log(myImmutableAddress.toString())
document.getElementById('testHash').innerHTML = '<a href="https://ipfs.io/ipfs/'+myImmutableAddress.toString()+'" target="_blank">'+myImmutableAddress.toString()+'</a>'
document.getElementById('testContent').innerHTML = await s.get(myImmutableAddress)
console.log(await s.get(myImmutableAddress))
} else {
setTimeout(testdata, 1000)
}
}

setTimeout(testdata, 5000)
  
  </script>
  <script nomodule>
    alert('Your browser does not support importing ESM modules')
  </script>
</html>


@AlexCherrypi
Copy link
Author

AlexCherrypi commented Jun 18, 2023

helia_.html ->helia_.zip

@AlexCherrypi
Copy link
Author

Seems to be the same issue as #138

@AlexCherrypi
Copy link
Author

referenced this issue on the ipfs forum

@whizzzkid
Copy link
Contributor

Thanks for submitting this issue @AlexCherrypi I briefly looked into it and was able to reproduce this issue. I feel I know the cause of why this might be happening, but would like to test a few things out before I post my findings. I think this will be a good candidate for a an example.

In the mean time I think @achingbrain's input could be valuable here.

@whizzzkid whizzzkid added kind/bug A bug in existing code (including security flaws) need/maintainers-input Needs input from the current maintainer(s) labels Jun 22, 2023
@eccker
Copy link

eccker commented Jun 23, 2023

Having the same issue, apparently all examples works on browser at the time but when accessing data from other window, gateway or ipfs explorer no data is retrieved. My console outputs this when running "Bundle Helia with esbuild"
example image

Looking for network issues on my side, but with another project using js-ipfs everything works fine.

@AlexCherrypi
Copy link
Author

AlexCherrypi commented Jun 23, 2023

@eccker This is exactly what I discovered as well. It seems to be a problem with helia, not ipfs in the browser in general

@eccker
Copy link

eccker commented Jun 23, 2023

@AlexCherrypi Yes, but maybe there are new security policies applied to browsers, just tried a project used last year working fine with js-ipfs on chrome (don't remember version) and now both helia and js-ipfs got me a security phishing warning on Chrome Versión 114.0.5735.134 (Build oficial) (64 bits)

@SgtPooki
Copy link
Member

Having the same issue, apparently all examples works on browser at the time but when accessing data from other window, gateway or ipfs explorer no data is retrieved.

My console outputs this when running "Bundle Helia with esbuild"

These are failed dial attempts to peers, which is to be expected. No one should expect to be able to connect to every peer in the network.

Looking for network issues on my side, but with another project using js-ipfs everything works fine.

@eccker js-ipfs uses preload nodes which are being deprecated and helps to ensure the network (specifically, nodes that are probably very close to ipfs gateway nodes) is populated with the CID content you've added to your node.

"In practice, [...] js-ipfs clients can add some content locally, then use a preload node to request that CID, effectively caching the data and allowing the browser tab to be closed without the data instantly becoming unavailable."

Helia does not use preload nodes, but Helia can be ran in a service-worker. That means your node can continue running in the browser even after a tab closes (there are caveats & exceptions here)


In order to debug the access of your content, you should use https://pl-diagnose.on.fleek.co/#/diagnose/access-content. When I use this tool, and helia, I can see that new content and CIDs I create in my browser node are "on the DHT", and that the PeerID of my browser node are providing this content.

Providing content from a browser node will be slow until webrtc/webtransport and other browser-compatible transports become more ubiquitous. See my answer at https://discuss.ipfs.tech/t/how-to-retrieve-content-uploaded-via-helia-using-the-ipfs-gateway/16582/4?u=sgtpooki and let's continue discussion there.

@eccker
Copy link

eccker commented Jun 24, 2023

@SgtPooki thank you very much for your amazing response. Is there any example of service-worker?
Btw thanks for the tool I gonna deep dive.

Providing content from a browser node will be slow until webrtc/webtransport and other browser-compatible transports become more ubiquitous.

yeah! It's what i though

@SgtPooki
Copy link
Member

The only example of a service worker with Helia at the moment is https://github.com/ipfs-shipyard/helia-service-worker-gateway, which is more than just Helia as a service-worker.. it's a POC for Helia-as-a-service-worker operating as a local in-browser IPFS gateway.

I'm going to close this issue, because I think the discussion for the issues you were running into are better held at https://discuss.ipfs.tech/t/how-to-retrieve-content-uploaded-via-helia-using-the-ipfs-gateway/16582/4?u=sgtpooki. If you're interested in following our implementation of an example where we show how to host/provide content from Helia (in and out of the browser) then please follow ipfs-examples/helia-examples#39

achingbrain added a commit that referenced this issue Jan 8, 2024
This should be a dep not a dev dep.

Refs #158
achingbrain pushed a commit that referenced this issue Jan 8, 2024
## [@helia/ipns-v4.0.0](https://github.com/ipfs/helia-ipns/compare/@helia/ipns-v3.0.1...@helia/ipns-v4.0.0) (2024-01-08)

### ⚠ BREAKING CHANGES

* uses multiformats v13 and helia v3, renames `dht` routing to `libp2p`

### Features

* update helia to v3 and multiformats to v13 ([#167](ipfs/helia-ipns#167)) ([a0381b9](ipfs/helia-ipns@a0381b9))

### Bug Fixes

* make @libp2p/interface a dependency ([#159](ipfs/helia-ipns#159)) ([546ecf0](ipfs/helia-ipns@546ecf0)), closes [#158](ipfs/helia-ipns#158)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug A bug in existing code (including security flaws) need/maintainers-input Needs input from the current maintainer(s)
Projects
No open projects
Development

No branches or pull requests

4 participants