mirror of
https://github.com/tlsnotary/explorer.git
synced 2026-01-09 06:48:09 -05:00
feat: replace Helia with Pinata (#9)
* wip: testing pinata * fix: replace helia with pinata.cloud * chore: update gitignore * feat: replace ipfs with pinata
This commit is contained in:
4
.env.sample
Normal file
4
.env.sample
Normal file
@@ -0,0 +1,4 @@
|
||||
PINATA_API_SECRET=""
|
||||
PINATA_API_KEY=""
|
||||
PINATA_GATEWAY=""
|
||||
PINATA_GATEWAY_KEY=""
|
||||
17429
package-lock.json
generated
17429
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -27,14 +27,15 @@
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||
"@helia/unixfs": "^3.0.0",
|
||||
"@pinata/sdk": "^2.1.0",
|
||||
"@types/node-forge": "^1.3.11",
|
||||
"buffer": "^6.0.3",
|
||||
"charwise": "^3.0.1",
|
||||
"classnames": "^2.3.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.18.2",
|
||||
"express-fileupload": "^1.4.3",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"helia": "^4.0.1",
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"multiformats": "^13.1.0",
|
||||
"node-forge": "^1.3.1",
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
TLSN Explorer is server that will handle the social discovery and visualization of proofs generated from the TLS Notary protocol.
|
||||
|
||||
## Set up .env
|
||||
1. `cp .env.sample .env`
|
||||
2. Create an API key in [Pinata.cloud](https://docs.pinata.cloud/quickstart/node-js#generate-your-api-keys)
|
||||
3. Create a new Gateway in [Pinata.cloud](https://app.pinata.cloud/gateway)
|
||||
4. Create a new Gateway access token in [Pinata.cloud](https://app.pinata.cloud/developers/gateway-settings)
|
||||
5. Update your `.env` file
|
||||
|
||||
## Development
|
||||
```bash
|
||||
npm i
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dotenv/config';
|
||||
import express from 'express';
|
||||
import fileUpload from 'express-fileupload';
|
||||
import stream from 'stream';
|
||||
@@ -26,23 +27,22 @@ app.use(fileUpload({
|
||||
limits: { fileSize: 1024 * 1024 }, // 1mb file limit
|
||||
}));
|
||||
|
||||
|
||||
|
||||
app.post('/upload', async (req, res) => {
|
||||
app.post('/api/upload', async (req, res) => {
|
||||
for (const file of Object.values(req.files!)) {
|
||||
// @ts-ignore
|
||||
const data = file.data;
|
||||
const cid = await addBytes(data);
|
||||
res.send(JSON.stringify(cid.toString()));
|
||||
res.json(cid);
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(400).send({ error: true, message: 'request is missing file' });
|
||||
});
|
||||
|
||||
app.get('/ipfs/:cid', async (req, res) => {
|
||||
app.get('/gateway/ipfs/:cid', async (req, res) => {
|
||||
const cid = req.params.cid;
|
||||
const file = await getCID(req.params.cid);
|
||||
console.log(file);
|
||||
const readStream = new stream.PassThrough();
|
||||
readStream.end(Buffer.from(file));
|
||||
res.set('Content-Type', 'application/octet-stream');
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
import { createHelia, HeliaLibp2p } from 'helia';
|
||||
import { unixfs } from '@helia/unixfs';
|
||||
import { CID } from 'multiformats/cid'
|
||||
import pinataSDK from '@pinata/sdk';
|
||||
import { Readable } from 'stream';
|
||||
const PINATA_API_KEY = process.env.PINATA_API_KEY;
|
||||
const PINATA_API_SECRET = process.env.PINATA_API_SECRET;
|
||||
const pinata = new pinataSDK(PINATA_API_KEY, PINATA_API_SECRET);
|
||||
|
||||
|
||||
let node: HeliaLibp2p | null = null;
|
||||
export async function addBytes(file: Buffer) {
|
||||
const res = await pinata.pinFileToIPFS(Readable.from(file), {
|
||||
pinataMetadata: {
|
||||
name: 'proof.json',
|
||||
},
|
||||
pinataOptions: {
|
||||
cidVersion: 1
|
||||
}
|
||||
});
|
||||
|
||||
export async function getIPFS() {
|
||||
if (!node)
|
||||
node = await createHelia();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export async function addBytes(buf: Buffer) {
|
||||
const ipfs = await getIPFS();
|
||||
const fs = unixfs(ipfs);
|
||||
const cid = await fs.addBytes(buf);
|
||||
return cid;
|
||||
if (res.IpfsHash) return res.IpfsHash;
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function getCID(hash: string) {
|
||||
const ipfs = await getIPFS();
|
||||
const cid = CID.parse(hash);
|
||||
const file = await ipfs.blockstore.get(cid);
|
||||
return file;
|
||||
console.log(process.env.PINATA_GATEWAY + '/' + hash);
|
||||
const res = await fetch(process.env.PINATA_GATEWAY + '/ipfs/' + hash, {
|
||||
headers: {
|
||||
'x-pinata-gateway-token': process.env.PINATA_GATEWAY_KEY!,
|
||||
}
|
||||
});
|
||||
|
||||
return res.text();
|
||||
}
|
||||
@@ -60,7 +60,9 @@ const ProofDetails: React.FC<ProofDetailsProps> = ({proof, cid, file}): ReactEle
|
||||
};
|
||||
|
||||
const proofToDisplay = selectedProof?.proof || proof;
|
||||
const inputValue = process.env.NODE_ENV === "development" ? `http://localhost:3000/${selectedProof?.ipfsCID ? selectedProof?.ipfsCID : cid}` : `www.tlsnexplorer.com/${selectedProof?.ipfsCID ? selectedProof?.ipfsCID : cid}`;
|
||||
const inputValue = process.env.NODE_ENV === "development"
|
||||
? `http://localhost:3000/${selectedProof?.ipfsCID ? selectedProof?.ipfsCID : cid}`
|
||||
: `www.tlsnexplorer.com/${selectedProof?.ipfsCID ? selectedProof?.ipfsCID : cid}`;
|
||||
|
||||
// TODO - Format proof details for redacted data
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function SharedProof(): ReactElement {
|
||||
setErrors('No CID provided');
|
||||
return;
|
||||
}
|
||||
const response = await fetch(`/ipfs/${cid}`);
|
||||
const response = await fetch(`/gateway/ipfs/${cid}`);
|
||||
if (!response.ok) {
|
||||
setErrors('Failed to fetch file from IPFS');
|
||||
throw new Error('Failed to fetch file from IPFS');
|
||||
@@ -28,6 +28,7 @@ export default function SharedProof(): ReactElement {
|
||||
const data = await response.json();
|
||||
try {
|
||||
const proof = await verify(data, notaryKey);
|
||||
console.log(data);
|
||||
setVerifiedProof(proof);
|
||||
|
||||
} catch (e) {
|
||||
|
||||
@@ -11,7 +11,7 @@ export const uploadFileToIpfs = (file: File) => {
|
||||
formData.append('file', file);
|
||||
|
||||
try {
|
||||
const response = await fetch('/upload', {
|
||||
const response = await fetch('/api/upload', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user