From 89a1cf729dfbb8b14c105654be413bff0b7b9cf5 Mon Sep 17 00:00:00 2001 From: DougA Date: Sun, 12 Jul 2020 12:34:52 -0400 Subject: [PATCH 01/22] ipns publish example --- .../examples/browser-ipns-publish/.gitignore | 2 + .../examples/browser-ipns-publish/README.md | 83 ++++++ .../examples/browser-ipns-publish/index.html | 198 +++++++++++++ .../examples/browser-ipns-publish/index.js | 263 ++++++++++++++++++ .../browser-ipns-publish/package.json | 34 +++ .../examples/browser-ipns-publish/util.js | 31 +++ 6 files changed, 611 insertions(+) create mode 100644 packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore create mode 100644 packages/ipfs-http-client/examples/browser-ipns-publish/README.md create mode 100644 packages/ipfs-http-client/examples/browser-ipns-publish/index.html create mode 100644 packages/ipfs-http-client/examples/browser-ipns-publish/index.js create mode 100644 packages/ipfs-http-client/examples/browser-ipns-publish/package.json create mode 100644 packages/ipfs-http-client/examples/browser-ipns-publish/util.js diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore b/packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore new file mode 100644 index 0000000000..4a94694d21 --- /dev/null +++ b/packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore @@ -0,0 +1,2 @@ +bundle.js +.cache \ No newline at end of file diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/README.md b/packages/ipfs-http-client/examples/browser-ipns-publish/README.md new file mode 100644 index 0000000000..25d9b0532c --- /dev/null +++ b/packages/ipfs-http-client/examples/browser-ipns-publish/README.md @@ -0,0 +1,83 @@ +# Publish to IPNS from the browser + +> Use ipns from the browser! + +This example is a demo web application that allows you to connect to a go-IPFS node, and publish your IPNS record to the go-DHT network but using your js-ipfs private key. We'll start two IPFS nodes; one in the browser and one on a go-Server. We'll use `ipfs-http-client` to connect to the go-Node to ensure our pubsub messages are getting through, and confirm the IPNS record resolves on the go-Node. We're aiming for something like this: + +``` + +-----------+ websocket +-----------+ + | +-------------------> | + | js-ipfs | pubsub | go-ipfs | + | <-------------------+ | + +-----^-----+ +-----^-----+ + | | + | IPFS in browser | HTTP API + | | ++-------------------------------------------------+ +| Browser | ++-------------------------------------------------+ +| | | | +| | | | +| IPFS direct | | js-http-client | +| a.k.a. ipfsNode | | a.k.a. ipfsAPI | +| | | | ++-------------------------------------------------+ +``` + +## 1. Get started + +With Node.js and git installed, clone the repo and install the project dependencies: + +```sh +git clone https://github.com/ipfs/js-ipfs-http-client.git +cd js-ipfs-http-client +npm install # Installs ipfs-http-client dependencies +cd examples/browser-pubsub +npm install # Installs browser-pubsub app dependencies +``` + +Start the example application: + +```sh +npm start +``` + +You should see something similar to the following in your terminal and the web app should now be available if you navigate to http://127.0.0.1:8888 using your browser: + +```sh +Starting up http-server, serving ./ +Available on: + http://127.0.0.1:8888 +``` + +## 2. Start two IPFS nodes + +The first node is the js-ipfs made in the browser and the demo does that for you. + +The second is a go-ipfs node on a server. To get our IPNS record to the DHT, we'll need [a server running go-IPFS](https://blog.ipfs.io/22-run-ipfs-on-a-vps/) with the API enabled on port 5001. + +Right now the easiest way to do this is to install and start a `go-ipfs` node. + +### Install and start the Go IPFS node + +Head over to https://dist.ipfs.io/#go-ipfs and hit the "Download go-ipfs" button. Extract the archive and read the instructions to install. + +After installation: + +```sh +ipfs init +# Configure CORS to allow ipfs-http-client to access this IPFS node +ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://127.0.0.1:8888"]' +# Start the IPFS node, enabling pubsub +ipfs daemon --enable-pubsub-experiment & +``` + +## 3. Open the demo in a browser and connect to the go-node + +Now, open up the demo in a browser window. + +In the "CONNECT TO GO-IPFS VIA API MULTIADDRESS" field enter `/ip4/YourServerIP/tcp/5001` (where `YourSeverIP` is your server's IP address or use `/dns4/yourdomain.com/tcp/5001`) and click connect. Once it connects, put your go-IPFS websocket address in the next field `/dns4/yourdomain.com/tcp/4003/wss/p2p/QmPeerIDHash` and hit the second "Connect" button. + +This connects the API to the go-Node and connects your js-IPFS node via websocket to the go-Node so pubsub will work. + +Finally, enter `/ipfs/QmSomeHash` as the content you want to publish to IPNS.You should see the messages sent from the browser to the server appear in the logs below, ending with "Success, reolved" if it all worked. diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/index.html b/packages/ipfs-http-client/examples/browser-ipns-publish/index.html new file mode 100644 index 0000000000..ebe7ff99ef --- /dev/null +++ b/packages/ipfs-http-client/examples/browser-ipns-publish/index.html @@ -0,0 +1,198 @@ + + + + Publish to IPNS from the browser + + + + +
+ + + +

+ IPNS Publish from JS to Go Peer +

+
+
+
+ IPNS PUBLISH SET-UP STEPS +
+
+
+
+

+ Code repo for this demo + on Github +

+

+ The idea is to publish from js-ipfs so you control your own + private keys, but publish to go-ipfs to benefit from the DHT. + Since the DHT in js-ipfs isn't working yet, we need to use PubSub + and have a go-ipfs node subscribed to that PubSub to get our IPNS + record onto the DHT. +

+
+ To make this demo work, you're going to need: +
    +
  • + 1. Access to a go-ipfs node and it's API, a-la +
    /dns4/domain.com/tcp/5001
    +
  • +
  • + This is how the demo talks to the server, to ensure things + like: +
  • +
      +
    • + A) pubsub is enabled, { EXPERIMENTAL: { ipnsPubsub: true } } + and --enable-pubsub-experiment +
    • +
    • + B) go-ipfs is connected to the js-ipfs node in the browser, + via node.swarm.peers(), +
    • +
    • + C) the pubsub messages are getting through to the go node, + via node.pubsub.subscribe(). +
    • +
    +
+
    +
  • + 2. Access to a go-ipfs Websocket port, a-la +
    /dns4/domain.com/tcp/4003/wss/p2p/QmTheDomainPeerId
    +
  • +
  • + Since we need PubSub for IPNS to reach the go-IPFS node (and + further replicate through the go-DHT network) we need to + connect our pubsub enabled JS-IPFS node in the browser to our + go-IPFS node on the server. The way we connect is via + Websocket. See + this example + for reference. +
  • +
+

+ Once we can talk to go-IPFS and we're connected via Websocket, + then we can publish in our browser node, have the pubsub push it + to the go-IPFS server, and then check with the server that it's + confirmed as published. Once it's on the go-IPFS node it should + replicate throughout the rest of the DHT amongst the go-Nodes. +

+
+
+
+
+
+
+
+ 1. Connect to Go-IPFS via API MultiAddress +
+ + +
+
+
+ 2. Connect to Go-IPFS via Websocket MultiAddress (for PubSub to work) +
+ + +
+ +
+
+ 3. Choose a key: +
+
+
    +
  • + +
    +
  • +
  • + +
    +
  • +
+
+
+
+
+ 4. IPFS hash to publish +
+ + +
+
+
Browser Console
+
+
+
+
Server Console
+
+
+ + + diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/index.js b/packages/ipfs-http-client/examples/browser-ipns-publish/index.js new file mode 100644 index 0000000000..311c4d73c2 --- /dev/null +++ b/packages/ipfs-http-client/examples/browser-ipns-publish/index.js @@ -0,0 +1,263 @@ +"use strict"; + +const IpfsHttpClient = require("ipfs-http-client"); +const ipns = require("ipns"); +const IPFS = require("ipfs"); +const pRetry = require("p-retry"); +const base64url = require("base64url"); +const last = require("it-last"); +const cryptoKeys = require("human-crypto-keys"); // { getKeyPairFromSeed } + +const { sleep, Logger, onEnterPress, catchAndLog } = require("./util"); +const { Date } = require("ipfs-utils/src/globalthis"); + +async function main() { + const apiUrlInput = document.getElementById("api-url"); + const nodeConnectBtn = document.getElementById("node-connect"); + + const peerAddrInput = document.getElementById("peer-addr"); + const wsConnectBtn = document.getElementById("peer-connect"); + + const ipnsInput = document.getElementById("topic"); + const publishBtn = document.getElementById("publish"); + + const namespace = "/record/"; + const retryOptions = { + retries: 5, + }; + + let log = Logger(document.getElementById("console")); + let sLog = Logger(document.getElementById("server-console")); + let keyName = "self"; + + let ipfsAPI; // remote server IPFS node + let ipfsBrowser; // local browser IPFS node + let peerId; + + // init local browser node right away + log(`Browser IPFS getting ready...`); + ipfsBrowser = await IPFS.create({ pass: "01234567890123456789", EXPERIMENTAL: { ipnsPubsub: true } }); + const { id } = await ipfsBrowser.id(); + log(`Browser IPFS ready! Node id: ${id}`); + + async function nodeConnect(url) { + log(`Connecting to ${url}`); + ipfsAPI = IpfsHttpClient(url); + const { id, agentVersion } = await ipfsAPI.id(); + peerId = id; + log(`Success!`); + log(`Version ${agentVersion}`); + log(`Peer ID ${id}`); + } + + async function wsConnect(addr) { + if (!addr) throw new Error("Missing peer multiaddr"); + if (!ipfsBrowser) + throw new Error("Wait for the local IPFS node to start first"); + log(`Connecting to peer ${addr}`); + await ipfsBrowser.swarm.connect(addr); + log(`Success!`); + log("Listing swarm peers..."); + await sleep(); + const peers = await ipfsBrowser.swarm.peers(); + peers.forEach((peer) => { + //console.log(`peer: ${JSON.stringify(peer, null, 2)}`); + const fullAddr = `${peer.addr}/ipfs/${peer.peer}`; + log( + `${fullAddr}` + ); + }); + log(`(${peers.length} peers total)`); + } + + // Wait until a peer subscribes a topic + const waitForPeerToSubscribe = async (daemon, topic) => { + await pRetry(async () => { + const res = await daemon.pubsub.ls(); + + if (!res || !res.length || !res.includes(topic)) { + throw new Error("Could not find subscription"); + } + + return res[0]; + }, retryOptions); + }; + + // wait until a peer know about other peer to subscribe a topic + const waitForNotificationOfSubscription = (daemon, topic, peerId) => + pRetry(async () => { + const res = await daemon.pubsub.peers(topic); + + if (!res || !res.length || !res.includes(peerId)) { + throw new Error("Could not find peer subscribing"); + } + }, retryOptions); + + async function subs(node, topic, tLog) { + tLog(`Subscribing to ${topic}`); + await node.pubsub.subscribe( + topic, + (msg) => { + const from = msg.from; + const seqno = msg.seqno.toString("hex"); + + tLog( + `${new Date( + Date.now() + ).toLocaleTimeString()}\n Message ${seqno} from ${from}` + ); + + let regex = "/record/"; + if (topic.match(regex) ? topic.match(regex).length > 0 : false) { + tLog( + "#" + + ipns.unmarshal(msg.data).sequence.toString() + + ") Topic: " + + msg.topicIDs[0].toString() + ); + tLog("Value:\n" + ipns.unmarshal(msg.data).value.toString()); + } else { + try { + tLog(JSON.stringify(msg.data.toString(), null, 2)); + } catch (_) { + tLog(msg.data.toString("hex")); + } + } + }, + { + onError: (err, fatal) => { + if (fatal) { + console.error(err); + tLog(`${err.message}`); + tLog(`Resubscribing in 5s to ${topic}...`); + setTimeout( + catchAndLog(() => subs(node, topic, tLog), tLog), + 5000 + ); + } else { + console.warn(err); + } + }, + } + ); + } + + async function createKey(keyName) { + return new Promise(async (resolve, reject) => { + try { + // quick and dirty key gen, don't do this in real life + const key = await IPFS.multihashing.digest( + Buffer.from(keyName + Math.random().toString(36).substring(2)), + "sha2-256" + ); + const keyPair = await cryptoKeys.getKeyPairFromSeed(key, "rsa"); + + // put it on the browser IPNS keychain and name it + await ipfsBrowser.key.import(keyName, keyPair.privateKey); + // now this key can be used to publish to this ipns publicKey + resolve(true); + } catch (err) { + console.log(`Error creating Key ${keyName}: \n ${err}`); + reject(false); + } + }); + } + + async function publish(content) { + if (!content) throw new Error("Missing ipns content to publish"); + if (!ipfsAPI) throw new Error("Connect to a go-server node first"); + if (!ipfsAPI.name.pubsub.state()) + throw new Error( + "IPNS Pubsub must be enabled on bother peers, use --enable-namesys-pubsub" + ); + + let browserNode = await ipfsBrowser.id(); + let serverNode = await ipfsAPI.id(); + + let b58 = await IPFS.multihash.fromB58String(browserNode.id); + const keys = ipns.getIdKeys(b58); + const topic = `${namespace}${base64url.encode(keys.routingKey.toBuffer())}`; + + log(`Initial Resolve ${browserNode.id}`); // subscribes the server to our IPNS topics + last(ipfsAPI.name.resolve(browserNode.id, { stream: false })); // save the pubsub topic to the server to make them listen + + await sleep(1000); // give it a moment to save it + + // subscribe and log on both nodes + await subs(ipfsBrowser, topic, log); // browserLog + await subs(ipfsAPI, topic, sLog); // serverLog + + // confirm they are subscribed + await waitForPeerToSubscribe(ipfsAPI, topic); // confirm topic is on THEIR list // API + await waitForNotificationOfSubscription(ipfsBrowser, topic, serverNode.id); // confirm they are on OUR list + + await sleep(2500); // give it a moment to save it + + let remList = await ipfsAPI.pubsub.ls(); // API + if (!remList.includes(topic)) sLog(`[Fail] !Pubsub.ls ${topic}`); + else sLog(`[Pass] Pubsub.ls`); + + let remListSubs = await ipfsAPI.name.pubsub.subs(); // API + if (!remListSubs.includes(`/ipns/${browserNode.id}`)) + sLog(`[Fail] !Name.Pubsub.subs ${browserNode.id}`); + else sLog(`[Pass] Name.Pubsub.subs`); + + keyName = document.querySelector('input[name="keyName"]:checked').value; + if (keyName != "self") { + await createKey(keyName); + let keys = await ipfsBrowser.key.list() + log(JSON.stringify(keys)); + } + + // publish will send a pubsub msg to the server to update their ipns record + log(`Publishing ${content} to ${keyName}...`); + const results = await ipfsBrowser.name.publish(content, { + resolve: false, + key: keyName, + }); + log(`Published`); // ${results.name} to ${results.value} + + log(`Wait 5 seconds, then resolve...`); + await sleep(5000); + + log( + `Try to resolve ${browserNode.id} on server through API to confirm published` + ); + + let name = await last( + ipfsAPI.name.resolve(browserNode.id, { + stream: false, + }) + ); + log(`Resolved: ${name}`); + if (name == content) + log(`IPNS Publish Success!`); + log( + `Look at that! /ipns/${browserNode.id} resolves to ${content}` + ); + } + + const onNodeConnectClick = catchAndLog( + () => nodeConnect(apiUrlInput.value), + log + ); + + apiUrlInput.addEventListener("keydown", onEnterPress(onNodeConnectClick)); + nodeConnectBtn.addEventListener("click", onNodeConnectClick); + + const onwsConnectClick = catchAndLog( + () => wsConnect(peerAddrInput.value), + log + ); + peerAddrInput.addEventListener("keydown", onEnterPress(onwsConnectClick)); + wsConnectBtn.addEventListener("click", onwsConnectClick); + + const onPublishClick = catchAndLog(() => publish(ipnsInput.value), log); + ipnsInput.addEventListener("keydown", onEnterPress(onPublishClick)); + publishBtn.addEventListener("click", onPublishClick); + +} + +main(); diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/package.json b/packages/ipfs-http-client/examples/browser-ipns-publish/package.json new file mode 100644 index 0000000000..b3f7a5fdd1 --- /dev/null +++ b/packages/ipfs-http-client/examples/browser-ipns-publish/package.json @@ -0,0 +1,34 @@ +{ + "name": "browser-ipns-publish-example", + "version": "1.0.0", + "description": "An example demonstrating publishing to IPNS in the browser", + "private": true, + "main": "index.js", + "scripts": { + "start": "parcel index.html" + }, + "author": "Doug Anderson", + "license": "MIT", + "dependencies": { + "ipfs": "file:../../../ipfs", + "ipfs-http-client": "../../", + "p-retry": "^4.2.0", + "it-last": "^1.0.2", + "base64url": "^3.0.1", + "human-crypto-keys": "^0.1.4" + }, + "browserslist": [ + "last 2 versions and not dead and > 2%" + ], + "devDependencies": { + "parcel-bundler": "^1.12.4" + }, + "repository": { + "type": "git", + "url": "https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-http-client/examples" + }, + "keywords": [ + "IPNS", + "Publish" + ] +} diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/util.js b/packages/ipfs-http-client/examples/browser-ipns-publish/util.js new file mode 100644 index 0000000000..e6aada61f8 --- /dev/null +++ b/packages/ipfs-http-client/examples/browser-ipns-publish/util.js @@ -0,0 +1,31 @@ +exports.sleep = (ms = 1000) => new Promise(resolve => setTimeout(resolve, ms)) + +exports.Logger = outEl => { + outEl.innerHTML = '' + return message => { + const container = document.createElement('div') + container.innerHTML = message + outEl.appendChild(container) + outEl.scrollTop = outEl.scrollHeight + } +} + +exports.onEnterPress = fn => { + return e => { + if (event.which == 13 || event.keyCode == 13) { + e.preventDefault() + fn() + } + } +} + +exports.catchAndLog = (fn, log) => { + return async (...args) => { + try { + await fn(...args) + } catch (err) { + console.error(err) + log(`${err.message}`) + } + } +} From 250cbd8957b55000d53285136233f21eaa74ae0f Mon Sep 17 00:00:00 2001 From: DougA Date: Sun, 12 Jul 2020 12:56:13 -0400 Subject: [PATCH 02/22] slight adjustments to readme --- .../examples/browser-ipns-publish/.gitignore | 3 ++- .../examples/browser-ipns-publish/README.md | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore b/packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore index 4a94694d21..46b007034c 100644 --- a/packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore +++ b/packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore @@ -1,2 +1,3 @@ bundle.js -.cache \ No newline at end of file +.cache +/node_modules/ \ No newline at end of file diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/README.md b/packages/ipfs-http-client/examples/browser-ipns-publish/README.md index 25d9b0532c..1b146bc012 100644 --- a/packages/ipfs-http-client/examples/browser-ipns-publish/README.md +++ b/packages/ipfs-http-client/examples/browser-ipns-publish/README.md @@ -32,7 +32,7 @@ With Node.js and git installed, clone the repo and install the project dependenc git clone https://github.com/ipfs/js-ipfs-http-client.git cd js-ipfs-http-client npm install # Installs ipfs-http-client dependencies -cd examples/browser-pubsub +cd examples/browser-ipns-publish npm install # Installs browser-pubsub app dependencies ``` @@ -42,12 +42,12 @@ Start the example application: npm start ``` -You should see something similar to the following in your terminal and the web app should now be available if you navigate to http://127.0.0.1:8888 using your browser: +You should see something similar to the following in your terminal and the web app should now be available if you navigate to http://127.0.0.1:1234 using your browser: ```sh Starting up http-server, serving ./ Available on: - http://127.0.0.1:8888 + http://127.0.0.1:1234 ``` ## 2. Start two IPFS nodes @@ -67,9 +67,9 @@ After installation: ```sh ipfs init # Configure CORS to allow ipfs-http-client to access this IPFS node -ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://127.0.0.1:8888"]' +ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://127.0.0.1:1234"]' # Start the IPFS node, enabling pubsub -ipfs daemon --enable-pubsub-experiment & +ipfs daemon --enable-pubsub-experiment ``` ## 3. Open the demo in a browser and connect to the go-node @@ -80,4 +80,6 @@ In the "CONNECT TO GO-IPFS VIA API MULTIADDRESS" field enter `/ip4/YourServerIP/ This connects the API to the go-Node and connects your js-IPFS node via websocket to the go-Node so pubsub will work. -Finally, enter `/ipfs/QmSomeHash` as the content you want to publish to IPNS.You should see the messages sent from the browser to the server appear in the logs below, ending with "Success, reolved" if it all worked. +You can choose whether to publish this record under the PeerId of the node that is running in the browser ('self') or choose to add a custom key to the IPFS keychain and publish under that instead. Either should work. + +Finally, enter `/ipfs/QmSomeHash` as the content you want to publish to IPNS. You should see the messages sent from the browser to the server appear in the logs below, ending with "Success, reolved" if it all worked. From a57bb528dc304d8f67e7bf112d2084dba22d6165 Mon Sep 17 00:00:00 2001 From: DougA Date: Wed, 15 Jul 2020 13:36:19 -0400 Subject: [PATCH 03/22] move to /examples folder --- .../examples => examples}/browser-ipns-publish/.gitignore | 0 .../examples => examples}/browser-ipns-publish/README.md | 4 ++-- .../examples => examples}/browser-ipns-publish/index.html | 0 .../examples => examples}/browser-ipns-publish/index.js | 0 .../examples => examples}/browser-ipns-publish/package.json | 0 .../examples => examples}/browser-ipns-publish/util.js | 0 6 files changed, 2 insertions(+), 2 deletions(-) rename {packages/ipfs-http-client/examples => examples}/browser-ipns-publish/.gitignore (100%) rename {packages/ipfs-http-client/examples => examples}/browser-ipns-publish/README.md (97%) rename {packages/ipfs-http-client/examples => examples}/browser-ipns-publish/index.html (100%) rename {packages/ipfs-http-client/examples => examples}/browser-ipns-publish/index.js (100%) rename {packages/ipfs-http-client/examples => examples}/browser-ipns-publish/package.json (100%) rename {packages/ipfs-http-client/examples => examples}/browser-ipns-publish/util.js (100%) diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore b/examples/browser-ipns-publish/.gitignore similarity index 100% rename from packages/ipfs-http-client/examples/browser-ipns-publish/.gitignore rename to examples/browser-ipns-publish/.gitignore diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/README.md b/examples/browser-ipns-publish/README.md similarity index 97% rename from packages/ipfs-http-client/examples/browser-ipns-publish/README.md rename to examples/browser-ipns-publish/README.md index 1b146bc012..8bdb02546d 100644 --- a/packages/ipfs-http-client/examples/browser-ipns-publish/README.md +++ b/examples/browser-ipns-publish/README.md @@ -29,8 +29,8 @@ This example is a demo web application that allows you to connect to a go-IPFS n With Node.js and git installed, clone the repo and install the project dependencies: ```sh -git clone https://github.com/ipfs/js-ipfs-http-client.git -cd js-ipfs-http-client +git clone https://github.com/ipfs/js-ipfs.git +cd js-ipfs npm install # Installs ipfs-http-client dependencies cd examples/browser-ipns-publish npm install # Installs browser-pubsub app dependencies diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/index.html b/examples/browser-ipns-publish/index.html similarity index 100% rename from packages/ipfs-http-client/examples/browser-ipns-publish/index.html rename to examples/browser-ipns-publish/index.html diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/index.js b/examples/browser-ipns-publish/index.js similarity index 100% rename from packages/ipfs-http-client/examples/browser-ipns-publish/index.js rename to examples/browser-ipns-publish/index.js diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json similarity index 100% rename from packages/ipfs-http-client/examples/browser-ipns-publish/package.json rename to examples/browser-ipns-publish/package.json diff --git a/packages/ipfs-http-client/examples/browser-ipns-publish/util.js b/examples/browser-ipns-publish/util.js similarity index 100% rename from packages/ipfs-http-client/examples/browser-ipns-publish/util.js rename to examples/browser-ipns-publish/util.js From ddbf720e5cbf4182dca9fc9ecfa1cc0140ec3122 Mon Sep 17 00:00:00 2001 From: DougA Date: Wed, 15 Jul 2020 13:48:25 -0400 Subject: [PATCH 04/22] edit package.json for new location --- examples/browser-ipns-publish/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index b3f7a5fdd1..ebb0d351a6 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -10,8 +10,8 @@ "author": "Doug Anderson", "license": "MIT", "dependencies": { - "ipfs": "file:../../../ipfs", - "ipfs-http-client": "../../", + "ipfs": "file:../packages/ipfs", + "ipfs-http-client": "file:../packages/ipfs-http-client", "p-retry": "^4.2.0", "it-last": "^1.0.2", "base64url": "^3.0.1", @@ -25,7 +25,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-http-client/examples" + "url": "https://github.com/ipfs/js-ipfs/examples" }, "keywords": [ "IPNS", From 6670b1ee96b4b1236082cdd373eb4b1937bcb2ed Mon Sep 17 00:00:00 2001 From: DougA Date: Fri, 17 Jul 2020 09:56:46 -0400 Subject: [PATCH 05/22] bump http-server version --- examples/test-ipfs-example/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/test-ipfs-example/package.json b/examples/test-ipfs-example/package.json index 4f5590c846..f110bb9bdd 100644 --- a/examples/test-ipfs-example/package.json +++ b/examples/test-ipfs-example/package.json @@ -10,7 +10,7 @@ "chromedriver": "^83.0.0", "execa": "^4.0.0", "fs-extra": "^8.1.0", - "http-server": "^0.11.1", + "http-server": "^0.12.3", "nightwatch": "^1.2.4", "which": "^2.0.1" } From b7bf749e943e7e32195fea51f978d5bad24b5c05 Mon Sep 17 00:00:00 2001 From: DougA Date: Fri, 17 Jul 2020 09:57:55 -0400 Subject: [PATCH 06/22] init test commit --- examples/browser-ipns-publish/test.js | 221 ++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 examples/browser-ipns-publish/test.js diff --git a/examples/browser-ipns-publish/test.js b/examples/browser-ipns-publish/test.js new file mode 100644 index 0000000000..2f72c037de --- /dev/null +++ b/examples/browser-ipns-publish/test.js @@ -0,0 +1,221 @@ +"use strict"; + +const fs = require("fs-extra"); +const os = require("os"); +const path = require("path"); +const execa = require("execa"); +const delay = require("delay"); +const { startServer } = require("test-ipfs-example/utils"); +const pkg = require("./package.json"); +const { createFactory } = require("ipfsd-ctl"); +const df = createFactory({ + ipfsHttpModule: require("ipfs-http-client"), +}); + +const daemonsOptions = { + args: ["--enable-namesys-pubsub"], // enable ipns over pubsub +}; +const apiPort = "5001"; + +async function testUI(url, apiMultiAddr) { + const proc = execa( + require.resolve("test-ipfs-example/node_modules/.bin/nightwatch"), + [ + "--config", + require.resolve("test-ipfs-example/nightwatch.conf.js"), + path.join(__dirname, "test.js"), + ], + { + cwd: path.resolve(__dirname, "../"), + env: { + ...process.env, + CI: true, + IPFS_EXAMPLE_TEST_URL: url, + IPFS_API_MULTIADDR: apiMultiAddr, + }, + all: true, + } + ); + proc.all.on("data", (data) => { + process.stdout.write(data); + }); + + await proc; +} + +/* +This test needs: +✓ a server listening on an API port 5001 +✓ listening on websocket port 4003 + +then + +1. +*/ +async function runTest() { + let nodes = []; + nodes = await Promise.all([ + df.spawn({ + type: "go", + test: true, + ipfsOptions: { + config: { + Addresses: { + Swarm: ["/ip4/127.0.0.1/tcp/4003/ws", "/ip4/0.0.0.0/tcp/4001"], + API: `/ip4/127.0.0.1/tcp/${apiPort}`, + }, + }, + }, + ...daemonsOptions, + }), + df.spawn({ + type: "js", + test: true, + ...daemonsOptions, + }), + // go-ipfs needs two nodes in the DHT to be able to publish a record + // TODO: Remove this when js-ipfs has a DHT + df.spawn({ + type: "go", + test: true, + ...daemonsOptions, + }), + ]); + + const server = await startServer(__dirname); + + try { + + // swarm the go node to the other 2 nodes + await nodes[0].api.swarm.connect(nodes[1].api.peerId.addresses[0]) + // go-ipfs needs two nodes in the DHT to be able to publish a record + // TODO: Remove this when js-ipfs has a DHT + await nodes[0].api.swarm.connect(nodes[2].api.peerId.addresses[0]) + + console.log('wait for republish as we can receive the republish message first') // eslint-disable-line no-console + await delay(60000); + + const goPeer = await nodes[0].api.id(); + + const address = goPeer.addresses + .map((ma) => ma.toString()) + .find((addr) => addr.includes("/ws/p2p/Qm")); + + if (!address) { + throw new Error( + `Could not find web socket address in ${goPeer.addresses}` + ); + } + + let apiMultiAddr = `/ip4/${server.url}/tcp/${apiPort}`; + + await testUI(server.url, apiMultiAddr); + + } finally { + await nodes[0].stop(); + await nodes[1].stop(); + await nodes[2].stop(); + await server.stop(); + } +} + +module.exports = runTest; + +/* +This test needs: + +1. put the server API port in the text input, click connect +assert connected + +2. put the websocket multiaddr int he input, click connect +assert connected + +3. put the content to publish in the input, click publish +assert published + +4. listen for resolve + +*/ +module.exports[pkg.name] = function (browser) { + let local = null; + let remote = null; + + browser + .url(process.env.IPFS_EXAMPLE_TEST_URL) + .waitForElementVisible("#api-url") + .clearValue("#api-url") + .setValue("#api-url", process.env.IPFS_API_MULTIADDR) + .pause(1000) + .click("#node-connect"); + + /* + browser.expect + .element("#peers-addrs") + .text.to.contain(process.env.IPFS_RELAY_ID); + browser.expect.element("#peer-id").text.to.not.equal(""); + + // exchange peer info + browser + .getText("#addrs", (result) => { + local = { + addr: result.value.trim(), + }; + console.info(`got local circuit relay address ${local.addr}`); // eslint-disable-line no-console + }) + .getText("#peer-id", (result) => { + local.id = result.value.trim(); + console.info(`got local peer id ${local.id}`); // eslint-disable-line no-console + }) + .perform(async (browser, done) => { + console.info(`writing local data ${local.addr}`); // eslint-disable-line no-console + await fs.writeJson(process.env.IPFS_LOCAL_PEER_ID_FILE, local); + + console.info("reading remote circuit relay address"); // eslint-disable-line no-console + for (let i = 0; i < 100; i++) { + try { + remote = await fs.readJson(process.env.IPFS_REMOTE_PEER_ID_FILE, { + encoding: "utf8", + }); + + if (!remote || !remote.addr || !remote.id) { + throw new Error("Remote circuit relay address was empty"); + } + + console.info(`got remote circuit relay address ${remote.addr}`); // eslint-disable-line no-console + done(); + + break; + } catch (err) { + // ignore + } + + await delay(1000); + } + + console.info(`connecting to remote peer ${remote.addr}`); // eslint-disable-line no-console + + browser + .clearValue("#peer") + .setValue("#peer", remote.addr) + .pause(1000) + .click("#connect"); + + browser.expect.element("#peers-addrs").text.to.contain(remote.id); + + browser + .clearValue("#message") + .setValue("#message", "hello") + .pause(1000) + .click("#send"); + + browser.expect + .element("#msgs") + .text.to.contain(`${remote.id.substr(-4)}: hello`); + browser.expect + .element("#msgs") + .text.to.contain(`${local.id.substr(-4)}: hello`); + }); + */ + + browser.end(); +}; From 518ad1c25b3d527f6baf794db3775eedb0dddca3 Mon Sep 17 00:00:00 2001 From: DougA Date: Fri, 17 Jul 2020 09:58:39 -0400 Subject: [PATCH 07/22] package.json installs --- examples/browser-ipns-publish/package.json | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index ebb0d351a6..8f744ad6bd 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -5,17 +5,20 @@ "private": true, "main": "index.js", "scripts": { - "start": "parcel index.html" + "start": "parcel index.html", + "test": "test-ipfs-example" }, "author": "Doug Anderson", "license": "MIT", "dependencies": { - "ipfs": "file:../packages/ipfs", - "ipfs-http-client": "file:../packages/ipfs-http-client", - "p-retry": "^4.2.0", - "it-last": "^1.0.2", "base64url": "^3.0.1", - "human-crypto-keys": "^0.1.4" + "human-crypto-keys": "^0.1.4", + "ipfs": "file:../../packages/ipfs/", + "ipfs-http-client": "file:../../packages/ipfs-http-client/", + "ipfs-utils": "^2.3.1", + "ipns": "^0.7.3", + "it-last": "^1.0.2", + "p-retry": "^4.2.0" }, "browserslist": [ "last 2 versions and not dead and > 2%" From 9c4834686adaf55843e4e2ffe361273c9ce44244 Mon Sep 17 00:00:00 2001 From: DougA Date: Fri, 17 Jul 2020 09:59:51 -0400 Subject: [PATCH 08/22] bug fixes --- examples/browser-ipns-publish/index.html | 38 ++++++----- examples/browser-ipns-publish/index.js | 80 ++++++++++++++---------- 2 files changed, 69 insertions(+), 49 deletions(-) diff --git a/examples/browser-ipns-publish/index.html b/examples/browser-ipns-publish/index.html index ebe7ff99ef..fbd4a2dcbb 100644 --- a/examples/browser-ipns-publish/index.html +++ b/examples/browser-ipns-publish/index.html @@ -34,7 +34,7 @@

Code repo for this demo on Github

@@ -43,7 +43,8 @@

private keys, but publish to go-ipfs to benefit from the DHT. Since the DHT in js-ipfs isn't working yet, we need to use PubSub and have a go-ipfs node subscribed to that PubSub to get our IPNS - record onto the DHT. + record onto the DHT. In order to use PubSub between these two + nodes, you'll need a websocket to connect them.

To make this demo work, you're going to need: @@ -141,23 +142,26 @@

diff --git a/examples/browser-ipns-publish/index.js b/examples/browser-ipns-publish/index.js index 311c4d73c2..33248db32f 100644 --- a/examples/browser-ipns-publish/index.js +++ b/examples/browser-ipns-publish/index.js @@ -9,7 +9,7 @@ const last = require("it-last"); const cryptoKeys = require("human-crypto-keys"); // { getKeyPairFromSeed } const { sleep, Logger, onEnterPress, catchAndLog } = require("./util"); -const { Date } = require("ipfs-utils/src/globalthis"); +const { Date, Element } = require("ipfs-utils/src/globalthis"); async function main() { const apiUrlInput = document.getElementById("api-url"); @@ -36,7 +36,10 @@ async function main() { // init local browser node right away log(`Browser IPFS getting ready...`); - ipfsBrowser = await IPFS.create({ pass: "01234567890123456789", EXPERIMENTAL: { ipnsPubsub: true } }); + ipfsBrowser = await IPFS.create({ + pass: "01234567890123456789", + EXPERIMENTAL: { ipnsPubsub: true }, + }); const { id } = await ipfsBrowser.id(); log(`Browser IPFS ready! Node id: ${id}`); @@ -112,7 +115,7 @@ async function main() { let regex = "/record/"; if (topic.match(regex) ? topic.match(regex).length > 0 : false) { tLog( - "#" + + "\n#" + ipns.unmarshal(msg.data).sequence.toString() + ") Topic: " + msg.topicIDs[0].toString() @@ -168,23 +171,41 @@ async function main() { async function publish(content) { if (!content) throw new Error("Missing ipns content to publish"); if (!ipfsAPI) throw new Error("Connect to a go-server node first"); - if (!ipfsAPI.name.pubsub.state()) + if (!ipfsAPI.name.pubsub.state() || !ipfsBrowser.name.pubsub.state()) throw new Error( "IPNS Pubsub must be enabled on bother peers, use --enable-namesys-pubsub" ); + log(`Publish to IPNS`); // subscribes the server to our IPNS topic + let browserNode = await ipfsBrowser.id(); let serverNode = await ipfsAPI.id(); - let b58 = await IPFS.multihash.fromB58String(browserNode.id); - const keys = ipns.getIdKeys(b58); - const topic = `${namespace}${base64url.encode(keys.routingKey.toBuffer())}`; + // get which key this will be publish under, self or an imported custom key + keyName = document.querySelector('input[name="keyName"]:checked').value; + let keys = { name: "self", id: browserNode.id }; // default init + + if (keyName != "self") { + if (!(await ipfsBrowser.key.list()).find((k) => k.name == keyName)) + // skip if custom key exists already + await createKey(keyName); + let r = await ipfsBrowser.key.list(); + keys = r.find((k) => k.name == keyName); + log(JSON.stringify(keys)); + } - log(`Initial Resolve ${browserNode.id}`); // subscribes the server to our IPNS topics - last(ipfsAPI.name.resolve(browserNode.id, { stream: false })); // save the pubsub topic to the server to make them listen + log(`Initial Resolve ${keys.id}`); // subscribes the server to our IPNS topic + last(ipfsAPI.name.resolve(keys.id, { stream: false })); // save the pubsub topic to the server to make them listen await sleep(1000); // give it a moment to save it + // set up the topic from ipns key + let b58 = await IPFS.multihash.fromB58String(keys.id); + const ipnsKeys = ipns.getIdKeys(b58); + const topic = `${namespace}${base64url.encode( + ipnsKeys.routingKey.toBuffer() + )}`; + // subscribe and log on both nodes await subs(ipfsBrowser, topic, log); // browserLog await subs(ipfsAPI, topic, sLog); // serverLog @@ -196,47 +217,43 @@ async function main() { await sleep(2500); // give it a moment to save it let remList = await ipfsAPI.pubsub.ls(); // API - if (!remList.includes(topic)) sLog(`[Fail] !Pubsub.ls ${topic}`); + if (!remList.includes(topic)) sLog(`[Fail] !Pubsub.ls ${topic}`); else sLog(`[Pass] Pubsub.ls`); let remListSubs = await ipfsAPI.name.pubsub.subs(); // API - if (!remListSubs.includes(`/ipns/${browserNode.id}`)) - sLog(`[Fail] !Name.Pubsub.subs ${browserNode.id}`); + if (!remListSubs.includes(`/ipns/${keys.id}`)) + sLog(`[Fail] !Name.Pubsub.subs ${keys.id}`); else sLog(`[Pass] Name.Pubsub.subs`); - keyName = document.querySelector('input[name="keyName"]:checked').value; - if (keyName != "self") { - await createKey(keyName); - let keys = await ipfsBrowser.key.list() - log(JSON.stringify(keys)); - } - // publish will send a pubsub msg to the server to update their ipns record - log(`Publishing ${content} to ${keyName}...`); + log(`Publishing ${content} to ${keys.name} /ipns/${keys.id}`); const results = await ipfsBrowser.name.publish(content, { resolve: false, key: keyName, }); - log(`Published`); // ${results.name} to ${results.value} + log(`Published ${results.name} to ${results.value}`); // - log(`Wait 5 seconds, then resolve...`); - await sleep(5000); + log(`Wait 45 seconds, then resolve...`); + await sleep(45000); - log( - `Try to resolve ${browserNode.id} on server through API to confirm published` - ); + log(`Try resolve ${keys.id} on server through API`); let name = await last( - ipfsAPI.name.resolve(browserNode.id, { + ipfsAPI.name.resolve(keys.id, { stream: false, }) ); log(`Resolved: ${name}`); - if (name == content) + if (name == content) { log(`IPNS Publish Success!`); - log( - `Look at that! /ipns/${browserNode.id} resolves to ${content}` - ); + log( + `Look at that! /ipns/${keys.id} resolves to ${content}` + ); + } else { + log( + `Error, resolve did not match ${name} !== ${content}` + ); + } } const onNodeConnectClick = catchAndLog( @@ -257,7 +274,6 @@ async function main() { const onPublishClick = catchAndLog(() => publish(ipnsInput.value), log); ipnsInput.addEventListener("keydown", onEnterPress(onPublishClick)); publishBtn.addEventListener("click", onPublishClick); - } main(); From bad6942960d877256a3fcbbbd9ab47745c8ee3a8 Mon Sep 17 00:00:00 2001 From: DougA Date: Fri, 17 Jul 2020 13:18:24 -0400 Subject: [PATCH 09/22] add dev Deps --- examples/browser-ipns-publish/package.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index 8f744ad6bd..dbde4a279b 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -24,7 +24,14 @@ "last 2 versions and not dead and > 2%" ], "devDependencies": { - "parcel-bundler": "^1.12.4" + "delay": "^4.3.0", + "execa": "^4.0.0", + "fs-extra": "^9.0.1", + "ipfsd-ctl": "^5.0.0", + "os": "^0.1.1", + "parcel-bundler": "^1.12.4", + "path": "^0.12.7", + "test-ipfs-example": "file:../test-ipfs-example/" }, "repository": { "type": "git", From dd9a235cc1a41ff7c6f29635134a3fa928d6952e Mon Sep 17 00:00:00 2001 From: DougA Date: Sat, 18 Jul 2020 21:42:44 -0400 Subject: [PATCH 10/22] index tweaks --- examples/browser-ipns-publish/index.html | 9 ++++++++- examples/browser-ipns-publish/index.js | 13 ++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/examples/browser-ipns-publish/index.html b/examples/browser-ipns-publish/index.html index fbd4a2dcbb..74e52fd1e6 100644 --- a/examples/browser-ipns-publish/index.html +++ b/examples/browser-ipns-publish/index.html @@ -110,10 +110,12 @@

id="api-url" class="dib w-50 ph1 pv2 monospace input-reset ba b--black-20 border-box" placeholder="/dns4/yourdomain.com/tcp/5001" + disabled="disabled" /> @@ -126,10 +128,12 @@

id="peer-addr" class="dib w-50 ph1 pv2 monospace input-reset ba b--black-20 border-box" placeholder="/dns4/yourdomain.com/tcp/4003/wss/p2p/QmTheirServerPeerId" + disabled="disabled" /> @@ -153,7 +157,7 @@

>
  • - +
  • +
    Browser Console
    Success!`); log(`Version ${agentVersion}`); log(`Peer ID ${id}`); + document.getElementById("peer-addr").disabled = false; + document.getElementById("peer-connect").disabled = false; } async function wsConnect(addr) { @@ -73,6 +77,8 @@ async function main() { ); }); log(`(${peers.length} peers total)`); + document.getElementById("topic").disabled = false; + document.getElementById("publish").disabled = false; } // Wait until a peer subscribes a topic @@ -217,7 +223,8 @@ async function main() { await sleep(2500); // give it a moment to save it let remList = await ipfsAPI.pubsub.ls(); // API - if (!remList.includes(topic)) sLog(`[Fail] !Pubsub.ls ${topic}`); + if (!remList.includes(topic)) + sLog(`[Fail] !Pubsub.ls ${topic}`); else sLog(`[Pass] Pubsub.ls`); let remListSubs = await ipfsAPI.name.pubsub.subs(); // API @@ -233,8 +240,8 @@ async function main() { }); log(`Published ${results.name} to ${results.value}`); // - log(`Wait 45 seconds, then resolve...`); - await sleep(45000); + log(`Wait 5 seconds, then resolve...`); + await sleep(5000); log(`Try resolve ${keys.id} on server through API`); From 7e0b87d58add781c3dcc03121ec74102dd1f7713 Mon Sep 17 00:00:00 2001 From: DougA Date: Sat, 18 Jul 2020 21:44:03 -0400 Subject: [PATCH 11/22] switch nightwatch to chromedriver to work on windows --- examples/test-ipfs-example/nightwatch.conf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/test-ipfs-example/nightwatch.conf.js b/examples/test-ipfs-example/nightwatch.conf.js index fa7def7b23..524dc76a6b 100644 --- a/examples/test-ipfs-example/nightwatch.conf.js +++ b/examples/test-ipfs-example/nightwatch.conf.js @@ -2,6 +2,7 @@ const { ephemeralPort } = require('./utils') const path = require('path') +const chrome = require('chromedriver') // added to work on windows const WEBRIVER_PORT = ephemeralPort() @@ -11,7 +12,7 @@ module.exports = { webdriver: { start_process: true, - server_path: require.resolve(path.resolve(__dirname, 'node_modules/.bin/chromedriver')), + server_path: chrome.path, //require.resolve(path.resolve(__dirname, 'node_modules/.bin/chromedriver')), // this wasn't working on windows port: WEBRIVER_PORT, cli_args: [ `--port=${WEBRIVER_PORT}` From cdf7699d4c8591ce9ca245ee70101ec74b250cf8 Mon Sep 17 00:00:00 2001 From: DougA Date: Sat, 18 Jul 2020 21:45:18 -0400 Subject: [PATCH 12/22] add go-ipfs --- examples/browser-ipns-publish/package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index dbde4a279b..8f8044f820 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -1,10 +1,11 @@ { - "name": "browser-ipns-publish-example", + "name": "browser-ipns-publish", "version": "1.0.0", "description": "An example demonstrating publishing to IPNS in the browser", "private": true, "main": "index.js", "scripts": { + "build": "parcel build index.html --public-url ./", "start": "parcel index.html", "test": "test-ipfs-example" }, @@ -26,11 +27,11 @@ "devDependencies": { "delay": "^4.3.0", "execa": "^4.0.0", - "fs-extra": "^9.0.1", "ipfsd-ctl": "^5.0.0", - "os": "^0.1.1", + "go-ipfs": "^0.6.0", "parcel-bundler": "^1.12.4", "path": "^0.12.7", + "fs-extra": "^9.0.1", "test-ipfs-example": "file:../test-ipfs-example/" }, "repository": { From c5ed1fd3bf592af94212ed4785ca0708f6b82ae8 Mon Sep 17 00:00:00 2001 From: DougA Date: Sat, 18 Jul 2020 21:54:20 -0400 Subject: [PATCH 13/22] test added --- examples/browser-ipns-publish/test.js | 250 +++++++++----------------- 1 file changed, 87 insertions(+), 163 deletions(-) diff --git a/examples/browser-ipns-publish/test.js b/examples/browser-ipns-publish/test.js index 2f72c037de..e9a9df102d 100644 --- a/examples/browser-ipns-publish/test.js +++ b/examples/browser-ipns-publish/test.js @@ -1,23 +1,28 @@ "use strict"; -const fs = require("fs-extra"); -const os = require("os"); const path = require("path"); const execa = require("execa"); -const delay = require("delay"); const { startServer } = require("test-ipfs-example/utils"); const pkg = require("./package.json"); const { createFactory } = require("ipfsd-ctl"); -const df = createFactory({ - ipfsHttpModule: require("ipfs-http-client"), -}); - -const daemonsOptions = { - args: ["--enable-namesys-pubsub"], // enable ipns over pubsub -}; -const apiPort = "5001"; +const df = createFactory( + { + ipfsHttpModule: require("ipfs-http-client"), + }, + { + js: { + ipfsBin: require.resolve("ipfs/src/cli/bin.js"), + args: ["--enable-pubsub-experiment"], + }, + go: { + ipfsBin: require("go-ipfs").path(), + // ipfsBin: require('go-ipfs-dep').path(), + args: ["--enable-pubsub-experiment"], + }, + } +); -async function testUI(url, apiMultiAddr) { +async function testUI(url, apiAddr, peerAddr, topic) { const proc = execa( require.resolve("test-ipfs-example/node_modules/.bin/nightwatch"), [ @@ -31,7 +36,9 @@ async function testUI(url, apiMultiAddr) { ...process.env, CI: true, IPFS_EXAMPLE_TEST_URL: url, - IPFS_API_MULTIADDR: apiMultiAddr, + IPFS_API_ADDRESS: apiAddr, + IPFS_PEER_ADDRESS: peerAddr, + IPFS_TOPIC: topic, }, all: true, } @@ -43,179 +50,96 @@ async function testUI(url, apiMultiAddr) { await proc; } -/* -This test needs: -✓ a server listening on an API port 5001 -✓ listening on websocket port 4003 - -then - -1. -*/ async function runTest() { - let nodes = []; - nodes = await Promise.all([ - df.spawn({ - type: "go", - test: true, - ipfsOptions: { - config: { - Addresses: { - Swarm: ["/ip4/127.0.0.1/tcp/4003/ws", "/ip4/0.0.0.0/tcp/4001"], - API: `/ip4/127.0.0.1/tcp/${apiPort}`, + const app = await startServer(__dirname); + const go = await df.spawn({ + type: "go", + test: true, + ipfsOptions: { + config: { + Addresses: { + Swarm: ["/ip4/127.0.0.1/tcp/4003/ws", "/ip4/127.0.0.1/tcp/0"], + API: "/ip4/127.0.0.1/tcp/0", + }, + API: { + HTTPHeaders: { + "Access-Control-Allow-Origin": [app.url], }, }, }, - ...daemonsOptions, - }), - df.spawn({ - type: "js", - test: true, - ...daemonsOptions, - }), - // go-ipfs needs two nodes in the DHT to be able to publish a record - // TODO: Remove this when js-ipfs has a DHT - df.spawn({ - type: "go", - test: true, - ...daemonsOptions, - }), - ]); - - const server = await startServer(__dirname); - - try { - - // swarm the go node to the other 2 nodes - await nodes[0].api.swarm.connect(nodes[1].api.peerId.addresses[0]) - // go-ipfs needs two nodes in the DHT to be able to publish a record - // TODO: Remove this when js-ipfs has a DHT - await nodes[0].api.swarm.connect(nodes[2].api.peerId.addresses[0]) - - console.log('wait for republish as we can receive the republish message first') // eslint-disable-line no-console - await delay(60000); - - const goPeer = await nodes[0].api.id(); - - const address = goPeer.addresses - .map((ma) => ma.toString()) - .find((addr) => addr.includes("/ws/p2p/Qm")); - - if (!address) { - throw new Error( - `Could not find web socket address in ${goPeer.addresses}` - ); - } + }, + }); - let apiMultiAddr = `/ip4/${server.url}/tcp/${apiPort}`; + const js = await df.spawn({ + type: "js", + test: true + }); - await testUI(server.url, apiMultiAddr); + const topic = `/ipfs/QmWCnkCXYYPP7NgH6ZHQiQxw7LJAMjnAySdoz9i1oxD5XJ`; + try { + await testUI( + app.url, + go.apiAddr, + go.api.peerId.addresses[0].toString(), + topic + ); } finally { - await nodes[0].stop(); - await nodes[1].stop(); - await nodes[2].stop(); - await server.stop(); + await js.stop(); + await go.stop(); + await app.stop(); } } module.exports = runTest; -/* -This test needs: - -1. put the server API port in the text input, click connect -assert connected - -2. put the websocket multiaddr int he input, click connect -assert connected - -3. put the content to publish in the input, click publish -assert published - -4. listen for resolve - -*/ module.exports[pkg.name] = function (browser) { - let local = null; - let remote = null; + const apiSelector = "#api-url:enabled"; + // connect to the API browser .url(process.env.IPFS_EXAMPLE_TEST_URL) - .waitForElementVisible("#api-url") - .clearValue("#api-url") - .setValue("#api-url", process.env.IPFS_API_MULTIADDR) + .waitForElementVisible(apiSelector) + .clearValue(apiSelector) + .setValue(apiSelector, process.env.IPFS_API_ADDRESS) .pause(1000) + .perform(() => { + console.log( + "process.env.IPFS_API_ADDRESS: ", + process.env.IPFS_API_ADDRESS + ); + }) .click("#node-connect"); - /* browser.expect - .element("#peers-addrs") - .text.to.contain(process.env.IPFS_RELAY_ID); - browser.expect.element("#peer-id").text.to.not.equal(""); + .element("#console") + .text.to.contain(`Connecting to ${process.env.IPFS_API_ADDRESS}\nSuccess!`); - // exchange peer info + // connect via websocket + const peerAddrSelector = "#peer-addr:enabled"; browser - .getText("#addrs", (result) => { - local = { - addr: result.value.trim(), - }; - console.info(`got local circuit relay address ${local.addr}`); // eslint-disable-line no-console - }) - .getText("#peer-id", (result) => { - local.id = result.value.trim(); - console.info(`got local peer id ${local.id}`); // eslint-disable-line no-console - }) - .perform(async (browser, done) => { - console.info(`writing local data ${local.addr}`); // eslint-disable-line no-console - await fs.writeJson(process.env.IPFS_LOCAL_PEER_ID_FILE, local); - - console.info("reading remote circuit relay address"); // eslint-disable-line no-console - for (let i = 0; i < 100; i++) { - try { - remote = await fs.readJson(process.env.IPFS_REMOTE_PEER_ID_FILE, { - encoding: "utf8", - }); - - if (!remote || !remote.addr || !remote.id) { - throw new Error("Remote circuit relay address was empty"); - } - - console.info(`got remote circuit relay address ${remote.addr}`); // eslint-disable-line no-console - done(); - - break; - } catch (err) { - // ignore - } - - await delay(1000); - } - - console.info(`connecting to remote peer ${remote.addr}`); // eslint-disable-line no-console - - browser - .clearValue("#peer") - .setValue("#peer", remote.addr) - .pause(1000) - .click("#connect"); - - browser.expect.element("#peers-addrs").text.to.contain(remote.id); - - browser - .clearValue("#message") - .setValue("#message", "hello") - .pause(1000) - .click("#send"); - - browser.expect - .element("#msgs") - .text.to.contain(`${remote.id.substr(-4)}: hello`); - browser.expect - .element("#msgs") - .text.to.contain(`${local.id.substr(-4)}: hello`); - }); - */ + .waitForElementVisible(peerAddrSelector) + .clearValue(peerAddrSelector) + .setValue(peerAddrSelector, process.env.IPFS_PEER_ADDRESS) + .pause(1000) + .click("#peer-connect"); + + browser.expect + .element("#console") + .text.to.contain( + `Connecting to peer ${process.env.IPFS_PEER_ADDRESS}\nSuccess!` + ); + + // publish to IPNS + const publishSelector = "#topic:enabled"; + browser + .waitForElementVisible(publishSelector) + .clearValue(publishSelector) + .setValue(publishSelector, process.env.IPFS_TOPIC) + .pause(1000) + .click("#publish"); + + browser.expect.element("#console").text.to.contain(`IPNS Publish Success!`); browser.end(); }; From 8254686e0b19edf46ec2a23c7d1c0b85daa2fa1a Mon Sep 17 00:00:00 2001 From: DougA Date: Sat, 18 Jul 2020 21:55:12 -0400 Subject: [PATCH 14/22] code for windows path --- examples/test-ipfs-example/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/test-ipfs-example/test.js b/examples/test-ipfs-example/test.js index 42cd7947b7..cd93337cd7 100755 --- a/examples/test-ipfs-example/test.js +++ b/examples/test-ipfs-example/test.js @@ -25,7 +25,7 @@ async function testExample (dir) { //await installDeps(dir) await build(dir) - if (dir.includes('examples/browser-')) { + if (dir.includes('examples/browser-') || dir.includes('examples\\browser-') ) { await runBrowserTest(dir) } else { await runNodeTest(dir) From b3c246493b41f0dccd9975a2d9c81cfa829eba68 Mon Sep 17 00:00:00 2001 From: DougA Date: Sun, 19 Jul 2020 09:31:36 -0400 Subject: [PATCH 15/22] hack to get the port to parse in Windows --- examples/test-ipfs-example/utils.js | 195 ++++++++++++++++------------ 1 file changed, 109 insertions(+), 86 deletions(-) diff --git a/examples/test-ipfs-example/utils.js b/examples/test-ipfs-example/utils.js index 6261efd2c1..30aebac0b4 100644 --- a/examples/test-ipfs-example/utils.js +++ b/examples/test-ipfs-example/utils.js @@ -1,159 +1,182 @@ -'use strict' +"use strict"; -const fs = require('fs-extra') -const path = require('path') -const execa = require('execa') -const which = require('which') +const fs = require("fs-extra"); +const path = require("path"); +const execa = require("execa"); +const which = require("which"); -async function startServer (dir) { - async function serveFrom (appDir) { +async function startServer(dir) { + async function serveFrom(appDir) { return new Promise((resolve, reject) => { - let output = '' - - const proc = execa.command(`${path.resolve(__dirname, 'node_modules/.bin/http-server')} ${appDir} -a 127.0.0.1`, { - cwd: __dirname, - all: true - }) - proc.all.on('data', (data) => { - process.stdout.write(data) - - const line = data.toString('utf8') - output += line - - if (output.includes('Hit CTRL-C to stop the server')) { - // find the port - const port = output.match(/http:\/\/127.0.0.1:(\d+)/)[1] + let output = ""; + + const proc = execa.command( + `${path.resolve( + __dirname, + "node_modules/.bin/http-server" + )} ${appDir} -a 127.0.0.1`, + { + cwd: __dirname, + all: true, + } + ); + proc.all.on("data", (data) => { + process.stdout.write(data); + + const line = data.toString("utf8"); + output += line; + + let port; + if (output.includes("Hit CTRL-C to stop the server")) { + // windows hack, windows inserts a bunch of unicode around the port + if (output.includes(`\u001b[32m`)) { + port = output.split(`\u001b[32m`)[1].split(`\u001b[39m`)[0]; + } else { + // find the port + const regex = /http:\/\/127.0.0.1:(\d+)/; //|(?<=\\u001b\[32m)(.\d+?)(?=\\u001b\[39m)/; // positive lookbehind regex didn't work + port = output.match(regex)[output.match(regex).length - 1]; + } if (!port) { - throw new Error(`Could not find port in ${output}`) + throw new Error(`Could not find port in ${output}`); } resolve({ stop: () => { - console.info('Stopping server') - proc.kill('SIGINT', { - forceKillAfterTimeout: 2000 - }) + console.info("Stopping server"); + proc.kill("SIGINT", { + forceKillAfterTimeout: 2000, + }); }, - url: `http://127.0.0.1:${port}` - }) + url: `http://127.0.0.1:${port}`, + }); } - }) + }); - proc.then(() => {}, (err) => reject(err)) - }) + proc.then( + () => {}, + (err) => reject(err) + ); + }); } // start something.. const serverPaths = [ - path.join(dir, 'build'), - path.join(dir, 'dist'), - path.join(dir, 'public') - ] + path.join(dir, "build"), + path.join(dir, "dist"), + path.join(dir, "public"), + ]; for (const p of serverPaths) { if (fs.existsSync(p)) { - return serveFrom(p) + return serveFrom(p); } } // running a bare index.html file - const files = [ - path.join(dir, 'index.html') - ] + const files = [path.join(dir, "index.html")]; for (const f of files) { if (fs.existsSync(f)) { - console.info('Found bare file', f) + console.info("Found bare file", f); return Promise.resolve({ url: `file://${f}`, - stop: () => {} - }) + stop: () => {}, + }); } } - throw new Error('Browser examples must contain a `public`, `dist` or `build` folder or an `index.html` file') + throw new Error( + "Browser examples must contain a `public`, `dist` or `build` folder or an `index.html` file" + ); } -function ephemeralPort (min = 49152, max = 65535) { - return Math.floor(Math.random() * (max - min + 1) + min) +function ephemeralPort(min = 49152, max = 65535) { + return Math.floor(Math.random() * (max - min + 1) + min); } -async function isExecutable (command) { +async function isExecutable(command) { try { - await fs.access(command, fs.constants.X_OK) + await fs.access(command, fs.constants.X_OK); - return true + return true; } catch (err) { - if (err.code === 'ENOENT') { - return isExecutable(await which(command)) + if (err.code === "ENOENT") { + return isExecutable(await which(command)); } - if (err.code === 'EACCES') { - return false + if (err.code === "EACCES") { + return false; } - throw err + throw err; } } -async function waitForOutput (expectedOutput, command, args = [], opts = {}) { - if (!await isExecutable(command)) { - args.unshift(command) - command = 'node' +async function waitForOutput(expectedOutput, command, args = [], opts = {}) { + if (!(await isExecutable(command))) { + args.unshift(command); + command = "node"; } - const proc = execa(command, args, { ...opts, all: true }) - let output = '' - const time = 120000 + const proc = execa(command, args, { ...opts, all: true }); + let output = ""; + const time = 120000; - let foundExpectedOutput = false - let cancelTimeout + let foundExpectedOutput = false; + let cancelTimeout; const timeoutPromise = new Promise((resolve, reject) => { const timeout = setTimeout(() => { - reject(new Error(`Did not see "${expectedOutput}" in output from "${[command].concat(args).join(' ')}" after ${time / 1000}s`)) + reject( + new Error( + `Did not see "${expectedOutput}" in output from "${[command] + .concat(args) + .join(" ")}" after ${time / 1000}s` + ) + ); setTimeout(() => { - proc.kill() - }, 100) - }, time) + proc.kill(); + }, 100); + }, time); cancelTimeout = () => { - clearTimeout(timeout) - resolve() - } - }) + clearTimeout(timeout); + resolve(); + }; + }); - proc.all.on('data', (data) => { - process.stdout.write(data) - output += data.toString('utf8') + proc.all.on("data", (data) => { + process.stdout.write(data); + output += data.toString("utf8"); if (output.includes(expectedOutput)) { - foundExpectedOutput = true - proc.kill() - cancelTimeout() + foundExpectedOutput = true; + proc.kill(); + cancelTimeout(); } - }) + }); try { - await Promise.race([ - proc, - timeoutPromise - ]) + await Promise.race([proc, timeoutPromise]); } catch (err) { if (!err.killed) { - throw err + throw err; } } if (!foundExpectedOutput) { - throw new Error(`Did not see "${expectedOutput}" in output from "${[command].concat(args).join(' ')}"`) + throw new Error( + `Did not see "${expectedOutput}" in output from "${[command] + .concat(args) + .join(" ")}"` + ); } } module.exports = { startServer, ephemeralPort, - waitForOutput -} + waitForOutput, +}; From 1b3b4b8de09bd9f452b1bf8dac5f7861635987b6 Mon Sep 17 00:00:00 2001 From: DougA Date: Sun, 19 Jul 2020 09:32:55 -0400 Subject: [PATCH 16/22] changes to get tests to work --- examples/browser-ipns-publish/package.json | 1 - lerna.json | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index 8f8044f820..0f14202a14 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -31,7 +31,6 @@ "go-ipfs": "^0.6.0", "parcel-bundler": "^1.12.4", "path": "^0.12.7", - "fs-extra": "^9.0.1", "test-ipfs-example": "file:../test-ipfs-example/" }, "repository": { diff --git a/lerna.json b/lerna.json index 60756e2343..8ed30bf2ea 100644 --- a/lerna.json +++ b/lerna.json @@ -1,7 +1,8 @@ { "lerna": "3.22.0", "packages": [ - "packages/*" + "packages/*", + "examples/*" ], "version": "independent", "command": { @@ -9,7 +10,9 @@ "hoist": true, "nohoist": [ "libp2p-delegated-content-routing", - "libp2p-delegated-peer-routing" + "libp2p-delegated-peer-routing", + "ipfs-css", + "tachyons" ] }, "run": { From 5348d3529017f850e018a30ba76b9100ab29e32a Mon Sep 17 00:00:00 2001 From: DougA Date: Mon, 20 Jul 2020 13:58:51 -0400 Subject: [PATCH 17/22] remove js daemon, not needed --- examples/browser-ipns-publish/test.js | 35 ++++++++++----------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/examples/browser-ipns-publish/test.js b/examples/browser-ipns-publish/test.js index e9a9df102d..918e40cb3b 100644 --- a/examples/browser-ipns-publish/test.js +++ b/examples/browser-ipns-publish/test.js @@ -2,25 +2,15 @@ const path = require("path"); const execa = require("execa"); +const { createFactory } = require("ipfsd-ctl"); +const df = createFactory({ + ipfsHttpModule: require("ipfs-http-client"), + ipfsBin: require("go-ipfs").path(), + args: ["--enable-pubsub-experiment"], + disposable: true, +}); const { startServer } = require("test-ipfs-example/utils"); const pkg = require("./package.json"); -const { createFactory } = require("ipfsd-ctl"); -const df = createFactory( - { - ipfsHttpModule: require("ipfs-http-client"), - }, - { - js: { - ipfsBin: require.resolve("ipfs/src/cli/bin.js"), - args: ["--enable-pubsub-experiment"], - }, - go: { - ipfsBin: require("go-ipfs").path(), - // ipfsBin: require('go-ipfs-dep').path(), - args: ["--enable-pubsub-experiment"], - }, - } -); async function testUI(url, apiAddr, peerAddr, topic) { const proc = execa( @@ -58,7 +48,6 @@ async function runTest() { ipfsOptions: { config: { Addresses: { - Swarm: ["/ip4/127.0.0.1/tcp/4003/ws", "/ip4/127.0.0.1/tcp/0"], API: "/ip4/127.0.0.1/tcp/0", }, API: { @@ -70,11 +59,13 @@ async function runTest() { }, }); - const js = await df.spawn({ - type: "js", - test: true + const go2 = await df.spawn({ + type: "go", + test: true, }); + await go.api.swarm.connect(go2.api.peerId.addresses[0]); + const topic = `/ipfs/QmWCnkCXYYPP7NgH6ZHQiQxw7LJAMjnAySdoz9i1oxD5XJ`; try { @@ -85,8 +76,8 @@ async function runTest() { topic ); } finally { - await js.stop(); await go.stop(); + await go2.stop(); await app.stop(); } } From 2fd88ac6a545a4f6d949e8b43538dbdb471e6e1e Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 4 Aug 2020 12:25:26 +0100 Subject: [PATCH 18/22] chore: update test and example --- examples/browser-ipns-publish/README.md | 18 +++++----- examples/browser-ipns-publish/index.html | 2 +- examples/browser-ipns-publish/index.js | 15 -------- examples/browser-ipns-publish/package.json | 6 ++-- examples/browser-ipns-publish/test.js | 42 ++++++++++++---------- 5 files changed, 36 insertions(+), 47 deletions(-) diff --git a/examples/browser-ipns-publish/README.md b/examples/browser-ipns-publish/README.md index 8bdb02546d..de26585fb0 100644 --- a/examples/browser-ipns-publish/README.md +++ b/examples/browser-ipns-publish/README.md @@ -30,8 +30,6 @@ With Node.js and git installed, clone the repo and install the project dependenc ```sh git clone https://github.com/ipfs/js-ipfs.git -cd js-ipfs -npm install # Installs ipfs-http-client dependencies cd examples/browser-ipns-publish npm install # Installs browser-pubsub app dependencies ``` @@ -56,7 +54,7 @@ The first node is the js-ipfs made in the browser and the demo does that for you The second is a go-ipfs node on a server. To get our IPNS record to the DHT, we'll need [a server running go-IPFS](https://blog.ipfs.io/22-run-ipfs-on-a-vps/) with the API enabled on port 5001. -Right now the easiest way to do this is to install and start a `go-ipfs` node. +Right now the easiest way to do this is to install and start a `go-ipfs` node. ### Install and start the Go IPFS node @@ -67,19 +65,21 @@ After installation: ```sh ipfs init # Configure CORS to allow ipfs-http-client to access this IPFS node -ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://127.0.0.1:1234"]' -# Start the IPFS node, enabling pubsub -ipfs daemon --enable-pubsub-experiment +ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\"*\"]" +# Configure go-ipfs to listen on a websocket address +npx json -I -f ~/.ipfs/config -e "this.Addresses.Swarm.push('/ip4/127.0.0.1/tcp/4003/ws')" +# Start the IPFS node, enabling pubsub and IPNS over pubsub +ipfs daemon --enable-pubsub-experiment --enable-namesys-pubsub ``` ## 3. Open the demo in a browser and connect to the go-node -Now, open up the demo in a browser window. +Now, open up the demo in a browser window. In the "CONNECT TO GO-IPFS VIA API MULTIADDRESS" field enter `/ip4/YourServerIP/tcp/5001` (where `YourSeverIP` is your server's IP address or use `/dns4/yourdomain.com/tcp/5001`) and click connect. Once it connects, put your go-IPFS websocket address in the next field `/dns4/yourdomain.com/tcp/4003/wss/p2p/QmPeerIDHash` and hit the second "Connect" button. -This connects the API to the go-Node and connects your js-IPFS node via websocket to the go-Node so pubsub will work. +This connects the API to the go-Node and connects your js-IPFS node via websocket to the go-IPFS node so pubsub will work. You can choose whether to publish this record under the PeerId of the node that is running in the browser ('self') or choose to add a custom key to the IPFS keychain and publish under that instead. Either should work. -Finally, enter `/ipfs/QmSomeHash` as the content you want to publish to IPNS. You should see the messages sent from the browser to the server appear in the logs below, ending with "Success, reolved" if it all worked. +Finally, enter `/ipfs/QmSomeHash` as the content you want to publish to IPNS. You should see the messages sent from the browser to the server appear in the logs below, ending with "Success, resolved" if it all worked. diff --git a/examples/browser-ipns-publish/index.html b/examples/browser-ipns-publish/index.html index 74e52fd1e6..ce7c5c9187 100644 --- a/examples/browser-ipns-publish/index.html +++ b/examples/browser-ipns-publish/index.html @@ -41,7 +41,7 @@

    The idea is to publish from js-ipfs so you control your own private keys, but publish to go-ipfs to benefit from the DHT. - Since the DHT in js-ipfs isn't working yet, we need to use PubSub + Since the DHT in js-ipfs is still in the experimental phase, we need to use PubSub and have a go-ipfs node subscribed to that PubSub to get our IPNS record onto the DHT. In order to use PubSub between these two nodes, you'll need a websocket to connect them. diff --git a/examples/browser-ipns-publish/index.js b/examples/browser-ipns-publish/index.js index 5040105a3e..c9db076017 100644 --- a/examples/browser-ipns-publish/index.js +++ b/examples/browser-ipns-publish/index.js @@ -134,21 +134,6 @@ async function main() { tLog(msg.data.toString("hex")); } } - }, - { - onError: (err, fatal) => { - if (fatal) { - console.error(err); - tLog(`${err.message}`); - tLog(`Resubscribing in 5s to ${topic}...`); - setTimeout( - catchAndLog(() => subs(node, topic, tLog), tLog), - 5000 - ); - } else { - console.warn(err); - } - }, } ); } diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index 0f14202a14..5228598022 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -14,8 +14,8 @@ "dependencies": { "base64url": "^3.0.1", "human-crypto-keys": "^0.1.4", - "ipfs": "file:../../packages/ipfs/", - "ipfs-http-client": "file:../../packages/ipfs-http-client/", + "ipfs": "^0.48.0", + "ipfs-http-client": "^45.0.0", "ipfs-utils": "^2.3.1", "ipns": "^0.7.3", "it-last": "^1.0.2", @@ -31,7 +31,7 @@ "go-ipfs": "^0.6.0", "parcel-bundler": "^1.12.4", "path": "^0.12.7", - "test-ipfs-example": "file:../test-ipfs-example/" + "test-ipfs-example": "^2.0.3" }, "repository": { "type": "git", diff --git a/examples/browser-ipns-publish/test.js b/examples/browser-ipns-publish/test.js index 918e40cb3b..ce7ddf9dbb 100644 --- a/examples/browser-ipns-publish/test.js +++ b/examples/browser-ipns-publish/test.js @@ -6,8 +6,11 @@ const { createFactory } = require("ipfsd-ctl"); const df = createFactory({ ipfsHttpModule: require("ipfs-http-client"), ipfsBin: require("go-ipfs").path(), - args: ["--enable-pubsub-experiment"], - disposable: true, + args: [ + "--enable-pubsub-experiment", + '--enable-namesys-pubsub' + ], + test: true }); const { startServer } = require("test-ipfs-example/utils"); const pkg = require("./package.json"); @@ -43,12 +46,13 @@ async function testUI(url, apiAddr, peerAddr, topic) { async function runTest() { const app = await startServer(__dirname); const go = await df.spawn({ - type: "go", - test: true, ipfsOptions: { config: { Addresses: { API: "/ip4/127.0.0.1/tcp/0", + Swarm: [ + "/ip4/127.0.0.1/tcp/0/ws" + ] }, API: { HTTPHeaders: { @@ -59,26 +63,27 @@ async function runTest() { }, }); - const go2 = await df.spawn({ - type: "go", - test: true, - }); - + const go2 = await df.spawn(); await go.api.swarm.connect(go2.api.peerId.addresses[0]); - const topic = `/ipfs/QmWCnkCXYYPP7NgH6ZHQiQxw7LJAMjnAySdoz9i1oxD5XJ`; + const { cid } = await go.api.add(`Some data ${Date.now()}`) + const topic = `/ipfs/${cid}`; + + const peerAddr = go.api.peerId.addresses + .map(addr => addr.toString()) + .filter(addr => addr.includes("/ws/p2p/")) + .pop() try { await testUI( app.url, go.apiAddr, - go.api.peerId.addresses[0].toString(), + peerAddr, topic ); } finally { - await go.stop(); - await go2.stop(); await app.stop(); + await df.clean(); } } @@ -94,12 +99,6 @@ module.exports[pkg.name] = function (browser) { .clearValue(apiSelector) .setValue(apiSelector, process.env.IPFS_API_ADDRESS) .pause(1000) - .perform(() => { - console.log( - "process.env.IPFS_API_ADDRESS: ", - process.env.IPFS_API_ADDRESS - ); - }) .click("#node-connect"); browser.expect @@ -130,6 +129,11 @@ module.exports[pkg.name] = function (browser) { .pause(1000) .click("#publish"); + browser.expect.element("#console").text.to.contain('Publish to IPNS'); + browser.expect.element("#console").text.to.contain('Initial Resolve'); + browser.expect.element("#console").text.to.contain('Published'); + browser.expect.element("#console").text.to.contain('Wait 5 seconds, then resolve..'); + browser.pause(5000) browser.expect.element("#console").text.to.contain(`IPNS Publish Success!`); browser.end(); From 91eec621929108e47efde2e396fc4bec859d61b4 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 2 Sep 2020 14:21:27 +0100 Subject: [PATCH 19/22] chore: remove waits, update deps --- examples/browser-ipns-publish/index.js | 14 ++------------ examples/browser-ipns-publish/package.json | 14 +++++++------- examples/browser-ipns-publish/test.js | 2 -- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/examples/browser-ipns-publish/index.js b/examples/browser-ipns-publish/index.js index c9db076017..7e916c5940 100644 --- a/examples/browser-ipns-publish/index.js +++ b/examples/browser-ipns-publish/index.js @@ -4,12 +4,11 @@ const IpfsHttpClient = require("ipfs-http-client"); const ipns = require("ipns"); const IPFS = require("ipfs"); const pRetry = require("p-retry"); -const base64url = require("base64url"); const last = require("it-last"); const cryptoKeys = require("human-crypto-keys"); // { getKeyPairFromSeed } +const uint8ArrayToString = require('uint8arrays/to-string') const { sleep, Logger, onEnterPress, catchAndLog } = require("./util"); -const { Date, Element } = require("ipfs-utils/src/globalthis"); async function main() { const apiUrlInput = document.getElementById("api-url"); @@ -188,14 +187,10 @@ async function main() { log(`Initial Resolve ${keys.id}`); // subscribes the server to our IPNS topic last(ipfsAPI.name.resolve(keys.id, { stream: false })); // save the pubsub topic to the server to make them listen - await sleep(1000); // give it a moment to save it - // set up the topic from ipns key let b58 = await IPFS.multihash.fromB58String(keys.id); const ipnsKeys = ipns.getIdKeys(b58); - const topic = `${namespace}${base64url.encode( - ipnsKeys.routingKey.toBuffer() - )}`; + const topic = `${namespace}${uint8ArrayToString(ipnsKeys.routingKey, 'base64url')}`; // subscribe and log on both nodes await subs(ipfsBrowser, topic, log); // browserLog @@ -205,8 +200,6 @@ async function main() { await waitForPeerToSubscribe(ipfsAPI, topic); // confirm topic is on THEIR list // API await waitForNotificationOfSubscription(ipfsBrowser, topic, serverNode.id); // confirm they are on OUR list - await sleep(2500); // give it a moment to save it - let remList = await ipfsAPI.pubsub.ls(); // API if (!remList.includes(topic)) sLog(`[Fail] !Pubsub.ls ${topic}`); @@ -225,9 +218,6 @@ async function main() { }); log(`Published ${results.name} to ${results.value}`); // - log(`Wait 5 seconds, then resolve...`); - await sleep(5000); - log(`Try resolve ${keys.id} on server through API`); let name = await last( diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index 5228598022..21d3cf0680 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -12,14 +12,14 @@ "author": "Doug Anderson", "license": "MIT", "dependencies": { - "base64url": "^3.0.1", "human-crypto-keys": "^0.1.4", - "ipfs": "^0.48.0", - "ipfs-http-client": "^45.0.0", - "ipfs-utils": "^2.3.1", - "ipns": "^0.7.3", + "ipfs": "^0.49.1", + "ipfs-http-client": "^46.0.1", + "ipfs-utils": "^3.0.0", + "ipns": "^0.8.0", "it-last": "^1.0.2", - "p-retry": "^4.2.0" + "p-retry": "^4.2.0", + "uint8arrays": "1.1.0" }, "browserslist": [ "last 2 versions and not dead and > 2%" @@ -27,7 +27,7 @@ "devDependencies": { "delay": "^4.3.0", "execa": "^4.0.0", - "ipfsd-ctl": "^5.0.0", + "ipfsd-ctl": "^7.0.0", "go-ipfs": "^0.6.0", "parcel-bundler": "^1.12.4", "path": "^0.12.7", diff --git a/examples/browser-ipns-publish/test.js b/examples/browser-ipns-publish/test.js index ce7ddf9dbb..2b6dece1ff 100644 --- a/examples/browser-ipns-publish/test.js +++ b/examples/browser-ipns-publish/test.js @@ -132,8 +132,6 @@ module.exports[pkg.name] = function (browser) { browser.expect.element("#console").text.to.contain('Publish to IPNS'); browser.expect.element("#console").text.to.contain('Initial Resolve'); browser.expect.element("#console").text.to.contain('Published'); - browser.expect.element("#console").text.to.contain('Wait 5 seconds, then resolve..'); - browser.pause(5000) browser.expect.element("#console").text.to.contain(`IPNS Publish Success!`); browser.end(); From b66e3a7350f21032e289b6b79a3204c0d5476495 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 2 Sep 2020 14:34:19 +0100 Subject: [PATCH 20/22] chore: revert lerna config changes --- lerna.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lerna.json b/lerna.json index f6cd362abb..eaac4e1e8d 100644 --- a/lerna.json +++ b/lerna.json @@ -1,8 +1,7 @@ { "lerna": "3.22.0", "packages": [ - "packages/*", - "examples/*" + "packages/*" ], "version": "independent", "command": { From 609f890490ba99d1872c1f9e46662fc13483ceb9 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 2 Sep 2020 14:52:33 +0100 Subject: [PATCH 21/22] chore: update dep version --- examples/browser-ipns-publish/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/browser-ipns-publish/package.json b/examples/browser-ipns-publish/package.json index 21d3cf0680..761bb9e81e 100644 --- a/examples/browser-ipns-publish/package.json +++ b/examples/browser-ipns-publish/package.json @@ -19,7 +19,7 @@ "ipns": "^0.8.0", "it-last": "^1.0.2", "p-retry": "^4.2.0", - "uint8arrays": "1.1.0" + "uint8arrays": "^1.1.0" }, "browserslist": [ "last 2 versions and not dead and > 2%" From 63099ac8804f120279c6ee07a082e07a3771fd0d Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 2 Sep 2020 15:15:09 +0100 Subject: [PATCH 22/22] chore: align versions --- examples/browser-browserify/package.json | 2 +- examples/browser-exchange-files/package.json | 2 +- examples/browser-mfs/package.json | 2 +- examples/browser-readablestream/package.json | 2 +- examples/browser-script-tag/package.json | 2 +- examples/browser-video-streaming/package.json | 2 +- packages/interface-ipfs-core/package.json | 2 +- packages/ipfs-http-client/package.json | 2 +- packages/ipfs/package.json | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/browser-browserify/package.json b/examples/browser-browserify/package.json index f886f49d3c..4f05bfb4a5 100644 --- a/examples/browser-browserify/package.json +++ b/examples/browser-browserify/package.json @@ -17,7 +17,7 @@ "browserify": "^16.2.3", "concat-stream": "^2.0.0", "execa": "^4.0.0", - "http-server": "^0.11.1", + "http-server": "^0.12.3", "ipfs": "^0.49.1", "test-ipfs-example": "^2.0.3" }, diff --git a/examples/browser-exchange-files/package.json b/examples/browser-exchange-files/package.json index 506ea0323c..1bfdf439de 100644 --- a/examples/browser-exchange-files/package.json +++ b/examples/browser-exchange-files/package.json @@ -13,7 +13,7 @@ "devDependencies": { "browserify": "^16.2.3", "execa": "^4.0.0", - "http-server": "^0.11.1", + "http-server": "^0.12.3", "ipfs-http-client": "^46.0.1", "uint8arrays": "^1.1.0" }, diff --git a/examples/browser-mfs/package.json b/examples/browser-mfs/package.json index 2435bf829b..e2f6c73c4b 100644 --- a/examples/browser-mfs/package.json +++ b/examples/browser-mfs/package.json @@ -14,7 +14,7 @@ "license": "ISC", "devDependencies": { "html-webpack-plugin": "^3.2.0", - "http-server": "^0.11.1", + "http-server": "^0.12.3", "terser-webpack-plugin": "^1.2.1", "test-ipfs-example": "^2.0.3", "webpack": "^4.43.0", diff --git a/examples/browser-readablestream/package.json b/examples/browser-readablestream/package.json index 6568cc4f23..2255250b0c 100644 --- a/examples/browser-readablestream/package.json +++ b/examples/browser-readablestream/package.json @@ -14,7 +14,7 @@ "license": "ISC", "devDependencies": { "html-webpack-plugin": "^3.2.0", - "http-server": "^0.11.1", + "http-server": "^0.12.3", "terser-webpack-plugin": "^1.2.1", "test-ipfs-example": "^2.0.3", "webpack": "^4.43.0" diff --git a/examples/browser-script-tag/package.json b/examples/browser-script-tag/package.json index 28b65626c5..86d945819e 100644 --- a/examples/browser-script-tag/package.json +++ b/examples/browser-script-tag/package.json @@ -12,7 +12,7 @@ "keywords": [], "license": "MIT", "devDependencies": { - "http-server": "^0.11.1", + "http-server": "^0.12.3", "test-ipfs-example": "^2.0.3" }, "dependencies": { diff --git a/examples/browser-video-streaming/package.json b/examples/browser-video-streaming/package.json index dd9e675d15..7cb4f48a24 100644 --- a/examples/browser-video-streaming/package.json +++ b/examples/browser-video-streaming/package.json @@ -12,7 +12,7 @@ "keywords": [], "license": "MIT", "devDependencies": { - "http-server": "^0.11.1", + "http-server": "^0.12.3", "test-ipfs-example": "^2.0.3" }, "dependencies": { diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 93dde85de4..b4a91ddd3a 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -48,7 +48,7 @@ "iso-random-stream": "^1.1.1", "it-all": "^1.0.1", "it-drain": "^1.0.1", - "it-last": "^1.0.1", + "it-last": "^1.0.2", "it-map": "^1.0.2", "it-pushable": "^1.3.1", "libp2p-crypto": "^0.18.0", diff --git a/packages/ipfs-http-client/package.json b/packages/ipfs-http-client/package.json index 253edefe7f..06a29f0337 100644 --- a/packages/ipfs-http-client/package.json +++ b/packages/ipfs-http-client/package.json @@ -53,7 +53,7 @@ "ipld-dag-pb": "^0.20.0", "ipld-raw": "^6.0.0", "iso-url": "^0.4.7", - "it-last": "^1.0.1", + "it-last": "^1.0.2", "it-map": "^1.0.2", "it-tar": "^1.2.2", "it-to-buffer": "^1.0.0", diff --git a/packages/ipfs/package.json b/packages/ipfs/package.json index 4a01ed800e..e5d7c2a811 100644 --- a/packages/ipfs/package.json +++ b/packages/ipfs/package.json @@ -118,7 +118,7 @@ "it-drain": "^1.0.1", "it-first": "^1.0.1", "it-glob": "0.0.8", - "it-last": "^1.0.1", + "it-last": "^1.0.2", "it-map": "^1.0.2", "it-multipart": "^1.0.1", "it-pipe": "^1.1.0",