Skip to content

Commit

Permalink
feat: making data mappings fetching dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
kemuru committed Oct 10, 2023
1 parent 09b430b commit 1ce3e09
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 235 deletions.
148 changes: 41 additions & 107 deletions kleros-sdk/dataMappings/dataMappings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,66 +11,6 @@ const publicClient = createPublicClient({
transport,
});

export const mappings = [
{
type: "fetch",
source: "someAPIEndpoint",
inputs: {
variableName: "disputeData",
link: "https://someapi.com/disputeData",
},
seek: [],
populate: [],
},
{
type: "graphql",
source: "someGraphqlEndpoint",
inputs: {
variableName: "submissionData",
query: "someGraphqlQuery",
},
seek: [],
populate: [],
},
{
type: "json",
source: "evidence",
inputs: {},
seek: ["fileURI"],
populate: ["fileURI"],
},
{
type: "json",
source: "fileURI",
inputs: {},
seek: ["photo", "video"],
populate: ["photoUrl", "videoUrl"],
},
{
type: "abi/call",
source: "contractCall",
inputs: [],
seek: [],
populate: [],
},
{
type: "abi/event",
source: "contractEvent",
inputs: [],
seek: [],
populate: [],
},
];

const initialState = {
evidence: {
fileURI: {
photo: "https://photo.url",
video: "https://video.url",
},
},
};

const findNestedKey = (data, keyToFind) => {
if (data.hasOwnProperty(keyToFind)) return data[keyToFind];
for (let key in data) {
Expand All @@ -82,11 +22,11 @@ const findNestedKey = (data, keyToFind) => {
return null;
};

export const jsonAction = (data, seek, populate) => {
export const jsonAction = (source, seek, populate) => {
let jsonData = {};

seek.forEach((key, idx) => {
const foundValue = findNestedKey(data, key);
const foundValue = findNestedKey(source, key);
jsonData[populate[idx]] = foundValue;
});

Expand Down Expand Up @@ -129,17 +69,22 @@ export const graphqlAction = async (query: string, seek, populate) => {
return populatedData;
};

export const callAction = async (abi, inputs, seek, populate) => {
export const callAction = async (source, inputs, seek, populate) => {
let parsedAbi;

if (typeof source === "string") {
parsedAbi = parseAbiItem(source);
} else {
parsedAbi = source;
}

const data = await publicClient.readContract({
address: inputs[0],
abi: [abi],
abi: [parsedAbi],
functionName: inputs[1],
args: inputs.slice(2),
});

// seek values should be the index of the values we want from the return of the contract since
// wagmi/viem returns an array instead of an object

let populatedData = {};

seek.map((item) => {
Expand All @@ -154,14 +99,22 @@ export const callAction = async (abi, inputs, seek, populate) => {
};

export const eventAction = async (source, inputs, seek, populate) => {
let parsedAbi;

if (typeof source === "string") {
parsedAbi = parseAbiItem(source);
} else {
parsedAbi = source;
}

const argsObject = seek.reduce((acc, key, index) => {
acc[key] = inputs[index + 2];
return acc;
}, {});

const filter = await publicClient.createEventFilter({
address: inputs[0],
event: source,
event: parsedAbi,
args: { ...argsObject },
fromBlock: inputs[1],
toBlock: "latest",
Expand All @@ -171,7 +124,6 @@ export const eventAction = async (source, inputs, seek, populate) => {
filter: filter as any,
});

// @ts-ignore
const eventData = contractEvent[0].args;

let populatedData = {};
Expand All @@ -183,41 +135,23 @@ export const eventAction = async (source, inputs, seek, populate) => {
return populatedData;
};

// const accumulatedData = mappings.reduce(async (acc, { type, source, inputs, seek, populate }) => {
// const currentAcc = await acc;

// switch (type) {
// case "fetch":
// return {
// ...currentAcc,
// ...(await fetchAction(inputs.variableName, inputs.link)),
// };

// case "graphql":
// return {
// ...currentAcc,
// ...(await graphqlAction(inputs.variableName, inputs.query)),
// };

// case "json":
// return {
// ...currentAcc,
// ...jsonAction(currentAcc, source, seek, populate),
// };
// case "abi/call":
// return {
// ...currentAcc,
// ...(await callAction(source, inputs, seek, populate)),
// };
// // case "abi/event":
// // return {
// // ...currentAcc,
// // ...(await eventAction(source, inputs, seek, populate)),
// // };

// default:
// return currentAcc;
// }
// }, Promise.resolve(initialState));

// console.log(accumulatedData);
export const executeAction = async (action) => {
switch (action.type) {
case "fetch":
return await fetchAction(action.source, action.seek, action.populate);
case "graphql":
return await graphqlAction(action.source, action.seek, action.populate);
case "json":
return jsonAction(action.source, action.seek, action.populate);
case "abi/call":
return await callAction(action.source, action.inputs, action.seek, action.populate);
case "abi/event":
return await eventAction(action.source, action.inputs, action.seek, action.populate);
default:
throw new Error(`Unsupported action type: ${action.type}`);
}
};

export const parseTemplateWithData = (template, data) => {
return template.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || "");
};
45 changes: 24 additions & 21 deletions web/src/pages/DisputeTemplateView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import ReactMarkdown from "components/ReactMarkdown";
import { isUndefined } from "utils/index";
import { IPFS_GATEWAY } from "consts/index";
import { useDisputeTemplate } from "hooks/queries/useDisputeTemplate";
import { jsonAction, callAction } from "utils/dataMappings";
import { parseAbiItem } from "viem";
import { executeAction, parseTemplateWithData } from "utils/dataMappings";

const Container = styled.div`
width: 50%;
Expand Down Expand Up @@ -84,37 +83,41 @@ const StyledTextArea = styled(Textarea)`
const DisputeTemplateView: React.FC = () => {
const [disputeTemplate, setDisputeTemplate] = useState<string>("");
const [errorMsg, setErrorMessage] = useState<string>("");
const { data: template } = useDisputeTemplate("4", "0xE4af4D800Ce12149199FA6f8870cD650cD8f3164");
// console.log("πŸš€ ~ file: DisputeTemplateView.tsx:86 ~ template:", template!.templateDataMappings);
const { data: template } = useDisputeTemplate("7", "0xE4af4D800Ce12149199FA6f8870cD650cD8f3164");

const parsedDisputeTemplate = useMemo(async () => {
try {
const parsedMapping = JSON.parse(template?.templateDataMappings);
console.log(template);
const parsedTemplate = JSON.parse(template?.templateData);
console.log("πŸš€ ~ file: DisputeTemplateView.tsx:94 ~ parsedDisputeTemplate ~ parsedTemplate:", parsedTemplate);
console.log("πŸš€ ~ file: DisputeTemplateView.tsx:90 ~ parsedDisputeTemplate ~ parsed:", parsedMapping);
const { inputs, populate, seeks, source } = parsedMapping[0];
const parsedAbi = parseAbiItem(source);
inputs[3] = BigInt(inputs[3]);
console.log(
"πŸš€ ~ file: DisputeTemplateView.tsx:94 ~ parsedDisputeTemplate ~ inputs:",
inputs.slice(2),
populate,
seeks,
parsedAbi
);
const result = await callAction(parsedAbi, inputs, seeks, populate);
console.log("πŸš€ ~ file: DisputeTemplateView.tsx:96 ~ parsedDisputeTemplate ~ result:", result);
const parsedMapping = JSON.parse(template?.templateDataMappings);

console.log("parsedTemplate", parsedTemplate);
console.log("parsedMapping", parsedMapping);

let populatedData = {};

for (const action of parsedMapping) {
console.log("action of parsedMapping", action);
const result = await executeAction(action);
console.log("result of executeAction", result);
populatedData = { ...populatedData, ...result };
console.log("populatedData inside loop", populatedData);
}

const finalTemplate = parseTemplateWithData(parsedTemplate.template.content, populatedData);
console.log("finalTemplate with everything parsed", finalTemplate);
setDisputeTemplate(finalTemplate);
setErrorMessage("");
return parsedTemplate;
return finalTemplate;
} catch (e) {
console.log("error", e);

setErrorMessage((e as SyntaxError).message);
return undefined;
}
}, [template, disputeTemplate]);

const isThereInput = useMemo(() => disputeTemplate !== "", [disputeTemplate]);

return (
<Wrapper>
<StyledTextArea
Expand Down
Loading

0 comments on commit 1ce3e09

Please sign in to comment.