-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
107 lines (93 loc) · 3.45 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
const server = Deno.listen({ port: 8080 });
// IPFS Gateway
const metadataApi = 'https://ipfs.io/ipfs';
// ENS GraphQL Endpoint
const ensUrl = 'https://api.thegraph.com/subgraphs/name/ensdomains/ens'
// GraphQL API
const graphApi = 'https://api.studio.thegraph.com/query/30654/mainnet-dev/0.5.0';
// GraphQL query
const query = `{
projects(first: 5, orderBy: createdAt, orderDirection: desc){
projectId
metadataUri
createdAt
owner
currentBalance
handle
}
}`;
for await (const conn of server) {
serveHttp(conn);
}
async function serveHttp(conn: Deno.Conn) {
const httpConn = Deno.serveHttp(conn);
// Query GraphQL API
for await (const requestEvent of httpConn) {
const res = await fetch(graphApi, {
body: JSON.stringify({ query }),
method: 'POST',
headers: { 'Content-Type': 'application/json' },
})
const answer = await res.json();
// Initialize RSS XML
let body = `<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel>
<title>Juicebox Projects</title>
<link>http://juice-rss.deno.dev/</link>
<description>Latest projects on juicebox.money</description>
<language>en-us</language>
<atom:link href="http://juice-rss.deno.dev/" rel="self" type="application/rss+xml"/>`;
// Add items
for(const { projectId, metadataUri, createdAt, owner, currentBalance, handle } of answer.data.projects){
// Fetch IPFS metadata
const ipfsRes = await fetch(`${metadataApi}/${metadataUri}`);
const metadata = ipfsRes.ok ? await ipfsRes.json() : null;
// Fetch ENS
const query = `{
domains(where: {resolvedAddress: "${owner.toLowerCase()}"}){
name
}
}`;
const ensRes = await fetch(ensUrl, {
body: JSON.stringify({ query }),
method: 'POST',
headers: { 'Content-Type': 'application/json' },
})
const ensData = (await ensRes.json()).data;
// Add item
body += `<item>
<title>${projectId}: ${metadata?.name}</title>
<link>https://juicebox.money/v2/p/${projectId}/</link>
<description>Current balance: ${currentBalance / 1000000000000000000 } ETH<br>
Owner Address: ${owner}<br>`
if(ensData.domains[0])
for(const { name } of ensData.domains)
body += `Owner ENS: ${name}<br>`
if(handle){ body += `Project Handle: ${handle}<br>`; }
if(!metadata){
body += `Could not resolve project metadata.<br>`;
} else {
if(metadata.description){ body += `<br>Description: ${metadata.description}<br>`; }
if(metadata.payDisclosure){ body += `<br/>Disclosure: ${metadata.payDisclosure}<br/><br/>`; }
if(metadata.twitter){ body += `Twitter: <a href='https://twitter.com/${metadata.twitter}'>@${metadata.twitter}</a>`; }
if(metadata.discord){ body += ` Discord: <a href='${metadata.discord}'>${metadata.discord}</a>`; }
}
body += `</description>`;
if(ensData.domains[0])
body += `<author>${ensData.domains[0].name}</author>`;
else
body += `<author>${owner}</author>`;
body += `<guid>${projectId}</guid>
<pubDate>${new Date(createdAt * 1000).toISOString()}</pubDate>
</item>`;
}
// Close XML body
body += `</channel></rss>`;
// XML Response
requestEvent.respondWith(
new Response(body, {
status: 200,
headers: { 'Content-Type': 'text/xml'}
}),
);
}
}