Skip to content

Commit 0dbacc3

Browse files
committed
chore: graph migration
1 parent 6e19e33 commit 0dbacc3

File tree

1 file changed

+41
-127
lines changed

1 file changed

+41
-127
lines changed

developer/light-curate.md

Lines changed: 41 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -32,139 +32,53 @@ Since we use `@graphprotocol/graph-ts` we must submit items to its ipfs endpoint
3232
Full example [here](https://github.com/kleros/gtcr/blob/5e313ced24f5e3fc3a54f812e07fb1f86a6b2621/src/utils/ipfs-publish.js)
3333

3434
```text
35-
REACT_APP_IPFS_GATEWAY=https://ipfs.kleros.io
35+
REACT_APP_IPFS_GATEWAY=https://cdn.kleros.link
3636
REACT_APP_HOSTED_GRAPH_IPFS_ENDPOINT=https://api.thegraph.com/ipfs
3737
```
3838

3939
#### Upload and Transaction
4040

41-
```text
42-
// ipfs-publish.js
43-
44-
import deepEqual from 'fast-deep-equal/es6'
45-
46-
const mirroredExtensions = ['.json']
47-
48-
/**
49-
* Send file to IPFS network.
50-
* @param {string} fileName - The name that will be used to store the file. This is useful to preserve extension type.
51-
* @param {ArrayBuffer} data - The raw data from the file to upload.
52-
* @returns {object} ipfs response. Should include the hash and path of the stored item.
53-
*/
54-
export default async function ipfsPublish(fileName, data) {
55-
if (!mirroredExtensions.some(ext => fileName.endsWith(ext)))
56-
return publishToKlerosNode(fileName, data)
57-
58-
const [klerosResult, theGraphResult] = await Promise.all([
59-
publishToKlerosNode(fileName, data),
60-
publishToTheGraphNode(fileName, data),
61-
// Pin to your own ipfs node here as well.
62-
])
63-
64-
if (!deepEqual(klerosResult, theGraphResult)) {
65-
console.warn('IPFS upload result is different:', {
66-
kleros: klerosResult,
67-
theGraph: theGraphResult
68-
})
69-
throw new Error('IPFS upload result is different.')
70-
}
71-
72-
return klerosResult
73-
}
41+
```typescript
42+
const pinFiles = async (
43+
data: FormData,
44+
pinToGraph: boolean
45+
): Promise<
46+
[Array<string>, Array<{ filebaseCid: string; graphCid: string }>]
47+
> => {
48+
const cids = new Array<string>();
49+
// keep track in case some cids are inconsistent
50+
const inconsistentCids = new Array<{
51+
filebaseCid: string;
52+
graphCid: string;
53+
}>();
54+
55+
for (const [_, dataElement] of Object.entries(data)) {
56+
if (dataElement.isFile) {
57+
const { filename, mimeType, content } = dataElement;
58+
const path = `${filename}`;
59+
const cid = await filebase.storeDirectory([
60+
new File([content], path, { type: mimeType }),
61+
]);
62+
63+
if (pinToGraph) {
64+
const graphResult = await publishToGraph(filename, content);
65+
if (!areCidsConsistent(cid, graphResult)) {
66+
console.warn("Inconsistent cids from Filebase and Graph Node :", {
67+
filebaseCid: cid,
68+
graphCid: graphResult[1].hash,
69+
});
70+
inconsistentCids.push({
71+
filebaseCid: cid,
72+
graphCid: graphResult[1].hash,
73+
});
74+
}
75+
}
7476

75-
/**
76-
* Send file to IPFS network via the Kleros IPFS node
77-
* @param {string} fileName - The name that will be used to store the file. This is useful to preserve extension type.
78-
* @param {ArrayBuffer} data - The raw data from the file to upload.
79-
* @returns {object} ipfs response. Should include the hash and path of the stored item.
80-
*/
81-
async function publishToKlerosNode(fileName, data) {
82-
const buffer = await Buffer.from(data)
83-
const url = `${process.env.REACT_APP_IPFS_GATEWAY}/add`
84-
85-
const response = await fetch(url, {
86-
method: 'POST',
87-
body: JSON.stringify({
88-
fileName,
89-
buffer
90-
}),
91-
headers: {
92-
'content-type': 'application/json'
77+
cids.push(`/ipfs/${cid}/${path}`);
9378
}
94-
})
95-
96-
const body = await response.json()
97-
98-
return body.data
99-
}
100-
101-
/**
102-
* Send file to IPFS network via The Graph hosted IPFS node
103-
* @param {string} fileName - The name that will be used to store the file. This is useful to preserve extension type.
104-
* @param {ArrayBuffer} data - The raw data from the file to upload.
105-
* @returns {object} ipfs response. Should include the hash and path of the stored item.
106-
*/
107-
async function publishToTheGraphNode(fileName, data) {
108-
const url = `${process.env.REACT_APP_HOSTED_GRAPH_IPFS_ENDPOINT}/api/v0/add?wrap-with-directory=true`
109-
110-
const payload = new FormData()
111-
payload.append('file', new Blob([data]), fileName)
112-
113-
const response = await fetch(url, {
114-
method: 'POST',
115-
body: payload
116-
})
117-
118-
const result = await jsonStreamToPromise(response.body)
119-
120-
return result.map(({ Name, Hash }) => ({
121-
hash: Hash,
122-
path: `/${Name}`
123-
}))
124-
}
125-
126-
/**
127-
* Accumulates a JSON stream body into an array of JSON objects.
128-
* @param {ReadableStream} stream The stream to read from.
129-
* @returns {Promise<any>} An array of all JSON objects emitted by the stream.
130-
*/
131-
async function jsonStreamToPromise(stream) {
132-
const reader = stream.getReader()
133-
const decoder = new TextDecoder('utf-8')
134-
135-
const deferred = {
136-
resolve: undefined,
137-
reject: undefined
138-
}
139-
140-
const result = new Promise((resolve, reject) => {
141-
deferred.resolve = resolve
142-
deferred.reject = reject
143-
})
144-
145-
const acc = []
146-
const start = async () => {
147-
reader
148-
.read()
149-
.then(({ done, value }) => {
150-
if (done) return deferred.resolve(acc)
151-
152-
// Each `read` can produce one or more lines...
153-
const lines = decoder.decode(value).split(/\n/)
154-
const objects = lines
155-
.filter(line => line.trim() !== '')
156-
.map(line => JSON.parse(line))
157-
acc.push(...objects)
158-
159-
return start()
160-
})
161-
.catch(err => deferred.reject(err))
16279
}
163-
164-
start()
165-
166-
return result
167-
}
80+
return [cids, inconsistentCids];
81+
};
16882
```
16983

17084
The JSON file for the object is composed of the its metadata and fields.
@@ -258,7 +172,7 @@ See [this react example](https://github.com/kleros/gtcr/blob/5e313ced24f5e3fc3a5
258172

259173
A standard query for the first page of a given list, ordered by the most recent requests, looks like this.
260174

261-
```javascript
175+
```typescript
262176
const ITEMS_PER_PAGE = 40
263177
const orderDirection = 'asc'
264178
const page = 1
@@ -314,7 +228,7 @@ const query = {
314228

315229
If you want, you can also use apollo to cache queries and make the app load faster.
316230

317-
```text
231+
```typescript
318232
const ITEM_DETAILS_QUERY = gql`
319233
query itemDetailsQuery($id: String!) {
320234
item(id: $id) {

0 commit comments

Comments
 (0)