Skip to content

Commit 5e2273b

Browse files
Merge pull request #88 from ProtoSchool/cids-everywhere
fix: updating to new CID API in latest js-ipfs, fixes #79
2 parents 9c5b048 + 2d1354b commit 5e2273b

28 files changed

+5011
-6791
lines changed

package-lock.json

Lines changed: 4852 additions & 6593 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
},
1010
"dependencies": {
1111
"async": "^2.6.1",
12-
"cids": "^0.5.3",
12+
"cids": "^0.5.6",
1313
"highlight.js": "^9.12.0",
14-
"ipfs": "^0.31.0",
14+
"ipfs": "^0.33.1",
1515
"ipfs-css": "^0.6.0",
1616
"marked": "^0.4.0",
1717
"monaco-editor": "^0.6.1",

src/components/Lesson.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ const defaultCode = `/* globals ipfs */
154154
155155
const run = async () => {
156156
// your code goes here!
157-
// example: ipfs.dag.put({hello: 'world'})
157+
// be sure this function returns the requested value
158158
}
159159
160160
return run
@@ -206,7 +206,7 @@ export default {
206206
let basePath = this.$route.path.slice(0, -2)
207207
let number = this.$route.path.slice(-2)
208208
while (this.$router.resolve(basePath + number).route.name !== '404') {
209-
number ++
209+
number++
210210
number = number.toString().padStart(2, '0')
211211
}
212212
return parseInt(number) - 1

src/lessons/Basics/01-concepts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
**CID** - Content Identifier. An unique address for a block of data in IPFS that is derived from it's content.
1+
**CID** - Content Identifier. An unique address for a block of data in IPFS that is derived from its content.

src/lessons/Basics/01-exercise.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
Use `ipfs.dag.put` to create a node for the data `{test: 1}`.
2-
3-
This method will return a CID (Content Identifier), which you should in turn return from your `run()` function.
1+
Use `ipfs.dag.put` to create a node for the data `{test: 1}`. Return the CID of your new node.

src/lessons/Basics/01.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,20 @@
1-
You can create nodes using the `ipfs.dag.put` API.
1+
In this workshop we'll be exploring the IPFS DAG API, which lets us store data
2+
objects in IPFS. (You can store more exciting things in IPFS, like your favorite
3+
cat GIF, but you'd need to use a different API for that.)
4+
5+
You can create a new node by passing a data object into the `ipfs.dag.put` method,
6+
which returns a Content Identifier (CID) for the newly created node.
7+
8+
```javascript
9+
ipfs.dag.put({hello: 'world'})
10+
```
11+
12+
A CID is an address for a block of data in IPFS that is derived from its content. Every
13+
time someone puts the same `{hello: 'world'}` data into IPFS, they'll get back an
14+
identical CID to the one you got. If they put in `{hell0: 'w0rld'}` instead, the
15+
CID will be different.
16+
17+
_Note: Throughout our lessons we'll be using a code editor like the one below.
18+
Enter your solution code within the `run` function that's pre-populated for you,
19+
being sure to return the requested value within that function. (You won't need to
20+
update the `return run` line at the end; that's just there to make the code editor work.)_

src/lessons/Basics/02-concepts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
**CID** - Content Identifier. An unique address for a block of data in IPFS that is derived from it's content.
1+
**CID** - Content Identifier. An unique address for a block of data in IPFS that is derived from its content.
22

33
**DAG** - Directed Acyclic Graph. Blocks in IPFS form a graph as they can point to other blocks by their CID. These links can only point one direction (directed) and across the whole graph there are no loops or cycles (acyclic).

src/lessons/Basics/02-exercise.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
Create a link named `bar` that points to the node we created in the first the lesson. Put it into IPFS and return its CID.
1+
Create a named link called `bar` that points to the node we created in the first the lesson. Put it into IPFS and return its CID.
22

33
The editor is pre-populated with the code to create the node we're linking to.

src/lessons/Basics/02.md

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1-
One important feature of DAGs is the ability to link them together.
1+
One important feature of Directed Acyclic Graphs (DAGs) is the ability to link them together.
22

3-
The way you express links in the `ipfs` DAG store is with an object with a
4-
single `'/'` attribute pointed at the `CID` of another node.
3+
The way you express links in the `ipfs` DAG store is with the `CID` of
4+
another node.
55

66
For example, if we wanted one node to have a link called "foo" pointed
7-
to another CID, it might look like:
7+
to another CID instance previously saved as `barCid`, it might look like:
88

99
```javascript
1010
{
11-
foo: {'/': 'z43AaGEvwdfzjrCZ3Sq7DKxdDHrwoaPQDtqF4jfdkNEVTiqGVFW'}
12-
}
13-
```
14-
15-
In `js-ipfs` we tend to work with instances of `CID` from the `cids` module.
16-
Links need to be expressed with a base encoded string, so to create the
17-
structure above you might use:
18-
19-
```javascript
20-
{
21-
foo: {'/': cid.toBaseEncodedString()}
11+
foo: barCid
2212
}
2313
```
14+
When we give a field a name and make its value a link to a CID, we call this a named link.

src/lessons/Basics/02.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const validate = async (result, ipfs) => {
3838
return {success: 'Everything works!'}
3939
} else {
4040
let obj = await ipfs.dag.get(result)
41-
let expected = JSON.stringify({bar: {'/': hash}})
41+
let expected = JSON.stringify({bar: new CID(hash)})
4242
let got = JSON.stringify(obj.value)
4343
let fail = `Was expecting "${expected}" but got "${got}"`
4444
return {fail}

src/lessons/Basics/03.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ console.log(await ipfs.dag.get(cid, '/my/deep/obj'))
1313
/* prints {value: 'is cool', remainderPath: ''} */
1414
```
1515

16-
`ipfs.dag.get()` allows queries using IPFS paths.
16+
`ipfs.dag.get` allows queries using IPFS paths.
1717
These queries return an object containing the value of the query and any remaining path that was unresolved.
1818

1919
The cool thing about this API is that it can also traverse through links.
@@ -22,7 +22,7 @@ The cool thing about this API is that it can also traverse through links.
2222
let cid = await ipfs.dag.put({foo: 'bar'})
2323
let cid2 = await ipfs.dag.put({
2424
my: {
25-
other: {'/': cid.toBaseEncodedString()}
25+
other: cid
2626
}
2727
})
2828

src/lessons/Basics/03.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ let code = `/* globals ipfs */
1818
1919
const run = async () => {
2020
let cid = await ipfs.dag.put({test: 1})
21-
let cid2 = await ipfs.dag.put(
22-
{bar: {'/': cid.toBaseEncodedString()}}
23-
)
21+
let cid2 = await ipfs.dag.put({bar: cid})
2422
/* your code goes here */
2523
}
2624

src/lessons/Blog/01-exercise.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Modify the two existing blog posts and add a new field `author` that links to the author of the blog post. The post about trees was authored by Sam, while Nat wrote the post about computers. Remember to use `toBaseEncodedString()` to make the CID links.
1+
Modify the two existing blog posts by adding a new field `author` that links to the author of each post. The post about trees was authored by Sam, while Nat wrote the post about computers.

src/lessons/Blog/01.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
This exercise has some prepared code to get started faster. It resembles a blog. There are authors (Nat and Sam) and some blog posts about trees and computers. At the moment there’s no relation between them. Let’s update the blog posts so that they link to the author.
2-
3-
In the [basic lessons](#/basics/02), we learned that a link in IPFS is represented as an object with a slash as its only field:
1+
In the [Basics workshop](#/basics/02), we learned that a link in IPFS is represented as an instance of `CID`:
42

53
```javascript
6-
const link = {'/': 'a-base-encoded-cid'}
4+
{
5+
linkToAwesomeNode: awesomeCid
6+
}
77
```
8+
When we give a field a name and make its value a link to a CID, we call this a named link.
9+
10+
The exercise below has some prepared code to get us started. The data structure resembles a blog which has two authors, Nat and Sam, and some blog posts about trees and computers. At the moment there’s no relation between them. Let’s update the blog posts so that they link to the author.

src/lessons/Blog/01.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ const run = async () => {
4242
const samCid = await ipfs.dag.put({author: "Sam"})
4343
const treePostCid = await ipfs.dag.put({
4444
content: "trees",
45-
author: {"/": samCid.toBaseEncodedString()}
45+
author: samCid
4646
})
4747
const computerPostCid = await ipfs.dag.put({
4848
content: "computers",
49-
author: {"/": natCid.toBaseEncodedString()}
49+
author: natCid
5050
})
5151
5252
return [treePostCid, computerPostCid]
@@ -71,11 +71,11 @@ const validate = async (result, ipfs) => {
7171
if (node.author === undefined) {
7272
return {fail: 'Blog posts need to have an `author` field.'}
7373
}
74-
if (node.author['/'] === undefined) {
74+
if (!CID.isCID(node.author)) {
7575
return {fail: 'The value of `author` needs to be a link (`{"/": "some-cid"}`).'}
7676
}
77-
const nodeAuthor = new CID(node.author['/']).toBaseEncodedString()
78-
if (![natCid, samCid].includes(nodeAuthor)) {
77+
const nodeAuthor = node.author
78+
if (![natCid, samCid].includes(nodeAuthor.toBaseEncodedString())) {
7979
return {fail: 'You need to link to the CID of an author (Nat or Sam).'}
8080
}
8181
let expectedAuthor
@@ -87,7 +87,7 @@ const validate = async (result, ipfs) => {
8787
expectedAuthor = natCid
8888
break
8989
}
90-
if (nodeAuthor !== expectedAuthor) {
90+
if (nodeAuthor.toBaseEncodedString() !== expectedAuthor) {
9191
return {fail: `The author of the "${node.content}" blog post (${nodeAuthor}) did not match the the expected author (${expectedAuthor}).`}
9292
}
9393
}

src/lessons/Blog/02.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Everything that is stored in IPFS has an associated CID. That CID is constructed by hashing the data itself. If the same hash and encoding is used, then the same data will result in the same CID. This means that as soon as you edit data and store it, it will have a new CID. The old data won’t be overridden; it’s still there.
1+
Everything that is stored in IPFS has an associated CID. That CID is constructed by hashing the data itself. If the same hash and encoding is used, then the same data will result in the same CID. However, as soon as you edit data and store it again, it will have a new CID. The old data won’t be overridden; it’s still stored there with its old CID.
22

3-
Before modifying the code, please open the developer tools in your browser and submit the code. You’ll see the CIDs of the blog posts in the console. When you look at the console again after you’ve modified the code, you’ll see the CIDs have changed.
3+
Our blog doesn't have any tags yet. Let’s modify the posts again to add some tags, watching how the CID for each post changes as we change its contents.
44

5-
Another common thing in blogs is tagging. Let’s modify the blog posts again and add some tags.
5+
Before modifying the code, please open the developer tools in your browser and submit the code in its current state. You’ll see the CIDs of the blog posts in the console. When you look at the console again after you’ve modified the code, you’ll see that the CIDs have changed. (Notice how we use `CID.toBaseEncodedString()` to access the CID as a string for purposes of console logging.)

src/lessons/Blog/02.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ const run = async () => {
2525
2626
const treePostCid = await ipfs.dag.put({
2727
content: "trees",
28-
author: {"/": samCid.toBaseEncodedString()}
28+
author: samCid
2929
})
3030
const computerPostCid = await ipfs.dag.put({
3131
content: "computers",
32-
author: {"/": natCid.toBaseEncodedString()}
32+
author: natCid
3333
})
3434
3535
console.log('post about trees:', treePostCid.toBaseEncodedString())
@@ -49,12 +49,12 @@ const run = async () => {
4949
const samCid = await ipfs.dag.put({author: "Sam"})
5050
const treePostCid = await ipfs.dag.put({
5151
content: "trees",
52-
author: {"/": samCid.toBaseEncodedString()},
52+
author: samCid,
5353
tags: ["outdoor", "hobby"]
5454
})
5555
const computerPostCid = await ipfs.dag.put({
5656
content: "computers",
57-
author: {"/": natCid.toBaseEncodedString()},
57+
author: natCid,
5858
tags: ["hobby"]
5959
})
6060
@@ -100,7 +100,7 @@ const validate = async (result, ipfs) => {
100100
}
101101
// Don't check the CIDs as then the order of the tags would matter.
102102
// But that order really doesn't matter.
103-
return {success: 'Everything works!'}
103+
return {success: 'Everything works! Did you remember to check the console logs?'}
104104
}
105105
106106
export default {

src/lessons/Blog/03-exercise.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Insert those new tag objects into IPFS via `ipfs.dag.put()` and return the two resulting CIDs as an array.
1+
Create new nodes for the tags "outdoor" and "hobby" in the format shown above, linking to the relevant blog posts using arrays. Insert the new tag objects into IPFS via `ipfs.dag.put()` and return the two resulting CIDs as an array.

src/lessons/Blog/03.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
1-
A single object can have many links to other nodes. To illustrate this, we are creating new nodes which could be used for a tag cloud.
1+
A single object can have many links to other nodes. To illustrate this, let's create new nodes which could be used for a tag cloud.
22

3-
Links don’t necessarily need to be the value of a field (we call those “named links”); they can also be in an array.
3+
Until now, we've been using named links, meaning that we create a named field with a single link as its value, such as:
4+
5+
```javascript
6+
{
7+
author: samCid
8+
}
9+
```
10+
However, we can also choose to gather links into an array without naming each one individually.
411

512
```javascript
613
{ links: [
7-
{'/': 'a-base-encoded-cid'},
8-
{'/': 'another-base-encoded-cid'}
14+
natCid,
15+
samCid
916
]
1017
}
1118
```
1219

13-
This is perfect for our use case. Create a new node for the tags “outdoor” and “hobby.” The structure should look like this:
20+
This is perfect for our use case, where a single tag should be associated with many posts, like so:
1421

15-
```javavscript
22+
```javascript
1623
{
1724
tag: "name-of-the-tag",
1825
posts: [
@@ -21,4 +28,4 @@ This is perfect for our use case. Create a new node for the tags “outdoor” a
2128
}
2229
```
2330

24-
Please note that arrays are order-dependent. This means that two arrays with the same links in a different order will get a different CID.
31+
Please note that arrays are order-dependent. This means that two arrays with the same links in a different order will get different CIDs.

src/lessons/Blog/03.vue

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ const run = async () => {
2323
const samCid = await ipfs.dag.put({author: "Sam"})
2424
const treePostCid = await ipfs.dag.put({
2525
content: "trees",
26-
author: {"/": samCid.toBaseEncodedString()},
26+
author: samCid,
2727
tags: ["outdoor", "hobby"]
2828
})
2929
const computerPostCid = await ipfs.dag.put({
3030
content: "computers",
31-
author: {"/": natCid.toBaseEncodedString()},
31+
author: natCid,
3232
tags: ["hobby"]
3333
})
3434
@@ -46,26 +46,26 @@ const run = async () => {
4646
const samCid = await ipfs.dag.put({author: "Sam"})
4747
const treePostCid = await ipfs.dag.put({
4848
content: "trees",
49-
author: {"/": samCid.toBaseEncodedString()},
49+
author: samCid,
5050
tags: ["outdoor", "hobby"]
5151
})
5252
const computerPostCid = await ipfs.dag.put({
5353
content: "computers",
54-
author: {"/": natCid.toBaseEncodedString()},
54+
author: natCid,
5555
tags: ["hobby"]
5656
})
5757
5858
const outdoorTagCid = await ipfs.dag.put({
5959
tag: "outdoor",
6060
posts: [
61-
{"/": treePostCid.toBaseEncodedString()}
61+
treePostCid
6262
]
6363
})
6464
const hobbyTagCid = await ipfs.dag.put({
6565
tag: "hobby",
6666
posts: [
67-
{"/": treePostCid.toBaseEncodedString()},
68-
{"/": computerPostCid.toBaseEncodedString()}
67+
treePostCid,
68+
computerPostCid
6969
]
7070
})
7171
@@ -98,7 +98,7 @@ const validate = async (result, ipfs) => {
9898
if (!Array.isArray(node.posts)) {
9999
return {fail: 'The value of the `posts` field must be an array of links.'}
100100
}
101-
const isLinks = node.posts.every((post) => '/' in post)
101+
const isLinks = node.posts.every((post) => CID.isCID(post))
102102
if (!isLinks) {
103103
return {fail: 'The values of the `posts` array must be links.'}
104104
}
@@ -116,7 +116,7 @@ const validate = async (result, ipfs) => {
116116
default:
117117
return {fail: `Wrong tag (${node.tag}). Did you mean "hobby" or "outdoor"?`}
118118
}
119-
const nodePosts = node.posts.map((post) => new CID(post['/']).toBaseEncodedString())
119+
const nodePosts = node.posts.map(post => post.toBaseEncodedString())
120120
if (!shallowEqualArrays(nodePosts.sort(), expectedPosts.sort())) {
121121
return {fail: `The posts of the tag "${node.tag}" ${utils.stringify(nodePosts)} did not match the the expected posts ${utils.stringify(expectedPosts)}.`}
122122
}

0 commit comments

Comments
 (0)