Compare commits

..

2 Commits

Author SHA1 Message Date
Ladd Hoffman df646a2a8f Add SS import UI
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 30s Details
2024-04-21 12:51:58 -05:00
Ladd Hoffman f1bb21c9ad fixup citation weights for ss import 2024-04-21 12:51:38 -05:00
12 changed files with 92 additions and 22 deletions

View File

@ -1,9 +1,9 @@
{
"localhost": {
"DAO": "0x4C767e62c92b58B2308E02ba5Cc4A3BD246060ac",
"Work1": "0x39B7522Ee1A5B13aE5580C40114239D4cE0e7D29",
"Onboarding": "0xC0Bb36820Ba891DE4ed6D60f75066805361dbeB8",
"Proposals": "0x268A0A6bB80282542e0Be0864Cfa1c2206c5491F"
"DAO": "0x4774670f82A590e7eD6072bd7098836B06FFd8ce",
"Work1": "0xc72A4CF5499D0de850457C0d4C0a4b8071441C6f",
"Onboarding": "0xadB35d0E9d7B33441C7ED26add5D42F873430790",
"Proposals": "0xE9aa427d985aE50AdD10a3404bF7a1300fa9f667"
},
"sepolia": {
"DAO": "0x8e5bd58B2ca8910C5F9be8de847d6883B15c60d2",

View File

@ -15,6 +15,7 @@
"dotenv": "^16.4.5",
"ethers": "^6.12.0",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"level": "^8.0.1",
"object-hash": "^3.0.0"
},
@ -1813,6 +1814,14 @@
"node": ">= 0.10.0"
}
},
"node_modules/express-async-errors": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
"integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
"peerDependencies": {
"express": "^4.16.2"
}
},
"node_modules/express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",

View File

@ -15,6 +15,7 @@
"dotenv": "^16.4.5",
"ethers": "^6.12.0",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"level": "^8.0.1",
"object-hash": "^3.0.0"
},

View File

@ -35,12 +35,14 @@ const getContract = (name) => new ethers.Contract(
DAOArtifact.abi,
signer,
);
const dao = getContract('DAO');
const fetchPaperInfo = async (paperId, retryDelay = 5000) => {
const url = `https://api.semanticscholar.org/graph/v1/paper/${paperId}?`
+ 'fields=title,url,authors,references.title,references.url,references.authors';
let retry = false;
let paper;
let requestError;
const response = await axios.get(url, {
headers: {
'api-key': process.env.SEMANTIC_SCHOLAR_API_KEY,
@ -52,9 +54,11 @@ const fetchPaperInfo = async (paperId, retryDelay = 5000) => {
return;
}
// Some other error occurred
throw new Error(error);
requestError = error;
});
if (retry) {
if (requestError) {
throw requestError;
} else if (retry) {
console.log('retry delay (sec):', retryDelay / 1000);
await new Promise((resolve) => {
setTimeout(resolve, retryDelay);
@ -138,7 +142,6 @@ HREF ${paper.url}`;
};
module.exports = async (req, res) => {
const dao = await getContract('DAO');
const {
body: {
paperId,
@ -152,9 +155,10 @@ module.exports = async (req, res) => {
console.log('references count:', paper.references.length);
const eachCitationWeightPercent = Math.floor(PPM_TO_CITATIONS / paper.references.length);
const references = paper.references.filter((x) => !!x.paperId);
const eachCitationWeightPercent = Math.floor(PPM_TO_CITATIONS / references.length);
const citations = await Promise.mapSeries(
paper.references.filter((x) => !!x.paperId),
references,
async (citedPaper) => {
// We need to fetch this paper so we can generate the post we WOULD add to the forum.
// That way, if we later add the cited paper to the blockchain it will have the correct hash.
@ -187,12 +191,12 @@ module.exports = async (req, res) => {
} catch (e) {
if (e.reason === 'A post with this contentId already exists') {
console.log(`Post already added for paper ${paperId}`);
res.status(204).end();
res.json({ alreadyAdded: true, postId: hash });
return;
}
throw e;
}
console.log(`Added post to blockchain for paper ${paperId}`);
res.status(201).end();
res.json({ postId: hash });
};

View File

@ -5,6 +5,7 @@ const write = require('./write');
const importFromSS = require('./import-from-ss');
require('dotenv').config();
require('express-async-errors');
const app = express();
const port = process.env.PORT || 3000;
@ -20,6 +21,14 @@ app.get('*', (req, res) => {
res.status(404).json({ errorCode: 404 });
});
app.use((err, req, res, next) => {
const status = err.response?.status ?? 500;
const message = err.response?.data?.error ?? err.message;
console.error(`error: ${message}`);
res.status(status).send(message);
next();
});
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});

View File

@ -23,8 +23,6 @@ module.exports = async (req, res) => {
authors, content, signature, embeddedData,
} = data;
console.log({ content, embeddedData });
// Verify hash
const derivedHash = objectHash({
authors, content, signature, embeddedData,

View File

@ -1,9 +1,9 @@
{
"localhost": {
"DAO": "0x4C767e62c92b58B2308E02ba5Cc4A3BD246060ac",
"Work1": "0x39B7522Ee1A5B13aE5580C40114239D4cE0e7D29",
"Onboarding": "0xC0Bb36820Ba891DE4ed6D60f75066805361dbeB8",
"Proposals": "0x268A0A6bB80282542e0Be0864Cfa1c2206c5491F"
"DAO": "0x4774670f82A590e7eD6072bd7098836B06FFd8ce",
"Work1": "0xc72A4CF5499D0de850457C0d4C0a4b8071441C6f",
"Onboarding": "0xadB35d0E9d7B33441C7ED26add5D42F873430790",
"Proposals": "0xE9aa427d985aE50AdD10a3404bF7a1300fa9f667"
},
"sepolia": {
"DAO": "0x8e5bd58B2ca8910C5F9be8de847d6883B15c60d2",

View File

@ -1,9 +1,9 @@
{
"localhost": {
"DAO": "0x4C767e62c92b58B2308E02ba5Cc4A3BD246060ac",
"Work1": "0x39B7522Ee1A5B13aE5580C40114239D4cE0e7D29",
"Onboarding": "0xC0Bb36820Ba891DE4ed6D60f75066805361dbeB8",
"Proposals": "0x268A0A6bB80282542e0Be0864Cfa1c2206c5491F"
"DAO": "0x4774670f82A590e7eD6072bd7098836B06FFd8ce",
"Work1": "0xc72A4CF5499D0de850457C0d4C0a4b8071441C6f",
"Onboarding": "0xadB35d0E9d7B33441C7ED26add5D42F873430790",
"Proposals": "0xE9aa427d985aE50AdD10a3404bF7a1300fa9f667"
},
"sepolia": {
"DAO": "0x8e5bd58B2ca8910C5F9be8de847d6883B15c60d2",

View File

@ -1,3 +1,7 @@
.post-content {
white-space: pre-line;
}
.input-paper-id {
width: 30em !important;
}

View File

@ -25,6 +25,7 @@ import AddPostModal from './components/posts/AddPostModal';
import ViewPostModal from './components/posts/ViewPostModal';
import Post from './utils/Post';
import Proposals from './components/Proposals';
import Import from './components/Import';
import getAddressName from './utils/get-address-name';
function App() {
@ -573,6 +574,9 @@ function App() {
<Tab eventKey="proposals" title="Proposals">
<Proposals />
</Tab>
<Tab eventKey="import" title="Import">
<Import />
</Tab>
</Tabs>
</>
)}

View File

@ -0,0 +1,42 @@
import { useState } from 'react';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import axios from 'axios';
function Import() {
const [paperId, setPaperId] = useState();
const [status, setStatus] = useState('');
const handleImport = async () => {
setStatus(`Importing paper ${paperId}...`);
const { data: { alreadyAdded, postId } } = await axios.post('/api/importFromSemanticScholar', { paperId })
.catch((error) => {
setStatus(`Error: ${error.response?.data ?? error.message}`);
});
if (alreadyAdded) {
setStatus(`Paper ${paperId} was already imported as post ${postId}`);
} else {
setStatus(`Imported paper ${paperId} as post ${postId}`);
}
};
return (
<>
<h1>Semantic Scholar Import</h1>
<Form>
<Form.Group controlId="SSImport.paperId">
<Form.Label>Paper ID</Form.Label>
<Form.Control
as="input"
className="input-paper-id mb-3"
onChange={(e) => setPaperId(e.target.value)}
/>
</Form.Group>
</Form>
<Button className="mb-2" onClick={handleImport}>Import</Button>
<p>{status}</p>
</>
);
}
export default Import;

View File

@ -1,5 +1,4 @@
import axios from 'axios';
// trailing slash is deliberate, to differentiate this package from the core node module
import { Buffer } from 'buffer';
import { recoverPersonalSignature } from '@metamask/eth-sig-util';
import objectHash from 'object-hash/dist/object_hash';