This repository has been archived by the owner on Feb 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(example): create an example of cat'ing files added from ipfs CLI
using only webrtc-star as a transport
- Loading branch information
Showing
8 changed files
with
514 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules/ | ||
public/ipfs.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# access-go-ipfs-files - cat-a-file | ||
|
||
**WIP** | ||
|
||
## TODO | ||
|
||
- Add "connect to peer" input field and "connect" button under the "Peers" section in index.html | ||
- Add `connectToPeer` function which calls `ipfs.swarm.connect(multiaddr)`. See https://github.com/ipfs/js-ipfs/blob/b0a7cd83cbf146b0f147467dedc686f94a5f751f/examples/ipfm/src/DataStore.js#L82 and https://github.com/ipfs/js-ipfs/blob/b0a7cd83cbf146b0f147467dedc686f94a5f751f/examples/ipfm/README.md#start-an-interplanetary-file-exchange-daemon. The multiaddr to connect to looks like this: `/ip4/127.0.0.1/tcp/9999/ws/ipfs/QmZGH8GeASSkSZoNLPEBu1MqtzLTERNUEwh9yTHLEF5kcW` | ||
- Hook up "connect" button's click event to `connectToPeer` function | ||
- Add instructions to this README on how to add a file in go-ipfs | ||
- Add instructions to this README on how to cat it in the UI | ||
- Make sure the "Start a go-ipfs daemon" instructions are correct | ||
- Make sure go-ipfs daemon and the example connect to each other | ||
|
||
## Step-by-step Instructions | ||
|
||
### Start a go-ipfs daemon | ||
|
||
1. Install go-ipfs from master (TODO: link). | ||
|
||
2. Run `ipfs init` | ||
|
||
3. Edit your IPFS config file, located at `~/.ipfs/config` | ||
|
||
4. Add a Websocket listener address to `Addresses.Swarm`. It should look like this after editing: | ||
``` | ||
"Addresses": { | ||
"API": "/ip4/127.0.0.1/tcp/5001", | ||
"Gateway": "/ip4/0.0.0.0/tcp/8080", | ||
"Swarm": [ | ||
"/ip4/0.0.0.0/tcp/4001", | ||
"/ip4/0.0.0.0/tcp/9999/ws" | ||
] | ||
}, | ||
``` | ||
|
||
5. Start the go-ipfs daemon with: | ||
``` | ||
ipfs daemon | ||
``` | ||
|
||
6. You should see the Websocket address in the output: | ||
``` | ||
Initializing daemon... | ||
Swarm listening on /ip4/127.0.0.1/tcp/4001 | ||
Swarm listening on /ip4/127.0.0.1/tcp/9999/ws | ||
Swarm listening on /ip4/192.168.10.38/tcp/4001 | ||
Swarm listening on /ip4/192.168.10.38/tcp/9999/ws | ||
API server listening on /ip4/127.0.0.1/tcp/5001 | ||
Gateway (readonly) server listening on /ip4/0.0.0.0/tcp/8080 | ||
Daemon is ready | ||
``` | ||
|
||
If you see address like `Swarm listening on /ip4/127.0.0.1/tcp/9999/ws`, it means all good! | ||
|
||
## Start the example | ||
|
||
**NOTE!** Before running the examples, you need to build `js-ipfs`. You can do this by following the instructions in https://github.com/ipfs/js-ipfs#clone-and-install-dependnecies and then building it as per https://github.com/ipfs/js-ipfs#build-a-dist-version. | ||
|
||
``` | ||
npm install | ||
npm start | ||
``` | ||
|
||
Open http://127.0.0.1:8080 in a browser. | ||
|
||
**TODO: add instructions how to cat a hash in the UI.** | ||
|
||
## Tutorial | ||
|
||
Steps | ||
1. create IPFS instance | ||
|
||
TODO. See `./start-ipfs.js` | ||
|
||
3. add a file in go-ipfs | ||
4. copy file's hash | ||
5. ipfs.files.cat | ||
|
||
TODO. add ipfs.files.cat code examples from index.html | ||
|
||
6. output the buffer to <img> | ||
|
||
``` | ||
... | ||
stream.on('end', () => { | ||
const blob = new Blob(buf) | ||
picture.src = URL.createObjectURL(blob) | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "cat-a-file", | ||
"version": "1.0.0", | ||
"description": "", | ||
"scripts": { | ||
"postinstall": "cp ../../../dist/index.js ./public/ipfs.js", | ||
"start": "http-server -c-1" | ||
}, | ||
"author": "Haad", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"http-server": "^0.9.0" | ||
} | ||
} |
281 changes: 281 additions & 0 deletions
281
examples/access-go-ipfs-files/cat-a-file/public/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,281 @@ | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<link rel="stylesheet" href="styles.css"> | ||
<!-- Include IPFS --> | ||
<script src="ipfs.js"></script> | ||
<!-- Include a helper script that starts IPFS --> | ||
<script type="text/javascript" src="start-ipfs.js" charset="utf-8"></script> | ||
</head> | ||
|
||
<body> | ||
<div class="center"> | ||
<div id="ipfs" class="ipfs" ondragover="event.preventDefault()"> | ||
<h1 id="state" class="center"></h1> | ||
<div> | ||
<div id="buttons" class="buttons center"> | ||
<button id="start" type="button">Start</button> | ||
<button id="stop" type="button">Stop</button> | ||
</div> | ||
<div id="directory"> | ||
<h2>IPFS Settings</h2> | ||
<label for="dir">Data Directory</label> | ||
<input id="dir" type="text" placeholder="IPFS data directory"/> | ||
<br><br> | ||
<label for="signalServerInput">Signal Server</label> | ||
<input id="signalServerInput" type="text" value="188.166.203.82:20000"/> | ||
</div> | ||
</div> | ||
<div id="details"></div> | ||
<div id="peers"></div> | ||
<div id="files"> | ||
<h2>Files</h2> | ||
<div id="filesStatus"></div> | ||
<br> | ||
<label for="multihash">Mutihash</label> | ||
<input id="multihash" type="text" placeholder="Multihash"/> | ||
<button id="cat" type="button">Cat</button> | ||
<img id="picture"/> | ||
</div> | ||
<pre id="errors"></pre> | ||
</div> | ||
</div> | ||
|
||
<script type="text/javascript"> | ||
const rootElement = document.getElementById("ipfs") | ||
const startButton = document.getElementById("start") | ||
const stopButton = document.getElementById("stop") | ||
const output = document.getElementById("state") | ||
const details = document.getElementById("details") | ||
const peers = document.getElementById("peers") | ||
const errors = document.getElementById("errors") | ||
const directory = document.getElementById("directory") | ||
const dirInput = document.getElementById("dir") | ||
const signalServerInput = document.getElementById("signalServerInput") | ||
const files = document.getElementById("files") | ||
const filesStatus = document.getElementById("filesStatus") | ||
const picture = document.getElementById("picture") | ||
const multihashInput = document.getElementById("multihash") | ||
const catButton = document.getElementById("cat") | ||
|
||
let ipfs, peerInfo, pollPeersTimer | ||
|
||
const ipfsOptions = { | ||
// Directory to which save IPFS data to | ||
IpfsDataDir: dirInput.value, | ||
// IPFS dev server: webrtc-star-signalling.cloud.ipfs.team | ||
SignalServer: signalServerInput.value, | ||
// Local webrtc-star server, you can get it from: | ||
// https://github.com/libp2p/js-libp2p-webrtc-star | ||
// SignalServer: '127.0.0.1:9090', | ||
} | ||
|
||
// Start IPFS instance | ||
const start = () => { | ||
if (!ipfs) { | ||
// Update the UI with initial settings | ||
updateView('starting', ipfs) | ||
|
||
// Create an IPFS instance | ||
// window.startIpfs() is exposed in ./start-ipfs.js | ||
window.startIpfs(ipfsOptions, (err, node) => { | ||
if (err) { | ||
onError(err) | ||
return | ||
} | ||
|
||
ipfs = node | ||
|
||
// Get our IPFS instance's info: ID and address | ||
ipfs.id().then((id) => { | ||
peerInfo = id | ||
// Update the UI | ||
updateView('ready', ipfs) | ||
|
||
// Poll for peers from IPFS and display them | ||
pollPeersTimer = setInterval(updatePeers, 1000) | ||
peers.innerHTML = '<h2>Peers</h2><i>Waiting for peers...</i>' | ||
}) | ||
}) | ||
} | ||
} | ||
|
||
// Stop IPFS instance | ||
const stop = () => { | ||
if (ipfs) { | ||
if (pollPeersTimer) | ||
clearInterval(pollPeersTimer) | ||
|
||
ipfs.goOffline() | ||
ipfs = null | ||
updateView('stopped', ipfs) | ||
} | ||
} | ||
|
||
// Fetch file contents from IPFS and display it | ||
const catFile = () => { | ||
// Get the hash to cat from the input field | ||
const multihash = multihashInput.value | ||
|
||
// Update UI | ||
picture.innerHTML = multihash ? '<i>Loading...</i>' : '' | ||
picture.className = multihash ? 'picture visible' : 'hidden' | ||
errors.className = 'hidden' | ||
|
||
// Get the file from IPFS | ||
if (multihash) { | ||
// IPFS.files.cat() | ||
// https://github.com/ipfs/interface-ipfs-core/tree/master/API/files#javascript---ipfscatmultihash-callback | ||
ipfs.files.cat(multihash) | ||
.then((stream) => { | ||
// Buffer all contents of the file as text | ||
// and once buffered, create a blob for the picture | ||
let buf = [] | ||
stream.on('data', (d) => buf.push(d)) | ||
stream.on('end', () => { | ||
const blob = new Blob(buf) | ||
picture.src = URL.createObjectURL(blob) | ||
}) | ||
}) | ||
.catch(onError) | ||
} | ||
} | ||
|
||
// Display an error | ||
const onError = (e) => { | ||
console.error(e) | ||
errors.innerHTML = '<br/><span class="error">' + e.stack + '</span>' | ||
errors.className = 'error visible' | ||
} | ||
|
||
// Handle file drop | ||
const onDrop = (event) => { | ||
picture.innerHTML = '' | ||
picture.className = 'hidden' | ||
errors.className = 'hidden' | ||
|
||
event.preventDefault() | ||
var dt = event.dataTransfer | ||
var files = dt.files | ||
|
||
const readFileContents = (file) => { | ||
return new Promise((resolve) => { | ||
const reader = new FileReader() | ||
reader.onload = (event) => resolve(event.target.result) | ||
reader.readAsArrayBuffer(file) | ||
}) | ||
} | ||
|
||
// TODO: Promise reduce? | ||
for (var i = 0; i < files.length; i++) { | ||
const file = files[i] | ||
console.log("Add file", file.name, file.size) | ||
readFileContents(file) | ||
.then((buffer) => { | ||
// IPFS.files.add() | ||
// https://github.com/ipfs/interface-ipfs-core/tree/master/API/files#javascript---ipfsfilesadddata-options-callback | ||
return ipfs.files.add([{ | ||
path: file.name, | ||
content: new ipfs.types.Buffer(buffer) | ||
}]) | ||
}) | ||
.then((files) => { | ||
console.log("Files added", files) | ||
multihashInput.value = files[0].hash | ||
filesStatus.innerHTML = files | ||
.map((e) => `Added ${e.path} as ${e.hash}`) | ||
.join('<br>') | ||
}) | ||
.catch(onError) | ||
} | ||
} | ||
|
||
// Get peers from IPFS and display them | ||
const updatePeers = () => { | ||
ipfs.swarm.peers((err, res) => { | ||
// PeerId.toJSON() | ||
// https://github.com/libp2p/js-peer-id/blob/3ef704ba32a97a9da26a1f821702cdd3f09c778f/src/index.js#L106 | ||
// Multiaddr.toString() | ||
// https://multiformats.github.io/js-multiaddr/#multiaddrtostring | ||
const peersAsHtml = res | ||
.map((e, idx) => { | ||
return (idx + 1) + '.' | ||
+ e.peer.id.toJSON().id | ||
+ '<br>' | ||
+ e.addr.toString() | ||
+ '<br>' | ||
}) | ||
.join('') | ||
|
||
peers.innerHTML = res.length > 0 | ||
? '<h2>Peers</h2>' + peersAsHtml | ||
: '<h2>Peers</h2><i>Waiting for peers...</i>' | ||
}) | ||
} | ||
|
||
/* UI functions */ | ||
function initView() { | ||
const initElement = (e, className) => { | ||
e.innerHTML = '' | ||
e.className = className | ||
} | ||
|
||
// Initial view | ||
const elements = [errors, details, peers] | ||
elements.map((e) => initElement(e, 'hidden')) | ||
errors.innerHTML = '' | ||
output.innerHTML = '🔌 IPFS stopped' | ||
dirInput.value = '/ipfs/' + new Date().getTime() | ||
directory.className = 'visible' | ||
files.className = 'hidden' | ||
filesStatus.innerHTML = '' | ||
picture.innerHTML = '' | ||
startButton.disabled = false | ||
stopButton.disabled = true | ||
multihashInput.value = null | ||
picture.className = 'hidden' | ||
// Remove old event listeners | ||
rootElement.removeEventListener('drop', onDrop) | ||
startButton.removeEventListener('click', start) | ||
stopButton.removeEventListener('click', stop) | ||
catButton.removeEventListener('click', catFile) | ||
// Setup event listeners for interaction | ||
rootElement.addEventListener('drop', onDrop) | ||
startButton.addEventListener('click', start) | ||
stopButton.addEventListener('click', stop) | ||
catButton.addEventListener('click', catFile) | ||
} | ||
|
||
function updateView(state, ipfs) { | ||
if (state === 'ready') { | ||
// Set the header to display the current state | ||
output.innerHTML = '🚀 IPFS started' | ||
// Display IPFS info | ||
details.innerHTML = '<div>' | ||
+ '<h2>IPFS Node</h2>' | ||
+ '<b>ID</b><br>' | ||
+ peerInfo.id + '<br><br>' | ||
+ '<b>Address</b><br>' | ||
+ peerInfo.addresses[0] + '<br><br>' | ||
+ '<b>IPFS Data Directory</b><br>' | ||
+ dirInput.value | ||
// Set the file status | ||
filesStatus.innerHTML = '<i>Drop a picture here to add it to IPFS.</i>' | ||
details.className = 'visible' | ||
peers.className = 'visible' | ||
files.className = 'visible' | ||
stopButton.disabled = false | ||
} else if (state === 'starting') { | ||
output.innerHTML = '📡 IPFS starting' | ||
startButton.disabled = true | ||
directory.className = 'hidden' | ||
} else if (state === 'stopped') { | ||
initView() | ||
} | ||
} | ||
|
||
// Start the app | ||
initView() | ||
</script> | ||
</body> | ||
</html> |
Oops, something went wrong.