Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c27c2f9

Browse files
authoredMar 1, 2025
Df/data fix (#30)
1 parent 2dcfde9 commit c27c2f9

File tree

13 files changed

+273
-58
lines changed

13 files changed

+273
-58
lines changed
 

‎apps/cms/src/app/cms/_components/ArticleDrawer.tsx

+92-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { Minus, Plus } from "lucide-react";
44
import * as React from "react";
55

6+
import { Badge } from "@/components/ui/badge";
67
import { Button } from "@/components/ui/button";
78
import {
89
Drawer,
@@ -14,27 +15,107 @@ import {
1415
DrawerTitle,
1516
DrawerTrigger,
1617
} from "@/components/ui/drawer";
18+
import { useEffect } from "react";
19+
import { createEthstorageArticleUrl } from "../utils";
1720
import { ReviewCard } from "./ReviewCard";
21+
import { ReviewTabs } from "./ReviewTabs";
1822

19-
export const ArticleDrawer = ({ articleKey = "" }: { articleKey?: string }) => {
20-
const [goal, setGoal] = React.useState(350);
23+
export const DIRECTORY_ADDRESS_MANAGER =
24+
"0x649318865AF1A2aE6EE1C5dE9aD6cF6162e28E22";
2125

22-
function onClick(adjustment: number) {
23-
setGoal(Math.max(200, Math.min(400, goal + adjustment)));
24-
}
26+
export const DIRECTORY_ADDRESS_EDITOR =
27+
"0xF8C27D74473A2eE89c52fb594Aef8b239a0b7194";
28+
29+
// DIRECTORY_ADDRESS_TEMPLATE = '0xcf4dc300ab2ea01151945d5b06bd281da27dc943';
30+
31+
export const ArticleDrawer = ({
32+
articleKey = "",
33+
isReview,
34+
}: { articleKey?: string; isReview: boolean }) => {
35+
const reviewers = ["vitalik-eth", "cz"];
36+
const [currentReviewerIndex, setCurrentReviewerIndex] = React.useState(0);
37+
const [reviews, setReviews] = React.useState<string[]>([]);
38+
const [factcheckResult, setFactcheckResult] = React.useState<any>({});
39+
40+
const reviewUrls = React.useMemo(() => {
41+
return reviewers.map((reviewer) =>
42+
createEthstorageArticleUrl(
43+
DIRECTORY_ADDRESS_EDITOR,
44+
`review-${reviewer}/${articleKey}`,
45+
),
46+
);
47+
}, [articleKey]);
48+
49+
const factCheckUrl = React.useMemo(() => {
50+
return createEthstorageArticleUrl(
51+
DIRECTORY_ADDRESS_EDITOR,
52+
`factcheck/${articleKey.replace(".md", ".json")}`,
53+
);
54+
}, [articleKey]);
55+
56+
useEffect(() => {
57+
console.log("factCheckUrl", factCheckUrl);
58+
fetch(factCheckUrl).then(async (res) => {
59+
const results = await res.json();
60+
console.log("factcheck results", results);
61+
setFactcheckResult(results);
62+
});
63+
64+
Promise.all(
65+
reviewUrls.map((reviewUrl: string) => {
66+
console.log("reviewUrl", reviewUrl);
67+
return fetch(reviewUrl).then(async (res) => res.text());
68+
}),
69+
).then((results) => {
70+
console.log("results", results);
71+
72+
setReviews(results);
73+
});
74+
}, [articleKey, reviewUrls, factCheckUrl]);
2575

2676
return (
2777
<DrawerContent>
28-
<div className="mx-auto w-full max-w-sm">
78+
<div className="mx-auto w-full max-w-[600px]">
2979
<DrawerHeader>
3080
<DrawerTitle>{articleKey}</DrawerTitle>
31-
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
81+
<DrawerDescription>
82+
{isReview
83+
? "Reviews by AI review agents"
84+
: "Fact Check by AI agent base on Polymarket and trusted domains"}
85+
</DrawerDescription>
3286
</DrawerHeader>
3387
<div className="p-4 pb-0">
34-
<div className="flex items-center justify-center space-x-2">
35-
<ReviewCard />
36-
</div>
37-
<div className="mt-3 h-[120px]">test</div>
88+
{isReview ? (
89+
<ReviewTabs
90+
reviewers={reviewers}
91+
reviews={reviews}
92+
reviewUrls={reviewUrls}
93+
/>
94+
) : (
95+
<div>
96+
<div>Claim: {factcheckResult.claim}</div>
97+
<div>{factcheckResult.is_true ? "✅True" : "False"}</div>
98+
<div>Confidence Level: {factcheckResult.confidence_level}</div>
99+
<div>Citations: {factcheckResult.citations}</div>
100+
<div>Explanation: {factcheckResult.explanation}</div>
101+
<div>
102+
<a
103+
className="underline"
104+
href={factCheckUrl}
105+
target="_blank"
106+
rel="noreferrer"
107+
>
108+
on-chain record
109+
</a>
110+
</div>
111+
</div>
112+
)}
113+
114+
{/* <Badge>{currentReviewer}</Badge>
115+
<div className="flex p-0 items-center justify-center space-x-2 overflow-y-hidden">
116+
<ReviewCard reviewer="" comment={reviews[0]} />
117+
</div> */}
118+
{/* <div className="mt-3 h-[120px]">test</div> */}
38119
</div>
39120
<DrawerFooter>
40121
{/* <DrawerClose asChild>

‎apps/cms/src/app/cms/_components/ArticleList.tsx

+25-6
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,32 @@ import {
1212
TableRow,
1313
} from "@/components/ui/table";
1414
import { useState } from "react";
15+
import React from "react";
1516
import { createEthstorageArticleUrl } from "../utils";
1617
import { ArticleDrawer } from "./ArticleDrawer";
1718

1819
const directoryAddress = "0x73b6443ff19e7ea934ae8e4b0ddcf3d899580be8";
1920

20-
export const ArticleList = ({ articles }: { articles: any[] }) => {
21+
export const ArticleList = ({
22+
articles,
23+
directoryAddress,
24+
}: { articles: any[]; directoryAddress: string }) => {
2125
const [articleKey, setArticleKey] = useState(undefined);
22-
26+
const [isReview, setIsReview] = React.useState(true);
2327
return (
2428
<Drawer>
2529
<Table>
2630
<TableCaption>
2731
<div>Articles of Site</div>
28-
<div>Directory Address: 0xs</div>
32+
<div>Directory Address: {directoryAddress}</div>
2933
</TableCaption>
3034
<TableHeader>
3135
<TableRow>
3236
<TableHead className="w-[100px]">Key</TableHead>
3337
<TableHead>Status</TableHead>
3438
<TableHead>Author</TableHead>
35-
<TableHead className="text-right">W3Url</TableHead>
39+
<TableHead className="text-right">FactCheck</TableHead>
40+
<TableHead className="text-right">Reviews</TableHead>
3641
</TableRow>
3742
</TableHeader>
3843
<TableBody>
@@ -44,12 +49,26 @@ export const ArticleList = ({ articles }: { articles: any[] }) => {
4449
<TableCell className="text-right">
4550
<DrawerTrigger
4651
key={article.key}
52+
asChild
4753
onClick={() => {
54+
setIsReview(false);
4855
console.log("clicking", article.key);
4956
setArticleKey(article.key);
5057
}}
5158
>
52-
<Button>Inspect</Button>
59+
<div className="cursor-pointer">Check Facts</div>
60+
</DrawerTrigger>
61+
</TableCell>
62+
<TableCell className="text-right">
63+
<DrawerTrigger
64+
key={article.key}
65+
asChild
66+
onClick={() => {
67+
setIsReview(true);
68+
setArticleKey(article.key);
69+
}}
70+
>
71+
<div className="cursor-pointer">Check Reviews</div>
5372
</DrawerTrigger>
5473
</TableCell>
5574
</TableRow>
@@ -62,7 +81,7 @@ export const ArticleList = ({ articles }: { articles: any[] }) => {
6281
</TableRow>
6382
</TableFooter> */}
6483
</Table>
65-
<ArticleDrawer articleKey={articleKey} />
84+
<ArticleDrawer articleKey={articleKey} isReview={isReview} />
6685
</Drawer>
6786
);
6887
};

‎apps/cms/src/app/cms/_components/ReviewCard.tsx

+8-5
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@ import {
77
CardTitle,
88
} from "@/components/ui/card";
99

10-
export const ReviewCard = () => {
11-
const reviewer = "vitalik.eth";
12-
13-
const comment = `This is a great article!`;
10+
export const ReviewCard = ({
11+
reviewer,
12+
comment,
13+
}: {
14+
reviewer?: string;
15+
comment: string;
16+
}) => {
1417
return (
1518
<Card>
1619
<CardHeader>
17-
<CardTitle>Review by {reviewer}</CardTitle>
20+
<CardTitle>Review</CardTitle>
1821
{/* <CardDescription>{comment}</CardDescription> */}
1922
</CardHeader>
2023
<CardContent>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Button } from "@/components/ui/button";
2+
import {
3+
Card,
4+
CardContent,
5+
CardDescription,
6+
CardFooter,
7+
CardHeader,
8+
CardTitle,
9+
} from "@/components/ui/card";
10+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
11+
12+
export function ReviewTabs({
13+
reviewers,
14+
reviews,
15+
reviewUrls,
16+
}: {
17+
reviewers: string[];
18+
reviewUrls: string[];
19+
reviews: any[];
20+
}) {
21+
return (
22+
<Tabs defaultValue="vitalik-eth" className="w-[600px]">
23+
<TabsList className="grid w-full grid-cols-2">
24+
{reviewers.map((reviewer, index) => (
25+
<TabsTrigger key={reviewer} value={reviewer}>
26+
{reviewer}
27+
</TabsTrigger>
28+
))}
29+
{/* <TabsTrigger value="account">Account</TabsTrigger>
30+
<TabsTrigger value="password">Password</TabsTrigger> */}
31+
</TabsList>
32+
{reviews.map((review, index) => {
33+
const reviewer = reviewers[index];
34+
return (
35+
<TabsContent key={`review-${reviewer}`} value={reviewer}>
36+
<Card>
37+
{/* <CardHeader> */}
38+
{/* <CardTitle>Account</CardTitle> */}
39+
{/* </CardHeader> */}
40+
<CardContent className="space-y-2 mt-2">{review}</CardContent>
41+
<CardFooter>
42+
<a
43+
className="underline"
44+
href={reviewUrls[index]}
45+
target="_blank"
46+
rel="noreferrer"
47+
>
48+
on-chain record
49+
</a>
50+
</CardFooter>
51+
</Card>
52+
</TabsContent>
53+
);
54+
})}
55+
</Tabs>
56+
);
57+
}

‎apps/cms/src/app/explorer/page.tsx

+27-15
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,29 @@ import { useChainId } from "wagmi";
88
import { ArticleList } from "../cms/_components/ArticleList";
99
import { createEthstorageArticleUrl } from "../cms/utils";
1010

11-
const directoryAddress = "0x73b6443ff19e7ea934ae8e4b0ddcf3d899580be8";
11+
const directoryAddressManager = "0x649318865AF1A2aE6EE1C5dE9aD6cF6162e28E22";
12+
const directoryAddressAuthor = "0x30B00979c33F826BCF7e182545A3353aD97e1C42";
1213

13-
const articles = [
14-
{
15-
key: "article1.md",
16-
status: "approved",
17-
author: "0x111",
18-
},
19-
{
20-
key: "article2.md",
21-
status: "approved",
22-
author: "0x111",
23-
},
24-
];
14+
const articleMetas = [1, 2, 3, 4, 5].map((key) => ({
15+
key: `article${key}.md`,
16+
status: "approved",
17+
}));
18+
19+
const articles = articleMetas.map((article) => ({
20+
...article,
21+
22+
status: "approved",
23+
author: "0x30B00979c33F826BCF7e182545A3353aD97e1C42",
24+
}));
2525

2626
const ExplorerPage = () => {
2727
const [mounted, setMounted] = useState(false);
2828
const [isAuthorized, setIsAuthorized] = useState(false);
2929
const { address } = useAccount();
3030
const chainId = useChainId();
3131

32+
const ensName = "thisweekin.eth";
33+
3234
useEffect(() => {
3335
setMounted(true);
3436
}, []);
@@ -53,8 +55,18 @@ const ExplorerPage = () => {
5355
<div className="lg:row-span-2">
5456
<div>
5557
<div>w3link.io: https://thisweekin.eth.1.w3link.io/</div>
56-
ENS: <span>thisweekin.eth</span>
57-
<ArticleList articles={articles} />
58+
ENS:{" "}
59+
<a
60+
href={`https://app.ens.domains/${ensName}?tab=records`}
61+
target="_blank"
62+
rel="noreferrer"
63+
>
64+
<span>{ensName}</span>
65+
</a>
66+
<ArticleList
67+
articles={articles}
68+
directoryAddress={directoryAddressManager}
69+
/>
5870
</div>
5971
</div>
6072
</div>

‎packages/agents/src/agents/address-book.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
export const addressAuthor =
2+
process.env.ADDRESS_AUTHOR! || "0x30B00979c33F826BCF7e182545A3353aD97e1C42";
3+
14
export const addressEditor =
25
process.env.ADDRESS_EDITOR! || "0xaf61897967730E19e5e6Fb43a7b64d9aCE0BFc95";
36

‎packages/agents/src/agents/fact-checker.test.ts

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { buildEthFactBank } from "@seele/data-fetch/polymarket/polymarket";
12
import { createAgent } from "@statelyai/agent";
23
import type { Storage } from "unstorage";
34
import { beforeAll, describe, expect, it } from "vitest";
@@ -61,6 +62,26 @@ describe(
6162
});
6263

6364
it.only("#factcheck and persist", async () => {
65+
const facts = await buildEthFactBank(300);
66+
// TODO clean data
67+
68+
await storage.setItems(
69+
facts.map((fact: any) => ({
70+
key: `polymarket:${fact.id}`,
71+
value: {
72+
title: fact.statement,
73+
content: `
74+
<Statment>
75+
${fact.statement}
76+
</Statment>
77+
<Result>
78+
${fact.yesOrNo}
79+
</Result>
80+
`,
81+
},
82+
})),
83+
);
84+
6485
await factCheckAndPersist(agent)(ARTICLE_METAS, storage);
6586
});
6687
},

‎packages/agents/src/agents/fact-checker.ts

+28-15
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,19 @@ export const agentParamsFactChecker = {
2626
events: {},
2727
};
2828

29-
export const createFactCheckPromptParams = (query: string, facts: string[]) => {
29+
export const createFactCheckPromptParams = (claim: string, facts: string[]) => {
3030
const newsContext = facts.join("\n");
3131

3232
const prompt = `
33-
Facts are provided in the context.
34-
<Context>
35-
33+
Facts are provided in the <Sources> below.
34+
35+
<Sources>
3636
${newsContext}
37-
</Context>
37+
</Sources>
3838
3939
Fact-check the following statement:
4040
41-
${query}
41+
${claim}
4242
4343
4444
`;
@@ -50,7 +50,8 @@ export const createFactCheckPromptParams = (query: string, facts: string[]) => {
5050
5151
Provide explanation and state what you can really confirm.
5252
53-
Provide citations on context you used to fact-check the statement and put the citation URL at citation_url
53+
Provide citations on specific part of sources you used to fact-check the statement and put the citation URL at citation_url
54+
Do not just say "context provided" or "the context"
5455
5556
Provide confidence_level from 0-1 on how confident you are on the fact-checking result.
5657
@@ -60,7 +61,8 @@ export const createFactCheckPromptParams = (query: string, facts: string[]) => {
6061
6162
{
6263
"is_true": false,
63-
"confidence_level": 0.8
64+
"confidence_level": 0.8,
65+
"claim": "Biden will be serving his 2nd term in 2026",
6466
"explanation": "Biden did not serve 2nd term of president"
6567
"citations": "According to Polymarket market "2024 Election winner" , Biden served as president from 2021-2025 and loss the last election in 2025",
6668
"citation_url: "https://www.forbes.com/sites/digital-assets/2024/12/10/leak-reveals-russias-bid-for-bitcoin-reserve-amid-huge-2025-price-predictions/"
@@ -96,10 +98,10 @@ export const FactCheckResult = z
9698
.describe("Result of fact checking if statement is true");
9799

98100
export const identifyClaimWithKeywords =
99-
(agent: Agent<any, any>) => async (query: string) => {
101+
(agent: Agent<any, any>) => async (content: string) => {
100102
const result = await generateObjectWithAgent(agent, {
101103
schema: FactCheckQuery,
102-
prompt: createRAGPrompt(query),
104+
prompt: createRAGPrompt(content),
103105
});
104106

105107
return result;
@@ -115,9 +117,10 @@ export const factCheckWithRAG =
115117
storage,
116118
);
117119

120+
console.log("relevantNews", relevantNews);
118121
const params = createFactCheckPromptParams(
119-
content,
120-
relevantNews.map(({ item }) => item.value.content),
122+
claimWithKeywords?.claim,
123+
relevantNews.map(({ item }) => item?.value?.content || ""),
121124
);
122125

123126
console.log("===fact check===");
@@ -127,7 +130,10 @@ export const factCheckWithRAG =
127130

128131
console.log("fact check results", results);
129132

130-
return results;
133+
return {
134+
...results,
135+
claim: claimWithKeywords?.claim,
136+
};
131137
};
132138

133139
// TODO polymarket data
@@ -160,9 +166,15 @@ export const findRelevantInfo = async (
160166
});
161167
};
162168

163-
export const createRAGPrompt = (query: string) => {
169+
export const createRAGPrompt = (content: string) => {
164170
return `
165-
identify 1-3 keywords in the query "${query}, delimited by "," Example: "Trump,Biden,election"
171+
Identify and summarize a claim in the content in less than 10 words, the statement should be a claim that
172+
is clearly true or false.
173+
Then identify 1-3 keywords in the claim, delimited by "," Example: "Trump,Biden,election"
174+
175+
<Content>
176+
${content}
177+
</Content>
166178
`;
167179
};
168180

@@ -180,6 +192,7 @@ export const factCheckAndPersist =
180192
storage,
181193
);
182194

195+
console.log("results", factCheckResults);
183196
await persistWithDirectory(
184197
{
185198
privateKey: privateKeyEditor,

‎packages/agents/src/agents/reviewer.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const reviewArticlesAndPersist =
6767
directoryAddress,
6868
},
6969
{
70-
namespace: `review-${soul.name}`,
70+
namespace: `review-${soul.name.replace(".", "-")}`,
7171
contentKey: article.key,
7272
content: reviewed,
7373
},

‎packages/agents/src/orchestrate.ts

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
factCheckWithRAG,
2727
} from "./agents/fact-checker";
2828
import { agentParamsManager } from "./agents/manager";
29+
import { pullAttestations, verifyAndDeploy } from "./agents/manager.js";
2930
import {
3031
type ResearchResult,
3132
agentParamsResearcher,
@@ -182,6 +183,8 @@ export const reviewAndDeploy = async (soulByName: Record<string, any>) => {
182183
}),
183184
);
184185

186+
const attestations = (await pullAttestations()) || [];
187+
await verifyAndDeploy(attestations, ARTICLE_METAS);
185188
// const factCheckResults = await factCheckWithRAG(agentFactChecker)(
186189
// article,
187190
// storage,

‎packages/data-fetch/src/polymarket/__tests__/polymarket.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { buildEthFactBank } from "../polymarket";
33
import { fetchOptimisticPriceRequests } from "../queries";
44

55
describe("Polymarket", () => {
6-
it("should fetch optimistic price requests", async () => {
7-
const result = await buildEthFactBank(300);
8-
// console.log(result);
6+
it("should fetch polymarket oracles", async () => {
7+
const results = await buildEthFactBank(300);
8+
console.log(results);
99

10-
expect(result.length).toBeGreaterThan(0);
10+
expect(results.length).toBeGreaterThan(0);
1111
}, 60_000);
1212
});

‎packages/data-fetch/src/polymarket/polymarket.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ export async function buildEthFactBank(qty = 5): Promise<EthFact[]> {
88

99
// parse data and statement
1010
const ethFacts = await optimisticPriceRequests.map((request): EthFact => {
11-
const { ancillaryData, settlementPrice } = request;
11+
const { ancillaryData, settlementPrice, id, identifier } = request;
1212

1313
return {
14+
id,
15+
// identifier,
1416
statement: Buffer.from(ancillaryData.slice(2), "hex").toString("utf8"),
1517
yesOrNo: settlementPrice > 0 ? "yes" : "no",
1618
};
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export type EthFact = {
2+
id: string;
23
statement: string; // description from polymarket, decoded from ancillary data hex
34
yesOrNo: "yes" | "no"; // known from polymarket results by proposedPrice / settlementPrice
45
};

0 commit comments

Comments
 (0)
Please sign in to comment.