Skip to content

Instantly share code, notes, and snippets.

@leordev
Created September 28, 2023 15:17
Show Gist options
  • Save leordev/8d6aa6e418673b9e07f203c0461de364 to your computer and use it in GitHub Desktop.
Save leordev/8d6aa6e418673b9e07f203c0461de364 to your computer and use it in GitHub Desktop.
web5 on client side only
import { useContext, useState, updateState, setState, useEffect } from "react";
import AppContext from "../components/AppContext";
import { useRouter } from "next/router";
import { Web5 } from "@web5/api";
import Ajv from "ajv";
/*import { webcrypto } from "node:crypto";
// @ts-ignore
if (!globalThis.crypto) globalThis.crypto = webcrypto;*/
//import * as dotenv from 'dotenv';
//dotenv.config(
const PROTOCOL_ID = 'http://selfkey.org/protocols/credentialSharing';
const CREDENTIAL_SCHEMA = {
"type": "object",
"properties": {
"@context": {
"type": "array",
"items": [
{
"type": "string"
},
{
"type": "string"
}
],
"minItems": 1,
},
"id": {
"type": "string"
},
"type": {
"type": "array",
"items": [
{
"type": "string"
},
{
"type": "string"
}
],
"minItems": 1
},
"issuer": {
"type": "string"
},
"validFrom": {
"type": "string"
},
"credentialSubject": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"degree": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"type",
"name"
]
}
},
"required": [
"id",
"degree"
]
},
"proof": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"created": {
"type": "string"
},
"verificationMethod": {
"type": "string"
},
"proofPurpose": {
"type": "string"
},
"proofValue": {
"type": "string"
}
},
"required": [
"type",
"created",
"verificationMethod",
"proofPurpose",
"proofValue"
]
}
},
"required": [
"@context",
"id",
"type",
"issuer",
"validFrom",
"credentialSubject",
"proof"
]
};
function Header(props) {
return(<h1>{props.title}</h1>);
}
function CredentialTable(props) {
const [refreshState, setRefreshState] = useState(0);
const context = useContext(AppContext);
const router = useRouter();
function viewCredential(index) {
var document = {
//name: props.names[index],
};
context.setSession({document: document});
router.push('/edit/');
}
function deleteCredential(did, recordId) {
console.log("deleteCredential id: ", recordId);
/*web5.dwn.records.delete({
from: did,
message: {
recordId: recordId,
}
})*/
refresh();
}
function refresh() {
console.log("CredentialTable refresh");
setRefreshState(refreshState + 1);
// empty arrays?
}
return (
<div onLoad={refresh}>
<p>My credentials:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{
props.recordIds.map((value, i) => {
return(
<tr key={i}>
<td>
{props.names[i]}
</td>
<td>
{props.descriptions[i]}
</td>
<td>
<button onClick={() => viewCredential(i)}>View</button>
</td>
<td>
<button onClick={() => deleteCredential(props.recordIds[i])}>Delete</button>
</td>
</tr>)
})}
</tbody>
</table>
</div>
);
}
export default function HomePage() {
const [file, setFile] = useState(null);
const [dataArray, setDataArray] = useState(new Array());
const [refreshState, setRefreshState] = useState("");
const [submitDisabled, setSubmitDisabled] = useState("false");
const [recordIds, setRecordIds] = useState([]);
const [names, setNames] = useState([]);
const [descriptions, setDescriptions] = useState([]);
const [credentials, setCredentials] = useState([]);
const [web5, setWeb5] = useState(undefined);
const [did, setDid] = useState(undefined);
const context = useContext(AppContext);
const router = useRouter();
useEffect(() => {
const fetchData = async () => {
// Instantianting Web5 on the client ONLY!
let { web5, did: myDid } = await Web5.connect()
setWeb5(web5)
setDid(myDid)
/*const { records } = await web5.dwn.records.query({
//from: did, // store did in session?
message: {
filter: {
protocol: PROTOCOL_ID,
schema: CREDENTIAL_SCHEMA,
dataFormat: "application/json",
},
},
});*/
/*for(var i = 0; i < records.length; i++) {
const record = records[i];
recordIds[i] = record.data.id;//;
names[i] = record.data.name;//;
descriptions[i] = record.data.description;
credentials[i] = record.data;
}*/
setRefreshState("done"); // check if necessary
}
setSubmitDisabled("false");
fetchData().catch(console.error);
}, []);
function retrieveFile(e) {
const data = e.target.files[0];
try{
const reader = new window.FileReader();
reader.readAsArrayBuffer(data);
reader.onloadend = () => {
const file = Buffer(reader.result);
const jsonData = JSON.parse(file.toString());
const ajv = new Ajv() // options can be passed, e.g. {allErrors: true}
const validate = ajv.compile(CREDENTIAL_SCHEMA);
const valid = validate(jsonData);
if (!valid) {
setSubmitDisabled("true");
console.log(validate.errors);
} else {
setSubmitDisabled("false");
console.log("schema check passed");
}
setFile(file);
};
} catch (error) {
console.log(error);
}
e.preventDefault();
}
async function handleSubmit(e) {
/*if (web5 == undefined) {
{ web5, did: myDid } = await Web5.connect();
}*/
e.preventDefault();
try {
const f = file.toString();
const data = JSON.parse(f);
const { record } = await web5.dwn.records.create({
store: false,
data: data,
message: {
dataFormat: "text/plain",
//protocol: PROTOCOL_ID,
//schema: CREDENTIAL_SCHEMA,
},
});
if (record)
console.log("new record created: ", record);
refresh();
} catch (error) {
console.log(error.message);
}
}
function refresh() {
console.log("Homepage refresh");
setRefreshState(refreshState == 0 ? 1 : 0);
}
return (
<div onLoad={refresh}>
<Header title="Lit Protocol PoC" />
<br></br>
<CredentialTable recordIds={recordIds} names={names} descriptions={descriptions} credentials={credentials}></CredentialTable>
<p>Submit a credential to store on Decentralized Web Node</p>
<form onSubmit={handleSubmit}>
<table>
<tbody>
<tr>
<td><label>File:</label></td>
<td><input type="file" onChange={retrieveFile} required /></td>
</tr>
<tr>
<td><label>Name: </label></td>
<td><input id="dataName" type="text" /></td>
</tr>
<tr>
<td><label>Description: </label></td>
<td><input id="dataDescription" type="text" /></td>
</tr>
<tr>
<td><button /*disabled={{ submitDisabled }}*/ type="submit" className="button">Submit</button></td>
<td></td>
</tr>
</tbody>
</table>
</form>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment