From 5e353465a2b1610f02d888d2d0d4e4e80ad89463 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Thu, 17 Aug 2023 19:12:38 +0200 Subject: [PATCH 01/37] feat(sdk): draft of some actions in web utils --- web/src/utils/dataMappings.ts | 105 ++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 web/src/utils/dataMappings.ts diff --git a/web/src/utils/dataMappings.ts b/web/src/utils/dataMappings.ts new file mode 100644 index 000000000..477e30958 --- /dev/null +++ b/web/src/utils/dataMappings.ts @@ -0,0 +1,105 @@ +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"], + }, +]; + +const initialState = { + evidence: { + fileURI: { + photo: "https://photo.url", + video: "https://video.url", + }, + }, +}; + +const fetchAction = async (variableName: string, link: string) => { + const response = await fetch(link); + const data = await response.json(); + return { [variableName]: data }; +}; + +const graphqlAction = async (variableName: string, query: string) => { + const response = await fetch("http://graphql-server-endpoint.com", { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ query }), + }); + + const { data } = await response.json(); + return { [variableName]: data }; +}; + +const jsonAction = (currentAcc, source, seek, populate) => { + const dataFromSource = currentAcc[source]; + let jsonData = {}; + + seek.forEach((key, idx) => { + jsonData[populate[idx]] = dataFromSource[key]; + }); + + return jsonData; +}; + +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), + }; + + default: + return currentAcc; + } +}, Promise.resolve(initialState)); + +console.log(accumulatedData); From 84bea912942ad6f280e5563527c0c7a845e6327e Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Mon, 21 Aug 2023 16:52:20 +0300 Subject: [PATCH 02/37] feat: add contract calls, events --- web/src/utils/dataMappings.ts | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/web/src/utils/dataMappings.ts b/web/src/utils/dataMappings.ts index 477e30958..ffad42e28 100644 --- a/web/src/utils/dataMappings.ts +++ b/web/src/utils/dataMappings.ts @@ -1,3 +1,11 @@ +import { createPublicClient, http, parseAbiItem } from "viem"; +import { arbitrumGoerli } from "viem/chains"; + +const publicClient = createPublicClient({ + chain: arbitrumGoerli, + transport: http(), +}); + export const mappings = [ { type: "fetch", @@ -33,6 +41,20 @@ export const mappings = [ seek: ["photo", "video"], populate: ["photoUrl", "videoUrl"], }, + { + type: "abi/call", + source: "contractCall", + inputs: [], + seek: [], + populate: [], + }, + { + type: "abi/event", + source: "contractEvent", + inputs: [], + seek: [], + populate: [], + }, ]; const initialState = { @@ -75,6 +97,45 @@ const jsonAction = (currentAcc, source, seek, populate) => { return jsonData; }; +const callAction = async (source, inputs, seek, populate) => { + const data = await publicClient.readContract({ + address: inputs[1], + abi: parseAbiItem(source), + functionName: "", + args: inputs, + }); + + let populatedData = {}; + + seek.map((item, index) => { + populatedData[populate[index]] = data[item]; + }); + + return populatedData; +}; + +const eventAction = async (source, inputs, seek, populate) => { + const filter = await publicClient.createEventFilter({ + address: inputs[1], + event: parseAbiItem(source), + args: inputs, + }); + + const contractEvent = await publicClient.getFilterLogs({ + filter: filter, + }); + + const eventData = contractEvent[0].args; + + let populatedData = {}; + + seek.map((item, index) => { + populatedData[populate[index]] = eventData[item]; + }); + + return populatedData; +}; + const accumulatedData = mappings.reduce(async (acc, { type, source, inputs, seek, populate }) => { const currentAcc = await acc; @@ -96,6 +157,16 @@ const accumulatedData = mappings.reduce(async (acc, { type, source, inputs, seek ...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; From 2ba5d0b6558e10657c2d6bebe51bbc2a3933cfe0 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:19:09 +0200 Subject: [PATCH 03/37] feat(sdk): added some data mappings action tests --- kleros-sdk/dataMappings/dataMappings.ts | 184 ++++++++++++++++++++++++ kleros-sdk/dataMappings/test.ts | 129 +++++++++++++++++ package.json | 4 + tsconfig.json | 8 ++ yarn.lock | 28 +++- 5 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 kleros-sdk/dataMappings/dataMappings.ts create mode 100644 kleros-sdk/dataMappings/test.ts create mode 100644 tsconfig.json diff --git a/kleros-sdk/dataMappings/dataMappings.ts b/kleros-sdk/dataMappings/dataMappings.ts new file mode 100644 index 000000000..5ebd1fed9 --- /dev/null +++ b/kleros-sdk/dataMappings/dataMappings.ts @@ -0,0 +1,184 @@ +import { createPublicClient, http, parseAbiItem } from "viem"; +import { arbitrumGoerli } from "viem/chains"; +import fetch from "node-fetch"; + +const publicClient = createPublicClient({ + chain: arbitrumGoerli, + transport: http(), +}); + +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", + }, + }, +}; + +// Utility function to access nested objects +const getNestedObject = (nestedObj, pathArr) => { + return pathArr.reduce((obj, key) => (obj && obj[key] !== "undefined" ? obj[key] : undefined), nestedObj); +}; + +export const jsonAction = (currentAcc, source, seek, populate) => { + const pathArray = typeof source === "string" ? source.split(".") : source; + + const dataFromSource = getNestedObject(currentAcc, pathArray); + let jsonData = {}; + + seek.forEach((key, idx) => { + jsonData[populate[idx]] = dataFromSource[key]; + }); + + return jsonData; +}; + +export const fetchAction = async (variableName: string, link: string) => { + const response = await fetch(link); + const data = await response.json(); + return { [variableName]: data }; +}; + +export const graphqlAction = async (variableName: string, query: string) => { + const response = await fetch("https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-arbitrum-goerli", { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ query }), + }); + + const { data } = await response.json(); + return { [variableName]: data }; +}; + +// export const callAction = async (abi, inputs, seek, populate) => { +// const data = await publicClient.readContract({ +// address: inputs[0], +// abi: abi, +// functionName: seek, +// args: inputs, +// }); + +// let populatedData = {}; + +// seek.map((item, index) => { +// populatedData[populate[index]] = data[item]; +// }); + +// return populatedData; +// }; + +// export const eventAction = async (source, inputs, seek, populate) => { +// const filter = await publicClient.createEventFilter({ +// address: inputs[1], +// event: parseAbiItem(source) as any, +// args: inputs, +// }); + +// const contractEvent = await publicClient.getFilterLogs({ +// filter: filter as any, +// }); + +// const eventData = contractEvent[0].args; + +// let populatedData = {}; + +// seek.map((item, index) => { +// populatedData[populate[index]] = eventData[item]; +// }); + +// 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); diff --git a/kleros-sdk/dataMappings/test.ts b/kleros-sdk/dataMappings/test.ts new file mode 100644 index 000000000..39b317607 --- /dev/null +++ b/kleros-sdk/dataMappings/test.ts @@ -0,0 +1,129 @@ +import { expect } from "chai"; +import { createPublicClient, http } from "viem"; +import { arbitrumGoerli } from "viem/chains"; +import { jsonAction, graphqlAction, fetchAction, callAction } from "./dataMappings"; +import { klerosCoreABI } from "../../web/src/hooks/contracts/generated"; + +const currentAcc = { + evidence: { + fileURI: { + photo: "https://photo.url", + video: "https://video.url", + }, + }, +}; + +const publicClient = createPublicClient({ + chain: arbitrumGoerli, + transport: http(), +}); + +describe("jsonAction", () => { + it("should extract and map data correctly", () => { + const result = jsonAction(currentAcc, "evidence.fileURI", ["photo", "video"], ["photoUrl", "videoUrl"]); + expect(result).to.eql({ + photoUrl: "https://photo.url", + videoUrl: "https://video.url", + }); + }); +}); + +describe("fetchAction", () => { + it("should fetch data and return in expected format", async () => { + const result = await fetchAction("product", "https://fakestoreapi.com/products/1"); + expect(result).to.eql({ + product: { + id: 1, + title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops", + price: 109.95, + description: + "Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday", + category: "men's clothing", + image: "https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg", + rating: { + rate: 3.9, + count: 120, + }, + }, + }); + }); +}); + +describe("graphqlAction", () => { + it("should fetch GraphQL data and return in expected format", async () => { + const mockQuery = ` + { + court(id: 1) { + id + } + } + `; + + const mockData = { + court: { + id: "1", + }, + }; + + const result = await graphqlAction("court", mockQuery); + expect(result).to.eql({ court: mockData }); + }); +}); + +// describe("callAction", () => { +// it("should call the contract and return populated data", async () => { +// const mockAbi = klerosCoreABI; +// const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1"]; // Add the contract address as an input +// const mockSeek = ["pinakion"]; // Adjusting this to seek for 'pinakion' +// const mockPopulate = ["result1", "tokenAddress"]; // Changing 'result2' to 'tokenAddress' to be more descriptive + +// const result = await callAction(mockAbi, mockInputs, mockSeek, mockPopulate); + +// console.log(result); +// expect(result).to.eql({ +// result1: "data1", +// tokenAddress: "0x4deeefd054434bf6721ef39aa18efb3fd0d12610", +// }); +// }); +// }); + +// describe("eventAction", () => { +// let createEventFilterStub; +// let getFilterLogsStub; + +// beforeEach(() => { +// // Mock the methods from publicClient +// createEventFilterStub = sinon.stub(publicClient, "createEventFilter"); +// getFilterLogsStub = sinon.stub(publicClient, "getFilterLogs"); +// }); + +// afterEach(() => { +// // Restore the mocked methods +// createEventFilterStub.restore(); +// getFilterLogsStub.restore(); +// }); + +// it("should fetch event data and return populated data", async () => { +// const mockSource = "contractEvent"; +// const mockInputs = []; +// const mockSeek = ["eventItem1", "eventItem2"]; +// const mockPopulate = ["result1", "result2"]; +// const mockEventData = { +// eventItem1: "eventData1", +// eventItem2: "eventData2", +// }; + +// const mockFilter = {}; // dummy filter for this test +// const mockContractEvent = [{ args: mockEventData }]; + +// // Mock the return values +// createEventFilterStub.resolves(mockFilter); +// getFilterLogsStub.resolves(mockContractEvent); + +// const result = await eventAction(mockSource, mockInputs, mockSeek, mockPopulate); +// expect(result).to.eql({ +// result1: "eventData1", +// result2: "eventData2", +// }); +// }); +// }); diff --git a/package.json b/package.json index 05e6fe2bf..8d6ef0c63 100644 --- a/package.json +++ b/package.json @@ -36,10 +36,14 @@ "devDependencies": { "@commitlint/cli": "^17.6.5", "@commitlint/config-conventional": "^17.6.7", + "@types/chai": "^4.3.6", + "@types/mocha": "^10.0.1", "buffer": "^5.5.0", + "chai": "^4.3.8", "conventional-changelog-cli": "^2.2.2", "husky": "^8.0.3", "lint-staged": "^13.2.2", + "mocha": "^10.2.0", "process": "^0.11.10" }, "resolutions": { diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..90d1f029d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "types": [ + "mocha", + "node" + ] + } +} diff --git a/yarn.lock b/yarn.lock index 3447b0119..799b5fd58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8599,6 +8599,13 @@ __metadata: languageName: node linkType: hard +"@types/chai@npm:^4.3.6": + version: 4.3.6 + resolution: "@types/chai@npm:4.3.6" + checksum: 32a6c18bf53fb3dbd89d1bfcadb1c6fd45cc0007c34e436393cc37a0a5a556f9e6a21d1e8dd71674c40cc36589d2f30bf4d9369d7787021e54d6e997b0d7300a + languageName: node + linkType: hard + "@types/cli-progress@npm:^3.11.0": version: 3.11.0 resolution: "@types/cli-progress@npm:3.11.0" @@ -12359,6 +12366,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.3.8": + version: 4.3.8 + resolution: "chai@npm:4.3.8" + dependencies: + assertion-error: ^1.1.0 + check-error: ^1.0.2 + deep-eql: ^4.1.2 + get-func-name: ^2.0.0 + loupe: ^2.3.1 + pathval: ^1.1.1 + type-detect: ^4.0.5 + checksum: 29e0984ed13308319cadc35437c8ef0a3e271544d226c991bf7e3b6d771bf89707321669e11d05e362bc0ad0bd26585079b989d1032f3c106e3bb95d7f079cce + languageName: node + linkType: hard + "chalk@npm:3.0.0": version: 3.0.0 resolution: "chalk@npm:3.0.0" @@ -21160,10 +21182,14 @@ __metadata: dependencies: "@commitlint/cli": ^17.6.5 "@commitlint/config-conventional": ^17.6.7 + "@types/chai": ^4.3.6 + "@types/mocha": ^10.0.1 buffer: ^5.5.0 + chai: ^4.3.8 conventional-changelog-cli: ^2.2.2 husky: ^8.0.3 lint-staged: ^13.2.2 + mocha: ^10.2.0 process: ^0.11.10 languageName: unknown linkType: soft @@ -22951,7 +22977,7 @@ __metadata: languageName: node linkType: hard -"mocha@npm:^10.0.0": +"mocha@npm:^10.0.0, mocha@npm:^10.2.0": version: 10.2.0 resolution: "mocha@npm:10.2.0" dependencies: From 4e80b8d421addbac537dfb418d498729fa1904da Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Wed, 13 Sep 2023 11:41:16 +0300 Subject: [PATCH 04/37] feat: tests for contract call and events --- kleros-sdk/dataMappings/dataMappings.ts | 76 ++++++++++++--------- kleros-sdk/dataMappings/test.ts | 90 ++++++++++--------------- 2 files changed, 80 insertions(+), 86 deletions(-) diff --git a/kleros-sdk/dataMappings/dataMappings.ts b/kleros-sdk/dataMappings/dataMappings.ts index 5ebd1fed9..4f51f9ec6 100644 --- a/kleros-sdk/dataMappings/dataMappings.ts +++ b/kleros-sdk/dataMappings/dataMappings.ts @@ -1,10 +1,14 @@ -import { createPublicClient, http, parseAbiItem } from "viem"; +import { createPublicClient, http, parseAbiItem, webSocket } from "viem"; import { arbitrumGoerli } from "viem/chains"; import fetch from "node-fetch"; +const ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY; + +const transport = webSocket(`wss://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}`); + const publicClient = createPublicClient({ chain: arbitrumGoerli, - transport: http(), + transport, }); export const mappings = [ @@ -105,44 +109,54 @@ export const graphqlAction = async (variableName: string, query: string) => { return { [variableName]: data }; }; -// export const callAction = async (abi, inputs, seek, populate) => { -// const data = await publicClient.readContract({ -// address: inputs[0], -// abi: abi, -// functionName: seek, -// args: inputs, -// }); +export const callAction = async (abi, inputs, seek, populate) => { + const data = await publicClient.readContract({ + address: inputs[0], + abi: [abi], + functionName: seek[0], + args: [inputs[1]], + }); + console.log("callaction"); + + console.log("data", data); + + let populatedData = {}; + + seek.map((item, index) => { + populatedData[populate[index]] = data; + }); -// let populatedData = {}; + return populatedData; +}; -// seek.map((item, index) => { -// populatedData[populate[index]] = data[item]; -// }); +export const eventAction = async (source, inputs, seek, populate) => { + console.log("entry", inputs[0]); -// return populatedData; -// }; + const filter = await publicClient.createEventFilter({ + address: inputs[0], + event: source, + fromBlock: inputs[1], + toBlock: "latest", + }); -// export const eventAction = async (source, inputs, seek, populate) => { -// const filter = await publicClient.createEventFilter({ -// address: inputs[1], -// event: parseAbiItem(source) as any, -// args: inputs, -// }); + const contractEvent = await publicClient.getFilterLogs({ + filter: filter as any, + }); -// const contractEvent = await publicClient.getFilterLogs({ -// filter: filter as any, -// }); + // @ts-ignore + const eventData = contractEvent[0].args; + // console.log("🚀 ~ file: dataMappings.ts:145 ~ eventAction ~ eventData:", eventData); -// const eventData = contractEvent[0].args; + let populatedData = {}; -// let populatedData = {}; + seek.map((item, index) => { + // console.log("item", item); -// seek.map((item, index) => { -// populatedData[populate[index]] = eventData[item]; -// }); + populatedData[populate[index]] = eventData[item]; + }); -// return populatedData; -// }; + return populatedData; +}; // const accumulatedData = mappings.reduce(async (acc, { type, source, inputs, seek, populate }) => { // const currentAcc = await acc; diff --git a/kleros-sdk/dataMappings/test.ts b/kleros-sdk/dataMappings/test.ts index 39b317607..671b7b256 100644 --- a/kleros-sdk/dataMappings/test.ts +++ b/kleros-sdk/dataMappings/test.ts @@ -1,7 +1,7 @@ import { expect } from "chai"; -import { createPublicClient, http } from "viem"; +import { createPublicClient, http, parseAbiItem } from "viem"; import { arbitrumGoerli } from "viem/chains"; -import { jsonAction, graphqlAction, fetchAction, callAction } from "./dataMappings"; +import { jsonAction, graphqlAction, fetchAction, eventAction, callAction } from "./dataMappings"; import { klerosCoreABI } from "../../web/src/hooks/contracts/generated"; const currentAcc = { @@ -70,60 +70,40 @@ describe("graphqlAction", () => { }); }); -// describe("callAction", () => { -// it("should call the contract and return populated data", async () => { -// const mockAbi = klerosCoreABI; -// const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1"]; // Add the contract address as an input -// const mockSeek = ["pinakion"]; // Adjusting this to seek for 'pinakion' -// const mockPopulate = ["result1", "tokenAddress"]; // Changing 'result2' to 'tokenAddress' to be more descriptive +describe("callAction", () => { + it("should call the contract and return populated data", async () => { + const mockAbi = parseAbiItem(`function appealCost(uint256 _disputeID) public view returns (uint256)`); + const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", BigInt(1)]; + const mockSeek = ["appealCost"]; + const mockPopulate = ["cost"]; -// const result = await callAction(mockAbi, mockInputs, mockSeek, mockPopulate); + const result = await callAction(mockAbi, mockInputs, mockSeek, mockPopulate); -// console.log(result); -// expect(result).to.eql({ -// result1: "data1", -// tokenAddress: "0x4deeefd054434bf6721ef39aa18efb3fd0d12610", -// }); -// }); -// }); - -// describe("eventAction", () => { -// let createEventFilterStub; -// let getFilterLogsStub; - -// beforeEach(() => { -// // Mock the methods from publicClient -// createEventFilterStub = sinon.stub(publicClient, "createEventFilter"); -// getFilterLogsStub = sinon.stub(publicClient, "getFilterLogs"); -// }); - -// afterEach(() => { -// // Restore the mocked methods -// createEventFilterStub.restore(); -// getFilterLogsStub.restore(); -// }); - -// it("should fetch event data and return populated data", async () => { -// const mockSource = "contractEvent"; -// const mockInputs = []; -// const mockSeek = ["eventItem1", "eventItem2"]; -// const mockPopulate = ["result1", "result2"]; -// const mockEventData = { -// eventItem1: "eventData1", -// eventItem2: "eventData2", -// }; - -// const mockFilter = {}; // dummy filter for this test -// const mockContractEvent = [{ args: mockEventData }]; + console.log("result", result); + expect(result).to.eql({ + cost: BigInt(30000000000000), + }); + }); +}); -// // Mock the return values -// createEventFilterStub.resolves(mockFilter); -// getFilterLogsStub.resolves(mockContractEvent); +describe("eventAction", () => { + it("should fetch event data and return populated data", async () => { + const mockSource = parseAbiItem( + "event Draw(address indexed _address, uint256 indexed _disputeID, uint256 _roundID, uint256 _voteID)" + ); + const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", BigInt(40250621)]; + const mockSeek = ["_address", "_disputeID"]; + const mockPopulate = ["address", "disputeID"]; + const mockEventData = { + eventItem1: "eventData1", + eventItem2: "eventData2", + }; -// const result = await eventAction(mockSource, mockInputs, mockSeek, mockPopulate); -// expect(result).to.eql({ -// result1: "eventData1", -// result2: "eventData2", -// }); -// }); -// }); + const result = await eventAction(mockSource, mockInputs, mockSeek, mockPopulate); + // console.log("🚀 ~ file: test.ts:108 ~ it ~ result:", result); + expect(result).to.eql({ + address: "0xaeaD6593710Bf28bF4848b24F4ed1F130773d7E6", + disputeID: BigInt(42), + }); + }); +}); From fe678ac58be1a58645aa0105eda98de68da52096 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Fri, 15 Sep 2023 17:25:55 +0200 Subject: [PATCH 05/37] feat(web): function to search for nested keys in json, fetch, graphql actions --- kleros-sdk/dataMappings/dataMappings.ts | 46 ++++++++++++++------ kleros-sdk/dataMappings/test.ts | 58 +++++++++++++++---------- 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/kleros-sdk/dataMappings/dataMappings.ts b/kleros-sdk/dataMappings/dataMappings.ts index 4f51f9ec6..4a68e25fc 100644 --- a/kleros-sdk/dataMappings/dataMappings.ts +++ b/kleros-sdk/dataMappings/dataMappings.ts @@ -71,31 +71,43 @@ const initialState = { }, }; -// Utility function to access nested objects -const getNestedObject = (nestedObj, pathArr) => { - return pathArr.reduce((obj, key) => (obj && obj[key] !== "undefined" ? obj[key] : undefined), nestedObj); +const findNestedKey = (data, keyToFind) => { + if (data.hasOwnProperty(keyToFind)) return data[keyToFind]; + for (let key in data) { + if (typeof data[key] === "object" && data[key] !== null) { + const found = findNestedKey(data[key], keyToFind); + if (found) return found; + } + } + return null; }; -export const jsonAction = (currentAcc, source, seek, populate) => { - const pathArray = typeof source === "string" ? source.split(".") : source; - - const dataFromSource = getNestedObject(currentAcc, pathArray); +export const jsonAction = (data, seek, populate) => { let jsonData = {}; seek.forEach((key, idx) => { - jsonData[populate[idx]] = dataFromSource[key]; + const foundValue = findNestedKey(data, key); + jsonData[populate[idx]] = foundValue; }); return jsonData; }; -export const fetchAction = async (variableName: string, link: string) => { +export const fetchAction = async (link: string, seek, populate) => { const response = await fetch(link); - const data = await response.json(); - return { [variableName]: data }; + const fetchedData = await response.json(); + console.log(fetchedData); + let populatedData = {}; + + seek.forEach((key, idx) => { + const foundValue = findNestedKey(fetchedData, key); + populatedData[populate[idx]] = foundValue; + }); + + return populatedData; }; -export const graphqlAction = async (variableName: string, query: string) => { +export const graphqlAction = async (query: string, seek, populate) => { const response = await fetch("https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-arbitrum-goerli", { method: "POST", headers: { @@ -106,7 +118,15 @@ export const graphqlAction = async (variableName: string, query: string) => { }); const { data } = await response.json(); - return { [variableName]: data }; + console.log(data); + let populatedData = {}; + + seek.forEach((key, idx) => { + const foundValue = findNestedKey(data, key); + populatedData[populate[idx]] = foundValue; + }); + + return populatedData; }; export const callAction = async (abi, inputs, seek, populate) => { diff --git a/kleros-sdk/dataMappings/test.ts b/kleros-sdk/dataMappings/test.ts index 671b7b256..ba759706e 100644 --- a/kleros-sdk/dataMappings/test.ts +++ b/kleros-sdk/dataMappings/test.ts @@ -4,7 +4,7 @@ import { arbitrumGoerli } from "viem/chains"; import { jsonAction, graphqlAction, fetchAction, eventAction, callAction } from "./dataMappings"; import { klerosCoreABI } from "../../web/src/hooks/contracts/generated"; -const currentAcc = { +const exampleObject = { evidence: { fileURI: { photo: "https://photo.url", @@ -20,7 +20,7 @@ const publicClient = createPublicClient({ describe("jsonAction", () => { it("should extract and map data correctly", () => { - const result = jsonAction(currentAcc, "evidence.fileURI", ["photo", "video"], ["photoUrl", "videoUrl"]); + const result = jsonAction(exampleObject, ["photo", "video"], ["photoUrl", "videoUrl"]); expect(result).to.eql({ photoUrl: "https://photo.url", videoUrl: "https://video.url", @@ -30,43 +30,53 @@ describe("jsonAction", () => { describe("fetchAction", () => { it("should fetch data and return in expected format", async () => { - const result = await fetchAction("product", "https://fakestoreapi.com/products/1"); - expect(result).to.eql({ - product: { - id: 1, - title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops", - price: 109.95, - description: - "Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday", - category: "men's clothing", - image: "https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg", - rating: { - rate: 3.9, - count: 120, - }, - }, - }); + const seek = ["rate"]; + const populate = ["rate"]; + const result = await fetchAction("https://fakestoreapi.com/products/1", seek, populate); + + const expectedResult = { + rate: 3.9, + }; + + expect(result).to.eql(expectedResult); }); }); describe("graphqlAction", () => { it("should fetch GraphQL data and return in expected format", async () => { + const seek = ["courts"]; + const populate = ["courts"]; + const mockQuery = ` { - court(id: 1) { + courts(first: 1) { id + stakedJurors(first:1){ + court { + id + } + } } } `; const mockData = { - court: { - id: "1", - }, + courts: [ + { + id: "1", + stakedJurors: [ + { + court: { + id: "1", + }, + }, + ], + }, + ], }; - const result = await graphqlAction("court", mockQuery); - expect(result).to.eql({ court: mockData }); + const result = await graphqlAction(mockQuery, seek, populate); + expect(result).to.eql(mockData); }); }); From 7baec99d3517ea4a01c43d0a12792bc10e70cb28 Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Fri, 15 Sep 2023 18:31:42 +0300 Subject: [PATCH 06/37] fix: contract read and event tests --- kleros-sdk/dataMappings/dataMappings.ts | 16 ++++++------- kleros-sdk/dataMappings/test.ts | 30 ++++++++++++------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/kleros-sdk/dataMappings/dataMappings.ts b/kleros-sdk/dataMappings/dataMappings.ts index 4a68e25fc..a3bd0c56c 100644 --- a/kleros-sdk/dataMappings/dataMappings.ts +++ b/kleros-sdk/dataMappings/dataMappings.ts @@ -133,12 +133,9 @@ export const callAction = async (abi, inputs, seek, populate) => { const data = await publicClient.readContract({ address: inputs[0], abi: [abi], - functionName: seek[0], - args: [inputs[1]], + functionName: inputs[1], + args: [inputs.slice(2)], }); - console.log("callaction"); - - console.log("data", data); let populatedData = {}; @@ -150,11 +147,15 @@ export const callAction = async (abi, inputs, seek, populate) => { }; export const eventAction = async (source, inputs, seek, populate) => { - console.log("entry", inputs[0]); + const argsObject = seek.reduce((acc, key, index) => { + acc[key] = inputs[index + 2]; + return acc; + }, {}); const filter = await publicClient.createEventFilter({ address: inputs[0], event: source, + args: { ...argsObject }, fromBlock: inputs[1], toBlock: "latest", }); @@ -165,13 +166,10 @@ export const eventAction = async (source, inputs, seek, populate) => { // @ts-ignore const eventData = contractEvent[0].args; - // console.log("🚀 ~ file: dataMappings.ts:145 ~ eventAction ~ eventData:", eventData); let populatedData = {}; seek.map((item, index) => { - // console.log("item", item); - populatedData[populate[index]] = eventData[item]; }); diff --git a/kleros-sdk/dataMappings/test.ts b/kleros-sdk/dataMappings/test.ts index ba759706e..2592c385a 100644 --- a/kleros-sdk/dataMappings/test.ts +++ b/kleros-sdk/dataMappings/test.ts @@ -83,8 +83,8 @@ describe("graphqlAction", () => { describe("callAction", () => { it("should call the contract and return populated data", async () => { const mockAbi = parseAbiItem(`function appealCost(uint256 _disputeID) public view returns (uint256)`); - const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", BigInt(1)]; - const mockSeek = ["appealCost"]; + const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", "appealCost", BigInt(1)]; + const mockSeek = ["_disputeID"]; const mockPopulate = ["cost"]; const result = await callAction(mockAbi, mockInputs, mockSeek, mockPopulate); @@ -98,22 +98,22 @@ describe("callAction", () => { describe("eventAction", () => { it("should fetch event data and return populated data", async () => { - const mockSource = parseAbiItem( - "event Draw(address indexed _address, uint256 indexed _disputeID, uint256 _roundID, uint256 _voteID)" - ); - const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", BigInt(40250621)]; - const mockSeek = ["_address", "_disputeID"]; - const mockPopulate = ["address", "disputeID"]; - const mockEventData = { - eventItem1: "eventData1", - eventItem2: "eventData2", - }; + // const mockSource = parseAbiItem( + // "event Draw(address indexed _address, uint256 indexed _disputeID, uint256 _roundID, uint256 _voteID)" + // ); + const mockSource = parseAbiItem("event StakeSet(address indexed _address, uint256 _courtID, uint256 _amount)"); + const mockInputs = [ + "0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", + BigInt(36205881), + "0xE652E5B6409B062FcE5f40E19682f31152d6CD1a", + ]; + const mockSeek = ["_address", "_courtID"]; + const mockPopulate = ["address", "courtID"]; const result = await eventAction(mockSource, mockInputs, mockSeek, mockPopulate); - // console.log("🚀 ~ file: test.ts:108 ~ it ~ result:", result); expect(result).to.eql({ - address: "0xaeaD6593710Bf28bF4848b24F4ed1F130773d7E6", - disputeID: BigInt(42), + address: "0xE652E5B6409B062FcE5f40E19682f31152d6CD1a", + courtID: BigInt(1), }); }); }); From 3cd6e7a8d1c934cb8f84bfb0ac7790ba2f2ed40f Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:37:21 +0200 Subject: [PATCH 07/37] docs(sdk): some info on how to run the tests --- kleros-sdk/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kleros-sdk/README.md b/kleros-sdk/README.md index 247be318a..7045821fe 100644 --- a/kleros-sdk/README.md +++ b/kleros-sdk/README.md @@ -1,7 +1,10 @@ # @kleros/kleros-v2-sdk -_Archon's successor_ +For running data mappings unit tests, first make sure the `ALCHEMY_API_KEY` variable is set inside the `dataMappings.ts` file, then run: -\ +```bash +cd kleros-sdk +yarn mocha -r ts-node/register dataMappings/test.ts +``` 🚧 ⚖️ 🚧 From 1af3f99e250ae0b6481efc35ff9ec60c68781706 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:40:03 +0200 Subject: [PATCH 08/37] docs(sdk): readding some info lines --- kleros-sdk/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kleros-sdk/README.md b/kleros-sdk/README.md index 7045821fe..2044db9d3 100644 --- a/kleros-sdk/README.md +++ b/kleros-sdk/README.md @@ -1,5 +1,7 @@ # @kleros/kleros-v2-sdk +_Archon's successor_ + For running data mappings unit tests, first make sure the `ALCHEMY_API_KEY` variable is set inside the `dataMappings.ts` file, then run: ```bash From 2177ced20cf5bf8844bfaf2be7c8b94d4e2e301f Mon Sep 17 00:00:00 2001 From: nhestrompia Date: Wed, 27 Sep 2023 17:06:48 +0300 Subject: [PATCH 09/37] refactor: data mappings implementation into front-end --- kleros-sdk/dataMappings/dataMappings.ts | 13 +- web/package.json | 1 + web/src/hooks/queries/useDisputeTemplate.ts | 3 +- web/src/pages/DisputeTemplateView.tsx | 33 +++- web/src/utils/dataMappings.ts | 177 +++++++++++++------- yarn.lock | 10 ++ 6 files changed, 164 insertions(+), 73 deletions(-) diff --git a/kleros-sdk/dataMappings/dataMappings.ts b/kleros-sdk/dataMappings/dataMappings.ts index a3bd0c56c..6803d596c 100644 --- a/kleros-sdk/dataMappings/dataMappings.ts +++ b/kleros-sdk/dataMappings/dataMappings.ts @@ -134,13 +134,20 @@ export const callAction = async (abi, inputs, seek, populate) => { address: inputs[0], abi: [abi], functionName: inputs[1], - args: [inputs.slice(2)], + 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, index) => { - populatedData[populate[index]] = data; + seek.map((item) => { + if (typeof data == "object") { + populatedData[populate[item]] = data[item]; + } else { + populatedData[populate[item]] = data; + } }); return populatedData; diff --git a/web/package.json b/web/package.json index 7fb6d1826..b0eb9daba 100644 --- a/web/package.json +++ b/web/package.json @@ -82,6 +82,7 @@ "graphql": "^16.7.1", "graphql-request": "~6.1.0", "moment": "^2.29.4", + "mustache": "^4.2.0", "react": "^18.2.0", "react-chartjs-2": "^4.3.1", "react-dom": "^18.2.0", diff --git a/web/src/hooks/queries/useDisputeTemplate.ts b/web/src/hooks/queries/useDisputeTemplate.ts index 4372c2c20..e1a5bf009 100644 --- a/web/src/hooks/queries/useDisputeTemplate.ts +++ b/web/src/hooks/queries/useDisputeTemplate.ts @@ -39,8 +39,9 @@ export const useDisputeTemplate = (disputeID?: string, arbitrableAddress?: `0x${ { id: templateId.toString() }, true ); + console.log("🚀 ~ file: useDisputeTemplate.ts:38 ~ queryFn: ~ disputeTemplate:", disputeTemplate); - return JSON.parse(disputeTemplate.templateData); + return disputeTemplate; } catch { return {}; } diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index d8a21aa0f..c25cea9f4 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -6,6 +6,9 @@ import { StyledSkeleton } from "components/StyledSkeleton"; 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"; const Container = styled.div` width: 50%; @@ -81,16 +84,36 @@ const StyledTextArea = styled(Textarea)` const DisputeTemplateView: React.FC = () => { const [disputeTemplate, setDisputeTemplate] = useState(""); const [errorMsg, setErrorMessage] = useState(""); - const parsedDisputeTemplate = useMemo(() => { + const { data: template } = useDisputeTemplate("4", "0xE4af4D800Ce12149199FA6f8870cD650cD8f3164"); + // console.log("🚀 ~ file: DisputeTemplateView.tsx:86 ~ template:", template!.templateDataMappings); + + const parsedDisputeTemplate = useMemo(async () => { try { - const parsed = JSON.parse(disputeTemplate); + const parsedMapping = JSON.parse(template?.templateDataMappings); + 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); setErrorMessage(""); - return parsed; + return parsedTemplate; } catch (e) { + console.log("error", e); + setErrorMessage((e as SyntaxError).message); return undefined; } - }, [disputeTemplate]); + }, [template, disputeTemplate]); const isThereInput = useMemo(() => disputeTemplate !== "", [disputeTemplate]); return ( @@ -107,6 +130,8 @@ const DisputeTemplateView: React.FC = () => { }; const Overview: React.FC<{ disputeTemplate: any }> = ({ disputeTemplate }) => { + console.log("disputeTemplate 133", disputeTemplate); + return ( <> diff --git a/web/src/utils/dataMappings.ts b/web/src/utils/dataMappings.ts index ffad42e28..6803d596c 100644 --- a/web/src/utils/dataMappings.ts +++ b/web/src/utils/dataMappings.ts @@ -1,9 +1,14 @@ -import { createPublicClient, http, parseAbiItem } from "viem"; +import { createPublicClient, http, parseAbiItem, webSocket } from "viem"; import { arbitrumGoerli } from "viem/chains"; +import fetch from "node-fetch"; + +const ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY; + +const transport = webSocket(`wss://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}`); const publicClient = createPublicClient({ chain: arbitrumGoerli, - transport: http(), + transport, }); export const mappings = [ @@ -66,14 +71,44 @@ const initialState = { }, }; -const fetchAction = async (variableName: string, link: string) => { +const findNestedKey = (data, keyToFind) => { + if (data.hasOwnProperty(keyToFind)) return data[keyToFind]; + for (let key in data) { + if (typeof data[key] === "object" && data[key] !== null) { + const found = findNestedKey(data[key], keyToFind); + if (found) return found; + } + } + return null; +}; + +export const jsonAction = (data, seek, populate) => { + let jsonData = {}; + + seek.forEach((key, idx) => { + const foundValue = findNestedKey(data, key); + jsonData[populate[idx]] = foundValue; + }); + + return jsonData; +}; + +export const fetchAction = async (link: string, seek, populate) => { const response = await fetch(link); - const data = await response.json(); - return { [variableName]: data }; + const fetchedData = await response.json(); + console.log(fetchedData); + let populatedData = {}; + + seek.forEach((key, idx) => { + const foundValue = findNestedKey(fetchedData, key); + populatedData[populate[idx]] = foundValue; + }); + + return populatedData; }; -const graphqlAction = async (variableName: string, query: string) => { - const response = await fetch("http://graphql-server-endpoint.com", { +export const graphqlAction = async (query: string, seek, populate) => { + const response = await fetch("https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-arbitrum-goerli", { method: "POST", headers: { "Content-Type": "application/json", @@ -83,48 +118,60 @@ const graphqlAction = async (variableName: string, query: string) => { }); const { data } = await response.json(); - return { [variableName]: data }; -}; - -const jsonAction = (currentAcc, source, seek, populate) => { - const dataFromSource = currentAcc[source]; - let jsonData = {}; + console.log(data); + let populatedData = {}; seek.forEach((key, idx) => { - jsonData[populate[idx]] = dataFromSource[key]; + const foundValue = findNestedKey(data, key); + populatedData[populate[idx]] = foundValue; }); - return jsonData; + return populatedData; }; -const callAction = async (source, inputs, seek, populate) => { +export const callAction = async (abi, inputs, seek, populate) => { const data = await publicClient.readContract({ - address: inputs[1], - abi: parseAbiItem(source), - functionName: "", - args: inputs, + address: inputs[0], + abi: [abi], + 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, index) => { - populatedData[populate[index]] = data[item]; + seek.map((item) => { + if (typeof data == "object") { + populatedData[populate[item]] = data[item]; + } else { + populatedData[populate[item]] = data; + } }); return populatedData; }; -const eventAction = async (source, inputs, seek, populate) => { +export const eventAction = async (source, inputs, seek, populate) => { + const argsObject = seek.reduce((acc, key, index) => { + acc[key] = inputs[index + 2]; + return acc; + }, {}); + const filter = await publicClient.createEventFilter({ - address: inputs[1], - event: parseAbiItem(source), - args: inputs, + address: inputs[0], + event: source, + args: { ...argsObject }, + fromBlock: inputs[1], + toBlock: "latest", }); const contractEvent = await publicClient.getFilterLogs({ - filter: filter, + filter: filter as any, }); + // @ts-ignore const eventData = contractEvent[0].args; let populatedData = {}; @@ -136,41 +183,41 @@ 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); +// 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); diff --git a/yarn.lock b/yarn.lock index 799b5fd58..18046f97d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5288,6 +5288,7 @@ __metadata: graphql-request: ~6.1.0 lru-cache: ^7.18.3 moment: ^2.29.4 + mustache: ^4.2.0 parcel: 2.8.3 react: ^18.2.0 react-chartjs-2: ^4.3.1 @@ -23240,6 +23241,15 @@ __metadata: languageName: node linkType: hard +"mustache@npm:^4.2.0": + version: 4.2.0 + resolution: "mustache@npm:4.2.0" + bin: + mustache: bin/mustache + checksum: 928fcb63e3aa44a562bfe9b59ba202cccbe40a46da50be6f0dd831b495be1dd7e38ca4657f0ecab2c1a89dc7bccba0885eab7ee7c1b215830da765758c7e0506 + languageName: node + linkType: hard + "mute-stream@npm:0.0.7": version: 0.0.7 resolution: "mute-stream@npm:0.0.7" From 1ce3e09a22db5b199301bdfd2c86ae7184f1eda2 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:34:04 +0200 Subject: [PATCH 10/37] feat: making data mappings fetching dynamic --- kleros-sdk/dataMappings/dataMappings.ts | 148 +++++++----------------- web/src/pages/DisputeTemplateView.tsx | 45 +++---- web/src/utils/dataMappings.ts | 148 +++++++----------------- 3 files changed, 106 insertions(+), 235 deletions(-) diff --git a/kleros-sdk/dataMappings/dataMappings.ts b/kleros-sdk/dataMappings/dataMappings.ts index 6803d596c..8881eb29a 100644 --- a/kleros-sdk/dataMappings/dataMappings.ts +++ b/kleros-sdk/dataMappings/dataMappings.ts @@ -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) { @@ -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; }); @@ -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) => { @@ -154,6 +99,14 @@ 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; @@ -161,7 +114,7 @@ export const eventAction = async (source, inputs, seek, populate) => { const filter = await publicClient.createEventFilter({ address: inputs[0], - event: source, + event: parsedAbi, args: { ...argsObject }, fromBlock: inputs[1], toBlock: "latest", @@ -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 = {}; @@ -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()] || ""); +}; diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index c25cea9f4..98adbfc73 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -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%; @@ -84,37 +83,41 @@ const StyledTextArea = styled(Textarea)` const DisputeTemplateView: React.FC = () => { const [disputeTemplate, setDisputeTemplate] = useState(""); const [errorMsg, setErrorMessage] = useState(""); - 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 ( { if (data.hasOwnProperty(keyToFind)) return data[keyToFind]; for (let key in data) { @@ -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; }); @@ -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) => { @@ -154,6 +99,14 @@ 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; @@ -161,7 +114,7 @@ export const eventAction = async (source, inputs, seek, populate) => { const filter = await publicClient.createEventFilter({ address: inputs[0], - event: source, + event: parsedAbi, args: { ...argsObject }, fromBlock: inputs[1], toBlock: "latest", @@ -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 = {}; @@ -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()] || ""); +}; From a41397c6115c565d1b9205c877afdc702219bebf Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Wed, 11 Oct 2023 02:33:14 +0200 Subject: [PATCH 11/37] feat(web): improved structures, dispute template view, case overview --- web/src/pages/Cases/CaseDetails/Overview.tsx | 52 ++++++++--- web/src/pages/DisputeTemplateView.tsx | 98 ++++++++++---------- web/src/utils/dataMappings.ts | 22 ++++- 3 files changed, 108 insertions(+), 64 deletions(-) diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index 470c328cf..8e8ffe6f1 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import styled, { css } from "styled-components"; import { landscapeStyle } from "styles/landscapeStyle"; import { useParams } from "react-router-dom"; @@ -8,6 +8,7 @@ import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { useCourtPolicy } from "queries/useCourtPolicy"; import { isUndefined } from "utils/index"; +import { deepParseTemplateWithData, executeAction } from "utils/dataMappings"; import { Periods } from "consts/periods"; import { IPFS_GATEWAY } from "consts/index"; import PolicyIcon from "svgs/icons/policy.svg"; @@ -117,12 +118,38 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex const { data: disputeDetails } = useDisputeDetailsQuery(id); const { data: courtPolicy } = useCourtPolicy(courtID); const { data: votingHistory } = useVotingHistory(id); + + const [parsedDisputeTemplate, setParsedDisputeTemplate] = useState({}); + const localRounds = votingHistory?.dispute?.disputeKitDispute?.localRounds; const courtName = courtPolicy?.name; const court = disputeDetails?.dispute?.court; const rewards = court ? `≥ ${formatEther(court.feeForJuror)} ETH` : undefined; const category = disputeTemplate ? disputeTemplate.category : undefined; + useEffect(() => { + const fetchData = async () => { + try { + const parsedTemplate = JSON.parse(disputeTemplate?.templateData); + const parsedMapping = JSON.parse(disputeTemplate?.templateDataMappings); + + let populatedData = {}; + + for (const action of parsedMapping) { + const result = await executeAction(action); + populatedData = { ...populatedData, ...result }; + } + + const finalTemplate = deepParseTemplateWithData(parsedTemplate, populatedData); + setParsedDisputeTemplate(finalTemplate); + } catch (e) { + console.error(e); + } + }; + + fetchData(); + }, [disputeTemplate]); + return ( <> @@ -130,25 +157,27 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex {isUndefined(disputeTemplate) ? ( ) : ( - disputeTemplate?.title ?? "The dispute's template is not correct please vote refuse to arbitrate" + parsedDisputeTemplate?.template?.content ?? + "The dispute's template is not correct please vote refuse to arbitrate" )} - {disputeTemplate?.question} - {disputeTemplate?.description} + {parsedDisputeTemplate?.question} + {parsedDisputeTemplate?.description} - {disputeTemplate?.frontendUrl && ( - + {parsedDisputeTemplate?.frontendUrl && ( + Go to arbitrable )} - {disputeTemplate &&

Voting Options

} + {parsedDisputeTemplate &&

Voting Options

} - {disputeTemplate?.answers?.map((answer: { title: string; description: string }, i: number) => ( + {parsedDisputeTemplate?.options?.titles?.map((title: string, i: number) => ( Option {i + 1}: - + + ))} @@ -160,14 +189,13 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex )} -

Make sure you understand the Policies

- {disputeTemplate?.policyURI && ( - + {parsedDisputeTemplate?.policyURI && ( + Dispute Policy diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index 98adbfc73..285da628a 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -1,13 +1,10 @@ -import React, { useMemo, useState } from "react"; +import React, { useEffect, useState } from "react"; import styled from "styled-components"; import { Textarea } from "@kleros/ui-components-library"; import PolicyIcon from "svgs/icons/policy.svg"; -import { StyledSkeleton } from "components/StyledSkeleton"; import ReactMarkdown from "components/ReactMarkdown"; -import { isUndefined } from "utils/index"; import { IPFS_GATEWAY } from "consts/index"; -import { useDisputeTemplate } from "hooks/queries/useDisputeTemplate"; -import { executeAction, parseTemplateWithData } from "utils/dataMappings"; +import { deepParseTemplateWithData, executeAction } from "utils/dataMappings"; const Container = styled.div` width: 50%; @@ -81,51 +78,54 @@ const StyledTextArea = styled(Textarea)` `; const DisputeTemplateView: React.FC = () => { - const [disputeTemplate, setDisputeTemplate] = useState(""); - const [errorMsg, setErrorMessage] = useState(""); - const { data: template } = useDisputeTemplate("7", "0xE4af4D800Ce12149199FA6f8870cD650cD8f3164"); - - const parsedDisputeTemplate = useMemo(async () => { - try { - console.log(template); - const parsedTemplate = JSON.parse(template?.templateData); - 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 [parsedDisputeTemplate, setParsedDisputeTemplate] = useState({}); + const [disputeTemplateInput, setDisputeTemplateInput] = useState(""); + const [dataMappingsInput, setDataMappingsInput] = useState(""); + + useEffect(() => { + if (!disputeTemplateInput || !dataMappingsInput) return; + + const fetchData = async () => { + let parsedTemplate, parsedMapping; + + try { + parsedTemplate = JSON.parse(disputeTemplateInput); + parsedMapping = JSON.parse(dataMappingsInput); + } catch (e) { + console.error(e); + setParsedDisputeTemplate(undefined); + return; } - const finalTemplate = parseTemplateWithData(parsedTemplate.template.content, populatedData); - console.log("finalTemplate with everything parsed", finalTemplate); - setDisputeTemplate(finalTemplate); - setErrorMessage(""); - return finalTemplate; - } catch (e) { - console.log("error", e); - setErrorMessage((e as SyntaxError).message); - return undefined; - } - }, [template, disputeTemplate]); + try { + let populatedData = {}; - const isThereInput = useMemo(() => disputeTemplate !== "", [disputeTemplate]); + for (const action of parsedMapping) { + const result = await executeAction(action); + populatedData = { ...populatedData, ...result }; + } + + const finalTemplate = deepParseTemplateWithData(parsedTemplate, populatedData); + setParsedDisputeTemplate(finalTemplate); + } catch (e) { + console.error(e); + } + }; + + fetchData(); + }, [disputeTemplateInput, dataMappingsInput]); return ( setDisputeTemplate(e.target.value)} + value={disputeTemplateInput} + onChange={(e) => setDisputeTemplateInput(e.target.value)} placeholder="Enter dispute template" - variant={isThereInput && errorMsg !== "" ? "error" : ""} - message={isThereInput ? errorMsg : ""} + /> + setDataMappingsInput(e.target.value)} + placeholder="Enter data mappings" /> @@ -133,17 +133,12 @@ const DisputeTemplateView: React.FC = () => { }; const Overview: React.FC<{ disputeTemplate: any }> = ({ disputeTemplate }) => { - console.log("disputeTemplate 133", disputeTemplate); - return ( <>

- {isUndefined(disputeTemplate) ? ( - - ) : ( - disputeTemplate?.title ?? "The dispute's template is not correct please vote refuse to arbitrate" - )} + {disputeTemplate?.template?.content ?? + "The dispute's template is not correct please vote refuse to arbitrate"}

{disputeTemplate?.question} @@ -156,10 +151,11 @@ const Overview: React.FC<{ disputeTemplate: any }> = ({ disputeTemplate }) => { )} {disputeTemplate &&

Voting Options

} - {disputeTemplate?.answers?.map((answer: { title: string; description: string }, i: number) => ( + {disputeTemplate?.options?.titles?.map((title: string, i: number) => ( Option {i + 1}: - + + ))}
diff --git a/web/src/utils/dataMappings.ts b/web/src/utils/dataMappings.ts index 8881eb29a..918f211f7 100644 --- a/web/src/utils/dataMappings.ts +++ b/web/src/utils/dataMappings.ts @@ -1,4 +1,4 @@ -import { createPublicClient, http, parseAbiItem, webSocket } from "viem"; +import { createPublicClient, parseAbiItem, webSocket } from "viem"; import { arbitrumGoerli } from "viem/chains"; import fetch from "node-fetch"; @@ -155,3 +155,23 @@ export const executeAction = async (action) => { export const parseTemplateWithData = (template, data) => { return template.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || ""); }; + +export const deepParseTemplateWithData = (templateObj: any, data: any): any => { + if (typeof templateObj === "string") { + return templateObj.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || ""); + } + + if (Array.isArray(templateObj)) { + return templateObj.map((item) => deepParseTemplateWithData(item, data)); + } + + if (typeof templateObj === "object") { + let newObject: any = {}; + for (let key in templateObj) { + newObject[key] = deepParseTemplateWithData(templateObj[key], data); + } + return newObject; + } + + return templateObj; +}; From 7f990aa4af340c214afbf12dd8734694c7915842 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 12 Oct 2023 01:59:22 +0100 Subject: [PATCH 12/37] docs: added a version field to the dispute template --- contracts/scripts/disputeCreatorBot.ts | 8 +-- .../NewDisputeTemplate.schema.json | 40 +++++++++------ .../curate/NewDisputeTemplate.curate.jsonc | 3 +- .../example/DisputeDetails.curate.jsonc | 1 + .../linguo/NewDisputeTemplate.linguo.jsonc | 3 +- .../example/DisputeDetails.linguo.jsonc | 1 + .../moderate/DisputeDetails.moderate.json | 33 ++++++++++++ .../poh/NewDisputeTemplate.poh1.jsonc | 3 +- .../poh/NewDisputeTemplate.poh2.jsonc | 3 +- .../DisputeDetails.poh1.jsonc | 1 + .../DisputeDetails.poh2.jsonc | 1 + .../DisputeDetails.reality.schema.json | 4 ++ .../reality/NewDisputeTemplate.reality.jsonc | 3 +- .../example1/DisputeDetails.reality1.jsonc | 1 + .../example2/DisputeDetails.reality2.jsonc | 1 + .../reality/example3/DisputeMappings.json | 50 +++++++++++++++++++ .../example3/DisputeTemplate.json.mustache | 27 ++++++++++ 17 files changed, 158 insertions(+), 25 deletions(-) create mode 100644 kleros-sdk/config/v2-disputetemplate/moderate/DisputeDetails.moderate.json create mode 100644 kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeMappings.json create mode 100644 kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeTemplate.json.mustache diff --git a/contracts/scripts/disputeCreatorBot.ts b/contracts/scripts/disputeCreatorBot.ts index d487a2267..4ac898b6e 100644 --- a/contracts/scripts/disputeCreatorBot.ts +++ b/contracts/scripts/disputeCreatorBot.ts @@ -36,10 +36,10 @@ export default async function main() { "000000000000000000000000000000000000000000000000000000000000000B" + // minJurors 11 "0000000000000000000000000000000000000000000000000000000000000002"; // disputeKitId 2 const templates = [ - `{"title":"A reality.eth question","description":"A reality.eth question has been raised to arbitration.","question":"**Kleros Moderate:** Did the user, **degenape6** (ID: 1554345080), break the Telegram group, ***[Kleros Trading Group]()*** (ID: -1001151472172), ***[rules](https://ipfs.kleros.io/ipfs/Qme3Qbj9rKUNHUe9vj9rqCLnTVUCWKy2YfveQF8HiuWQSu/Kleros%20Moderate%20Community%20Rules.pdf)*** due to conduct related to the ***[message](https://t.me/c/1151472172/116662)*** (***[backup](https://ipfs.kleros.io/ipfs/QmVbFrZR1bcyQzZjvLyXwL9ekDxrqHERykdreRxXrw4nqg/animations_file_23.mp4)***)?","answers":[{"id":"0x01","title":"Yes","reserved":false},{"id":"0x02","title":"No","reserved":false},{"id":"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF","title":"Answered Too Soon","reserved":true}],"policyURI":"/ipfs/QmZ5XaV2RVgBADq5qMpbuEwgCuPZdRgCeu8rhGtJWLV6yz","frontendUrl":"https://reality.eth.limo/app/#!/question/0xe78996a233895be74a66f451f1019ca9734205cc-0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39","arbitrableChainID":"100","arbitrableAddress":"0x2e39b8f43d0870ba896f516f78f57cde773cf805","arbitratorChainID":"421613","arbitratorAddress":"0xD08Ab99480d02bf9C092828043f611BcDFEA917b","category":"Oracle","lang":"en_US","specification":"KIP99"}`, - `{"title":"Add an entry to Ledger Contract Domain Name registry v2","description":"Someone requested to add an entry to Ledger Contract Domain Name registry v2","question":"Does the entry comply with the required criteria?","answers":[{"title":"Yes, Add It","description":"Select this if you think the entry complies with the required criteria and should be added."},{"title":"No, Don't Add It","description":"Select this if you think the entry does not comply with the required criteria and should not be added."}],"policyURI":"/ipfs/QmW3nQcMW2adyqe6TujRTYkyq26PiDqcmmTjdgKiz9ynPV","frontendUrl":"https://curate.kleros.io/tcr/100/0x957a53a994860be4750810131d9c876b2f52d6e1/0xc2c1aa705632f53051f22a9f65967c0944370020a7489aba608bd0d755ca1234","arbitratorChainID":"421613","arbitratorAddress":"0x791812B0B9f2ba260B2DA432BB02Ee23BC1bB509","category":"Curation","specification":"KIP0X","lang":"en_US"}`, - `{"title":"Omen Question: News & Politics","description":"This reality dispute has been created by Omen, we advise you to read [the Omen Rules](https://cdn.kleros.link/ipfs/QmU1oZzsduGwtC7vCUQPw1QcBP6BDNDkg4t6zkowPucVcx) and consult the evidence provided in [the Market Comments](https://omen.eth.limo/#/0x95b2271039b020aba31b933039e042b60b063800).","question":"**Assuming that today is December 20th 2020, will Joe Biden win the 2020 United States presidential election?**","answers":[{"title":"Yes"},{"title":"No"}],"policyURI":"/ipfs/QmU1oZzsduGwtC7vCUQPw1QcBP6BDNDkg4t6zkowPucVcx","frontendUrl":"https://omen.eth.limo/#/0x95b2271039b020aba31b933039e042b60b063800","arbitratorChainID":"421613","arbitratorAddress":"0x791812B0B9f2ba260B2DA432BB02Ee23BC1bB509","category":"Oracle","specification":"KIP0X","lang":"en_US"}`, - `{"title":"Proof of Humanity Registration Request","description":"A request to register the specified entry to a list of provable humans.","question":"Should the request to register be accepted?","answers":[{"title":"Yes","description":"Accept the request to register the entry."},{"title":"No","description":"Deny the request."}],"policyURI":"/ipfs/QmYPf2fdSyr9BiSy6pJFUmB1oTUPwg6dhEuFqL1n4ZosgH","frontendUrl":"https://app.proofofhumanity.id/profile/0x00de4b13153673bcae2616b67bf822500d325fc3?network=mainnet","arbitratorChainID":"421613","arbitratorAddress":"0x791812B0B9f2ba260B2DA432BB02Ee23BC1bB509","category":"Curated List","specification":"KIP0X","lang":"en_US"}`, + `{"title":"A reality.eth question","description":"A reality.eth question has been raised to arbitration.","question":"**Kleros Moderate:** Did the user, **degenape6** (ID: 1554345080), break the Telegram group, ***[Kleros Trading Group]()*** (ID: -1001151472172), ***[rules](https://ipfs.kleros.io/ipfs/Qme3Qbj9rKUNHUe9vj9rqCLnTVUCWKy2YfveQF8HiuWQSu/Kleros%20Moderate%20Community%20Rules.pdf)*** due to conduct related to the ***[message](https://t.me/c/1151472172/116662)*** (***[backup](https://ipfs.kleros.io/ipfs/QmVbFrZR1bcyQzZjvLyXwL9ekDxrqHERykdreRxXrw4nqg/animations_file_23.mp4)***)?","answers":[{"id":"0x01","title":"Yes","reserved":false},{"id":"0x02","title":"No","reserved":false},{"id":"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF","title":"Answered Too Soon","reserved":true}],"policyURI":"/ipfs/QmZ5XaV2RVgBADq5qMpbuEwgCuPZdRgCeu8rhGtJWLV6yz","frontendUrl":"https://reality.eth.limo/app/#!/question/0xe78996a233895be74a66f451f1019ca9734205cc-0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39","arbitrableChainID":"100","arbitrableAddress":"0x2e39b8f43d0870ba896f516f78f57cde773cf805","arbitratorChainID":"421613","arbitratorAddress":"0xD08Ab99480d02bf9C092828043f611BcDFEA917b","category":"Oracle","lang":"en_US","specification":"KIP99","version": "1.0"}`, + `{"title":"Add an entry to Ledger Contract Domain Name registry v2","description":"Someone requested to add an entry to Ledger Contract Domain Name registry v2","question":"Does the entry comply with the required criteria?","answers":[{"title":"Yes, Add It","description":"Select this if you think the entry complies with the required criteria and should be added."},{"title":"No, Don't Add It","description":"Select this if you think the entry does not comply with the required criteria and should not be added."}],"policyURI":"/ipfs/QmW3nQcMW2adyqe6TujRTYkyq26PiDqcmmTjdgKiz9ynPV","frontendUrl":"https://curate.kleros.io/tcr/100/0x957a53a994860be4750810131d9c876b2f52d6e1/0xc2c1aa705632f53051f22a9f65967c0944370020a7489aba608bd0d755ca1234","arbitratorChainID":"421613","arbitratorAddress":"0x791812B0B9f2ba260B2DA432BB02Ee23BC1bB509","category":"Curation","specification":"KIP0X","lang":"en_US","version": "1.0"}`, + `{"title":"Omen Question: News & Politics","description":"This reality dispute has been created by Omen, we advise you to read [the Omen Rules](https://cdn.kleros.link/ipfs/QmU1oZzsduGwtC7vCUQPw1QcBP6BDNDkg4t6zkowPucVcx) and consult the evidence provided in [the Market Comments](https://omen.eth.limo/#/0x95b2271039b020aba31b933039e042b60b063800).","question":"**Assuming that today is December 20th 2020, will Joe Biden win the 2020 United States presidential election?**","answers":[{"title":"Yes"},{"title":"No"}],"policyURI":"/ipfs/QmU1oZzsduGwtC7vCUQPw1QcBP6BDNDkg4t6zkowPucVcx","frontendUrl":"https://omen.eth.limo/#/0x95b2271039b020aba31b933039e042b60b063800","arbitratorChainID":"421613","arbitratorAddress":"0x791812B0B9f2ba260B2DA432BB02Ee23BC1bB509","category":"Oracle","specification":"KIP0X","lang":"en_US","version": "1.0"}`, + `{"title":"Proof of Humanity Registration Request","description":"A request to register the specified entry to a list of provable humans.","question":"Should the request to register be accepted?","answers":[{"title":"Yes","description":"Accept the request to register the entry."},{"title":"No","description":"Deny the request."}],"policyURI":"/ipfs/QmYPf2fdSyr9BiSy6pJFUmB1oTUPwg6dhEuFqL1n4ZosgH","frontendUrl":"https://app.proofofhumanity.id/profile/0x00de4b13153673bcae2616b67bf822500d325fc3?network=mainnet","arbitratorChainID":"421613","arbitratorAddress":"0x791812B0B9f2ba260B2DA432BB02Ee23BC1bB509","category":"Curated List","specification":"KIP0X","lang":"en_US","version": "1.0"}`, ]; const randomTemplate = templates[Math.floor(Math.random() * templates.length)]; const nbOfChoices = 2; diff --git a/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json b/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json index bb94f67b2..cf8efc141 100644 --- a/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json +++ b/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json @@ -22,22 +22,6 @@ "type": "string", "default": "NewDisputeTemplate.schema.json" }, - "category": { - "type": "string", - "default": "", - "title": "The category Schema", - "examples": [ - "Oracle" - ] - }, - "lang": { - "type": "string", - "default": "", - "title": "The lang Schema", - "examples": [ - "en_US" - ] - }, "title": { "type": "string", "default": "", @@ -335,6 +319,22 @@ "0xD08Ab99480d02bf9C092828043f611BcDFEA917b" ] }, + "category": { + "type": "string", + "default": "", + "title": "The category Schema", + "examples": [ + "Oracle" + ] + }, + "lang": { + "type": "string", + "default": "", + "title": "The lang Schema", + "examples": [ + "en_US" + ] + }, "specification": { "type": "string", "default": "", @@ -343,6 +343,14 @@ "KIP00", "KIP99" ] + }, + "version": { + "type": "string", + "default": "1.0", + "title": "The version Schema", + "examples": [ + "1.0" + ] } } } diff --git a/kleros-sdk/config/v2-disputetemplate/curate/NewDisputeTemplate.curate.jsonc b/kleros-sdk/config/v2-disputetemplate/curate/NewDisputeTemplate.curate.jsonc index bb99c033a..65731ddbd 100644 --- a/kleros-sdk/config/v2-disputetemplate/curate/NewDisputeTemplate.curate.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/curate/NewDisputeTemplate.curate.jsonc @@ -20,5 +20,6 @@ "arbitratorChainID": "421613", "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore "category": "Curated Lists", - "specification": "KIP88" + "specification": "KIP88", + "version": "1.0" } diff --git a/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeDetails.curate.jsonc b/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeDetails.curate.jsonc index e00b87af4..e303e5bf0 100644 --- a/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeDetails.curate.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeDetails.curate.jsonc @@ -32,6 +32,7 @@ "category": "Curated Lists", "lang": "en_US", "specification": "KIP88", + "version": "1.0", "metadata": { "tcrTitle": "Ledger Contract Domain Name registry v2", "tcrDescription": "A list of contract addresses and the domain names they are meant to be used from .", diff --git a/kleros-sdk/config/v2-disputetemplate/linguo/NewDisputeTemplate.linguo.jsonc b/kleros-sdk/config/v2-disputetemplate/linguo/NewDisputeTemplate.linguo.jsonc index e97ee3b0b..4bec1fc39 100644 --- a/kleros-sdk/config/v2-disputetemplate/linguo/NewDisputeTemplate.linguo.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/linguo/NewDisputeTemplate.linguo.jsonc @@ -20,5 +20,6 @@ "arbitratorChainID": "421613", "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore "category": "Translation", - "specification": "KIP999" + "specification": "KIP999", + "version": "1.0" } diff --git a/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeDetails.linguo.jsonc b/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeDetails.linguo.jsonc index e8119f2d8..d1d661f55 100644 --- a/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeDetails.linguo.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeDetails.linguo.jsonc @@ -32,6 +32,7 @@ "category": "Translation", "lang": "en_US", "specification": "KIP999", + "version": "1.0", "metadata": { "linguoAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", "linguoTranslationID": "76", diff --git a/kleros-sdk/config/v2-disputetemplate/moderate/DisputeDetails.moderate.json b/kleros-sdk/config/v2-disputetemplate/moderate/DisputeDetails.moderate.json new file mode 100644 index 000000000..efb4edc85 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/moderate/DisputeDetails.moderate.json @@ -0,0 +1,33 @@ +{ + "$schema": "./DisputeDetails.reality.schema.json", + "title": "A reality.eth question", + "description": "A reality.eth question has been raised to arbitration.", + "question": "**Kleros Moderate:** Did the user, **degenape6** (ID: 1554345080), break the Telegram group, ***[Kleros Trading Group]()*** (ID: -1001151472172), ***[rules](https://ipfs.kleros.io/ipfs/Qme3Qbj9rKUNHUe9vj9rqCLnTVUCWKy2YfveQF8HiuWQSu/Kleros%20Moderate%20Community%20Rules.pdf)*** due to conduct related to the ***[message](https://t.me/c/1151472172/116662)*** (***[backup](https://ipfs.kleros.io/ipfs/QmVbFrZR1bcyQzZjvLyXwL9ekDxrqHERykdreRxXrw4nqg/animations_file_23.mp4)***)?", + "answers": [ + { + "id": "0x01", + "title": "Yes", + "reserved": false + }, + { + "id": "0x02", + "title": "No", + "reserved": false + }, + { + "id": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "title": "Answered Too Soon", + "reserved": true + } + ], + "policyURI": "/ipfs/QmZ5XaV2RVgBADq5qMpbuEwgCuPZdRgCeu8rhGtJWLV6yz", + "frontendUrl": "https://reality.eth.limo/app/#!/question/0xe78996a233895be74a66f451f1019ca9734205cc-0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39", + "arbitrableChainID": "100", + "arbitrableAddress": "0x2e39b8f43d0870ba896f516f78f57cde773cf805", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", + "category": "Oracle", + "lang": "en_US", + "specification": "KIP99", + "version": "1.0" +} diff --git a/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh1.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh1.jsonc index aa644fb1e..a2da3e49d 100644 --- a/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh1.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh1.jsonc @@ -20,5 +20,6 @@ "arbitratorChainID": "421613", "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore "category": "Curated Lists", - "specification": "KIP88" + "specification": "KIP88", + "version": "1.0" } diff --git a/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh2.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh2.jsonc index f9225b917..2d3e43db6 100644 --- a/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh2.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh2.jsonc @@ -20,5 +20,6 @@ "arbitratorChainID": "421613", "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore "category": "Curated Lists", - "specification": "KIP88" + "specification": "KIP88", + "version": "1.0" } diff --git a/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeDetails.poh1.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeDetails.poh1.jsonc index 373f72556..032ab9e0d 100644 --- a/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeDetails.poh1.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeDetails.poh1.jsonc @@ -32,6 +32,7 @@ "category": "Curated Lists", "lang": "en_US", "specification": "KIP77", + "version": "1.0", "metadata": { }, "externalDisputeID": "0x306000938609016839401998194416306598562578921596", // hash(itemID, requestID) diff --git a/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeDetails.poh2.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeDetails.poh2.jsonc index d60c90757..c28604639 100644 --- a/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeDetails.poh2.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeDetails.poh2.jsonc @@ -32,6 +32,7 @@ "category": "Curated Lists", "lang": "en_US", "specification": "KIP77", + "version": "1.0", "metadata": { }, "externalDisputeID": "0x2f0c53ed326eb88ef6a01ff83df458c1cebe5b9ee5e8509525189d9422e28983", // hash(itemID, requestID) diff --git a/kleros-sdk/config/v2-disputetemplate/reality/DisputeDetails.reality.schema.json b/kleros-sdk/config/v2-disputetemplate/reality/DisputeDetails.reality.schema.json index 9eff1c055..bd595e2a7 100644 --- a/kleros-sdk/config/v2-disputetemplate/reality/DisputeDetails.reality.schema.json +++ b/kleros-sdk/config/v2-disputetemplate/reality/DisputeDetails.reality.schema.json @@ -19,6 +19,7 @@ "category", "lang", "specification", + "version", "metadata", "externalDisputeID", "arbitrableDisputeID", @@ -70,6 +71,9 @@ "specification": { "$ref": "../NewDisputeTemplate.schema.json#/properties/specification" }, + "version": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/version" + }, "metadata": { "type": "object", "default": {}, diff --git a/kleros-sdk/config/v2-disputetemplate/reality/NewDisputeTemplate.reality.jsonc b/kleros-sdk/config/v2-disputetemplate/reality/NewDisputeTemplate.reality.jsonc index ac9495234..9ae5fe399 100644 --- a/kleros-sdk/config/v2-disputetemplate/reality/NewDisputeTemplate.reality.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/reality/NewDisputeTemplate.reality.jsonc @@ -19,5 +19,6 @@ "arbitratorChainID": "421613", "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore "category": "Oracle", - "specification": "KIP99" + "specification": "KIP99", + "version": "1.0" } diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeDetails.reality1.jsonc b/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeDetails.reality1.jsonc index a70e1e928..69b2c5e5d 100644 --- a/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeDetails.reality1.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeDetails.reality1.jsonc @@ -34,6 +34,7 @@ "category": "Oracle", "lang": "en_US", "specification": "KIP99", + "version": "1.0", "metadata": { "realityAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", "realityTemplateID": "76", diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeDetails.reality2.jsonc b/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeDetails.reality2.jsonc index 669c28d1e..9e3215879 100644 --- a/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeDetails.reality2.jsonc +++ b/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeDetails.reality2.jsonc @@ -40,6 +40,7 @@ "category": "Oracle", "lang": "en_US", "specification": "KIP99", + "version": "1.0", "metadata": { "realityAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", "realityTemplateID": "2", diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeMappings.json b/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeMappings.json new file mode 100644 index 000000000..197db3a76 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeMappings.json @@ -0,0 +1,50 @@ +[ + { + "type": "json", + "source": { + "question": "**Kleros Moderate:** Did the user, **degenape6** (ID: 1554345080), break the Telegram group, ***[Kleros Trading Group]()*** (ID: -1001151472172), ***[rules](https://ipfs.kleros.io/ipfs/Qme3Qbj9rKUNHUe9vj9rqCLnTVUCWKy2YfveQF8HiuWQSu/Kleros%20Moderate%20Community%20Rules.pdf)*** due to conduct related to the ***[message](https://t.me/c/1151472172/116662)*** (***[backup](https://ipfs.kleros.io/ipfs/QmVbFrZR1bcyQzZjvLyXwL9ekDxrqHERykdreRxXrw4nqg/animations_file_23.mp4)***)?", + "type": "single-select", + "answers": [ + { + "title": "Refuse to Arbitrate or Invalid", + "id": "0x00", + "reserved": true + }, + { + "title": "Yes", + "description": "The user broke the rules.", + "id": "0x01", + "reserved": false + }, + { + "title": "No", + "description": "The user didnt break the rules.", + "id": "0x02", + "reserved": false + }, + { + "id": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "title": "Answered Too Soon", + "reserved": true, + "last": true + } + ], + "questionId": "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39", + "realityAddress": "0x14a6748192aBC6E10CA694Ae07bDd4327D6c7A51" + }, + "seek": [ + "question", + "type", + "answers", + "questionId", + "realityAddress" + ], + "populate": [ + "question", + "type", + "answers", + "questionId", + "realityAddress" + ] + } +] diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeTemplate.json.mustache b/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeTemplate.json.mustache new file mode 100644 index 000000000..10dc42896 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeTemplate.json.mustache @@ -0,0 +1,27 @@ +{ + "title": "A reality.eth question", + "description": "A reality.eth question has been raised to arbitration.", + "question": "{{ question }}", + "type": "{{ type }}", + "answers": [ + {{# answers }} + { + "title": "{{ title }}", + "description": "{{ description }}", + "id": "{{ id }}", + "reserved": {{ reserved }} + }{{^ last }},{{/ last }} + {{/ answers }} + + ], + "policyURI": "/ipfs/QmZ5XaV2RVgBADq5qMpbuEwgCuPZdRgCeu8rhGtJWLV6yz", + "frontendUrl": "https://reality.eth.limo/app/#!/question/{{ realityAddress }}-{{ questionId }}", + "arbitrableChainID": "100", + "arbitrableAddress": "0x2e39b8f43d0870ba896f516f78f57cde773cf805", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", + "category": "Oracle", + "lang": "en_US", + "specification": "KIP99", + "version": "1.0" +} \ No newline at end of file From 49830da99cd598b00900115465f1fb1be109ebe4 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 12 Oct 2023 02:04:00 +0100 Subject: [PATCH 13/37] feat: added mustache template rendering --- kleros-sdk/dataMappings/dataMappings.ts | 18 ++++-- web/.env.devnet.public | 2 +- web/package.json | 3 +- web/src/components/DisputeCard/index.tsx | 24 ++++--- web/src/consts/index.ts | 2 + web/src/pages/Cases/CaseDetails/Overview.tsx | 67 ++++++++++---------- web/src/pages/DisputeTemplateView.tsx | 60 ++++++++---------- web/src/utils/dataMappings.ts | 32 ++++------ web/src/utils/disputeDetails.ts | 32 ++++++++++ yarn.lock | 18 ++++-- 10 files changed, 150 insertions(+), 108 deletions(-) create mode 100644 web/src/utils/disputeDetails.ts diff --git a/kleros-sdk/dataMappings/dataMappings.ts b/kleros-sdk/dataMappings/dataMappings.ts index 8881eb29a..16cd8a25f 100644 --- a/kleros-sdk/dataMappings/dataMappings.ts +++ b/kleros-sdk/dataMappings/dataMappings.ts @@ -1,6 +1,8 @@ -import { createPublicClient, http, parseAbiItem, webSocket } from "viem"; +import { createPublicClient, parseAbiItem, webSocket } from "viem"; import { arbitrumGoerli } from "viem/chains"; import fetch from "node-fetch"; +import mustache from "mustache"; +import { DisputeDetails } from "./disputeDetails"; const ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY; @@ -37,7 +39,7 @@ export const fetchAction = async (link: string, seek, populate) => { const response = await fetch(link); const fetchedData = await response.json(); console.log(fetchedData); - let populatedData = {}; + const populatedData = {}; seek.forEach((key, idx) => { const foundValue = findNestedKey(fetchedData, key); @@ -85,7 +87,7 @@ export const callAction = async (source, inputs, seek, populate) => { args: inputs.slice(2), }); - let populatedData = {}; + const populatedData = {}; seek.map((item) => { if (typeof data == "object") { @@ -126,7 +128,7 @@ export const eventAction = async (source, inputs, seek, populate) => { const eventData = contractEvent[0].args; - let populatedData = {}; + const populatedData = {}; seek.map((item, index) => { populatedData[populate[index]] = eventData[item]; @@ -155,3 +157,11 @@ export const executeAction = async (action) => { export const parseTemplateWithData = (template, data) => { return template.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || ""); }; + +export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { + const render = mustache.render(mustacheTemplate, data); + console.log("MUSTACHE RENDER: ", render); + const dispute = JSON.parse(render); + // TODO: validate the object according to the DisputeDetails type or a JSON schema + return dispute; +}; diff --git a/web/.env.devnet.public b/web/.env.devnet.public index 6b5dbedb8..adeed1601 100644 --- a/web/.env.devnet.public +++ b/web/.env.devnet.public @@ -1,4 +1,4 @@ # Do not enter sensitive information here. export REACT_APP_DEPLOYMENT=devnet -export REACT_APP_KLEROS_CORE_SUBGRAPH_DEVNET=https://api.thegraph.com/subgraphs/name/alcercu/kleroscoredev +export REACT_APP_KLEROS_CORE_SUBGRAPH_DEVNET=https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-devnet export REACT_APP_DISPUTE_TEMPLATE_ARBGOERLI_SUBGRAPH_DEVNET=https://api.thegraph.com/subgraphs/name/alcercu/templateregistrydevnet diff --git a/web/package.json b/web/package.json index adbff3e82..d697f40f4 100644 --- a/web/package.json +++ b/web/package.json @@ -49,6 +49,7 @@ "@parcel/watcher": "~2.2.0", "@types/amqplib": "^0.10.1", "@types/busboy": "^1.5.0", + "@types/mustache": "^4.2.3", "@types/react": "^18.2.14", "@types/react-dom": "^18.2.7", "@types/styled-components": "^5.1.26", @@ -69,7 +70,7 @@ "dependencies": { "@filebase/client": "^0.0.5", "@kleros/kleros-v2-contracts": "workspace:^", - "@kleros/ui-components-library": "^2.6.2", + "@kleros/ui-components-library": "^2.6.3", "@sentry/react": "^7.55.2", "@sentry/tracing": "^7.55.2", "@supabase/supabase-js": "^2.33.1", diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index b9eaf5d7a..012a03cb0 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -14,6 +14,9 @@ import { useVotingHistory } from "queries/useVotingHistory"; import DisputeInfo from "./DisputeInfo"; import PeriodBanner from "./PeriodBanner"; import { isUndefined } from "utils/index"; +import { populateTemplate } from "utils/dataMappings"; +import { DisputeDetails } from "utils/disputeDetails"; +import { INVALID_DISPUTE_DATA_ERROR } from "consts/index"; const StyledCard = styled(Card)` width: 100%; @@ -95,14 +98,18 @@ const DisputeCard: React.FC = ({ id, arbitrated, period, lastPerio ? lastPeriodChange : getPeriodEndTimestamp(lastPeriodChange, currentPeriodIndex, court.timesPerPeriod); const { data: disputeTemplate } = useDisputeTemplate(id, arbitrated.id as `0x${string}`); - const title = isUndefined(disputeTemplate) ? ( - - ) : ( - disputeTemplate?.title ?? "The dispute's template is not correct please vote refuse to arbitrate" - ); + let disputeDetails: DisputeDetails | undefined; + try { + if (disputeTemplate) { + disputeDetails = populateTemplate(disputeTemplate.templateData, {}); + } + } catch (e) { + console.error(e); + } + const title = isUndefined(disputeDetails) ? : disputeDetails?.title ?? INVALID_DISPUTE_DATA_ERROR; const { data: courtPolicy } = useCourtPolicy(court.id); const courtName = courtPolicy?.name; - const category = disputeTemplate ? disputeTemplate.category : undefined; + const category = disputeTemplate?.category; const { data: votingHistory } = useVotingHistory(id); const localRounds = votingHistory?.dispute?.disputeKitDispute?.localRounds; const navigate = useNavigate(); @@ -127,10 +134,7 @@ const DisputeCard: React.FC = ({ id, arbitrated, period, lastPerio - + = ({ arbitrable, courtID, currentPeriodIndex }) => { const { id } = useParams(); const { data: disputeTemplate } = useDisputeTemplate(id, arbitrable); - const { data: disputeDetails } = useDisputeDetailsQuery(id); + const { data: dispute } = useDisputeDetailsQuery(id); const { data: courtPolicy } = useCourtPolicy(courtID); const { data: votingHistory } = useVotingHistory(id); - const [parsedDisputeTemplate, setParsedDisputeTemplate] = useState({}); + const [disputeDetails, setDisputeDetails] = useState(undefined); const localRounds = votingHistory?.dispute?.disputeKitDispute?.localRounds; const courtName = courtPolicy?.name; - const court = disputeDetails?.dispute?.court; + const court = dispute?.dispute?.court; const rewards = court ? `≥ ${formatEther(court.feeForJuror)} ETH` : undefined; const category = disputeTemplate ? disputeTemplate.category : undefined; + const disputeTemplateInput = disputeTemplate?.templateData; + const dataMappingsInput = disputeTemplate?.templateDataMappings; useEffect(() => { + if (!disputeTemplateInput || !dataMappingsInput) return; const fetchData = async () => { + let parsedMapping; try { - const parsedTemplate = JSON.parse(disputeTemplate?.templateData); - const parsedMapping = JSON.parse(disputeTemplate?.templateDataMappings); - - let populatedData = {}; - + parsedMapping = JSON.parse(dataMappingsInput); + } catch (e) { + console.error(e); + setDisputeDetails(undefined); + // return; + parsedMapping = JSON.parse("[]"); + } + try { + let data = {}; for (const action of parsedMapping) { const result = await executeAction(action); - populatedData = { ...populatedData, ...result }; + data = { ...data, ...result }; } - - const finalTemplate = deepParseTemplateWithData(parsedTemplate, populatedData); - setParsedDisputeTemplate(finalTemplate); + setDisputeDetails(populateTemplate(disputeTemplateInput, data)); } catch (e) { console.error(e); } }; - fetchData(); - }, [disputeTemplate]); + }, [disputeTemplateInput, dataMappingsInput]); return ( <>

- {isUndefined(disputeTemplate) ? ( - - ) : ( - parsedDisputeTemplate?.template?.content ?? - "The dispute's template is not correct please vote refuse to arbitrate" - )} + {isUndefined(disputeTemplate) ? : disputeDetails?.title ?? INVALID_DISPUTE_DATA_ERROR}

- {parsedDisputeTemplate?.question} - {parsedDisputeTemplate?.description} + {disputeDetails?.question ?? INVALID_DISPUTE_DATA_ERROR} + {disputeDetails?.description ?? INVALID_DISPUTE_DATA_ERROR} - {parsedDisputeTemplate?.frontendUrl && ( - + {disputeDetails?.frontendUrl && ( + Go to arbitrable )} - {parsedDisputeTemplate &&

Voting Options

} + {disputeDetails &&

Voting Options

} - {parsedDisputeTemplate?.options?.titles?.map((title: string, i: number) => ( - + {disputeDetails?.answers?.map((answer: Answer, i: number) => ( + Option {i + 1}: - - + + ))} @@ -194,8 +195,8 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex

Make sure you understand the Policies

- {parsedDisputeTemplate?.policyURI && ( - + {disputeDetails?.policyURI && ( + Dispute Policy diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index 285da628a..287ccd604 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -3,8 +3,9 @@ import styled from "styled-components"; import { Textarea } from "@kleros/ui-components-library"; import PolicyIcon from "svgs/icons/policy.svg"; import ReactMarkdown from "components/ReactMarkdown"; -import { IPFS_GATEWAY } from "consts/index"; -import { deepParseTemplateWithData, executeAction } from "utils/dataMappings"; +import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; +import { populateTemplate, executeAction } from "utils/dataMappings"; +import { Answer, DisputeDetails } from "utils/disputeDetails"; const Container = styled.div` width: 50%; @@ -78,40 +79,36 @@ const StyledTextArea = styled(Textarea)` `; const DisputeTemplateView: React.FC = () => { - const [parsedDisputeTemplate, setParsedDisputeTemplate] = useState({}); + const [disputeDetails, setDisputeDetails] = useState(undefined); const [disputeTemplateInput, setDisputeTemplateInput] = useState(""); const [dataMappingsInput, setDataMappingsInput] = useState(""); useEffect(() => { if (!disputeTemplateInput || !dataMappingsInput) return; - const fetchData = async () => { - let parsedTemplate, parsedMapping; - + let parsedMapping; try { - parsedTemplate = JSON.parse(disputeTemplateInput); parsedMapping = JSON.parse(dataMappingsInput); } catch (e) { console.error(e); - setParsedDisputeTemplate(undefined); + setDisputeDetails(undefined); return; } - try { - let populatedData = {}; - + let data = {}; for (const action of parsedMapping) { const result = await executeAction(action); - populatedData = { ...populatedData, ...result }; + data = { ...data, ...result }; } - - const finalTemplate = deepParseTemplateWithData(parsedTemplate, populatedData); - setParsedDisputeTemplate(finalTemplate); + console.log("disputeTemplateInput: ", disputeTemplateInput); + console.log("data: ", data); + const finalDisputeDetails = populateTemplate(disputeTemplateInput, data); + console.log("finalTemplate: ", finalDisputeDetails); + setDisputeDetails(finalDisputeDetails); } catch (e) { console.error(e); } }; - fetchData(); }, [disputeTemplateInput, dataMappingsInput]); @@ -127,43 +124,40 @@ const DisputeTemplateView: React.FC = () => { onChange={(e) => setDataMappingsInput(e.target.value)} placeholder="Enter data mappings" /> - +
); }; -const Overview: React.FC<{ disputeTemplate: any }> = ({ disputeTemplate }) => { +const Overview: React.FC<{ disputeDetails: DisputeDetails | undefined }> = ({ disputeDetails }) => { return ( <> -

- {disputeTemplate?.template?.content ?? - "The dispute's template is not correct please vote refuse to arbitrate"} -

+

{disputeDetails?.title ?? INVALID_DISPUTE_DATA_ERROR}

- {disputeTemplate?.question} - {disputeTemplate?.description} + {disputeDetails?.question ?? INVALID_DISPUTE_DATA_ERROR} + {disputeDetails?.description ?? INVALID_DISPUTE_DATA_ERROR} - {disputeTemplate?.frontendUrl && ( - + {disputeDetails?.frontendUrl && ( + Go to arbitrable )} - {disputeTemplate &&

Voting Options

} - {disputeTemplate?.options?.titles?.map((title: string, i: number) => ( - + {disputeDetails &&

Voting Options

} + {disputeDetails?.answers?.map((answer: Answer, i: number) => ( + Option {i + 1}: - - + + ))}

Make sure you understand the Policies

- {disputeTemplate?.policyURI && ( - + {disputeDetails?.policyURI && ( + Dispute Policy diff --git a/web/src/utils/dataMappings.ts b/web/src/utils/dataMappings.ts index 918f211f7..16cd8a25f 100644 --- a/web/src/utils/dataMappings.ts +++ b/web/src/utils/dataMappings.ts @@ -1,6 +1,8 @@ import { createPublicClient, parseAbiItem, webSocket } from "viem"; import { arbitrumGoerli } from "viem/chains"; import fetch from "node-fetch"; +import mustache from "mustache"; +import { DisputeDetails } from "./disputeDetails"; const ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY; @@ -37,7 +39,7 @@ export const fetchAction = async (link: string, seek, populate) => { const response = await fetch(link); const fetchedData = await response.json(); console.log(fetchedData); - let populatedData = {}; + const populatedData = {}; seek.forEach((key, idx) => { const foundValue = findNestedKey(fetchedData, key); @@ -85,7 +87,7 @@ export const callAction = async (source, inputs, seek, populate) => { args: inputs.slice(2), }); - let populatedData = {}; + const populatedData = {}; seek.map((item) => { if (typeof data == "object") { @@ -126,7 +128,7 @@ export const eventAction = async (source, inputs, seek, populate) => { const eventData = contractEvent[0].args; - let populatedData = {}; + const populatedData = {}; seek.map((item, index) => { populatedData[populate[index]] = eventData[item]; @@ -156,22 +158,10 @@ export const parseTemplateWithData = (template, data) => { return template.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || ""); }; -export const deepParseTemplateWithData = (templateObj: any, data: any): any => { - if (typeof templateObj === "string") { - return templateObj.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || ""); - } - - if (Array.isArray(templateObj)) { - return templateObj.map((item) => deepParseTemplateWithData(item, data)); - } - - if (typeof templateObj === "object") { - let newObject: any = {}; - for (let key in templateObj) { - newObject[key] = deepParseTemplateWithData(templateObj[key], data); - } - return newObject; - } - - return templateObj; +export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { + const render = mustache.render(mustacheTemplate, data); + console.log("MUSTACHE RENDER: ", render); + const dispute = JSON.parse(render); + // TODO: validate the object according to the DisputeDetails type or a JSON schema + return dispute; }; diff --git a/web/src/utils/disputeDetails.ts b/web/src/utils/disputeDetails.ts new file mode 100644 index 000000000..ae054c199 --- /dev/null +++ b/web/src/utils/disputeDetails.ts @@ -0,0 +1,32 @@ +export type DisputeDetails = { + title: string; + description: string; + question: string; + type: QuestionType; + answers: Answer[]; + policyURI: string; + frontendUrl: string; + arbitrableChainID: string; + arbitrableAddress: `0x${string}`; + arbitratorChainID: string; + arbitratorAddress: `0x${string}`; + category: string; + lang: string; + specification: string; + version: string; +}; + +export type Answer = { + title: string; + description: string; + id: `0x${string}`; + reserved: boolean; +}; + +export enum QuestionType { + Bool = "bool", + Datetime = "datetime", + MultipleSelect = "multiple-select", + SingleSelect = "single-select", + Uint = "uint", +} diff --git a/yarn.lock b/yarn.lock index 6bd146cee..cb81cd4ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5371,7 +5371,7 @@ __metadata: "@kleros/kleros-v2-eslint-config": "workspace:^" "@kleros/kleros-v2-prettier-config": "workspace:^" "@kleros/kleros-v2-tsconfig": "workspace:^" - "@kleros/ui-components-library": ^2.6.2 + "@kleros/ui-components-library": ^2.6.3 "@netlify/functions": ^1.6.0 "@parcel/transformer-svg-react": 2.8.3 "@parcel/watcher": ~2.2.0 @@ -5381,6 +5381,7 @@ __metadata: "@tanstack/react-query": ^4.28.0 "@types/amqplib": ^0.10.1 "@types/busboy": ^1.5.0 + "@types/mustache": ^4.2.3 "@types/react": ^18.2.14 "@types/react-dom": ^18.2.7 "@types/react-modal": ^3.16.0 @@ -5430,9 +5431,9 @@ __metadata: languageName: unknown linkType: soft -"@kleros/ui-components-library@npm:^2.6.2": - version: 2.6.2 - resolution: "@kleros/ui-components-library@npm:2.6.2" +"@kleros/ui-components-library@npm:^2.6.3": + version: 2.6.3 + resolution: "@kleros/ui-components-library@npm:2.6.3" dependencies: "@datepicker-react/hooks": ^2.8.4 "@swc/helpers": ^0.3.2 @@ -5449,7 +5450,7 @@ __metadata: react-dom: ^18.0.0 react-is: ^18.0.0 styled-components: ^5.3.3 - checksum: 499478dcacb825569d56f752de90954c58a737525a677b87645e330294ccd1f3d58bbc7b78b4cfb3bab8c0326eabc8f24fbad59c8db810e214791dbe8d4ea476 + checksum: 090e9e137283b22adad531f9f0917b5cb9d56f165647e579031dc20856913b45955539cb42b89b4392fadf7ef956b3a3b9468d3441d76a0328f2a774431f6002 languageName: node linkType: hard @@ -9149,6 +9150,13 @@ __metadata: languageName: node linkType: hard +"@types/mustache@npm:^4.2.3": + version: 4.2.3 + resolution: "@types/mustache@npm:4.2.3" + checksum: c2c7cf749a84a622648c7088fb10350b84ea935145514b6c51d17e808a4b4972fb137273339f4d93160a3c496a3943dab3be93251d74c185730daa300a299e2f + languageName: node + linkType: hard + "@types/node@npm:*, @types/node@npm:>=13.7.0": version: 20.3.1 resolution: "@types/node@npm:20.3.1" From d9406d5372cc38c073904e3321932816468ba26c Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Thu, 12 Oct 2023 16:26:17 +0200 Subject: [PATCH 14/37] feat(sdk): create more tests, better structuring of files, create kleros-sdk workspace --- kleros-sdk/.env.example | 1 + kleros-sdk/README.md | 6 +- .../{dataMappings.ts => index.ts} | 64 +++-- kleros-sdk/dataMappings/test.ts | 106 ++++++-- kleros-sdk/package.json | 31 +++ kleros-sdk/tsconfig.json | 29 +++ package.json | 10 +- tsconfig.json | 8 - web/package.json | 3 +- web/src/components/DisputeCard/index.tsx | 2 +- web/src/pages/Cases/CaseDetails/Overview.tsx | 4 +- web/src/pages/DisputeTemplateView.tsx | 6 +- web/src/utils/dataMappings.ts | 167 ------------ yarn.lock | 240 ++++++++++++++++-- 14 files changed, 414 insertions(+), 263 deletions(-) create mode 100644 kleros-sdk/.env.example rename kleros-sdk/dataMappings/{dataMappings.ts => index.ts} (76%) create mode 100644 kleros-sdk/package.json create mode 100644 kleros-sdk/tsconfig.json delete mode 100644 tsconfig.json delete mode 100644 web/src/utils/dataMappings.ts diff --git a/kleros-sdk/.env.example b/kleros-sdk/.env.example new file mode 100644 index 000000000..09de7c194 --- /dev/null +++ b/kleros-sdk/.env.example @@ -0,0 +1 @@ +ALCHEMY_API_KEY= \ No newline at end of file diff --git a/kleros-sdk/README.md b/kleros-sdk/README.md index 2044db9d3..443133444 100644 --- a/kleros-sdk/README.md +++ b/kleros-sdk/README.md @@ -2,11 +2,11 @@ _Archon's successor_ -For running data mappings unit tests, first make sure the `ALCHEMY_API_KEY` variable is set inside the `dataMappings.ts` file, then run: +Make sure to set the environment variables first by copying the file `.env.example`, pasting it, renaming it to `.env`, and then setting the variables. +To run the data mappings tests: ```bash -cd kleros-sdk -yarn mocha -r ts-node/register dataMappings/test.ts +yarn run test-data-mappings ``` 🚧 ⚖️ 🚧 diff --git a/kleros-sdk/dataMappings/dataMappings.ts b/kleros-sdk/dataMappings/index.ts similarity index 76% rename from kleros-sdk/dataMappings/dataMappings.ts rename to kleros-sdk/dataMappings/index.ts index 16cd8a25f..a6c51b7f0 100644 --- a/kleros-sdk/dataMappings/dataMappings.ts +++ b/kleros-sdk/dataMappings/index.ts @@ -3,17 +3,26 @@ import { arbitrumGoerli } from "viem/chains"; import fetch from "node-fetch"; import mustache from "mustache"; import { DisputeDetails } from "./disputeDetails"; +import dotenv from "dotenv"; + +dotenv.config(); + +let ALCHEMY_API_KEY: string | undefined = process.env.ALCHEMY_API_KEY; +let transport; +let publicClient; + +export const configureSDK = (config: { apiKey?: string }) => { + if (config.apiKey) { + ALCHEMY_API_KEY = config.apiKey; + transport = webSocket(`wss://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}`); + publicClient = createPublicClient({ + chain: arbitrumGoerli, + transport, + }); + } +}; -const ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY; - -const transport = webSocket(`wss://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}`); - -const publicClient = createPublicClient({ - chain: arbitrumGoerli, - transport, -}); - -const findNestedKey = (data, keyToFind) => { +export const findNestedKey = (data, keyToFind) => { if (data.hasOwnProperty(keyToFind)) return data[keyToFind]; for (let key in data) { if (typeof data[key] === "object" && data[key] !== null) { @@ -35,20 +44,6 @@ export const jsonAction = (source, seek, populate) => { return jsonData; }; -export const fetchAction = async (link: string, seek, populate) => { - const response = await fetch(link); - const fetchedData = await response.json(); - console.log(fetchedData); - const populatedData = {}; - - seek.forEach((key, idx) => { - const foundValue = findNestedKey(fetchedData, key); - populatedData[populate[idx]] = foundValue; - }); - - return populatedData; -}; - export const graphqlAction = async (query: string, seek, populate) => { const response = await fetch("https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-arbitrum-goerli", { method: "POST", @@ -72,6 +67,10 @@ export const graphqlAction = async (query: string, seek, populate) => { }; export const callAction = async (source, inputs, seek, populate) => { + if (!publicClient) { + throw new Error("SDK not configured. Please call `configureSDK` before using."); + } + let parsedAbi; if (typeof source === "string") { @@ -89,11 +88,11 @@ export const callAction = async (source, inputs, seek, populate) => { const populatedData = {}; - seek.map((item) => { + seek.map((item, index) => { if (typeof data == "object") { - populatedData[populate[item]] = data[item]; + populatedData[populate[index]] = data[item]; } else { - populatedData[populate[item]] = data; + populatedData[populate[index]] = data; } }); @@ -101,6 +100,10 @@ export const callAction = async (source, inputs, seek, populate) => { }; export const eventAction = async (source, inputs, seek, populate) => { + if (!publicClient) { + throw new Error("SDK not configured. Please call `configureSDK` before using."); + } + let parsedAbi; if (typeof source === "string") { @@ -139,8 +142,6 @@ export const eventAction = async (source, inputs, seek, populate) => { 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": @@ -154,14 +155,9 @@ export const executeAction = async (action) => { } }; -export const parseTemplateWithData = (template, data) => { - return template.replace(/\{\{(.*?)\}\}/g, (_, key) => data[key.trim()] || ""); -}; - export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { const render = mustache.render(mustacheTemplate, data); console.log("MUSTACHE RENDER: ", render); const dispute = JSON.parse(render); - // TODO: validate the object according to the DisputeDetails type or a JSON schema return dispute; }; diff --git a/kleros-sdk/dataMappings/test.ts b/kleros-sdk/dataMappings/test.ts index 2592c385a..6c2f8d2f1 100644 --- a/kleros-sdk/dataMappings/test.ts +++ b/kleros-sdk/dataMappings/test.ts @@ -1,8 +1,5 @@ import { expect } from "chai"; -import { createPublicClient, http, parseAbiItem } from "viem"; -import { arbitrumGoerli } from "viem/chains"; -import { jsonAction, graphqlAction, fetchAction, eventAction, callAction } from "./dataMappings"; -import { klerosCoreABI } from "../../web/src/hooks/contracts/generated"; +import { jsonAction, graphqlAction, eventAction, callAction, findNestedKey, populateTemplate, configureSDK } from "."; const exampleObject = { evidence: { @@ -13,9 +10,8 @@ const exampleObject = { }, }; -const publicClient = createPublicClient({ - chain: arbitrumGoerli, - transport: http(), +before(() => { + configureSDK({ apiKey: process.env.ALCHEMY_API_KEY }); }); describe("jsonAction", () => { @@ -28,20 +24,6 @@ describe("jsonAction", () => { }); }); -describe("fetchAction", () => { - it("should fetch data and return in expected format", async () => { - const seek = ["rate"]; - const populate = ["rate"]; - const result = await fetchAction("https://fakestoreapi.com/products/1", seek, populate); - - const expectedResult = { - rate: 3.9, - }; - - expect(result).to.eql(expectedResult); - }); -}); - describe("graphqlAction", () => { it("should fetch GraphQL data and return in expected format", async () => { const seek = ["courts"]; @@ -82,14 +64,13 @@ describe("graphqlAction", () => { describe("callAction", () => { it("should call the contract and return populated data", async () => { - const mockAbi = parseAbiItem(`function appealCost(uint256 _disputeID) public view returns (uint256)`); + const mockAbi = "function appealCost(uint256 _disputeID) public view returns (uint256)"; const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", "appealCost", BigInt(1)]; const mockSeek = ["_disputeID"]; const mockPopulate = ["cost"]; const result = await callAction(mockAbi, mockInputs, mockSeek, mockPopulate); - console.log("result", result); expect(result).to.eql({ cost: BigInt(30000000000000), }); @@ -98,10 +79,7 @@ describe("callAction", () => { describe("eventAction", () => { it("should fetch event data and return populated data", async () => { - // const mockSource = parseAbiItem( - // "event Draw(address indexed _address, uint256 indexed _disputeID, uint256 _roundID, uint256 _voteID)" - // ); - const mockSource = parseAbiItem("event StakeSet(address indexed _address, uint256 _courtID, uint256 _amount)"); + const mockSource = "event StakeSet(address indexed _address, uint256 _courtID, uint256 _amount)"; const mockInputs = [ "0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", BigInt(36205881), @@ -117,3 +95,77 @@ describe("eventAction", () => { }); }); }); + +describe("findNestedKey", () => { + const testData = { + level1: "value1", + nested: { + level2: "value2", + deeper: { + level3: "value3", + }, + }, + }; + + it("should find top-level keys", () => { + const result = findNestedKey(testData, "level1"); + expect(result).to.eql("value1"); + }); + + it("should find second-level nested keys", () => { + const result = findNestedKey(testData, "level2"); + expect(result).to.eql("value2"); + }); + + it("should find deeply nested keys", () => { + const result = findNestedKey(testData, "level3"); + expect(result).to.eql("value3"); + }); + + it("should return null if key not found", () => { + const result = findNestedKey(testData, "nonexistent"); + expect(result).to.be.null; + }); +}); + +describe("populateTemplate", () => { + it("should correctly populate the template with provided data", () => { + const template = '{"name": "{{name}}", "age": {{age}}, "isStudent": {{isStudent}}}'; + const data = { + name: "John", + age: 25, + isStudent: false, + }; + + const result = populateTemplate(template, data); + + expect(result).to.deep.equal({ + name: "John", + age: 25, + isStudent: false, + }); + }); + + it("should handle missing data by leaving placeholders untouched", () => { + const template = '{"name": "{{name}}", "age": {{age}}}'; + const data = { + age: 30, + }; + + const result = populateTemplate(template, data); + + expect(result).to.deep.equal({ + name: "", + age: 30, + }); + }); + + it("should throw an error for invalid JSON", () => { + const template = '{"name": "{{name}"}'; + const data = { + name: "Jane", + }; + + expect(() => populateTemplate(template, data)).to.throw(); + }); +}); diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json new file mode 100644 index 000000000..bff53f11c --- /dev/null +++ b/kleros-sdk/package.json @@ -0,0 +1,31 @@ +{ + "name": "@kleros/kleros-sdk", + "version": "0.1.0", + "description": "SDK for Kleros version 2", + "main": "index.ts", + "repository": "git@github.com:kleros/kleros-v2.git", + "author": "Kleros", + "license": "MIT", + "packageManager": "yarn@3.3.1", + "engines": { + "node": ">=16.0.0" + }, + "type": "commonjs", + "volta": { + "node": "16.20.1", + "yarn": "3.3.1" + }, + "scripts": { + "build": "your-build-script", + "test-data-mappings": "mocha -r ts-node/register/transpile-only dataMappings/test.ts" + }, + "devDependencies": { + "@types/chai": "^4.3.6", + "@types/mocha": "^10.0.1", + "chai": "^4.3.8", + "dotenv": "^16.3.1", + "mocha": "^10.2.0", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } +} diff --git a/kleros-sdk/tsconfig.json b/kleros-sdk/tsconfig.json new file mode 100644 index 000000000..74e37a08f --- /dev/null +++ b/kleros-sdk/tsconfig.json @@ -0,0 +1,29 @@ +{ + "extends": "@kleros/kleros-v2-tsconfig/react-library.json", + "compilerOptions": { + "baseUrl": ".", + "target": "ES6", + "module": "CommonJS", + "rootDir": "./", + "outDir": "build/dist", + "allowJs": true, + "forceConsistentCasingInFileNames": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "removeComments": true, + "isolatedModules": true + }, + "exclude": [ + "node_modules", + "build", + "scripts", + "acceptance-tests", + "webpack", + "jest", + "src/setupTests.ts", + "dist", + "commitlint.config.js" + ] +} diff --git a/package.json b/package.json index 55ab00180..b05ac064c 100644 --- a/package.json +++ b/package.json @@ -36,15 +36,15 @@ "devDependencies": { "@commitlint/cli": "^17.7.2", "@commitlint/config-conventional": "^17.6.7", - "@types/chai": "^4.3.6", - "@types/mocha": "^10.0.1", "buffer": "^5.5.0", - "chai": "^4.3.8", "conventional-changelog-cli": "^2.2.2", + "crypto-browserify": "^3.12.0", "husky": "^8.0.3", "lint-staged": "^13.2.2", - "mocha": "^10.2.0", - "process": "^0.11.10" + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "resolutions": { "async@npm^2.4.0": "^2.6.4", diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 90d1f029d..000000000 --- a/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "types": [ - "mocha", - "node" - ] - } -} diff --git a/web/package.json b/web/package.json index d697f40f4..ecea65876 100644 --- a/web/package.json +++ b/web/package.json @@ -69,8 +69,9 @@ }, "dependencies": { "@filebase/client": "^0.0.5", + "@kleros/kleros-sdk": "workspace:^", "@kleros/kleros-v2-contracts": "workspace:^", - "@kleros/ui-components-library": "^2.6.3", + "@kleros/ui-components-library": "^2.6.2", "@sentry/react": "^7.55.2", "@sentry/tracing": "^7.55.2", "@supabase/supabase-js": "^2.33.1", diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index 012a03cb0..b8c55732a 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -14,7 +14,7 @@ import { useVotingHistory } from "queries/useVotingHistory"; import DisputeInfo from "./DisputeInfo"; import PeriodBanner from "./PeriodBanner"; import { isUndefined } from "utils/index"; -import { populateTemplate } from "utils/dataMappings"; +import { populateTemplate } from "@kleros/kleros-sdk/dataMappings"; import { DisputeDetails } from "utils/disputeDetails"; import { INVALID_DISPUTE_DATA_ERROR } from "consts/index"; diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index 95718d222..1677c851b 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -8,7 +8,8 @@ import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { useCourtPolicy } from "queries/useCourtPolicy"; import { isUndefined } from "utils/index"; -import { populateTemplate, executeAction } from "utils/dataMappings"; +import { populateTemplate, executeAction, configureSDK } from "@kleros/kleros-sdk/dataMappings"; +import { alchemyApiKey } from "context/Web3Provider"; import { Answer, DisputeDetails } from "utils/disputeDetails"; import { Periods } from "consts/periods"; import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; @@ -131,6 +132,7 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex const dataMappingsInput = disputeTemplate?.templateDataMappings; useEffect(() => { + configureSDK({ apiKey: alchemyApiKey }); if (!disputeTemplateInput || !dataMappingsInput) return; const fetchData = async () => { let parsedMapping; diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index 287ccd604..0c900a76e 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -4,8 +4,9 @@ import { Textarea } from "@kleros/ui-components-library"; import PolicyIcon from "svgs/icons/policy.svg"; import ReactMarkdown from "components/ReactMarkdown"; import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; -import { populateTemplate, executeAction } from "utils/dataMappings"; +import { populateTemplate, executeAction, configureSDK } from "@kleros/kleros-sdk/dataMappings"; import { Answer, DisputeDetails } from "utils/disputeDetails"; +import { alchemyApiKey } from "context/Web3Provider"; const Container = styled.div` width: 50%; @@ -84,7 +85,10 @@ const DisputeTemplateView: React.FC = () => { const [dataMappingsInput, setDataMappingsInput] = useState(""); useEffect(() => { + configureSDK({ apiKey: alchemyApiKey }); + if (!disputeTemplateInput || !dataMappingsInput) return; + const fetchData = async () => { let parsedMapping; try { diff --git a/web/src/utils/dataMappings.ts b/web/src/utils/dataMappings.ts deleted file mode 100644 index 16cd8a25f..000000000 --- a/web/src/utils/dataMappings.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { createPublicClient, parseAbiItem, webSocket } from "viem"; -import { arbitrumGoerli } from "viem/chains"; -import fetch from "node-fetch"; -import mustache from "mustache"; -import { DisputeDetails } from "./disputeDetails"; - -const ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY; - -const transport = webSocket(`wss://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}`); - -const publicClient = createPublicClient({ - chain: arbitrumGoerli, - transport, -}); - -const findNestedKey = (data, keyToFind) => { - if (data.hasOwnProperty(keyToFind)) return data[keyToFind]; - for (let key in data) { - if (typeof data[key] === "object" && data[key] !== null) { - const found = findNestedKey(data[key], keyToFind); - if (found) return found; - } - } - return null; -}; - -export const jsonAction = (source, seek, populate) => { - let jsonData = {}; - - seek.forEach((key, idx) => { - const foundValue = findNestedKey(source, key); - jsonData[populate[idx]] = foundValue; - }); - - return jsonData; -}; - -export const fetchAction = async (link: string, seek, populate) => { - const response = await fetch(link); - const fetchedData = await response.json(); - console.log(fetchedData); - const populatedData = {}; - - seek.forEach((key, idx) => { - const foundValue = findNestedKey(fetchedData, key); - populatedData[populate[idx]] = foundValue; - }); - - return populatedData; -}; - -export const graphqlAction = async (query: string, seek, populate) => { - const response = await fetch("https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-arbitrum-goerli", { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify({ query }), - }); - - const { data } = await response.json(); - console.log(data); - let populatedData = {}; - - seek.forEach((key, idx) => { - const foundValue = findNestedKey(data, key); - populatedData[populate[idx]] = foundValue; - }); - - return populatedData; -}; - -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: [parsedAbi], - functionName: inputs[1], - args: inputs.slice(2), - }); - - const populatedData = {}; - - seek.map((item) => { - if (typeof data == "object") { - populatedData[populate[item]] = data[item]; - } else { - populatedData[populate[item]] = data; - } - }); - - return populatedData; -}; - -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: parsedAbi, - args: { ...argsObject }, - fromBlock: inputs[1], - toBlock: "latest", - }); - - const contractEvent = await publicClient.getFilterLogs({ - filter: filter as any, - }); - - const eventData = contractEvent[0].args; - - const populatedData = {}; - - seek.map((item, index) => { - populatedData[populate[index]] = eventData[item]; - }); - - return populatedData; -}; - -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()] || ""); -}; - -export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { - const render = mustache.render(mustacheTemplate, data); - console.log("MUSTACHE RENDER: ", render); - const dispute = JSON.parse(render); - // TODO: validate the object according to the DisputeDetails type or a JSON schema - return dispute; -}; diff --git a/yarn.lock b/yarn.lock index cb81cd4ba..7f47559a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5256,6 +5256,20 @@ __metadata: languageName: node linkType: hard +"@kleros/kleros-sdk@workspace:^, @kleros/kleros-sdk@workspace:kleros-sdk": + version: 0.0.0-use.local + resolution: "@kleros/kleros-sdk@workspace:kleros-sdk" + dependencies: + "@types/chai": ^4.3.6 + "@types/mocha": ^10.0.1 + chai: ^4.3.8 + dotenv: ^16.3.1 + mocha: ^10.2.0 + ts-node: ^10.9.1 + typescript: ^5.2.2 + languageName: unknown + linkType: soft + "@kleros/kleros-v2-bot-pinner@workspace:bot-pinner": version: 0.0.0-use.local resolution: "@kleros/kleros-v2-bot-pinner@workspace:bot-pinner" @@ -5367,11 +5381,12 @@ __metadata: "@filebase/client": ^0.0.5 "@graphql-codegen/cli": ^4.0.1 "@graphql-codegen/client-preset": ^4.0.1 + "@kleros/kleros-sdk": "workspace:^" "@kleros/kleros-v2-contracts": "workspace:^" "@kleros/kleros-v2-eslint-config": "workspace:^" "@kleros/kleros-v2-prettier-config": "workspace:^" "@kleros/kleros-v2-tsconfig": "workspace:^" - "@kleros/ui-components-library": ^2.6.3 + "@kleros/ui-components-library": ^2.6.2 "@netlify/functions": ^1.6.0 "@parcel/transformer-svg-react": 2.8.3 "@parcel/watcher": ~2.2.0 @@ -5431,7 +5446,7 @@ __metadata: languageName: unknown linkType: soft -"@kleros/ui-components-library@npm:^2.6.3": +"@kleros/ui-components-library@npm:^2.6.2": version: 2.6.3 resolution: "@kleros/ui-components-library@npm:2.6.3" dependencies: @@ -11350,6 +11365,18 @@ __metadata: languageName: node linkType: hard +"asn1.js@npm:^5.2.0": + version: 5.4.1 + resolution: "asn1.js@npm:5.4.1" + dependencies: + bn.js: ^4.0.0 + inherits: ^2.0.1 + minimalistic-assert: ^1.0.0 + safer-buffer: ^2.1.0 + checksum: 3786a101ac6f304bd4e9a7df79549a7561950a13d4bcaec0c7790d44c80d147c1a94ba3d4e663673406064642a40b23fcd6c82a9952468e386c1a1376d747f9a + languageName: node + linkType: hard + "asn1@npm:^0.2.6, asn1@npm:~0.2.3": version: 0.2.6 resolution: "asn1@npm:0.2.6" @@ -12057,7 +12084,7 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^4.11.0, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": +"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.0, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 @@ -12156,7 +12183,7 @@ __metadata: languageName: node linkType: hard -"brorand@npm:^1.1.0": +"brorand@npm:^1.0.1, brorand@npm:^1.1.0": version: 1.1.0 resolution: "brorand@npm:1.1.0" checksum: 8a05c9f3c4b46572dec6ef71012b1946db6cae8c7bb60ccd4b7dd5a84655db49fe043ecc6272e7ef1f69dc53d6730b9e2a3a03a8310509a3d797a618cbee52be @@ -12203,7 +12230,7 @@ __metadata: languageName: node linkType: hard -"browserify-aes@npm:^1.2.0": +"browserify-aes@npm:^1.0.0, browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": version: 1.2.0 resolution: "browserify-aes@npm:1.2.0" dependencies: @@ -12217,6 +12244,56 @@ __metadata: languageName: node linkType: hard +"browserify-cipher@npm:^1.0.0": + version: 1.0.1 + resolution: "browserify-cipher@npm:1.0.1" + dependencies: + browserify-aes: ^1.0.4 + browserify-des: ^1.0.0 + evp_bytestokey: ^1.0.0 + checksum: 2d8500acf1ee535e6bebe808f7a20e4c3a9e2ed1a6885fff1facbfd201ac013ef030422bec65ca9ece8ffe82b03ca580421463f9c45af6c8415fd629f4118c13 + languageName: node + linkType: hard + +"browserify-des@npm:^1.0.0": + version: 1.0.2 + resolution: "browserify-des@npm:1.0.2" + dependencies: + cipher-base: ^1.0.1 + des.js: ^1.0.0 + inherits: ^2.0.1 + safe-buffer: ^5.1.2 + checksum: b15a3e358a1d78a3b62ddc06c845d02afde6fc826dab23f1b9c016e643e7b1fda41de628d2110b712f6a44fb10cbc1800bc6872a03ddd363fb50768e010395b7 + languageName: node + linkType: hard + +"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.0.1": + version: 4.1.0 + resolution: "browserify-rsa@npm:4.1.0" + dependencies: + bn.js: ^5.0.0 + randombytes: ^2.0.1 + checksum: 155f0c135873efc85620571a33d884aa8810e40176125ad424ec9d85016ff105a07f6231650914a760cca66f29af0494087947b7be34880dd4599a0cd3c38e54 + languageName: node + linkType: hard + +"browserify-sign@npm:^4.0.0": + version: 4.2.1 + resolution: "browserify-sign@npm:4.2.1" + dependencies: + bn.js: ^5.1.1 + browserify-rsa: ^4.0.1 + create-hash: ^1.2.0 + create-hmac: ^1.1.7 + elliptic: ^6.5.3 + inherits: ^2.0.4 + parse-asn1: ^5.1.5 + readable-stream: ^3.6.0 + safe-buffer: ^5.2.0 + checksum: 0221f190e3f5b2d40183fa51621be7e838d9caa329fe1ba773406b7637855f37b30f5d83e52ff8f244ed12ffe6278dd9983638609ed88c841ce547e603855707 + languageName: node + linkType: hard + "browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.18.1, browserslist@npm:^4.21.3, browserslist@npm:^4.21.4, browserslist@npm:^4.21.5, browserslist@npm:^4.6.6": version: 4.21.9 resolution: "browserslist@npm:4.21.9" @@ -13873,6 +13950,16 @@ __metadata: languageName: node linkType: hard +"create-ecdh@npm:^4.0.0": + version: 4.0.4 + resolution: "create-ecdh@npm:4.0.4" + dependencies: + bn.js: ^4.1.0 + elliptic: ^6.5.3 + checksum: 0dd7fca9711d09e152375b79acf1e3f306d1a25ba87b8ff14c2fd8e68b83aafe0a7dd6c4e540c9ffbdd227a5fa1ad9b81eca1f233c38bb47770597ba247e614b + languageName: node + linkType: hard + "create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0": version: 1.2.0 resolution: "create-hash@npm:1.2.0" @@ -13886,7 +13973,7 @@ __metadata: languageName: node linkType: hard -"create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": +"create-hmac@npm:^1.1.0, create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": version: 1.1.7 resolution: "create-hmac@npm:1.1.7" dependencies: @@ -13947,6 +14034,25 @@ __metadata: languageName: node linkType: hard +"crypto-browserify@npm:^3.12.0": + version: 3.12.0 + resolution: "crypto-browserify@npm:3.12.0" + dependencies: + browserify-cipher: ^1.0.0 + browserify-sign: ^4.0.0 + create-ecdh: ^4.0.0 + create-hash: ^1.1.0 + create-hmac: ^1.1.0 + diffie-hellman: ^5.0.0 + inherits: ^2.0.1 + pbkdf2: ^3.0.3 + public-encrypt: ^4.0.0 + randombytes: ^2.0.0 + randomfill: ^1.0.3 + checksum: c1609af82605474262f3eaa07daa0b2140026bd264ab316d4bf1170272570dbe02f0c49e29407fe0d3634f96c507c27a19a6765fb856fed854a625f9d15618e2 + languageName: node + linkType: hard + "crypto-random-string@npm:^2.0.0": version: 2.0.0 resolution: "crypto-random-string@npm:2.0.0" @@ -14601,6 +14707,16 @@ __metadata: languageName: node linkType: hard +"des.js@npm:^1.0.0": + version: 1.1.0 + resolution: "des.js@npm:1.1.0" + dependencies: + inherits: ^2.0.1 + minimalistic-assert: ^1.0.0 + checksum: 0e9c1584b70d31e20f20a613fc9ef60fbc6a147dfec9e448a168794a4b97ac04d8dc47ea008f1fa93b0f8aaf7c1ead632a5e59ce1913a6079d2d244c9f5ebe33 + languageName: node + linkType: hard + "destroy@npm:1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" @@ -14722,6 +14838,17 @@ __metadata: languageName: node linkType: hard +"diffie-hellman@npm:^5.0.0": + version: 5.0.3 + resolution: "diffie-hellman@npm:5.0.3" + dependencies: + bn.js: ^4.1.0 + miller-rabin: ^4.0.0 + randombytes: ^2.0.0 + checksum: 0e620f322170c41076e70181dd1c24e23b08b47dbb92a22a644f3b89b6d3834b0f8ee19e37916164e5eb1ee26d2aa836d6129f92723995267250a0b541811065 + languageName: node + linkType: hard + "difflib@npm:^0.2.4": version: 0.2.4 resolution: "difflib@npm:0.2.4" @@ -15108,7 +15235,7 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:6.5.4, elliptic@npm:^6.5.2, elliptic@npm:^6.5.4": +"elliptic@npm:6.5.4, elliptic@npm:^6.5.2, elliptic@npm:^6.5.3, elliptic@npm:^6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" dependencies: @@ -16365,7 +16492,7 @@ __metadata: languageName: node linkType: hard -"evp_bytestokey@npm:^1.0.3": +"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": version: 1.0.3 resolution: "evp_bytestokey@npm:1.0.3" dependencies: @@ -21411,15 +21538,15 @@ __metadata: dependencies: "@commitlint/cli": ^17.7.2 "@commitlint/config-conventional": ^17.6.7 - "@types/chai": ^4.3.6 - "@types/mocha": ^10.0.1 buffer: ^5.5.0 - chai: ^4.3.8 conventional-changelog-cli: ^2.2.2 + crypto-browserify: ^3.12.0 husky: ^8.0.3 lint-staged: ^13.2.2 - mocha: ^10.2.0 + os-browserify: ^0.3.0 + path-browserify: ^1.0.0 process: ^0.11.10 + string_decoder: ^1.3.0 languageName: unknown linkType: soft @@ -22889,6 +23016,18 @@ __metadata: languageName: node linkType: hard +"miller-rabin@npm:^4.0.0": + version: 4.0.1 + resolution: "miller-rabin@npm:4.0.1" + dependencies: + bn.js: ^4.0.0 + brorand: ^1.0.1 + bin: + miller-rabin: bin/miller-rabin + checksum: 00cd1ab838ac49b03f236cc32a14d29d7d28637a53096bf5c6246a032a37749c9bd9ce7360cbf55b41b89b7d649824949ff12bc8eee29ac77c6b38eada619ece + languageName: node + linkType: hard + "mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -24281,6 +24420,13 @@ __metadata: languageName: node linkType: hard +"os-browserify@npm:^0.3.0": + version: 0.3.0 + resolution: "os-browserify@npm:0.3.0" + checksum: 16e37ba3c0e6a4c63443c7b55799ce4066d59104143cb637ecb9fce586d5da319cdca786ba1c867abbe3890d2cbf37953f2d51eea85e20dd6c4570d6c54bfebf + languageName: node + linkType: hard + "os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -24542,6 +24688,19 @@ __metadata: languageName: node linkType: hard +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.5": + version: 5.1.6 + resolution: "parse-asn1@npm:5.1.6" + dependencies: + asn1.js: ^5.2.0 + browserify-aes: ^1.0.0 + evp_bytestokey: ^1.0.0 + pbkdf2: ^3.0.3 + safe-buffer: ^5.1.1 + checksum: 9243311d1f88089bc9f2158972aa38d1abd5452f7b7cabf84954ed766048fe574d434d82c6f5a39b988683e96fb84cd933071dda38927e03469dc8c8d14463c7 + languageName: node + linkType: hard + "parse-cache-control@npm:^1.0.1": version: 1.0.1 resolution: "parse-cache-control@npm:1.0.1" @@ -24623,6 +24782,13 @@ __metadata: languageName: node linkType: hard +"path-browserify@npm:^1.0.0": + version: 1.0.1 + resolution: "path-browserify@npm:1.0.1" + checksum: c6d7fa376423fe35b95b2d67990060c3ee304fc815ff0a2dc1c6c3cfaff2bd0d572ee67e18f19d0ea3bbe32e8add2a05021132ac40509416459fffee35200699 + languageName: node + linkType: hard + "path-case@npm:^3.0.4": version: 3.0.4 resolution: "path-case@npm:3.0.4" @@ -24752,7 +24918,7 @@ __metadata: languageName: node linkType: hard -"pbkdf2@npm:^3.0.17": +"pbkdf2@npm:^3.0.17, pbkdf2@npm:^3.0.3": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" dependencies: @@ -26126,6 +26292,20 @@ __metadata: languageName: node linkType: hard +"public-encrypt@npm:^4.0.0": + version: 4.0.3 + resolution: "public-encrypt@npm:4.0.3" + dependencies: + bn.js: ^4.1.0 + browserify-rsa: ^4.0.0 + create-hash: ^1.1.0 + parse-asn1: ^5.0.0 + randombytes: ^2.0.1 + safe-buffer: ^5.1.2 + checksum: 215d446e43cef021a20b67c1df455e5eea134af0b1f9b8a35f9e850abf32991b0c307327bc5b9bc07162c288d5cdb3d4a783ea6c6640979ed7b5017e3e0c9935 + languageName: node + linkType: hard + "pump@npm:^1.0.0": version: 1.0.3 resolution: "pump@npm:1.0.3" @@ -26308,7 +26488,7 @@ __metadata: languageName: node linkType: hard -"randombytes@npm:^2.1.0": +"randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" dependencies: @@ -26317,6 +26497,16 @@ __metadata: languageName: node linkType: hard +"randomfill@npm:^1.0.3": + version: 1.0.4 + resolution: "randomfill@npm:1.0.4" + dependencies: + randombytes: ^2.0.5 + safe-buffer: ^5.1.0 + checksum: 33734bb578a868d29ee1b8555e21a36711db084065d94e019a6d03caa67debef8d6a1bfd06a2b597e32901ddc761ab483a85393f0d9a75838f1912461d4dbfc7 + languageName: node + linkType: hard + "range-parser@npm:^1.2.1, range-parser@npm:~1.2.1": version: 1.2.1 resolution: "range-parser@npm:1.2.1" @@ -29070,7 +29260,7 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:^1.1.1": +"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" dependencies: @@ -30434,6 +30624,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.2.2": + version: 5.2.2 + resolution: "typescript@npm:5.2.2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c + languageName: node + linkType: hard + "typescript@patch:typescript@^4.6.4 || ^5.0.0#~builtin": version: 5.1.3 resolution: "typescript@patch:typescript@npm%3A5.1.3#~builtin::version=5.1.3&hash=ad5954" @@ -30454,6 +30654,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@^5.2.2#~builtin": + version: 5.2.2 + resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=ad5954" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 07106822b4305de3f22835cbba949a2b35451cad50888759b6818421290ff95d522b38ef7919e70fb381c5fe9c1c643d7dea22c8b31652a717ddbd57b7f4d554 + languageName: node + linkType: hard + "typical@npm:^4.0.0": version: 4.0.0 resolution: "typical@npm:4.0.0" From 4420918277f5360df116c7af825d5f6ae161f2f1 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Thu, 12 Oct 2023 19:16:31 +0200 Subject: [PATCH 15/37] feat(web): make graphql action dynamic, dont show data in case if still loading --- kleros-sdk/dataMappings/index.ts | 7 ++++--- web/src/pages/Cases/CaseDetails/Overview.tsx | 12 ++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/kleros-sdk/dataMappings/index.ts b/kleros-sdk/dataMappings/index.ts index a6c51b7f0..bb67a59eb 100644 --- a/kleros-sdk/dataMappings/index.ts +++ b/kleros-sdk/dataMappings/index.ts @@ -44,8 +44,8 @@ export const jsonAction = (source, seek, populate) => { return jsonData; }; -export const graphqlAction = async (query: string, seek, populate) => { - const response = await fetch("https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-arbitrum-goerli", { +export const graphqlAction = async (endpoint: string, query: string, seek, populate) => { + const response = await fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json", @@ -143,7 +143,7 @@ export const eventAction = async (source, inputs, seek, populate) => { export const executeAction = async (action) => { switch (action.type) { case "graphql": - return await graphqlAction(action.source, action.seek, action.populate); + return await graphqlAction(action.source, action.inputs, action.seek, action.populate); case "json": return jsonAction(action.source, action.seek, action.populate); case "abi/call": @@ -158,6 +158,7 @@ export const executeAction = async (action) => { export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { const render = mustache.render(mustacheTemplate, data); console.log("MUSTACHE RENDER: ", render); + // TODO: validate the object according to the DisputeDetails type or a JSON schema const dispute = JSON.parse(render); return dispute; }; diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index 1677c851b..b123fdb12 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -133,7 +133,9 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex useEffect(() => { configureSDK({ apiKey: alchemyApiKey }); + if (!disputeTemplateInput || !dataMappingsInput) return; + const fetchData = async () => { let parsedMapping; try { @@ -164,10 +166,12 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex

{isUndefined(disputeTemplate) ? : disputeDetails?.title ?? INVALID_DISPUTE_DATA_ERROR}

- - {disputeDetails?.question ?? INVALID_DISPUTE_DATA_ERROR} - {disputeDetails?.description ?? INVALID_DISPUTE_DATA_ERROR} - + {!isUndefined(disputeTemplate) && ( + + {disputeDetails?.question ?? INVALID_DISPUTE_DATA_ERROR} + {disputeDetails?.description ?? INVALID_DISPUTE_DATA_ERROR} + + )} {disputeDetails?.frontendUrl && ( Go to arbitrable From ab608a5e4ad019df5446919547ddf3177aed2c65 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Thu, 12 Oct 2023 19:33:15 +0200 Subject: [PATCH 16/37] fix(web): graphql test --- kleros-sdk/dataMappings/test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kleros-sdk/dataMappings/test.ts b/kleros-sdk/dataMappings/test.ts index 6c2f8d2f1..588ff57eb 100644 --- a/kleros-sdk/dataMappings/test.ts +++ b/kleros-sdk/dataMappings/test.ts @@ -26,6 +26,7 @@ describe("jsonAction", () => { describe("graphqlAction", () => { it("should fetch GraphQL data and return in expected format", async () => { + const mockEndpoint = "https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-arbitrum-goerli"; const seek = ["courts"]; const populate = ["courts"]; @@ -57,7 +58,7 @@ describe("graphqlAction", () => { ], }; - const result = await graphqlAction(mockQuery, seek, populate); + const result = await graphqlAction(mockEndpoint, mockQuery, seek, populate); expect(result).to.eql(mockData); }); }); From 0c18d75c3c30a323eeb5d87684f1dd3b7822cefd Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Thu, 12 Oct 2023 19:38:45 +0200 Subject: [PATCH 17/37] feat(web): abstract alchemy api key in web3provider --- web/src/context/Web3Provider.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/src/context/Web3Provider.tsx b/web/src/context/Web3Provider.tsx index d47ddb479..5ad0eb314 100644 --- a/web/src/context/Web3Provider.tsx +++ b/web/src/context/Web3Provider.tsx @@ -11,8 +11,10 @@ import { useTheme } from "styled-components"; const chains = [arbitrumGoerli, mainnet, gnosisChiado]; const projectId = process.env.WALLETCONNECT_PROJECT_ID ?? "6efaa26765fa742153baf9281e218217"; +export const alchemyApiKey = process.env.ALCHEMY_API_KEY ?? ""; + const { publicClient, webSocketPublicClient } = configureChains(chains, [ - alchemyProvider({ apiKey: process.env.ALCHEMY_API_KEY ?? "" }), + alchemyProvider({ apiKey: alchemyApiKey }), jsonRpcProvider({ rpc: () => ({ http: `https://rpc.chiadochain.net`, From 33ba909732fbba0c1716319dcafb272fec43c7f7 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 16 Oct 2023 02:41:50 +0200 Subject: [PATCH 18/37] feat(sdk): modularization of utils, progress on reality dispute template mappings --- kleros-sdk/dataMappings/index.ts | 188 +++++--- .../dataMappings/utils/actionTypeDetectors.ts | 13 + kleros-sdk/dataMappings/utils/actionTypes.ts | 38 ++ .../dataMappings/utils/disputeDetailsTypes.ts | 0 .../dataMappings/utils/findNestedKey.ts | 10 + kleros-sdk/dataMappings/utils/isHexAddress.ts | 1 + .../utils/isValidDisputeDetails.ts | 30 ++ .../dataMappings/utils/populateTemplate.ts | 15 + kleros-sdk/package.json | 3 + package.json | 1 + web/src/pages/DisputeTemplateView.tsx | 16 +- yarn.lock | 429 +++++++++++++++++- 12 files changed, 659 insertions(+), 85 deletions(-) create mode 100644 kleros-sdk/dataMappings/utils/actionTypeDetectors.ts create mode 100644 kleros-sdk/dataMappings/utils/actionTypes.ts rename web/src/utils/disputeDetails.ts => kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts (100%) create mode 100644 kleros-sdk/dataMappings/utils/findNestedKey.ts create mode 100644 kleros-sdk/dataMappings/utils/isHexAddress.ts create mode 100644 kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts create mode 100644 kleros-sdk/dataMappings/utils/populateTemplate.ts diff --git a/kleros-sdk/dataMappings/index.ts b/kleros-sdk/dataMappings/index.ts index bb67a59eb..8ccd7a53d 100644 --- a/kleros-sdk/dataMappings/index.ts +++ b/kleros-sdk/dataMappings/index.ts @@ -1,9 +1,10 @@ import { createPublicClient, parseAbiItem, webSocket } from "viem"; import { arbitrumGoerli } from "viem/chains"; import fetch from "node-fetch"; -import mustache from "mustache"; -import { DisputeDetails } from "./disputeDetails"; import dotenv from "dotenv"; +import { AbiCallMapping, AbiEventMapping, ActionMapping, JsonMapping, SubgraphMapping } from "./utils/actionTypes"; +import { isAbiCallMapping, isAbiEventMapping, isJsonMapping, isSubgraphMapping } from "./utils/actionTypeDetectors"; +import { findNestedKey } from "./utils/findNestedKey"; dotenv.config(); @@ -22,20 +23,10 @@ export const configureSDK = (config: { apiKey?: string }) => { } }; -export const findNestedKey = (data, keyToFind) => { - if (data.hasOwnProperty(keyToFind)) return data[keyToFind]; - for (let key in data) { - if (typeof data[key] === "object" && data[key] !== null) { - const found = findNestedKey(data[key], keyToFind); - if (found) return found; - } - } - return null; -}; +export const jsonAction = (mapping: JsonMapping) => { + const { value: source, seek, populate } = mapping; -export const jsonAction = (source, seek, populate) => { let jsonData = {}; - seek.forEach((key, idx) => { const foundValue = findNestedKey(source, key); jsonData[populate[idx]] = foundValue; @@ -44,7 +35,9 @@ export const jsonAction = (source, seek, populate) => { return jsonData; }; -export const graphqlAction = async (endpoint: string, query: string, seek, populate) => { +export const subgraphAction = async (mapping: SubgraphMapping) => { + const { endpoint, query, seek, populate } = mapping; + const response = await fetch(endpoint, { method: "POST", headers: { @@ -55,9 +48,8 @@ export const graphqlAction = async (endpoint: string, query: string, seek, popul }); const { data } = await response.json(); - console.log(data); - let populatedData = {}; + let populatedData = {}; seek.forEach((key, idx) => { const foundValue = findNestedKey(data, key); populatedData[populate[idx]] = foundValue; @@ -66,73 +58,50 @@ export const graphqlAction = async (endpoint: string, query: string, seek, popul return populatedData; }; -export const callAction = async (source, inputs, seek, populate) => { +export const callAction = async (mapping: AbiCallMapping) => { + const { abi: source, address, args, seek, populate } = mapping; + if (!publicClient) { throw new Error("SDK not configured. Please call `configureSDK` before using."); } - let parsedAbi; - - if (typeof source === "string") { - parsedAbi = parseAbiItem(source); - } else { - parsedAbi = source; - } + let parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; const data = await publicClient.readContract({ - address: inputs[0], + address: address, abi: [parsedAbi], - functionName: inputs[1], - args: inputs.slice(2), + args: args, }); - const populatedData = {}; - + let populatedData = {}; seek.map((item, index) => { - if (typeof data == "object") { - populatedData[populate[index]] = data[item]; - } else { - populatedData[populate[index]] = data; - } + populatedData[populate[index]] = data[item]; }); return populatedData; }; -export const eventAction = async (source, inputs, seek, populate) => { +export const eventAction = async (mapping: AbiEventMapping) => { + const { abi: source, address, eventFilter, seek, populate } = mapping; + if (!publicClient) { throw new Error("SDK not configured. Please call `configureSDK` before using."); } - 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; - }, {}); + let parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; const filter = await publicClient.createEventFilter({ - address: inputs[0], + address: address, event: parsedAbi, - args: { ...argsObject }, - fromBlock: inputs[1], - toBlock: "latest", - }); - - const contractEvent = await publicClient.getFilterLogs({ - filter: filter as any, + args: eventFilter.args, + fromBlock: eventFilter.fromBlock, + toBlock: eventFilter.toBlock, }); + const contractEvent = await publicClient.getFilterLogs({ filter: filter as any }); const eventData = contractEvent[0].args; - const populatedData = {}; - + let populatedData = {}; seek.map((item, index) => { populatedData[populate[index]] = eventData[item]; }); @@ -140,25 +109,102 @@ export const eventAction = async (source, inputs, seek, populate) => { return populatedData; }; -export const executeAction = async (action) => { - switch (action.type) { +export const executeAction = async (mapping: ActionMapping) => { + switch (mapping.type) { case "graphql": - return await graphqlAction(action.source, action.inputs, action.seek, action.populate); + if (!isSubgraphMapping(mapping)) { + throw new Error("Invalid mapping for graphql action."); + } + return await subgraphAction(mapping); case "json": - return jsonAction(action.source, action.seek, action.populate); + if (!isJsonMapping(mapping)) { + throw new Error("Invalid mapping for json action."); + } + return jsonAction(mapping); case "abi/call": - return await callAction(action.source, action.inputs, action.seek, action.populate); + if (!isAbiCallMapping(mapping)) { + throw new Error("Invalid mapping for abi/call action."); + } + return await callAction(mapping); case "abi/event": - return await eventAction(action.source, action.inputs, action.seek, action.populate); + if (!isAbiEventMapping(mapping)) { + throw new Error("Invalid mapping for abi/event action."); + } + return await eventAction(mapping); default: - throw new Error(`Unsupported action type: ${action.type}`); + throw new Error(`Unsupported action type: ${mapping.type}`); } }; -export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { - const render = mustache.render(mustacheTemplate, data); - console.log("MUSTACHE RENDER: ", render); - // TODO: validate the object according to the DisputeDetails type or a JSON schema - const dispute = JSON.parse(render); - return dispute; +export const retrieveRealityData = async (realityQuestionID: string) => { + const questionMapping: AbiEventMapping = { + type: "abi/event", + abi: "event LogNewQuestion(bytes32 indexed question_id, address indexed user, uint256 template_id, string question, bytes32 indexed content_hash, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce, uint256 created)", + address: "0x14a6748192abc6e10ca694ae07bdd4327d6c7a51", + eventFilter: { + args: [realityQuestionID], + fromBlock: "0x1", + toBlock: "latest", + }, + + seek: [ + "question_id", + "user", + "template_id", + "question", + "content_hash", + "arbitrator", + "timeout", + "opening_ts", + "nonce", + "created", + ], + populate: [ + "realityQuestionID", + "realityUser", + "realityTemplateID", + "realityQuestion", + "contentHash", + "arbitrator", + "timeout", + "openingTs", + "nonce", + "created", + ], + }; + + const questionData = await executeAction(questionMapping); + console.log("questionData", questionData); + + const templateMapping: AbiEventMapping = { + type: "abi/event", + abi: "event LogNewTemplate(uint256 indexed template_id, address indexed user, string question_text)", + address: "0x14a6748192abc6e10ca694ae07bdd4327d6c7a51", + eventFilter: { + args: [0], + fromBlock: "0x1", + toBlock: "latest", + }, + seek: ["template_id", "question_text"], + populate: ["templateID", "questionText"], + }; + + const templateData = await executeAction(templateMapping); + console.log("templateData", templateData); + + const rc_question = require("@reality.eth/reality-eth-lib/formatters/question.js"); + const populatedTemplate = rc_question.populatedJSONForTemplate( + templateData.questionText, + questionData.realityQuestion + ); + + console.log("populatedTemplate", populatedTemplate); + + return { + question: questionData.realityQuestion, + type: populatedTemplate.type, + realityAddress: questionData.arbitrator, + questionId: questionData.realityQuestionID, + realityUser: questionData.realityUser, + }; }; diff --git a/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts b/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts new file mode 100644 index 000000000..8492c4a67 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts @@ -0,0 +1,13 @@ +import { SubgraphMapping, AbiEventMapping, AbiCallMapping, JsonMapping, ActionMapping } from "./actionTypes"; + +export const isSubgraphMapping = (mapping: ActionMapping): mapping is SubgraphMapping => + (mapping as SubgraphMapping).endpoint !== undefined; + +export const isAbiEventMapping = (mapping: ActionMapping): mapping is AbiEventMapping => + (mapping as AbiEventMapping).abi !== undefined && (mapping as AbiEventMapping).eventFilter !== undefined; + +export const isAbiCallMapping = (mapping: ActionMapping): mapping is AbiCallMapping => + (mapping as AbiCallMapping).abi !== undefined && (mapping as AbiCallMapping).args !== undefined; + +export const isJsonMapping = (mapping: ActionMapping): mapping is JsonMapping => + (mapping as JsonMapping).value !== undefined; diff --git a/kleros-sdk/dataMappings/utils/actionTypes.ts b/kleros-sdk/dataMappings/utils/actionTypes.ts new file mode 100644 index 000000000..b28546c07 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/actionTypes.ts @@ -0,0 +1,38 @@ +export type JsonMapping = { + type: string; + value: object; + seek: string[]; + populate: string[]; +}; + +export type SubgraphMapping = { + type: string; + endpoint: string; + query: string; + seek: string[]; + populate: string[]; +}; + +export type AbiCallMapping = { + type: string; + abi: string; + address: string; + args: any[]; + seek: string[]; + populate: string[]; +}; + +export type AbiEventMapping = { + type: string; + abi: string; + address: string; + eventFilter: { + fromBlock: BigInt | string; + toBlock: BigInt | string; + args: any; + }; + seek: string[]; + populate: string[]; +}; + +export type ActionMapping = SubgraphMapping | AbiEventMapping | AbiCallMapping | JsonMapping; diff --git a/web/src/utils/disputeDetails.ts b/kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts similarity index 100% rename from web/src/utils/disputeDetails.ts rename to kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts diff --git a/kleros-sdk/dataMappings/utils/findNestedKey.ts b/kleros-sdk/dataMappings/utils/findNestedKey.ts new file mode 100644 index 000000000..12668a257 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/findNestedKey.ts @@ -0,0 +1,10 @@ +export const findNestedKey = (data, keyToFind) => { + if (data.hasOwnProperty(keyToFind)) return data[keyToFind]; + for (let key in data) { + if (typeof data[key] === "object" && data[key] !== null) { + const found = findNestedKey(data[key], keyToFind); + if (found) return found; + } + } + return null; +}; diff --git a/kleros-sdk/dataMappings/utils/isHexAddress.ts b/kleros-sdk/dataMappings/utils/isHexAddress.ts new file mode 100644 index 000000000..ffe33b251 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/isHexAddress.ts @@ -0,0 +1 @@ +export const isHexAddress = (str: string): boolean => /^0x[a-fA-F0-9]{40}$/.test(str); diff --git a/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts b/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts new file mode 100644 index 000000000..565839f7e --- /dev/null +++ b/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts @@ -0,0 +1,30 @@ +import { DisputeDetails, QuestionType } from "./disputeDetailsTypes"; +import { isHexAddress } from "./isHexAddress"; + +export const isValidDisputeDetails = (data: any): data is DisputeDetails => { + return ( + typeof data.title === "string" && + typeof data.description === "string" && + typeof data.question === "string" && + Object.values(QuestionType).includes(data.type) && + // TODO: Uncomment when you figure out how to fetch answers from reality + // Array.isArray(data.answers) && + // data.answers.every( + // (answer) => + // typeof answer.title === "string" && + // typeof answer.description === "string" && + // isHexAddress(answer.id) && + // typeof answer.reserved === "boolean" + // ) && + typeof data.policyURI === "string" && + typeof data.frontendUrl === "string" && + typeof data.arbitrableChainID === "string" && + isHexAddress(data.arbitrableAddress) && + typeof data.arbitratorChainID === "string" && + isHexAddress(data.arbitratorAddress) && + typeof data.category === "string" && + typeof data.lang === "string" && + typeof data.specification === "string" && + typeof data.version === "string" + ); +}; diff --git a/kleros-sdk/dataMappings/utils/populateTemplate.ts b/kleros-sdk/dataMappings/utils/populateTemplate.ts new file mode 100644 index 000000000..5d84ac090 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/populateTemplate.ts @@ -0,0 +1,15 @@ +import mustache from "mustache"; +import { DisputeDetails } from "./disputeDetailsTypes"; +import { isValidDisputeDetails } from "./isValidDisputeDetails"; + +export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { + const render = mustache.render(mustacheTemplate, data); + console.log("MUSTACHE RENDER: ", render); + const dispute = JSON.parse(render); + + if (!isValidDisputeDetails(dispute)) { + throw new Error("Invalid dispute details format."); + } + + return dispute; +}; diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index bff53f11c..6d7092baf 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -27,5 +27,8 @@ "mocha": "^10.2.0", "ts-node": "^10.9.1", "typescript": "^5.2.2" + }, + "dependencies": { + "@reality.eth/reality-eth-lib": "^3.2.29" } } diff --git a/package.json b/package.json index b05ac064c..8f6748966 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "devDependencies": { "@commitlint/cli": "^17.7.2", "@commitlint/config-conventional": "^17.6.7", + "assert": "^2.0.0", "buffer": "^5.5.0", "conventional-changelog-cli": "^2.2.2", "crypto-browserify": "^3.12.0", diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index 0c900a76e..ead80fc28 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -4,8 +4,9 @@ import { Textarea } from "@kleros/ui-components-library"; import PolicyIcon from "svgs/icons/policy.svg"; import ReactMarkdown from "components/ReactMarkdown"; import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; -import { populateTemplate, executeAction, configureSDK } from "@kleros/kleros-sdk/dataMappings"; -import { Answer, DisputeDetails } from "utils/disputeDetails"; +import { executeAction, configureSDK, retrieveRealityData } from "@kleros/kleros-sdk/dataMappings"; +import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; +import { Answer, DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; import { alchemyApiKey } from "context/Web3Provider"; const Container = styled.div` @@ -101,8 +102,15 @@ const DisputeTemplateView: React.FC = () => { try { let data = {}; for (const action of parsedMapping) { - const result = await executeAction(action); - data = { ...data, ...result }; + if (action.type === "reality") { + const realityData = await retrieveRealityData(action.realityQuestionID); + data = { ...data, ...realityData }; + } else { + console.log("Parsed Mapping:", parsedMapping); + + const result = await executeAction(action); + data = { ...data, ...result }; + } } console.log("disputeTemplateInput: ", disputeTemplateInput); console.log("data: ", data); diff --git a/yarn.lock b/yarn.lock index 7f47559a0..4aa89bcb1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5260,6 +5260,7 @@ __metadata: version: 0.0.0-use.local resolution: "@kleros/kleros-sdk@workspace:kleros-sdk" dependencies: + "@reality.eth/reality-eth-lib": ^3.2.29 "@types/chai": ^4.3.6 "@types/mocha": ^10.0.1 chai: ^4.3.8 @@ -7545,6 +7546,31 @@ __metadata: languageName: node linkType: hard +"@reality.eth/contracts@npm:^3.0.45": + version: 3.0.45 + resolution: "@reality.eth/contracts@npm:3.0.45" + dependencies: + ethers: ^5.6.8 + checksum: e6e802fdf78d4bf1a6459bd78febddd6190fe3bc6448cc4dbc08203ebdccc25c99bf873951dd5f4c4523ff84e8f936981b0ef932377ae9ca7b884780904f9c15 + languageName: node + linkType: hard + +"@reality.eth/reality-eth-lib@npm:^3.2.29": + version: 3.2.29 + resolution: "@reality.eth/reality-eth-lib@npm:3.2.29" + dependencies: + "@reality.eth/contracts": ^3.0.45 + bignumber.js: ^7.2.1 + bn.js: ^5.2.1 + ethereumjs-abi: ^0.6.5 + html-to-text: ^8.2.1 + isomorphic-dompurify: ^0.23.0 + marked: ^4.1.1 + sprintf-js: ^1.1.1 + checksum: 2142e90b048b8f0f2b1228e8549880cb6ce306af22bdbb5ec174fe1285611e747680165b4fd82f4feb900a42a3465f8d76302cf3e38899f907a7cf1a58999b10 + languageName: node + linkType: hard + "@remix-run/router@npm:1.6.3": version: 1.6.3 resolution: "@remix-run/router@npm:1.6.3" @@ -7761,6 +7787,16 @@ __metadata: languageName: node linkType: hard +"@selderee/plugin-htmlparser2@npm:^0.6.0": + version: 0.6.0 + resolution: "@selderee/plugin-htmlparser2@npm:0.6.0" + dependencies: + domhandler: ^4.2.0 + selderee: ^0.6.0 + checksum: 3138bec99c874b0613bc5a096900d7352185060693cf08abdecb46a8d537535f5785c47f29f6028855c131c6724cf6af6237a71196d89aa1c96e99909a6f5ec3 + languageName: node + linkType: hard + "@sentry-internal/tracing@npm:7.56.0": version: 7.56.0 resolution: "@sentry-internal/tracing@npm:7.56.0" @@ -8896,6 +8932,15 @@ __metadata: languageName: node linkType: hard +"@types/dompurify@npm:^2.3.4": + version: 2.4.0 + resolution: "@types/dompurify@npm:2.4.0" + dependencies: + "@types/trusted-types": "*" + checksum: b48cd81e997794ebc390c7c5bef1a67ec14a6f2f0521973e07e06af186c7583abe114d94d24868c0632b9573f5bd77131a4b76f3fffdf089ba99a4e53dd46c39 + languageName: node + linkType: hard + "@types/eslint-scope@npm:^3.7.3": version: 3.7.4 resolution: "@types/eslint-scope@npm:3.7.4" @@ -9454,6 +9499,13 @@ __metadata: languageName: node linkType: hard +"@types/trusted-types@npm:*": + version: 2.0.4 + resolution: "@types/trusted-types@npm:2.0.4" + checksum: 5256c4576cd1c90d33ddd9cc9cbd4f202b39c98cbe8b7f74963298f9eb2159c285ea5c25a6181b4c594d8d75641765bff85d72c2d251ad076e6529ce0eeedd1c + languageName: node + linkType: hard + "@types/trusted-types@npm:^2.0.2": version: 2.0.3 resolution: "@types/trusted-types@npm:2.0.3" @@ -10639,7 +10691,7 @@ __metadata: languageName: node linkType: hard -"abab@npm:^2.0.3, abab@npm:^2.0.5": +"abab@npm:^2.0.3, abab@npm:^2.0.5, abab@npm:^2.0.6": version: 2.0.6 resolution: "abab@npm:2.0.6" checksum: 6ffc1af4ff315066c62600123990d87551ceb0aafa01e6539da77b0f5987ac7019466780bf480f1787576d4385e3690c81ccc37cfda12819bf510b8ab47e5a3e @@ -10739,6 +10791,16 @@ __metadata: languageName: node linkType: hard +"acorn-globals@npm:^7.0.0": + version: 7.0.1 + resolution: "acorn-globals@npm:7.0.1" + dependencies: + acorn: ^8.1.0 + acorn-walk: ^8.0.2 + checksum: 2a2998a547af6d0db5f0cdb90acaa7c3cbca6709010e02121fb8b8617c0fbd8bab0b869579903fde358ac78454356a14fadcc1a672ecb97b04b1c2ccba955ce8 + languageName: node + linkType: hard + "acorn-import-assertions@npm:^1.9.0": version: 1.9.0 resolution: "acorn-import-assertions@npm:1.9.0" @@ -10764,7 +10826,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.1.1": +"acorn-walk@npm:^8.0.2, acorn-walk@npm:^8.1.1": version: 8.2.0 resolution: "acorn-walk@npm:8.2.0" checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 @@ -10780,6 +10842,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.1.0, acorn@npm:^8.8.1": + version: 8.10.0 + resolution: "acorn@npm:8.10.0" + bin: + acorn: bin/acorn + checksum: 538ba38af0cc9e5ef983aee196c4b8b4d87c0c94532334fa7e065b2c8a1f85863467bb774231aae91613fcda5e68740c15d97b1967ae3394d20faddddd8af61d + languageName: node + linkType: hard + "acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.0, acorn@npm:^8.8.2": version: 8.9.0 resolution: "acorn@npm:8.9.0" @@ -11431,6 +11502,19 @@ __metadata: languageName: node linkType: hard +"assert@npm:^2.0.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: ^1.0.2 + is-nan: ^1.3.2 + object-is: ^1.1.5 + object.assign: ^4.1.4 + util: ^0.12.5 + checksum: 1ed1cabba9abe55f4109b3f7292b4e4f3cf2953aad8dc148c0b3c3bd676675c31b1abb32ef563b7d5a19d1715bf90d1e5f09fad2a4ee655199468902da80f7c2 + languageName: node + linkType: hard + "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -11933,6 +12017,13 @@ __metadata: languageName: node linkType: hard +"bignumber.js@npm:^7.2.1": + version: 7.2.1 + resolution: "bignumber.js@npm:7.2.1" + checksum: c4eab705fb3293170f248f13f38a06d24591710864632f78b1637d361feaf07ce782cc6ea23c6984c8ddb030ad1883b813a251448527d55650b403e6f2cc7e67 + languageName: node + linkType: hard + "bin-links@npm:^4.0.1": version: 4.0.2 resolution: "bin-links@npm:4.0.2" @@ -13391,7 +13482,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^2.20.0, commander@npm:^2.20.3": +"commander@npm:^2.19.0, commander@npm:^2.20.0, commander@npm:^2.20.3": version: 2.20.3 resolution: "commander@npm:2.20.3" checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e @@ -14335,6 +14426,13 @@ __metadata: languageName: node linkType: hard +"cssom@npm:^0.5.0": + version: 0.5.0 + resolution: "cssom@npm:0.5.0" + checksum: 823471aa30091c59e0a305927c30e7768939b6af70405808f8d2ce1ca778cddcb24722717392438329d1691f9a87cb0183b64b8d779b56a961546d54854fde01 + languageName: node + linkType: hard + "cssom@npm:~0.3.6": version: 0.3.8 resolution: "cssom@npm:0.3.8" @@ -14419,6 +14517,17 @@ __metadata: languageName: node linkType: hard +"data-urls@npm:^3.0.2": + version: 3.0.2 + resolution: "data-urls@npm:3.0.2" + dependencies: + abab: ^2.0.6 + whatwg-mimetype: ^3.0.0 + whatwg-url: ^11.0.0 + checksum: 033fc3dd0fba6d24bc9a024ddcf9923691dd24f90a3d26f6545d6a2f71ec6956f93462f2cdf2183cc46f10dc01ed3bcb36731a8208456eb1a08147e571fe2a76 + languageName: node + linkType: hard + "dataloader@npm:^2.2.2": version: 2.2.2 resolution: "dataloader@npm:2.2.2" @@ -14540,7 +14649,7 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.2.1": +"decimal.js@npm:^10.2.1, decimal.js@npm:^10.4.2": version: 10.4.3 resolution: "decimal.js@npm:10.4.3" checksum: 796404dcfa9d1dbfdc48870229d57f788b48c21c603c3f6554a1c17c10195fc1024de338b0cf9e1efe0c7c167eeb18f04548979bcc5fdfabebb7cc0ae3287bae @@ -14874,6 +14983,13 @@ __metadata: languageName: node linkType: hard +"discontinuous-range@npm:1.0.0": + version: 1.0.0 + resolution: "discontinuous-range@npm:1.0.0" + checksum: 8ee88d7082445b6eadc7c03bebe6dc978f96760c45e9f65d16ca66174d9e086a9e3855ee16acf65625e1a07a846a17de674f02a5964a6aebe5963662baf8b5c8 + languageName: node + linkType: hard + "dlv@npm:^1.1.3": version: 1.1.3 resolution: "dlv@npm:1.1.3" @@ -15053,6 +15169,15 @@ __metadata: languageName: node linkType: hard +"domexception@npm:^4.0.0": + version: 4.0.0 + resolution: "domexception@npm:4.0.0" + dependencies: + webidl-conversions: ^7.0.0 + checksum: ddbc1268edf33a8ba02ccc596735ede80375ee0cf124b30d2f05df5b464ba78ef4f49889b6391df4a04954e63d42d5631c7fcf8b1c4f12bc531252977a5f13d5 + languageName: node + linkType: hard + "domhandler@npm:^4.0.0, domhandler@npm:^4.2.0, domhandler@npm:^4.2.2, domhandler@npm:^4.3.1": version: 4.3.1 resolution: "domhandler@npm:4.3.1" @@ -15062,6 +15187,13 @@ __metadata: languageName: node linkType: hard +"dompurify@npm:^2.4.0": + version: 2.4.7 + resolution: "dompurify@npm:2.4.7" + checksum: 13c047e772a1998348191554dda403950d45ef2ec75fa0b9915cc179ccea0a39ef780d283109bd72cf83a2a085af6c77664281d4d0106a737bc5f39906364efe + languageName: node + linkType: hard + "domutils@npm:^1.7.0": version: 1.7.0 resolution: "domutils@npm:1.7.0" @@ -16329,7 +16461,7 @@ __metadata: languageName: node linkType: hard -"ethereumjs-abi@npm:^0.6.8": +"ethereumjs-abi@npm:^0.6.5, ethereumjs-abi@npm:^0.6.8": version: 0.6.8 resolution: "ethereumjs-abi@npm:0.6.8" dependencies: @@ -16398,7 +16530,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:^5.5.3, ethers@npm:^5.6.1, ethers@npm:^5.7.1, ethers@npm:^5.7.2": +"ethers@npm:^5.5.3, ethers@npm:^5.6.1, ethers@npm:^5.6.8, ethers@npm:^5.7.1, ethers@npm:^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" dependencies: @@ -18568,6 +18700,15 @@ __metadata: languageName: node linkType: hard +"html-encoding-sniffer@npm:^3.0.0": + version: 3.0.0 + resolution: "html-encoding-sniffer@npm:3.0.0" + dependencies: + whatwg-encoding: ^2.0.0 + checksum: 8d806aa00487e279e5ccb573366a951a9f68f65c90298eac9c3a2b440a7ffe46615aff2995a2f61c6746c639234e6179a97e18ca5ccbbf93d3725ef2099a4502 + languageName: node + linkType: hard + "html-entities@npm:^2.1.0, html-entities@npm:^2.3.2": version: 2.3.6 resolution: "html-entities@npm:2.3.6" @@ -18599,6 +18740,22 @@ __metadata: languageName: node linkType: hard +"html-to-text@npm:^8.2.1": + version: 8.2.1 + resolution: "html-to-text@npm:8.2.1" + dependencies: + "@selderee/plugin-htmlparser2": ^0.6.0 + deepmerge: ^4.2.2 + he: ^1.2.0 + htmlparser2: ^6.1.0 + minimist: ^1.2.6 + selderee: ^0.6.0 + bin: + html-to-text: bin/cli.js + checksum: ff4cc1d355e71eed610f5e3eb89cbf1b1f394aa971ee915781feceb903f2f6690de007294d3edde23ff204b240a59d65145e2f732112d73fac6dbc560ba3d3d0 + languageName: node + linkType: hard + "html-webpack-plugin@npm:^5.5.0": version: 5.5.3 resolution: "html-webpack-plugin@npm:5.5.3" @@ -18814,7 +18971,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^5.0.0": +"https-proxy-agent@npm:^5.0.0, https-proxy-agent@npm:^5.0.1": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" dependencies: @@ -18906,7 +19063,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": +"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -19840,6 +19997,16 @@ __metadata: languageName: node linkType: hard +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: ^1.0.0 + define-properties: ^1.1.3 + checksum: 5dfadcef6ad12d3029d43643d9800adbba21cf3ce2ec849f734b0e14ee8da4070d82b15fdb35138716d02587c6578225b9a22779cab34888a139cc43e4e3610a + languageName: node + linkType: hard + "is-negative-zero@npm:^2.0.2": version: 2.0.2 resolution: "is-negative-zero@npm:2.0.2" @@ -20151,6 +20318,17 @@ __metadata: languageName: node linkType: hard +"isomorphic-dompurify@npm:^0.23.0": + version: 0.23.0 + resolution: "isomorphic-dompurify@npm:0.23.0" + dependencies: + "@types/dompurify": ^2.3.4 + dompurify: ^2.4.0 + jsdom: ^20.0.1 + checksum: bcd5a99fb7cfae6c63446b31a0787ec79a629e42459a0eae99f222949b7ffbcbb0d6d524f105eca21939b4308fdf112e1c2fa7fc915b352cf5d938e11923e95c + languageName: node + linkType: hard + "isomorphic-ws@npm:5.0.0, isomorphic-ws@npm:^5.0.0": version: 5.0.0 resolution: "isomorphic-ws@npm:5.0.0" @@ -21261,6 +21439,45 @@ __metadata: languageName: node linkType: hard +"jsdom@npm:^20.0.1": + version: 20.0.3 + resolution: "jsdom@npm:20.0.3" + dependencies: + abab: ^2.0.6 + acorn: ^8.8.1 + acorn-globals: ^7.0.0 + cssom: ^0.5.0 + cssstyle: ^2.3.0 + data-urls: ^3.0.2 + decimal.js: ^10.4.2 + domexception: ^4.0.0 + escodegen: ^2.0.0 + form-data: ^4.0.0 + html-encoding-sniffer: ^3.0.0 + http-proxy-agent: ^5.0.0 + https-proxy-agent: ^5.0.1 + is-potential-custom-element-name: ^1.0.1 + nwsapi: ^2.2.2 + parse5: ^7.1.1 + saxes: ^6.0.0 + symbol-tree: ^3.2.4 + tough-cookie: ^4.1.2 + w3c-xmlserializer: ^4.0.0 + webidl-conversions: ^7.0.0 + whatwg-encoding: ^2.0.0 + whatwg-mimetype: ^3.0.0 + whatwg-url: ^11.0.0 + ws: ^8.11.0 + xml-name-validator: ^4.0.0 + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 6e2ae21db397133a061b270c26d2dbc0b9051733ea3b896a7ece78d79f475ff0974f766a413c1198a79c793159119169f2335ddb23150348fbfdcfa6f3105536 + languageName: node + linkType: hard + "jsesc@npm:^2.5.1": version: 2.5.2 resolution: "jsesc@npm:2.5.2" @@ -21538,6 +21755,7 @@ __metadata: dependencies: "@commitlint/cli": ^17.7.2 "@commitlint/config-conventional": ^17.6.7 + assert: ^2.0.0 buffer: ^5.5.0 conventional-changelog-cli: ^2.2.2 crypto-browserify: ^3.12.0 @@ -22544,6 +22762,15 @@ __metadata: languageName: node linkType: hard +"marked@npm:^4.1.1": + version: 4.3.0 + resolution: "marked@npm:4.3.0" + bin: + marked: bin/marked.js + checksum: 0db6817893952c3ec710eb9ceafb8468bf5ae38cb0f92b7b083baa13d70b19774674be04db5b817681fa7c5c6a088f61300815e4dd75a59696f4716ad69f6260 + languageName: node + linkType: hard + "match-all@npm:^1.2.6": version: 1.2.6 resolution: "match-all@npm:1.2.6" @@ -23453,6 +23680,13 @@ __metadata: languageName: node linkType: hard +"moo@npm:^0.5.0, moo@npm:^0.5.1": + version: 0.5.2 + resolution: "moo@npm:0.5.2" + checksum: 5a41ddf1059fd0feb674d917c4774e41c877f1ca980253be4d3aae1a37f4bc513f88815041243f36f5cf67a62fb39324f3f997cf7fb17b6cb00767c165e7c499 + languageName: node + linkType: hard + "motion@npm:10.16.2": version: 10.16.2 resolution: "motion@npm:10.16.2" @@ -23772,6 +24006,23 @@ __metadata: languageName: node linkType: hard +"nearley@npm:^2.20.1": + version: 2.20.1 + resolution: "nearley@npm:2.20.1" + dependencies: + commander: ^2.19.0 + moo: ^0.5.0 + railroad-diagrams: ^1.0.0 + randexp: 0.4.6 + bin: + nearley-railroad: bin/nearley-railroad.js + nearley-test: bin/nearley-test.js + nearley-unparse: bin/nearley-unparse.js + nearleyc: bin/nearleyc.js + checksum: 42c2c330c13c7991b48221c5df00f4352c2f8851636ae4d1f8ca3c8e193fc1b7668c78011d1cad88cca4c1c4dc087425420629c19cc286d7598ec15533aaef26 + languageName: node + linkType: hard + "negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" @@ -24116,6 +24367,13 @@ __metadata: languageName: node linkType: hard +"nwsapi@npm:^2.2.2": + version: 2.2.7 + resolution: "nwsapi@npm:2.2.7" + checksum: cab25f7983acec7e23490fec3ef7be608041b460504229770e3bfcf9977c41d6fe58f518994d3bd9aa3a101f501089a3d4a63536f4ff8ae4b8c4ca23bdbfda4e + languageName: node + linkType: hard + "oauth-sign@npm:~0.9.0": version: 0.9.0 resolution: "oauth-sign@npm:0.9.0" @@ -24144,6 +24402,16 @@ __metadata: languageName: node linkType: hard +"object-is@npm:^1.1.5": + version: 1.1.5 + resolution: "object-is@npm:1.1.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe + languageName: node + linkType: hard + "object-keys@npm:^1.0.11, object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" @@ -24755,6 +25023,25 @@ __metadata: languageName: node linkType: hard +"parse5@npm:^7.1.1": + version: 7.1.2 + resolution: "parse5@npm:7.1.2" + dependencies: + entities: ^4.4.0 + checksum: 59465dd05eb4c5ec87b76173d1c596e152a10e290b7abcda1aecf0f33be49646ea74840c69af975d7887543ea45564801736356c568d6b5e71792fd0f4055713 + languageName: node + linkType: hard + +"parseley@npm:^0.7.0": + version: 0.7.0 + resolution: "parseley@npm:0.7.0" + dependencies: + moo: ^0.5.1 + nearley: ^2.20.1 + checksum: b1bbc16a2fabe824ad2c4879b0c36d0300490f9ccda0fd60f4ee90f1f38e053fa58d40d953be3fc245fb9362e73e25fc600a129d5ef69d2d02ac739a2b62e319 + languageName: node + linkType: hard + "parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -26488,6 +26775,23 @@ __metadata: languageName: node linkType: hard +"railroad-diagrams@npm:^1.0.0": + version: 1.0.0 + resolution: "railroad-diagrams@npm:1.0.0" + checksum: 9e312af352b5ed89c2118edc0c06cef2cc039681817f65266719606e4e91ff6ae5374c707cc9033fe29a82c2703edf3c63471664f97f0167c85daf6f93496319 + languageName: node + linkType: hard + +"randexp@npm:0.4.6": + version: 0.4.6 + resolution: "randexp@npm:0.4.6" + dependencies: + discontinuous-range: 1.0.0 + ret: ~0.1.10 + checksum: 3c0d440a3f89d6d36844aa4dd57b5cdb0cab938a41956a16da743d3a3578ab32538fc41c16cc0984b6938f2ae4cbc0216967e9829e52191f70e32690d8e3445d + languageName: node + linkType: hard + "randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" @@ -27646,6 +27950,13 @@ __metadata: languageName: node linkType: hard +"ret@npm:~0.1.10": + version: 0.1.15 + resolution: "ret@npm:0.1.15" + checksum: d76a9159eb8c946586567bd934358dfc08a36367b3257f7a3d7255fdd7b56597235af23c6afa0d7f0254159e8051f93c918809962ebd6df24ca2a83dbe4d4151 + languageName: node + linkType: hard + "retimer@npm:^2.0.0": version: 2.0.0 resolution: "retimer@npm:2.0.0" @@ -27961,6 +28272,15 @@ __metadata: languageName: node linkType: hard +"saxes@npm:^6.0.0": + version: 6.0.0 + resolution: "saxes@npm:6.0.0" + dependencies: + xmlchars: ^2.2.0 + checksum: d3fa3e2aaf6c65ed52ee993aff1891fc47d5e47d515164b5449cbf5da2cbdc396137e55590472e64c5c436c14ae64a8a03c29b9e7389fc6f14035cf4e982ef3b + languageName: node + linkType: hard + "sc-istanbul@npm:^0.4.5": version: 0.4.6 resolution: "sc-istanbul@npm:0.4.6" @@ -28095,6 +28415,15 @@ __metadata: languageName: node linkType: hard +"selderee@npm:^0.6.0": + version: 0.6.0 + resolution: "selderee@npm:0.6.0" + dependencies: + parseley: ^0.7.0 + checksum: 0bbf1f29676bae4a97a198d9b5ac652a44fecdf54a1ca782c2715b1c7097a1780e0a235b2c6aff9e157698cb4aea93d012323858176dade4ea1deba7e2b95f50 + languageName: node + linkType: hard + "select-hose@npm:^2.0.0": version: 2.0.0 resolution: "select-hose@npm:2.0.0" @@ -28902,6 +29231,13 @@ __metadata: languageName: node linkType: hard +"sprintf-js@npm:^1.1.1": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + "sprintf-js@npm:~1.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -30222,7 +30558,7 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^4.0.0": +"tough-cookie@npm:^4.0.0, tough-cookie@npm:^4.1.2": version: 4.1.3 resolution: "tough-cookie@npm:4.1.3" dependencies: @@ -30252,6 +30588,15 @@ __metadata: languageName: node linkType: hard +"tr46@npm:^3.0.0": + version: 3.0.0 + resolution: "tr46@npm:3.0.0" + dependencies: + punycode: ^2.1.1 + checksum: 44c3cc6767fb800490e6e9fd64fd49041aa4e49e1f6a012b34a75de739cc9ed3a6405296072c1df8b6389ae139c5e7c6496f659cfe13a04a4bff3a1422981270 + languageName: node + linkType: hard + "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -31055,7 +31400,7 @@ __metadata: languageName: node linkType: hard -"util@npm:^0.12.3, util@npm:^0.12.4": +"util@npm:^0.12.3, util@npm:^0.12.4, util@npm:^0.12.5": version: 0.12.5 resolution: "util@npm:0.12.5" dependencies: @@ -31380,6 +31725,15 @@ __metadata: languageName: node linkType: hard +"w3c-xmlserializer@npm:^4.0.0": + version: 4.0.0 + resolution: "w3c-xmlserializer@npm:4.0.0" + dependencies: + xml-name-validator: ^4.0.0 + checksum: eba070e78deb408ae8defa4d36b429f084b2b47a4741c4a9be3f27a0a3d1845e277e3072b04391a138f7e43776842627d1334e448ff13ff90ad9fb1214ee7091 + languageName: node + linkType: hard + "wagmi@npm:^1.4.3": version: 1.4.3 resolution: "wagmi@npm:1.4.3" @@ -31555,6 +31909,13 @@ __metadata: languageName: node linkType: hard +"webidl-conversions@npm:^7.0.0": + version: 7.0.0 + resolution: "webidl-conversions@npm:7.0.0" + checksum: f05588567a2a76428515333eff87200fae6c83c3948a7482ebb109562971e77ef6dc49749afa58abb993391227c5697b3ecca52018793e0cb4620a48f10bd21b + languageName: node + linkType: hard + "webpack-dev-middleware@npm:^5.3.1": version: 5.3.3 resolution: "webpack-dev-middleware@npm:5.3.3" @@ -31734,6 +32095,15 @@ __metadata: languageName: node linkType: hard +"whatwg-encoding@npm:^2.0.0": + version: 2.0.0 + resolution: "whatwg-encoding@npm:2.0.0" + dependencies: + iconv-lite: 0.6.3 + checksum: 7087810c410aa9b689cbd6af8773341a53cdc1f3aae2a882c163bd5522ec8ca4cdfc269aef417a5792f411807d5d77d50df4c24e3abb00bb60192858a40cc675 + languageName: node + linkType: hard + "whatwg-fetch@npm:^3.6.2": version: 3.6.2 resolution: "whatwg-fetch@npm:3.6.2" @@ -31748,6 +32118,23 @@ __metadata: languageName: node linkType: hard +"whatwg-mimetype@npm:^3.0.0": + version: 3.0.0 + resolution: "whatwg-mimetype@npm:3.0.0" + checksum: ce08bbb36b6aaf64f3a84da89707e3e6a31e5ab1c1a2379fd68df79ba712a4ab090904f0b50e6693b0dafc8e6343a6157e40bf18fdffd26e513cf95ee2a59824 + languageName: node + linkType: hard + +"whatwg-url@npm:^11.0.0": + version: 11.0.0 + resolution: "whatwg-url@npm:11.0.0" + dependencies: + tr46: ^3.0.0 + webidl-conversions: ^7.0.0 + checksum: ed4826aaa57e66bb3488a4b25c9cd476c46ba96052747388b5801f137dd740b73fde91ad207d96baf9f17fbcc80fc1a477ad65181b5eb5fa718d27c69501d7af + languageName: node + linkType: hard + "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" @@ -32257,6 +32644,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.11.0": + version: 8.14.2 + resolution: "ws@npm:8.14.2" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 3ca0dad26e8cc6515ff392b622a1467430814c463b3368b0258e33696b1d4bed7510bc7030f7b72838b9fdeb8dbd8839cbf808367d6aae2e1d668ce741d4308b + languageName: node + linkType: hard + "xml-name-validator@npm:^3.0.0": version: 3.0.0 resolution: "xml-name-validator@npm:3.0.0" @@ -32264,6 +32666,13 @@ __metadata: languageName: node linkType: hard +"xml-name-validator@npm:^4.0.0": + version: 4.0.0 + resolution: "xml-name-validator@npm:4.0.0" + checksum: af100b79c29804f05fa35aa3683e29a321db9b9685d5e5febda3fa1e40f13f85abc40f45a6b2bf7bee33f68a1dc5e8eaef4cec100a304a9db565e6061d4cb5ad + languageName: node + linkType: hard + "xmlchars@npm:^2.2.0": version: 2.2.0 resolution: "xmlchars@npm:2.2.0" From 57d2e52a85741690fe1a7a075400c83de3c7e40e Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 16 Oct 2023 16:52:33 +0200 Subject: [PATCH 19/37] feat(web): add answers to dispute mappings for reality template id 0 bool --- kleros-sdk/dataMappings/index.ts | 30 +++++++++++++++++++ kleros-sdk/dataMappings/utils/isHexId.ts | 1 + .../utils/isValidDisputeDetails.ts | 18 +++++------ 3 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 kleros-sdk/dataMappings/utils/isHexId.ts diff --git a/kleros-sdk/dataMappings/index.ts b/kleros-sdk/dataMappings/index.ts index 8ccd7a53d..4e01b7282 100644 --- a/kleros-sdk/dataMappings/index.ts +++ b/kleros-sdk/dataMappings/index.ts @@ -200,11 +200,41 @@ export const retrieveRealityData = async (realityQuestionID: string) => { console.log("populatedTemplate", populatedTemplate); + let answers = []; + if (populatedTemplate.type === "bool") { + answers = [ + { + title: "Yes", + description: "", + id: "0x01", + reserved: false, + }, + { + title: "No", + description: "", + id: "0x02", + reserved: false, + }, + ]; + } + + answers.push({ + id: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + title: "Answered Too Soon", + description: "", + reserved: true, + }); + + for (let i = 0; i < answers.length; i++) { + answers[i].last = i === answers.length - 1; + } + return { question: questionData.realityQuestion, type: populatedTemplate.type, realityAddress: questionData.arbitrator, questionId: questionData.realityQuestionID, realityUser: questionData.realityUser, + answers: answers, }; }; diff --git a/kleros-sdk/dataMappings/utils/isHexId.ts b/kleros-sdk/dataMappings/utils/isHexId.ts new file mode 100644 index 000000000..39266f013 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/isHexId.ts @@ -0,0 +1 @@ +export const isHexId = (str: string): boolean => /^0x[a-fA-F0-9]{1,64}$/.test(str); diff --git a/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts b/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts index 565839f7e..ce105896f 100644 --- a/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts +++ b/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts @@ -1,5 +1,6 @@ import { DisputeDetails, QuestionType } from "./disputeDetailsTypes"; import { isHexAddress } from "./isHexAddress"; +import { isHexId } from "./isHexId"; export const isValidDisputeDetails = (data: any): data is DisputeDetails => { return ( @@ -7,15 +8,14 @@ export const isValidDisputeDetails = (data: any): data is DisputeDetails => { typeof data.description === "string" && typeof data.question === "string" && Object.values(QuestionType).includes(data.type) && - // TODO: Uncomment when you figure out how to fetch answers from reality - // Array.isArray(data.answers) && - // data.answers.every( - // (answer) => - // typeof answer.title === "string" && - // typeof answer.description === "string" && - // isHexAddress(answer.id) && - // typeof answer.reserved === "boolean" - // ) && + Array.isArray(data.answers) && + data.answers.every( + (answer) => + typeof answer.title === "string" && + typeof answer.description === "string" && + isHexId(answer.id) && + typeof answer.reserved === "boolean" + ) && typeof data.policyURI === "string" && typeof data.frontendUrl === "string" && typeof data.arbitrableChainID === "string" && From 060e58c1b9ae65248050127622c58ed5f496bf00 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 16 Oct 2023 19:57:59 +0200 Subject: [PATCH 20/37] fix(web): import error from sdk --- web/src/components/DisputeCard/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index b8c55732a..614f5548b 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -14,8 +14,8 @@ import { useVotingHistory } from "queries/useVotingHistory"; import DisputeInfo from "./DisputeInfo"; import PeriodBanner from "./PeriodBanner"; import { isUndefined } from "utils/index"; -import { populateTemplate } from "@kleros/kleros-sdk/dataMappings"; -import { DisputeDetails } from "utils/disputeDetails"; +import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; +import { DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; import { INVALID_DISPUTE_DATA_ERROR } from "consts/index"; const StyledCard = styled(Card)` From 8d4a87ccb4b4aa5d824be4d1b7a062e552420b62 Mon Sep 17 00:00:00 2001 From: marino <102478601+kemuru@users.noreply.github.com> Date: Mon, 16 Oct 2023 20:04:48 +0200 Subject: [PATCH 21/37] fix(web): another import update --- web/src/pages/Cases/CaseDetails/Overview.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index b123fdb12..48cf2dbb8 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -8,9 +8,10 @@ import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { useCourtPolicy } from "queries/useCourtPolicy"; import { isUndefined } from "utils/index"; -import { populateTemplate, executeAction, configureSDK } from "@kleros/kleros-sdk/dataMappings"; +import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; +import { executeAction, configureSDK } from "@kleros/kleros-sdk/dataMappings"; import { alchemyApiKey } from "context/Web3Provider"; -import { Answer, DisputeDetails } from "utils/disputeDetails"; +import { Answer, DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; import { Periods } from "consts/periods"; import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; import PolicyIcon from "svgs/icons/policy.svg"; From 399e98e077e8f659ee1f89955e418c22c9fb423b Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 4 Jan 2024 01:34:58 +0100 Subject: [PATCH 22/37] feat: escrow dispute template --- .../config/v1-metaevidence/escrow3.json | 39 ++++++++++++ .../NewDisputeTemplate.schema.json | 59 +++++++++++++++++++ .../escrow/DataMappings.escrow.jsonc | 34 +++++++++++ .../DisputeDetails.escrow.jsonc.mustache | 41 +++++++++++++ .../escrow/DisputeRequest.ts | 7 +++ 5 files changed, 180 insertions(+) create mode 100644 kleros-sdk/config/v1-metaevidence/escrow3.json create mode 100644 kleros-sdk/config/v2-disputetemplate/escrow/DataMappings.escrow.jsonc create mode 100644 kleros-sdk/config/v2-disputetemplate/escrow/DisputeDetails.escrow.jsonc.mustache create mode 100644 kleros-sdk/config/v2-disputetemplate/escrow/DisputeRequest.ts diff --git a/kleros-sdk/config/v1-metaevidence/escrow3.json b/kleros-sdk/config/v1-metaevidence/escrow3.json new file mode 100644 index 000000000..4257141eb --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/escrow3.json @@ -0,0 +1,39 @@ +{ + "subCategory": "General Service", + "arbitrableAddress": "0x0d67440946949fe293b45c52efd8a9b3d51e2522", + "title": "Liquidity Withdrawal Transfer Ownership Agreement ", + "description": "PARTIES:\nParty 1 (hereinafter referred to as the \"Seller\"):\n* Ethereum Address: 0xc4c4e8144823000d97310756d3237B305E967a09\n\nParty 2 (hereinafter referred to as the \"Buyer\"):\n* Ethereum Address: 0x213fea050A0dA676E97B4dc40e37E985008EA1a0\n\nRECITALS\n\nA. The Seller is the owner of an ERC-20 token contract, whose liquidity is locked on the UNCX.network platform.\nB. The \"Rights'' herein refer to the ability to demand liquidity withdrawal of the aforementioned ERC-20 token through the UNCX.network service by having the designated rights-holder's address assigned to the Gudetama in the contract 0x257EeF05f232B566cD0aF298Ec0B45C2C18d16c7 on the Ethereum chain.\n\nAGREEMENT\n\nTransfer of Rights:\n1.1. The transfer shall be completed by 12:00, Wednesday 20, December 2023 EDT, to the Buyer at the ETH wallet address: 0x8e6f7b23Cdf06db96FD96F4aF8369c0131FAf0F6.\n\nPayment:\n2.1. Upon successful fulfillment of 1.1, the Buyer shall transfer the full amount of 1,4 ETH to the Seller.\n\nNo Partial Payment:\n3.1. There shall be no conditions under which partial payment can be demanded by the Seller, unless the Buyer chooses to do so voluntarily through the Escrow contract.\n\nKleros Escrow:\n4.1. Any disputes arising from this Agreement shall be automatically escalated to the Court of Kleros after both parties fund the dispute resolution deposit. Should one side fail to do so in full, the other party will automatically win the dispute.", + "sender": "0x213fea050A0dA676E97B4dc40e37E985008EA1a0", + "receiver": "0xc4c4e8144823000d97310756d3237B305E967a09", + "amount": "1.4", + "timeout": 8640000000000000, + "token": { + "name": "Ethereum", + "ticker": "ETH", + "symbolURI": "/static/media/eth.33901ab6.png", + "address": null, + "decimals": 18 + }, + "extraData": { + "Contract Information": "PARTIES:\nParty 1 (hereinafter referred to as the \"Seller\"):\n* Ethereum Address: 0xc4c4e8144823000d97310756d3237B305E967a09\n\nParty 2 (hereinafter referred to as the \"Buyer\"):\n* Ethereum Address: 0x213fea050A0dA676E97B4dc40e37E985008EA1a0\n\nRECITALS\n\nA. The Seller is the owner of an ERC-20 token contract, whose liquidity is locked on the UNCX.network platform.\nB. The \"Rights'' herein refer to the ability to demand liquidity withdrawal of the aforementioned ERC-20 token through the UNCX.network service by having the designated rights-holder's address assigned to the Gudetama in the contract 0x257EeF05f232B566cD0aF298Ec0B45C2C18d16c7 on the Ethereum chain.\n\nAGREEMENT\n\nTransfer of Rights:\n1.1. The transfer shall be completed by 12:00, Wednesday 20, December 2023 EDT, to the Buyer at the ETH wallet address: 0x8e6f7b23Cdf06db96FD96F4aF8369c0131FAf0F6.\n\nPayment:\n2.1. Upon successful fulfillment of 1.1, the Buyer shall transfer the full amount of 1,4 ETH to the Seller.\n\nNo Partial Payment:\n3.1. There shall be no conditions under which partial payment can be demanded by the Seller, unless the Buyer chooses to do so voluntarily through the Escrow contract.\n\nKleros Escrow:\n4.1. Any disputes arising from this Agreement shall be automatically escalated to the Court of Kleros after both parties fund the dispute resolution deposit. Should one side fail to do so in full, the other party will automatically win the dispute." + }, + "invoice": false, + "category": "Escrow", + "question": "Which party abided by terms of the contract?", + "rulingOptions": { + "type": "single-select", + "titles": [ + "Refund Sender", + "Pay Receiver" + ], + "descriptions": [ + "Select to return funds to the Sender", + "Select to release funds to the Receiver" + ] + }, + "evidenceDisplayInterfaceURI": "/ipfs/QmfPnVdcCjApHdiCC8wAmyg5iR246JvVuQGQjQYgtF8gZU/index.html", + "aliases": { + "0x213fea050A0dA676E97B4dc40e37E985008EA1a0": "sender", + "0xc4c4e8144823000d97310756d3237B305E967a09": "receiver" + } +} diff --git a/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json b/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json index cf8efc141..24b022bc6 100644 --- a/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json +++ b/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json @@ -286,6 +286,32 @@ "/ipfs/QmeTBY7jZe2ut5WjifNASADo3E4zBxkMd62WwBpXtwP9pg" ] }, + "attachment": { + "type": "object", + "default": {}, + "title": "The attachment Schema", + "required": [ + "uri" + ], + "properties": { + "label": { + "type": "string", + "default": "", + "title": "The label Schema", + "examples": [ + "Terms" + ] + }, + "uri": { + "type": "string", + "default": "", + "title": "The uri Schema", + "examples": [ + "/ipfs//QmZ7R..7889/terms.json" + ] + } + } + }, "arbitrableChainID": { "type": "string", "default": "", @@ -319,6 +345,39 @@ "0xD08Ab99480d02bf9C092828043f611BcDFEA917b" ] }, + "metadata": { + "type": "object", + "default": {}, + "title": "The metadata Schema", + "required": [], + "properties": {}, + "examples": [ + {} + ] + }, + "aliases": { + "type": "object", + "default": {}, + "title": "The aliases Schema", + "properties": { + "Party1": { + "type": "string", + "default": "", + "title": "The Party1 Schema", + "examples": [ + "0x1234...CDEF" + ] + }, + "Party2": { + "type": "string", + "default": "", + "title": "The Party2 Schema", + "examples": [ + "0xFEDC...4321" + ] + } + } + }, "category": { "type": "string", "default": "", diff --git a/kleros-sdk/config/v2-disputetemplate/escrow/DataMappings.escrow.jsonc b/kleros-sdk/config/v2-disputetemplate/escrow/DataMappings.escrow.jsonc new file mode 100644 index 000000000..40e448678 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/escrow/DataMappings.escrow.jsonc @@ -0,0 +1,34 @@ +[ + { + "type": "abi/event", + "abi": "event TransactionCreated(uint256 indexed _transactionID, string _transactionUri, address indexed _buyer, address indexed _seller, uint256 _amount, string _asset, uint256 _deadline)", + "address": "[FIX AFTER DEPLOY]", + "eventFilter": { + "fromBlock": "[FIX AFTER DEPLOY]", + "toBlock": "latest", + "args": { + "_transactionID": "[FROM EXTERNAL DISPUTE ID]" + } + }, + "seek": [ + "transactionUri", + "buyer", + "seller", + "amount", + "asset", + "deadline" + ], + "populate": [ + "_transactionUri", + "_buyer", + "_seller", + "_amount", + "_asset", + "_deadline" + ] + }, + { + "type":"fetch/ipfsJson", + "todo": "get title, description, extraDescriptionUri from _transactionUri" + } +] \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/escrow/DisputeDetails.escrow.jsonc.mustache b/kleros-sdk/config/v2-disputetemplate/escrow/DisputeDetails.escrow.jsonc.mustache new file mode 100644 index 000000000..e62dd4b88 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/escrow/DisputeDetails.escrow.jsonc.mustache @@ -0,0 +1,41 @@ +{ + "$schema": "../NewDisputeTemplate.schema.json", + "title": "{{title}}", // from the form + "description": "{{description}}", // from the contract terms form + "question": "Which party abided by the terms of the contract?", + "answers": [ + { + "title": "Refund the Buyer", + "description": "Select this to return the funds to the Buyer." + }, + { + "title": "Pay the Seller", + "description": "Select this to release the funds to the Seller." + } + ], + "policyURI": "/ipfs/XxxxxXXX/escrow-general-policy.pdf", // not transaction-specific + "attachment": { // transaction-specific + "label": "Transaction Terms", + "uri": "{{extraDescriptionUri}}" + }, + "frontendUrl": "https://escrow-v2.kleros.builders/#/myTransactions/%s", // deployment specific, might break over time + "arbitrableChainID": "421614", + "arbitrableAddress": "0x??", // Escrow, hardcode after deploy-time + "arbitratorChainID": "421614", + "arbitratorAddress": "0x??", // KlerosCore, hardcode after deploy-time + "metadata": { + "buyer": "{{buyer}}", + "seller": "{{seller}}", + "amount": "{{amount}}", // in Wei or ERC20 units + "asset": "{{asset}}", // "0" or "native" or "0x1234..." or "erc20:0x1234...", cf. CAIP-19,20,21 + "deadline": "{{deadline}}", + "transactionUri": "{{transactionUri}}" // transaction-specific + }, + "category": "Escrow", + "specification": "KIPXXX", + "aliases": { + "Buyer": "{{buyer}}", + "Seller": "{{seller}}" + }, + "version": "1.0" +} diff --git a/kleros-sdk/config/v2-disputetemplate/escrow/DisputeRequest.ts b/kleros-sdk/config/v2-disputetemplate/escrow/DisputeRequest.ts new file mode 100644 index 000000000..62606c295 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/escrow/DisputeRequest.ts @@ -0,0 +1,7 @@ +type DisputeRequest = { + arbitrator: string; // klerosCore address + arbitrableDisputeID: number; // dispute id + externalDisputeID: number; // Escrow transaction id + templateId: number; // Escrow configuration + templateUri: string; // empty +}; From e9fe1b3e776653c7710231737c108a4fb912013b Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:38:58 +0100 Subject: [PATCH 23/37] feat(sdk): new fetch-ipfs-json data mappings action, common variable pool for concatenated mappings --- kleros-sdk/dataMappings/index.ts | 121 ++++++++++++++---- .../dataMappings/utils/actionTypeDetectors.ts | 12 +- kleros-sdk/dataMappings/utils/actionTypes.ts | 9 +- kleros-sdk/dataMappings/utils/maxByteSize.ts | 1 + web/src/pages/DisputeTemplateView.tsx | 20 +-- 5 files changed, 124 insertions(+), 39 deletions(-) create mode 100644 kleros-sdk/dataMappings/utils/maxByteSize.ts diff --git a/kleros-sdk/dataMappings/index.ts b/kleros-sdk/dataMappings/index.ts index 4e01b7282..b7e56d6bb 100644 --- a/kleros-sdk/dataMappings/index.ts +++ b/kleros-sdk/dataMappings/index.ts @@ -2,9 +2,23 @@ import { createPublicClient, parseAbiItem, webSocket } from "viem"; import { arbitrumGoerli } from "viem/chains"; import fetch from "node-fetch"; import dotenv from "dotenv"; -import { AbiCallMapping, AbiEventMapping, ActionMapping, JsonMapping, SubgraphMapping } from "./utils/actionTypes"; -import { isAbiCallMapping, isAbiEventMapping, isJsonMapping, isSubgraphMapping } from "./utils/actionTypeDetectors"; +import { + AbiCallMapping, + AbiEventMapping, + ActionMapping, + FetchIpfsJsonMapping, + JsonMapping, + SubgraphMapping, +} from "./utils/actionTypes"; +import { + isAbiCallMapping, + isAbiEventMapping, + isFetchIpfsJsonMapping, + isJsonMapping, + isSubgraphMapping, +} from "./utils/actionTypeDetectors"; import { findNestedKey } from "./utils/findNestedKey"; +import { MAX_BYTE_SIZE } from "./utils/maxByteSize"; dotenv.config(); @@ -23,16 +37,33 @@ export const configureSDK = (config: { apiKey?: string }) => { } }; -export const jsonAction = (mapping: JsonMapping) => { - const { value: source, seek, populate } = mapping; - - let jsonData = {}; +const createResultObject = (sourceData, seek, populate) => { + let result = {}; seek.forEach((key, idx) => { - const foundValue = findNestedKey(source, key); - jsonData[populate[idx]] = foundValue; + const foundValue = findNestedKey(sourceData, key); + console.log(`Seek key: ${key}, Found value:`, foundValue); + if (foundValue !== undefined) { + result[populate[idx]] = foundValue; + console.log(`Populate key: ${populate[idx]}, Value to add:`, foundValue); + } }); + console.log("Result object:", result); + return result; +}; - return jsonData; +const replacePlaceholdersWithValues = (mapping, context) => { + let newMapping = { ...mapping }; + for (const key of Object.keys(newMapping)) { + if (typeof newMapping[key] === "string" && context.hasOwnProperty(newMapping[key])) { + newMapping[key] = context[newMapping[key]]; + } + } + return newMapping; +}; + +export const jsonAction = (mapping: JsonMapping) => { + const { value: source, seek, populate } = mapping; + return createResultObject(source, seek, populate); }; export const subgraphAction = async (mapping: SubgraphMapping) => { @@ -49,13 +80,7 @@ export const subgraphAction = async (mapping: SubgraphMapping) => { const { data } = await response.json(); - let populatedData = {}; - seek.forEach((key, idx) => { - const foundValue = findNestedKey(data, key); - populatedData[populate[idx]] = foundValue; - }); - - return populatedData; + return createResultObject(data, seek, populate); }; export const callAction = async (mapping: AbiCallMapping) => { @@ -73,12 +98,7 @@ export const callAction = async (mapping: AbiCallMapping) => { args: args, }); - let populatedData = {}; - seek.map((item, index) => { - populatedData[populate[index]] = data[item]; - }); - - return populatedData; + return createResultObject(data, seek, populate); }; export const eventAction = async (mapping: AbiEventMapping) => { @@ -101,15 +121,40 @@ export const eventAction = async (mapping: AbiEventMapping) => { const contractEvent = await publicClient.getFilterLogs({ filter: filter as any }); const eventData = contractEvent[0].args; - let populatedData = {}; - seek.map((item, index) => { - populatedData[populate[index]] = eventData[item]; - }); + return createResultObject(eventData, seek, populate); +}; - return populatedData; +export const fetchIpfsJsonAction = async (mapping: FetchIpfsJsonMapping) => { + const { ipfsUri, seek, populate } = mapping; + + let httpUri; + if (ipfsUri.startsWith("/ipfs/")) { + httpUri = `https://ipfs.io${ipfsUri}`; + } else if (ipfsUri.startsWith("ipfs://")) { + httpUri = ipfsUri.replace("ipfs://", "https://ipfs.io/ipfs/"); + } else if (!ipfsUri.startsWith("http")) { + httpUri = `https://ipfs.io/ipfs/${ipfsUri}`; + } + const response = await fetch(httpUri, { method: "GET" }); + + if (response.headers.get("content-length") > MAX_BYTE_SIZE) { + throw new Error("Response size is too large"); + } + + const contentType = response.headers.get("content-type"); + + if (!contentType || !contentType.includes("application/json")) { + throw new Error("Fetched data is not JSON"); + } + + const data = await response.json(); + + return createResultObject(data, seek, populate); }; -export const executeAction = async (mapping: ActionMapping) => { +export const executeAction = async (mapping: ActionMapping, context = {}) => { + mapping = replacePlaceholdersWithValues(mapping, context); + switch (mapping.type) { case "graphql": if (!isSubgraphMapping(mapping)) { @@ -131,11 +176,31 @@ export const executeAction = async (mapping: ActionMapping) => { throw new Error("Invalid mapping for abi/event action."); } return await eventAction(mapping); + case "fetch/ipfs/json": + if (!isFetchIpfsJsonMapping(mapping)) { + throw new Error("Invalid mapping for fetch/ipfs/json action."); + } + return await fetchIpfsJsonAction(mapping); default: throw new Error(`Unsupported action type: ${mapping.type}`); } }; +export const executeActions = async (mappings) => { + let context = {}; + + for (const mapping of mappings) { + const actionResult = await executeAction(mapping, context); + if (actionResult) { + Object.keys(actionResult).forEach((key) => { + context[key] = actionResult[key]; + }); + } + } + + return context; +}; + export const retrieveRealityData = async (realityQuestionID: string) => { const questionMapping: AbiEventMapping = { type: "abi/event", diff --git a/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts b/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts index 8492c4a67..5531a04c1 100644 --- a/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts +++ b/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts @@ -1,4 +1,11 @@ -import { SubgraphMapping, AbiEventMapping, AbiCallMapping, JsonMapping, ActionMapping } from "./actionTypes"; +import { + SubgraphMapping, + AbiEventMapping, + AbiCallMapping, + JsonMapping, + ActionMapping, + FetchIpfsJsonMapping, +} from "./actionTypes"; export const isSubgraphMapping = (mapping: ActionMapping): mapping is SubgraphMapping => (mapping as SubgraphMapping).endpoint !== undefined; @@ -11,3 +18,6 @@ export const isAbiCallMapping = (mapping: ActionMapping): mapping is AbiCallMapp export const isJsonMapping = (mapping: ActionMapping): mapping is JsonMapping => (mapping as JsonMapping).value !== undefined; + +export const isFetchIpfsJsonMapping = (mapping: ActionMapping): mapping is FetchIpfsJsonMapping => + (mapping as FetchIpfsJsonMapping).ipfsUri !== undefined; diff --git a/kleros-sdk/dataMappings/utils/actionTypes.ts b/kleros-sdk/dataMappings/utils/actionTypes.ts index b28546c07..e6b238e5b 100644 --- a/kleros-sdk/dataMappings/utils/actionTypes.ts +++ b/kleros-sdk/dataMappings/utils/actionTypes.ts @@ -35,4 +35,11 @@ export type AbiEventMapping = { populate: string[]; }; -export type ActionMapping = SubgraphMapping | AbiEventMapping | AbiCallMapping | JsonMapping; +export type FetchIpfsJsonMapping = { + type: string; + ipfsUri: string; + seek: string[]; + populate: string[]; +}; + +export type ActionMapping = SubgraphMapping | AbiEventMapping | AbiCallMapping | JsonMapping | FetchIpfsJsonMapping; diff --git a/kleros-sdk/dataMappings/utils/maxByteSize.ts b/kleros-sdk/dataMappings/utils/maxByteSize.ts new file mode 100644 index 000000000..4304a20a5 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/maxByteSize.ts @@ -0,0 +1 @@ +export const MAX_BYTE_SIZE = 1000000; diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index ead80fc28..f6d406083 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -4,7 +4,7 @@ import { Textarea } from "@kleros/ui-components-library"; import PolicyIcon from "svgs/icons/policy.svg"; import ReactMarkdown from "components/ReactMarkdown"; import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; -import { executeAction, configureSDK, retrieveRealityData } from "@kleros/kleros-sdk/dataMappings"; +import { configureSDK, retrieveRealityData, executeActions } from "@kleros/kleros-sdk/dataMappings"; import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; import { Answer, DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; import { alchemyApiKey } from "context/Web3Provider"; @@ -91,36 +91,38 @@ const DisputeTemplateView: React.FC = () => { if (!disputeTemplateInput || !dataMappingsInput) return; const fetchData = async () => { - let parsedMapping; + let parsedMappings; try { - parsedMapping = JSON.parse(dataMappingsInput); + parsedMappings = JSON.parse(dataMappingsInput); } catch (e) { console.error(e); setDisputeDetails(undefined); return; } + try { let data = {}; - for (const action of parsedMapping) { + for (const action of parsedMappings) { if (action.type === "reality") { const realityData = await retrieveRealityData(action.realityQuestionID); data = { ...data, ...realityData }; } else { - console.log("Parsed Mapping:", parsedMapping); - - const result = await executeAction(action); - data = { ...data, ...result }; + const results = await executeActions(parsedMappings); + data = { ...data, ...results }; } } + console.log("disputeTemplateInput: ", disputeTemplateInput); console.log("data: ", data); const finalDisputeDetails = populateTemplate(disputeTemplateInput, data); - console.log("finalTemplate: ", finalDisputeDetails); setDisputeDetails(finalDisputeDetails); + console.log("finalTemplate: ", finalDisputeDetails); } catch (e) { console.error(e); + setDisputeDetails(undefined); } }; + fetchData(); }, [disputeTemplateInput, dataMappingsInput]); From 2cb3ec5963b76be7d22142f63e0f4e6c7c106a14 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Fri, 5 Jan 2024 02:53:32 +0100 Subject: [PATCH 24/37] feat(sdk): data mappings modularization, redo tests, remove findnestedkey, add variables to subgraph --- kleros-sdk/dataMappings/actions/callAction.ts | 20 ++ .../dataMappings/actions/eventAction.ts | 25 ++ .../actions/fetchIpfsJsonAction.ts | 32 ++ kleros-sdk/dataMappings/actions/jsonAction.ts | 7 + .../dataMappings/actions/subgraphAction.ts | 20 ++ kleros-sdk/dataMappings/executeActions.ts | 63 ++++ kleros-sdk/dataMappings/index.ts | 305 ------------------ .../dataMappings/retrieveRealityData.ts | 105 ++++++ kleros-sdk/dataMappings/test.ts | 248 ++++++++------ kleros-sdk/dataMappings/utils/actionTypes.ts | 1 + kleros-sdk/dataMappings/utils/configureSDK.ts | 26 ++ .../dataMappings/utils/createResultObject.ts | 19 ++ .../dataMappings/utils/findNestedKey.ts | 10 - .../utils/replacePlaceholdersWithValues.ts | 9 + web/src/pages/Cases/CaseDetails/Overview.tsx | 3 +- web/src/pages/DisputeTemplateView.tsx | 4 +- 16 files changed, 473 insertions(+), 424 deletions(-) create mode 100644 kleros-sdk/dataMappings/actions/callAction.ts create mode 100644 kleros-sdk/dataMappings/actions/eventAction.ts create mode 100644 kleros-sdk/dataMappings/actions/fetchIpfsJsonAction.ts create mode 100644 kleros-sdk/dataMappings/actions/jsonAction.ts create mode 100644 kleros-sdk/dataMappings/actions/subgraphAction.ts create mode 100644 kleros-sdk/dataMappings/executeActions.ts delete mode 100644 kleros-sdk/dataMappings/index.ts create mode 100644 kleros-sdk/dataMappings/retrieveRealityData.ts create mode 100644 kleros-sdk/dataMappings/utils/configureSDK.ts create mode 100644 kleros-sdk/dataMappings/utils/createResultObject.ts delete mode 100644 kleros-sdk/dataMappings/utils/findNestedKey.ts create mode 100644 kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts diff --git a/kleros-sdk/dataMappings/actions/callAction.ts b/kleros-sdk/dataMappings/actions/callAction.ts new file mode 100644 index 000000000..e8302be54 --- /dev/null +++ b/kleros-sdk/dataMappings/actions/callAction.ts @@ -0,0 +1,20 @@ +import { parseAbiItem } from "viem"; +import { AbiCallMapping } from "../utils/actionTypes"; +import { createResultObject } from "../utils/createResultObject"; +import { configureSDK, getPublicClient } from "../utils/configureSDK"; + +export const callAction = async (mapping: AbiCallMapping) => { + configureSDK({ apiKey: process.env.ALCHEMY_API_KEY }); + const publicClient = getPublicClient(); + + const { abi: source, address, args, seek, populate } = mapping; + let parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; + + const data = await publicClient.readContract({ + address: address, + abi: [parsedAbi], + args: args, + }); + + return createResultObject(data, seek, populate); +}; diff --git a/kleros-sdk/dataMappings/actions/eventAction.ts b/kleros-sdk/dataMappings/actions/eventAction.ts new file mode 100644 index 000000000..452dd3c7f --- /dev/null +++ b/kleros-sdk/dataMappings/actions/eventAction.ts @@ -0,0 +1,25 @@ +import { parseAbiItem } from "viem"; +import { AbiEventMapping } from "../utils/actionTypes"; +import { createResultObject } from "../utils/createResultObject"; +import { configureSDK, getPublicClient } from "../utils/configureSDK"; + +export const eventAction = async (mapping: AbiEventMapping) => { + configureSDK({ apiKey: process.env.ALCHEMY_API_KEY }); + const publicClient = getPublicClient(); + + const { abi: source, address, eventFilter, seek, populate } = mapping; + let parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; + + const filter = await publicClient.createEventFilter({ + address: address, + event: parsedAbi, + args: eventFilter.args, + fromBlock: eventFilter.fromBlock, + toBlock: eventFilter.toBlock, + }); + + const contractEvent = await publicClient.getFilterLogs({ filter: filter as any }); + const eventData = contractEvent[0].args; + + return createResultObject(eventData, seek, populate); +}; diff --git a/kleros-sdk/dataMappings/actions/fetchIpfsJsonAction.ts b/kleros-sdk/dataMappings/actions/fetchIpfsJsonAction.ts new file mode 100644 index 000000000..5d1933c28 --- /dev/null +++ b/kleros-sdk/dataMappings/actions/fetchIpfsJsonAction.ts @@ -0,0 +1,32 @@ +import fetch from "node-fetch"; +import { FetchIpfsJsonMapping } from "../utils/actionTypes"; +import { createResultObject } from "../utils/createResultObject"; +import { MAX_BYTE_SIZE } from "../utils/maxByteSize"; + +export const fetchIpfsJsonAction = async (mapping: FetchIpfsJsonMapping) => { + const { ipfsUri, seek, populate } = mapping; + + let httpUri; + if (ipfsUri.startsWith("/ipfs/")) { + httpUri = `https://ipfs.io${ipfsUri}`; + } else if (ipfsUri.startsWith("ipfs://")) { + httpUri = ipfsUri.replace("ipfs://", "https://ipfs.io/ipfs/"); + } else if (!ipfsUri.startsWith("http")) { + httpUri = `https://ipfs.io/ipfs/${ipfsUri}`; + } + const response = await fetch(httpUri, { method: "GET" }); + + if (response.headers.get("content-length") > MAX_BYTE_SIZE) { + throw new Error("Response size is too large"); + } + + const contentType = response.headers.get("content-type"); + + if (!contentType || !contentType.includes("application/json")) { + throw new Error("Fetched data is not JSON"); + } + + const data = await response.json(); + + return createResultObject(data, seek, populate); +}; diff --git a/kleros-sdk/dataMappings/actions/jsonAction.ts b/kleros-sdk/dataMappings/actions/jsonAction.ts new file mode 100644 index 000000000..3d4922f2e --- /dev/null +++ b/kleros-sdk/dataMappings/actions/jsonAction.ts @@ -0,0 +1,7 @@ +import { JsonMapping } from "../utils/actionTypes"; +import { createResultObject } from "../utils/createResultObject"; + +export const jsonAction = (mapping: JsonMapping) => { + const { value: source, seek, populate } = mapping; + return createResultObject(source, seek, populate); +}; diff --git a/kleros-sdk/dataMappings/actions/subgraphAction.ts b/kleros-sdk/dataMappings/actions/subgraphAction.ts new file mode 100644 index 000000000..f3fce37de --- /dev/null +++ b/kleros-sdk/dataMappings/actions/subgraphAction.ts @@ -0,0 +1,20 @@ +import fetch from "node-fetch"; +import { SubgraphMapping } from "../utils/actionTypes"; +import { createResultObject } from "../utils/createResultObject"; + +export const subgraphAction = async (mapping: SubgraphMapping) => { + const { endpoint, query, variables, seek, populate } = mapping; + + const response = await fetch(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ query, variables }), + }); + + const { data } = await response.json(); + + return createResultObject(data, seek, populate); +}; diff --git a/kleros-sdk/dataMappings/executeActions.ts b/kleros-sdk/dataMappings/executeActions.ts new file mode 100644 index 000000000..d283337d8 --- /dev/null +++ b/kleros-sdk/dataMappings/executeActions.ts @@ -0,0 +1,63 @@ +import { callAction } from "./actions/callAction"; +import { eventAction } from "./actions/eventAction"; +import { fetchIpfsJsonAction } from "./actions/fetchIpfsJsonAction"; +import { jsonAction } from "./actions/jsonAction"; +import { subgraphAction } from "./actions/subgraphAction"; +import { + isAbiCallMapping, + isAbiEventMapping, + isFetchIpfsJsonMapping, + isJsonMapping, + isSubgraphMapping, +} from "./utils/actionTypeDetectors"; +import { ActionMapping } from "./utils/actionTypes"; +import { replacePlaceholdersWithValues } from "./utils/replacePlaceholdersWithValues"; + +export const executeAction = async (mapping: ActionMapping, context = {}) => { + mapping = replacePlaceholdersWithValues(mapping, context); + + switch (mapping.type) { + case "graphql": + if (!isSubgraphMapping(mapping)) { + throw new Error("Invalid mapping for graphql action."); + } + return await subgraphAction(mapping); + case "json": + if (!isJsonMapping(mapping)) { + throw new Error("Invalid mapping for json action."); + } + return jsonAction(mapping); + case "abi/call": + if (!isAbiCallMapping(mapping)) { + throw new Error("Invalid mapping for abi/call action."); + } + return await callAction(mapping); + case "abi/event": + if (!isAbiEventMapping(mapping)) { + throw new Error("Invalid mapping for abi/event action."); + } + return await eventAction(mapping); + case "fetch/ipfs/json": + if (!isFetchIpfsJsonMapping(mapping)) { + throw new Error("Invalid mapping for fetch/ipfs/json action."); + } + return await fetchIpfsJsonAction(mapping); + default: + throw new Error(`Unsupported action type: ${mapping.type}`); + } +}; + +export const executeActions = async (mappings) => { + let context = {}; + + for (const mapping of mappings) { + const actionResult = await executeAction(mapping, context); + if (actionResult) { + Object.keys(actionResult).forEach((key) => { + context[key] = actionResult[key]; + }); + } + } + + return context; +}; diff --git a/kleros-sdk/dataMappings/index.ts b/kleros-sdk/dataMappings/index.ts deleted file mode 100644 index b7e56d6bb..000000000 --- a/kleros-sdk/dataMappings/index.ts +++ /dev/null @@ -1,305 +0,0 @@ -import { createPublicClient, parseAbiItem, webSocket } from "viem"; -import { arbitrumGoerli } from "viem/chains"; -import fetch from "node-fetch"; -import dotenv from "dotenv"; -import { - AbiCallMapping, - AbiEventMapping, - ActionMapping, - FetchIpfsJsonMapping, - JsonMapping, - SubgraphMapping, -} from "./utils/actionTypes"; -import { - isAbiCallMapping, - isAbiEventMapping, - isFetchIpfsJsonMapping, - isJsonMapping, - isSubgraphMapping, -} from "./utils/actionTypeDetectors"; -import { findNestedKey } from "./utils/findNestedKey"; -import { MAX_BYTE_SIZE } from "./utils/maxByteSize"; - -dotenv.config(); - -let ALCHEMY_API_KEY: string | undefined = process.env.ALCHEMY_API_KEY; -let transport; -let publicClient; - -export const configureSDK = (config: { apiKey?: string }) => { - if (config.apiKey) { - ALCHEMY_API_KEY = config.apiKey; - transport = webSocket(`wss://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}`); - publicClient = createPublicClient({ - chain: arbitrumGoerli, - transport, - }); - } -}; - -const createResultObject = (sourceData, seek, populate) => { - let result = {}; - seek.forEach((key, idx) => { - const foundValue = findNestedKey(sourceData, key); - console.log(`Seek key: ${key}, Found value:`, foundValue); - if (foundValue !== undefined) { - result[populate[idx]] = foundValue; - console.log(`Populate key: ${populate[idx]}, Value to add:`, foundValue); - } - }); - console.log("Result object:", result); - return result; -}; - -const replacePlaceholdersWithValues = (mapping, context) => { - let newMapping = { ...mapping }; - for (const key of Object.keys(newMapping)) { - if (typeof newMapping[key] === "string" && context.hasOwnProperty(newMapping[key])) { - newMapping[key] = context[newMapping[key]]; - } - } - return newMapping; -}; - -export const jsonAction = (mapping: JsonMapping) => { - const { value: source, seek, populate } = mapping; - return createResultObject(source, seek, populate); -}; - -export const subgraphAction = async (mapping: SubgraphMapping) => { - const { endpoint, query, seek, populate } = mapping; - - const response = await fetch(endpoint, { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify({ query }), - }); - - const { data } = await response.json(); - - return createResultObject(data, seek, populate); -}; - -export const callAction = async (mapping: AbiCallMapping) => { - const { abi: source, address, args, seek, populate } = mapping; - - if (!publicClient) { - throw new Error("SDK not configured. Please call `configureSDK` before using."); - } - - let parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; - - const data = await publicClient.readContract({ - address: address, - abi: [parsedAbi], - args: args, - }); - - return createResultObject(data, seek, populate); -}; - -export const eventAction = async (mapping: AbiEventMapping) => { - const { abi: source, address, eventFilter, seek, populate } = mapping; - - if (!publicClient) { - throw new Error("SDK not configured. Please call `configureSDK` before using."); - } - - let parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; - - const filter = await publicClient.createEventFilter({ - address: address, - event: parsedAbi, - args: eventFilter.args, - fromBlock: eventFilter.fromBlock, - toBlock: eventFilter.toBlock, - }); - - const contractEvent = await publicClient.getFilterLogs({ filter: filter as any }); - const eventData = contractEvent[0].args; - - return createResultObject(eventData, seek, populate); -}; - -export const fetchIpfsJsonAction = async (mapping: FetchIpfsJsonMapping) => { - const { ipfsUri, seek, populate } = mapping; - - let httpUri; - if (ipfsUri.startsWith("/ipfs/")) { - httpUri = `https://ipfs.io${ipfsUri}`; - } else if (ipfsUri.startsWith("ipfs://")) { - httpUri = ipfsUri.replace("ipfs://", "https://ipfs.io/ipfs/"); - } else if (!ipfsUri.startsWith("http")) { - httpUri = `https://ipfs.io/ipfs/${ipfsUri}`; - } - const response = await fetch(httpUri, { method: "GET" }); - - if (response.headers.get("content-length") > MAX_BYTE_SIZE) { - throw new Error("Response size is too large"); - } - - const contentType = response.headers.get("content-type"); - - if (!contentType || !contentType.includes("application/json")) { - throw new Error("Fetched data is not JSON"); - } - - const data = await response.json(); - - return createResultObject(data, seek, populate); -}; - -export const executeAction = async (mapping: ActionMapping, context = {}) => { - mapping = replacePlaceholdersWithValues(mapping, context); - - switch (mapping.type) { - case "graphql": - if (!isSubgraphMapping(mapping)) { - throw new Error("Invalid mapping for graphql action."); - } - return await subgraphAction(mapping); - case "json": - if (!isJsonMapping(mapping)) { - throw new Error("Invalid mapping for json action."); - } - return jsonAction(mapping); - case "abi/call": - if (!isAbiCallMapping(mapping)) { - throw new Error("Invalid mapping for abi/call action."); - } - return await callAction(mapping); - case "abi/event": - if (!isAbiEventMapping(mapping)) { - throw new Error("Invalid mapping for abi/event action."); - } - return await eventAction(mapping); - case "fetch/ipfs/json": - if (!isFetchIpfsJsonMapping(mapping)) { - throw new Error("Invalid mapping for fetch/ipfs/json action."); - } - return await fetchIpfsJsonAction(mapping); - default: - throw new Error(`Unsupported action type: ${mapping.type}`); - } -}; - -export const executeActions = async (mappings) => { - let context = {}; - - for (const mapping of mappings) { - const actionResult = await executeAction(mapping, context); - if (actionResult) { - Object.keys(actionResult).forEach((key) => { - context[key] = actionResult[key]; - }); - } - } - - return context; -}; - -export const retrieveRealityData = async (realityQuestionID: string) => { - const questionMapping: AbiEventMapping = { - type: "abi/event", - abi: "event LogNewQuestion(bytes32 indexed question_id, address indexed user, uint256 template_id, string question, bytes32 indexed content_hash, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce, uint256 created)", - address: "0x14a6748192abc6e10ca694ae07bdd4327d6c7a51", - eventFilter: { - args: [realityQuestionID], - fromBlock: "0x1", - toBlock: "latest", - }, - - seek: [ - "question_id", - "user", - "template_id", - "question", - "content_hash", - "arbitrator", - "timeout", - "opening_ts", - "nonce", - "created", - ], - populate: [ - "realityQuestionID", - "realityUser", - "realityTemplateID", - "realityQuestion", - "contentHash", - "arbitrator", - "timeout", - "openingTs", - "nonce", - "created", - ], - }; - - const questionData = await executeAction(questionMapping); - console.log("questionData", questionData); - - const templateMapping: AbiEventMapping = { - type: "abi/event", - abi: "event LogNewTemplate(uint256 indexed template_id, address indexed user, string question_text)", - address: "0x14a6748192abc6e10ca694ae07bdd4327d6c7a51", - eventFilter: { - args: [0], - fromBlock: "0x1", - toBlock: "latest", - }, - seek: ["template_id", "question_text"], - populate: ["templateID", "questionText"], - }; - - const templateData = await executeAction(templateMapping); - console.log("templateData", templateData); - - const rc_question = require("@reality.eth/reality-eth-lib/formatters/question.js"); - const populatedTemplate = rc_question.populatedJSONForTemplate( - templateData.questionText, - questionData.realityQuestion - ); - - console.log("populatedTemplate", populatedTemplate); - - let answers = []; - if (populatedTemplate.type === "bool") { - answers = [ - { - title: "Yes", - description: "", - id: "0x01", - reserved: false, - }, - { - title: "No", - description: "", - id: "0x02", - reserved: false, - }, - ]; - } - - answers.push({ - id: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - title: "Answered Too Soon", - description: "", - reserved: true, - }); - - for (let i = 0; i < answers.length; i++) { - answers[i].last = i === answers.length - 1; - } - - return { - question: questionData.realityQuestion, - type: populatedTemplate.type, - realityAddress: questionData.arbitrator, - questionId: questionData.realityQuestionID, - realityUser: questionData.realityUser, - answers: answers, - }; -}; diff --git a/kleros-sdk/dataMappings/retrieveRealityData.ts b/kleros-sdk/dataMappings/retrieveRealityData.ts new file mode 100644 index 000000000..2b33e6f65 --- /dev/null +++ b/kleros-sdk/dataMappings/retrieveRealityData.ts @@ -0,0 +1,105 @@ +import { executeAction } from "./executeActions"; +import { AbiEventMapping } from "./utils/actionTypes"; + +export const retrieveRealityData = async (realityQuestionID: string) => { + const questionMapping: AbiEventMapping = { + type: "abi/event", + abi: "event LogNewQuestion(bytes32 indexed question_id, address indexed user, uint256 template_id, string question, bytes32 indexed content_hash, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce, uint256 created)", + address: "INSERT REALITY'S CONTRACT ADDRESS IN ARBITRUM SEPOLIA HERE", + eventFilter: { + args: [realityQuestionID], + fromBlock: "0x1", + toBlock: "latest", + }, + + seek: [ + "question_id", + "user", + "template_id", + "question", + "content_hash", + "arbitrator", + "timeout", + "opening_ts", + "nonce", + "created", + ], + populate: [ + "realityQuestionID", + "realityUser", + "realityTemplateID", + "realityQuestion", + "contentHash", + "arbitrator", + "timeout", + "openingTs", + "nonce", + "created", + ], + }; + + const questionData = await executeAction(questionMapping); + console.log("questionData", questionData); + + const templateMapping: AbiEventMapping = { + type: "abi/event", + abi: "event LogNewTemplate(uint256 indexed template_id, address indexed user, string question_text)", + address: "INSERT REALITY'S CONTRACT ADDRESS IN ARBITRUM SEPOLIA HERE", + eventFilter: { + args: [0], + fromBlock: "0x1", + toBlock: "latest", + }, + seek: ["template_id", "question_text"], + populate: ["templateID", "questionText"], + }; + + const templateData = await executeAction(templateMapping); + console.log("templateData", templateData); + + const rc_question = require("@reality.eth/reality-eth-lib/formatters/question.js"); + const populatedTemplate = rc_question.populatedJSONForTemplate( + templateData.questionText, + questionData.realityQuestion + ); + + console.log("populatedTemplate", populatedTemplate); + + let answers = []; + if (populatedTemplate.type === "bool") { + answers = [ + { + title: "Yes", + description: "", + id: "0x01", + reserved: false, + }, + { + title: "No", + description: "", + id: "0x02", + reserved: false, + }, + ]; + } + + answers.push({ + id: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + title: "Answered Too Soon", + description: "", + reserved: true, + }); + + for (let i = 0; i < answers.length; i++) { + answers[i].last = i === answers.length - 1; + } + + return { + question: questionData.realityQuestion, + type: populatedTemplate.type, + realityAddress: questionData.arbitrator, + questionId: questionData.realityQuestionID, + realityUser: questionData.realityUser, + answers: answers, + }; +}; diff --git a/kleros-sdk/dataMappings/test.ts b/kleros-sdk/dataMappings/test.ts index 588ff57eb..65a67fb64 100644 --- a/kleros-sdk/dataMappings/test.ts +++ b/kleros-sdk/dataMappings/test.ts @@ -1,5 +1,10 @@ import { expect } from "chai"; -import { jsonAction, graphqlAction, eventAction, callAction, findNestedKey, populateTemplate, configureSDK } from "."; +import { populateTemplate } from "./utils/populateTemplate"; +import { jsonAction } from "./actions/jsonAction"; +import { subgraphAction } from "./actions/subgraphAction"; +import { callAction } from "./actions/callAction"; +import { eventAction } from "./actions/eventAction"; +import { fetchIpfsJsonAction } from "./actions/fetchIpfsJsonAction"; const exampleObject = { evidence: { @@ -10,13 +15,14 @@ const exampleObject = { }, }; -before(() => { - configureSDK({ apiKey: process.env.ALCHEMY_API_KEY }); -}); - describe("jsonAction", () => { it("should extract and map data correctly", () => { - const result = jsonAction(exampleObject, ["photo", "video"], ["photoUrl", "videoUrl"]); + const mapping = { + value: exampleObject.evidence.fileURI, + seek: ["photo", "video"], + populate: ["photoUrl", "videoUrl"], + }; + const result = jsonAction(mapping); expect(result).to.eql({ photoUrl: "https://photo.url", videoUrl: "https://video.url", @@ -24,145 +30,173 @@ describe("jsonAction", () => { }); }); -describe("graphqlAction", () => { - it("should fetch GraphQL data and return in expected format", async () => { - const mockEndpoint = "https://api.thegraph.com/subgraphs/name/kleros/kleros-v2-core-arbitrum-goerli"; - const seek = ["courts"]; - const populate = ["courts"]; - - const mockQuery = ` - { - courts(first: 1) { +describe("subgraphAction with variables", () => { + it("should fetch GraphQL data with variables and return in expected format", async () => { + const endpoint = "https://api.thegraph.com/subgraphs/name/kemuru/escrow-v2-devnet"; + const query = ` + query GetEscrows($buyer: Bytes!) { + escrows(where: {buyer: $buyer}) { id - stakedJurors(first:1){ - court { - id - } - } + amount + status } } `; - - const mockData = { - courts: [ - { - id: "1", - stakedJurors: [ - { - court: { - id: "1", - }, - }, - ], - }, - ], + const variables = { + buyer: "0x74199ddaC9607A3a694011793f674FA1E0d0Fe2D", + }; + const seek = ["escrows"]; + const populate = ["escrowsData"]; + + const mapping = { + endpoint: endpoint, + query: query, + variables: variables, + seek: seek, + populate: populate, }; - const result = await graphqlAction(mockEndpoint, mockQuery, seek, populate); - expect(result).to.eql(mockData); + const result = await subgraphAction(mapping); + + expect(result).to.have.property("escrowsData"); + expect(result.escrowsData).to.be.an("array"); + result.escrowsData.forEach((escrow) => { + expect(escrow).to.have.property("id"); + expect(escrow).to.have.property("amount"); + expect(escrow).to.have.property("status"); + }); }); }); describe("callAction", () => { - it("should call the contract and return populated data", async () => { - const mockAbi = "function appealCost(uint256 _disputeID) public view returns (uint256)"; - const mockInputs = ["0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", "appealCost", BigInt(1)]; - const mockSeek = ["_disputeID"]; - const mockPopulate = ["cost"]; + it("should call the contract and return token balance", async () => { + const abi = "function balanceOf(address account) public view returns (uint256)"; + const contractAddress = "0xa8e4235129258404A2ed3D36DAd20708CcB2d0b7"; + const knownAddress = "0x0000000000000000000000000000000000000000"; + + const mapping = { + abi: abi, + address: contractAddress, + args: [knownAddress], + seek: [""], + populate: ["tokenBalance"], + }; - const result = await callAction(mockAbi, mockInputs, mockSeek, mockPopulate); + const result = await callAction(mapping); - expect(result).to.eql({ - cost: BigInt(30000000000000), - }); + expect(result).to.have.property("tokenBalance"); + expect(result.tokenBalance).to.be.a("bigint"); }); }); describe("eventAction", () => { it("should fetch event data and return populated data", async () => { - const mockSource = "event StakeSet(address indexed _address, uint256 _courtID, uint256 _amount)"; - const mockInputs = [ - "0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", - BigInt(36205881), - "0xE652E5B6409B062FcE5f40E19682f31152d6CD1a", - ]; - const mockSeek = ["_address", "_courtID"]; - const mockPopulate = ["address", "courtID"]; - - const result = await eventAction(mockSource, mockInputs, mockSeek, mockPopulate); - expect(result).to.eql({ - address: "0xE652E5B6409B062FcE5f40E19682f31152d6CD1a", - courtID: BigInt(1), - }); - }); -}); - -describe("findNestedKey", () => { - const testData = { - level1: "value1", - nested: { - level2: "value2", - deeper: { - level3: "value3", + const eventAbi = "event Transfer(address indexed from, address indexed to, uint256 value)"; + const contractAddress = "0xa8e4235129258404A2ed3D36DAd20708CcB2d0b7"; + const fromBlock = "earliest"; + const toBlock = "latest"; + + const mapping = { + abi: eventAbi, + address: contractAddress, + eventFilter: { + fromBlock: fromBlock, + toBlock: toBlock, }, - }, - }; - - it("should find top-level keys", () => { - const result = findNestedKey(testData, "level1"); - expect(result).to.eql("value1"); - }); - - it("should find second-level nested keys", () => { - const result = findNestedKey(testData, "level2"); - expect(result).to.eql("value2"); - }); + seek: ["from", "to", "value"], + populate: ["fromAddress", "toAddress", "transferValue"], + }; - it("should find deeply nested keys", () => { - const result = findNestedKey(testData, "level3"); - expect(result).to.eql("value3"); - }); + const result = await eventAction(mapping); - it("should return null if key not found", () => { - const result = findNestedKey(testData, "nonexistent"); - expect(result).to.be.null; + expect(result).to.have.property("fromAddress"); + expect(result).to.have.property("toAddress"); + expect(result).to.have.property("transferValue"); + expect(result.transferValue).to.be.a("bigint"); }); }); -describe("populateTemplate", () => { - it("should correctly populate the template with provided data", () => { - const template = '{"name": "{{name}}", "age": {{age}}, "isStudent": {{isStudent}}}'; - const data = { - name: "John", - age: 25, - isStudent: false, +describe("fetchIpfsJsonAction", () => { + it("should fetch JSON data from IPFS and return the expected result", async () => { + const ipfsUri = "/ipfs/QmQ2XoA25HmnPUEWDduxj6LYwMwp6jtXPFRMHcNF2EvJfU/file.json"; + const seek = ["name", "firstName", "lastName", "anotherFile"]; + const populate = ["name", "firstName", "lastName", "anotherFile"]; + + const mapping = { + ipfsUri: ipfsUri, + seek: seek, + populate: populate, }; - const result = populateTemplate(template, data); + const result = await fetchIpfsJsonAction(mapping); - expect(result).to.deep.equal({ - name: "John", - age: 25, - isStudent: false, - }); + expect(result).to.have.property("name", "Mezozoic"); + expect(result).to.have.property("firstName", "Rafael"); + expect(result).to.have.property("lastName", "Camargo"); + expect(result).to.have.property("anotherFile", "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json"); }); +}); - it("should handle missing data by leaving placeholders untouched", () => { - const template = '{"name": "{{name}}", "age": {{age}}}'; +describe("populateTemplate", () => { + it("should correctly populate the template with provided data", () => { + const template = `{ + "title": "Test Title", + "description": "Test Description", + "question": "{{question}}", + "type": "single-select", + "answers": [ + { + "title": "Yes", + "description": "Affirmative", + "id": "0x01", + "reserved": false + } + ], + "policyURI": "https://example.com/policy", + "frontendUrl": "https://example.com", + "arbitrableChainID": "100", + "arbitrableAddress": "0x1234567890123456789012345678901234567890", + "arbitratorChainID": "421613", + "arbitratorAddress": "0x0987654321098765432109876543210987654321", + "category": "General", + "lang": "en_US", + "specification": "Spec", + "version": "1.0" + }`; const data = { - age: 30, + question: "Did the user break the rules?", }; const result = populateTemplate(template, data); expect(result).to.deep.equal({ - name: "", - age: 30, + title: "Test Title", + description: "Test Description", + question: "Did the user break the rules?", + type: "single-select", + answers: [ + { + title: "Yes", + description: "Affirmative", + id: "0x01", + reserved: false, + }, + ], + policyURI: "https://example.com/policy", + frontendUrl: "https://example.com", + arbitrableChainID: "100", + arbitrableAddress: "0x1234567890123456789012345678901234567890", + arbitratorChainID: "421613", + arbitratorAddress: "0x0987654321098765432109876543210987654321", + category: "General", + lang: "en_US", + specification: "Spec", + version: "1.0", }); }); it("should throw an error for invalid JSON", () => { - const template = '{"name": "{{name}"}'; + const template = `{"title": "{{name}"}`; const data = { name: "Jane", }; diff --git a/kleros-sdk/dataMappings/utils/actionTypes.ts b/kleros-sdk/dataMappings/utils/actionTypes.ts index e6b238e5b..746a91f34 100644 --- a/kleros-sdk/dataMappings/utils/actionTypes.ts +++ b/kleros-sdk/dataMappings/utils/actionTypes.ts @@ -9,6 +9,7 @@ export type SubgraphMapping = { type: string; endpoint: string; query: string; + variables?: string[]; seek: string[]; populate: string[]; }; diff --git a/kleros-sdk/dataMappings/utils/configureSDK.ts b/kleros-sdk/dataMappings/utils/configureSDK.ts new file mode 100644 index 000000000..eb184ae8b --- /dev/null +++ b/kleros-sdk/dataMappings/utils/configureSDK.ts @@ -0,0 +1,26 @@ +import { createPublicClient, webSocket } from "viem"; +import { arbitrumSepolia } from "viem/chains"; +import dotenv from "dotenv"; + +dotenv.config(); +let ALCHEMY_API_KEY: string | undefined = process.env.ALCHEMY_API_KEY; +let transport; +let publicClient; + +export const configureSDK = (config: { apiKey?: string }) => { + if (config.apiKey) { + ALCHEMY_API_KEY = config.apiKey; + transport = webSocket(`wss://arb-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}`); + publicClient = createPublicClient({ + chain: arbitrumSepolia, + transport, + }); + } +}; + +export const getPublicClient = () => { + if (!publicClient) { + throw new Error("SDK not configured. Please call `configureSDK` before using."); + } + return publicClient; +}; diff --git a/kleros-sdk/dataMappings/utils/createResultObject.ts b/kleros-sdk/dataMappings/utils/createResultObject.ts new file mode 100644 index 000000000..9c265a4a8 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/createResultObject.ts @@ -0,0 +1,19 @@ +export const createResultObject = (sourceData, seek, populate) => { + let result = {}; + seek.forEach((key, idx) => { + let foundValue; + if (typeof sourceData !== "object" || key === "0") { + foundValue = sourceData; + } else { + foundValue = sourceData[key]; + } + + console.log(`Seek key: ${key}, Found value:`, foundValue); + if (foundValue !== undefined) { + result[populate[idx]] = foundValue; + console.log(`Populate key: ${populate[idx]}, Value to add:`, foundValue); + } + }); + console.log("Result object:", result); + return result; +}; diff --git a/kleros-sdk/dataMappings/utils/findNestedKey.ts b/kleros-sdk/dataMappings/utils/findNestedKey.ts deleted file mode 100644 index 12668a257..000000000 --- a/kleros-sdk/dataMappings/utils/findNestedKey.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const findNestedKey = (data, keyToFind) => { - if (data.hasOwnProperty(keyToFind)) return data[keyToFind]; - for (let key in data) { - if (typeof data[key] === "object" && data[key] !== null) { - const found = findNestedKey(data[key], keyToFind); - if (found) return found; - } - } - return null; -}; diff --git a/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts b/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts new file mode 100644 index 000000000..25c31a255 --- /dev/null +++ b/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts @@ -0,0 +1,9 @@ +export const replacePlaceholdersWithValues = (mapping, context) => { + let newMapping = { ...mapping }; + for (const key of Object.keys(newMapping)) { + if (typeof newMapping[key] === "string" && context.hasOwnProperty(newMapping[key])) { + newMapping[key] = context[newMapping[key]]; + } + } + return newMapping; +}; diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index 48cf2dbb8..a17c22ad6 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -9,7 +9,8 @@ import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { useCourtPolicy } from "queries/useCourtPolicy"; import { isUndefined } from "utils/index"; import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; -import { executeAction, configureSDK } from "@kleros/kleros-sdk/dataMappings"; +import { executeAction } from "@kleros/kleros-sdk/dataMappings/executeActions"; +import { configureSDK } from "@kleros/kleros-sdk/dataMappings/utils/configureSDK"; import { alchemyApiKey } from "context/Web3Provider"; import { Answer, DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; import { Periods } from "consts/periods"; diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index f6d406083..66280cea7 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -4,7 +4,9 @@ import { Textarea } from "@kleros/ui-components-library"; import PolicyIcon from "svgs/icons/policy.svg"; import ReactMarkdown from "components/ReactMarkdown"; import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; -import { configureSDK, retrieveRealityData, executeActions } from "@kleros/kleros-sdk/dataMappings"; +import { configureSDK } from "@kleros/kleros-sdk/dataMappings/utils/configureSDK"; +import { retrieveRealityData } from "@kleros/kleros-sdk/dataMappings/retrieveRealityData"; +import { executeActions } from "@kleros/kleros-sdk/dataMappings/executeActions"; import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; import { Answer, DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; import { alchemyApiKey } from "context/Web3Provider"; From 8d72cc7a21e39bc3d32896485f1c6671715e700b Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 5 Jan 2024 16:34:10 +0100 Subject: [PATCH 25/37] chore: providing the arbitrable address to the SDK executeAction() --- kleros-sdk/dataMappings/executeActions.ts | 6 +++--- kleros-sdk/dataMappings/retrieveRealityData.ts | 10 ++++++---- web/src/pages/Cases/CaseDetails/Overview.tsx | 4 ++-- web/src/pages/DisputeTemplateView.tsx | 9 +++++++-- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/kleros-sdk/dataMappings/executeActions.ts b/kleros-sdk/dataMappings/executeActions.ts index d283337d8..d6c5d9969 100644 --- a/kleros-sdk/dataMappings/executeActions.ts +++ b/kleros-sdk/dataMappings/executeActions.ts @@ -13,7 +13,7 @@ import { import { ActionMapping } from "./utils/actionTypes"; import { replacePlaceholdersWithValues } from "./utils/replacePlaceholdersWithValues"; -export const executeAction = async (mapping: ActionMapping, context = {}) => { +export const executeAction = async (mapping: ActionMapping, arbitrable?: `0x${string}`, context = {}) => { mapping = replacePlaceholdersWithValues(mapping, context); switch (mapping.type) { @@ -47,11 +47,11 @@ export const executeAction = async (mapping: ActionMapping, context = {}) => { } }; -export const executeActions = async (mappings) => { +export const executeActions = async (mappings, arbitrable?: `0x${string}`) => { let context = {}; for (const mapping of mappings) { - const actionResult = await executeAction(mapping, context); + const actionResult = await executeAction(mapping, arbitrable, context); if (actionResult) { Object.keys(actionResult).forEach((key) => { context[key] = actionResult[key]; diff --git a/kleros-sdk/dataMappings/retrieveRealityData.ts b/kleros-sdk/dataMappings/retrieveRealityData.ts index 2b33e6f65..58314e190 100644 --- a/kleros-sdk/dataMappings/retrieveRealityData.ts +++ b/kleros-sdk/dataMappings/retrieveRealityData.ts @@ -1,17 +1,19 @@ import { executeAction } from "./executeActions"; import { AbiEventMapping } from "./utils/actionTypes"; -export const retrieveRealityData = async (realityQuestionID: string) => { +export const retrieveRealityData = async (realityQuestionID: string, arbitrable?: `0x${string}`) => { + if (!arbitrable) { + throw new Error("No arbitrable address provided"); + } const questionMapping: AbiEventMapping = { type: "abi/event", abi: "event LogNewQuestion(bytes32 indexed question_id, address indexed user, uint256 template_id, string question, bytes32 indexed content_hash, address arbitrator, uint32 timeout, uint32 opening_ts, uint256 nonce, uint256 created)", - address: "INSERT REALITY'S CONTRACT ADDRESS IN ARBITRUM SEPOLIA HERE", + address: arbitrable, eventFilter: { args: [realityQuestionID], fromBlock: "0x1", toBlock: "latest", }, - seek: [ "question_id", "user", @@ -44,7 +46,7 @@ export const retrieveRealityData = async (realityQuestionID: string) => { const templateMapping: AbiEventMapping = { type: "abi/event", abi: "event LogNewTemplate(uint256 indexed template_id, address indexed user, string question_text)", - address: "INSERT REALITY'S CONTRACT ADDRESS IN ARBITRUM SEPOLIA HERE", + address: arbitrable, eventFilter: { args: [0], fromBlock: "0x1", diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index a17c22ad6..bdbc5097e 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -151,7 +151,7 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex try { let data = {}; for (const action of parsedMapping) { - const result = await executeAction(action); + const result = await executeAction(action, arbitrable); data = { ...data, ...result }; } setDisputeDetails(populateTemplate(disputeTemplateInput, data)); @@ -160,7 +160,7 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex } }; fetchData(); - }, [disputeTemplateInput, dataMappingsInput]); + }, [disputeTemplateInput, dataMappingsInput, arbitrable]); return ( <> diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index 66280cea7..27b03ba49 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -87,6 +87,11 @@ const DisputeTemplateView: React.FC = () => { const [disputeTemplateInput, setDisputeTemplateInput] = useState(""); const [dataMappingsInput, setDataMappingsInput] = useState(""); + // TODO: add some input fields for the IArbitrableV2.DisputeRequest event which is available to the SDK in a real case + // - arbitrable (= the address which emitted DisputeRequest) + // - the DisputeRequest event params: arbitrator, arbitrableDisputeID, externalDisputeID, templateId, templateUri + const arbitrable = "0xdaf749DABE7be6C6894950AE69af35c20a00ABd9"; + useEffect(() => { configureSDK({ apiKey: alchemyApiKey }); @@ -106,10 +111,10 @@ const DisputeTemplateView: React.FC = () => { let data = {}; for (const action of parsedMappings) { if (action.type === "reality") { - const realityData = await retrieveRealityData(action.realityQuestionID); + const realityData = await retrieveRealityData(action.realityQuestionID, arbitrable); data = { ...data, ...realityData }; } else { - const results = await executeActions(parsedMappings); + const results = await executeActions(parsedMappings, arbitrable); data = { ...data, ...results }; } } From d7812323ef98398ac076ed8abb157370a1cef39f Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Fri, 5 Jan 2024 18:03:58 +0100 Subject: [PATCH 26/37] feat(sdk): modify replaceplaceholder with results.-value-to-populate- --- .../utils/replacePlaceholdersWithValues.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts b/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts index 25c31a255..b880a67f0 100644 --- a/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts +++ b/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts @@ -1,9 +1,13 @@ -export const replacePlaceholdersWithValues = (mapping, context) => { - let newMapping = { ...mapping }; - for (const key of Object.keys(newMapping)) { - if (typeof newMapping[key] === "string" && context.hasOwnProperty(newMapping[key])) { - newMapping[key] = context[newMapping[key]]; +export const replacePlaceholdersWithValues = (mapping: any, results: any) => { + let mappingAsString = JSON.stringify(mapping); + + const replacedMapping = mappingAsString.replace(/results\.([A-Za-z0-9_]+)/g, (_, variableName) => { + if (results.hasOwnProperty(variableName)) { + return results[variableName]; + } else { + throw new Error(`Variable '${variableName}' not found in results.`); } - } - return newMapping; + }); + + return JSON.parse(replacedMapping); }; From f7dc8f929ffbf63e1856a3a714828ecac64ca05b Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Wed, 10 Jan 2024 13:39:06 +0100 Subject: [PATCH 27/37] feat(web, sdk): parameter to include extra context in executeactions, modularize retrieverealitydata --- kleros-sdk/dataMappings/executeActions.ts | 7 ++++-- web/src/hooks/queries/useDrawQuery.ts | 2 +- web/src/pages/Cases/CaseDetails/Overview.tsx | 26 ++++++++------------ web/src/pages/DisputeTemplateView.tsx | 26 +++----------------- 4 files changed, 19 insertions(+), 42 deletions(-) diff --git a/kleros-sdk/dataMappings/executeActions.ts b/kleros-sdk/dataMappings/executeActions.ts index d6c5d9969..e709b0040 100644 --- a/kleros-sdk/dataMappings/executeActions.ts +++ b/kleros-sdk/dataMappings/executeActions.ts @@ -3,6 +3,7 @@ import { eventAction } from "./actions/eventAction"; import { fetchIpfsJsonAction } from "./actions/fetchIpfsJsonAction"; import { jsonAction } from "./actions/jsonAction"; import { subgraphAction } from "./actions/subgraphAction"; +import { retrieveRealityData } from "./retrieveRealityData"; import { isAbiCallMapping, isAbiEventMapping, @@ -17,6 +18,8 @@ export const executeAction = async (mapping: ActionMapping, arbitrable?: `0x${st mapping = replacePlaceholdersWithValues(mapping, context); switch (mapping.type) { + case "reality": + return await retrieveRealityData(mapping.realityQuestionID, arbitrable); case "graphql": if (!isSubgraphMapping(mapping)) { throw new Error("Invalid mapping for graphql action."); @@ -47,8 +50,8 @@ export const executeAction = async (mapping: ActionMapping, arbitrable?: `0x${st } }; -export const executeActions = async (mappings, arbitrable?: `0x${string}`) => { - let context = {}; +export const executeActions = async (mappings, arbitrable?: `0x${string}`, initialState = {}) => { + let context = { ...initialState }; for (const mapping of mappings) { const actionResult = await executeAction(mapping, arbitrable, context); diff --git a/web/src/hooks/queries/useDrawQuery.ts b/web/src/hooks/queries/useDrawQuery.ts index b152b5070..75e327ac8 100644 --- a/web/src/hooks/queries/useDrawQuery.ts +++ b/web/src/hooks/queries/useDrawQuery.ts @@ -7,7 +7,7 @@ export type { DrawQuery }; const drawQuery = graphql(` query Draw($address: String, $disputeID: String, $roundID: String) { draws(where: { dispute: $disputeID, juror: $address, round: $roundID }) { - voteID + voteIDNum } } `); diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index bdbc5097e..f218f9d12 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -9,7 +9,7 @@ import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { useCourtPolicy } from "queries/useCourtPolicy"; import { isUndefined } from "utils/index"; import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; -import { executeAction } from "@kleros/kleros-sdk/dataMappings/executeActions"; +import { executeActions } from "@kleros/kleros-sdk/dataMappings/executeActions"; import { configureSDK } from "@kleros/kleros-sdk/dataMappings/utils/configureSDK"; import { alchemyApiKey } from "context/Web3Provider"; import { Answer, DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; @@ -135,32 +135,26 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex useEffect(() => { configureSDK({ apiKey: alchemyApiKey }); + const initialState = { + disputeID: id, + }; if (!disputeTemplateInput || !dataMappingsInput) return; const fetchData = async () => { - let parsedMapping; try { - parsedMapping = JSON.parse(dataMappingsInput); + const parsedMappings = JSON.parse(dataMappingsInput); + const data = await executeActions(parsedMappings, arbitrable, initialState); + const finalDisputeDetails = populateTemplate(disputeTemplateInput, data); + setDisputeDetails(finalDisputeDetails); } catch (e) { console.error(e); setDisputeDetails(undefined); - // return; - parsedMapping = JSON.parse("[]"); - } - try { - let data = {}; - for (const action of parsedMapping) { - const result = await executeAction(action, arbitrable); - data = { ...data, ...result }; - } - setDisputeDetails(populateTemplate(disputeTemplateInput, data)); - } catch (e) { - console.error(e); } }; + fetchData(); - }, [disputeTemplateInput, dataMappingsInput, arbitrable]); + }, [disputeTemplateInput, dataMappingsInput, arbitrable, id]); return ( <> diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index 27b03ba49..d0193b061 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -98,29 +98,9 @@ const DisputeTemplateView: React.FC = () => { if (!disputeTemplateInput || !dataMappingsInput) return; const fetchData = async () => { - let parsedMappings; try { - parsedMappings = JSON.parse(dataMappingsInput); - } catch (e) { - console.error(e); - setDisputeDetails(undefined); - return; - } - - try { - let data = {}; - for (const action of parsedMappings) { - if (action.type === "reality") { - const realityData = await retrieveRealityData(action.realityQuestionID, arbitrable); - data = { ...data, ...realityData }; - } else { - const results = await executeActions(parsedMappings, arbitrable); - data = { ...data, ...results }; - } - } - - console.log("disputeTemplateInput: ", disputeTemplateInput); - console.log("data: ", data); + const parsedMappings = JSON.parse(dataMappingsInput); + const data = await executeActions(parsedMappings, arbitrable); const finalDisputeDetails = populateTemplate(disputeTemplateInput, data); setDisputeDetails(finalDisputeDetails); console.log("finalTemplate: ", finalDisputeDetails); @@ -131,7 +111,7 @@ const DisputeTemplateView: React.FC = () => { }; fetchData(); - }, [disputeTemplateInput, dataMappingsInput]); + }, [disputeTemplateInput, dataMappingsInput, arbitrable]); return ( From 3fc4468f7c439678045bcbc2df5936e923ca1200 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Wed, 10 Jan 2024 13:50:55 +0100 Subject: [PATCH 28/37] fix(web): abstract arbitrable into the initialcontext for mappings --- kleros-sdk/dataMappings/executeActions.ts | 10 +++++----- .../utils/replacePlaceholdersWithValues.ts | 10 +++++----- web/src/pages/Cases/CaseDetails/Overview.tsx | 5 +++-- web/src/pages/DisputeTemplateView.tsx | 5 ++++- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/kleros-sdk/dataMappings/executeActions.ts b/kleros-sdk/dataMappings/executeActions.ts index e709b0040..790b1f7ec 100644 --- a/kleros-sdk/dataMappings/executeActions.ts +++ b/kleros-sdk/dataMappings/executeActions.ts @@ -14,12 +14,12 @@ import { import { ActionMapping } from "./utils/actionTypes"; import { replacePlaceholdersWithValues } from "./utils/replacePlaceholdersWithValues"; -export const executeAction = async (mapping: ActionMapping, arbitrable?: `0x${string}`, context = {}) => { +export const executeAction = async (mapping: ActionMapping, context = {}) => { mapping = replacePlaceholdersWithValues(mapping, context); switch (mapping.type) { case "reality": - return await retrieveRealityData(mapping.realityQuestionID, arbitrable); + return await retrieveRealityData(mapping.realityQuestionID, context.arbitrable); case "graphql": if (!isSubgraphMapping(mapping)) { throw new Error("Invalid mapping for graphql action."); @@ -50,11 +50,11 @@ export const executeAction = async (mapping: ActionMapping, arbitrable?: `0x${st } }; -export const executeActions = async (mappings, arbitrable?: `0x${string}`, initialState = {}) => { - let context = { ...initialState }; +export const executeActions = async (mappings, initialContext = {}) => { + let context = { ...initialContext }; for (const mapping of mappings) { - const actionResult = await executeAction(mapping, arbitrable, context); + const actionResult = await executeAction(mapping, context); if (actionResult) { Object.keys(actionResult).forEach((key) => { context[key] = actionResult[key]; diff --git a/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts b/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts index b880a67f0..af45e5e11 100644 --- a/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts +++ b/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts @@ -1,11 +1,11 @@ -export const replacePlaceholdersWithValues = (mapping: any, results: any) => { +export const replacePlaceholdersWithValues = (mapping: any, context: any) => { let mappingAsString = JSON.stringify(mapping); - const replacedMapping = mappingAsString.replace(/results\.([A-Za-z0-9_]+)/g, (_, variableName) => { - if (results.hasOwnProperty(variableName)) { - return results[variableName]; + const replacedMapping = mappingAsString.replace(/context\.([A-Za-z0-9_]+)/g, (_, variableName) => { + if (context.hasOwnProperty(variableName)) { + return context[variableName]; } else { - throw new Error(`Variable '${variableName}' not found in results.`); + throw new Error(`Variable '${variableName}' not found in context.`); } }); diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index f218f9d12..d83e2ccbd 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -135,8 +135,9 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex useEffect(() => { configureSDK({ apiKey: alchemyApiKey }); - const initialState = { + const initialContext = { disputeID: id, + arbitrable: arbitrable, }; if (!disputeTemplateInput || !dataMappingsInput) return; @@ -144,7 +145,7 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex const fetchData = async () => { try { const parsedMappings = JSON.parse(dataMappingsInput); - const data = await executeActions(parsedMappings, arbitrable, initialState); + const data = await executeActions(parsedMappings, initialContext); const finalDisputeDetails = populateTemplate(disputeTemplateInput, data); setDisputeDetails(finalDisputeDetails); } catch (e) { diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index d0193b061..0c8b4cf3c 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -94,13 +94,16 @@ const DisputeTemplateView: React.FC = () => { useEffect(() => { configureSDK({ apiKey: alchemyApiKey }); + const initialContext = { + arbitrable: arbitrable, + }; if (!disputeTemplateInput || !dataMappingsInput) return; const fetchData = async () => { try { const parsedMappings = JSON.parse(dataMappingsInput); - const data = await executeActions(parsedMappings, arbitrable); + const data = await executeActions(parsedMappings, initialContext); const finalDisputeDetails = populateTemplate(disputeTemplateInput, data); setDisputeDetails(finalDisputeDetails); console.log("finalTemplate: ", finalDisputeDetails); From d281691f7c575e868bdb53da05dcd9db0f1d1b01 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Wed, 10 Jan 2024 14:14:18 +0100 Subject: [PATCH 29/37] feat(sdk): reality mapping types --- kleros-sdk/dataMappings/executeActions.ts | 8 ++++++-- .../dataMappings/utils/actionTypeDetectors.ts | 4 ++++ kleros-sdk/dataMappings/utils/actionTypes.ts | 13 ++++++++++++- web/src/pages/DisputeTemplateView.tsx | 1 - 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/kleros-sdk/dataMappings/executeActions.ts b/kleros-sdk/dataMappings/executeActions.ts index 790b1f7ec..21766a03f 100644 --- a/kleros-sdk/dataMappings/executeActions.ts +++ b/kleros-sdk/dataMappings/executeActions.ts @@ -9,6 +9,7 @@ import { isAbiEventMapping, isFetchIpfsJsonMapping, isJsonMapping, + isRealityMapping, isSubgraphMapping, } from "./utils/actionTypeDetectors"; import { ActionMapping } from "./utils/actionTypes"; @@ -18,8 +19,6 @@ export const executeAction = async (mapping: ActionMapping, context = {}) => { mapping = replacePlaceholdersWithValues(mapping, context); switch (mapping.type) { - case "reality": - return await retrieveRealityData(mapping.realityQuestionID, context.arbitrable); case "graphql": if (!isSubgraphMapping(mapping)) { throw new Error("Invalid mapping for graphql action."); @@ -45,6 +44,11 @@ export const executeAction = async (mapping: ActionMapping, context = {}) => { throw new Error("Invalid mapping for fetch/ipfs/json action."); } return await fetchIpfsJsonAction(mapping); + case "reality": + if (!isRealityMapping(mapping)) { + throw new Error("Invalid mapping for reality action."); + } + return await retrieveRealityData(mapping.realityQuestionID, context.arbitrable); default: throw new Error(`Unsupported action type: ${mapping.type}`); } diff --git a/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts b/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts index 5531a04c1..d42b9bc34 100644 --- a/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts +++ b/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts @@ -5,6 +5,7 @@ import { JsonMapping, ActionMapping, FetchIpfsJsonMapping, + RealityMapping, } from "./actionTypes"; export const isSubgraphMapping = (mapping: ActionMapping): mapping is SubgraphMapping => @@ -21,3 +22,6 @@ export const isJsonMapping = (mapping: ActionMapping): mapping is JsonMapping => export const isFetchIpfsJsonMapping = (mapping: ActionMapping): mapping is FetchIpfsJsonMapping => (mapping as FetchIpfsJsonMapping).ipfsUri !== undefined; + +export const isRealityMapping = (mapping: ActionMapping): mapping is RealityMapping => + mapping.type === "reality" && typeof (mapping as RealityMapping).realityQuestionID === "string"; diff --git a/kleros-sdk/dataMappings/utils/actionTypes.ts b/kleros-sdk/dataMappings/utils/actionTypes.ts index 746a91f34..fe0fe1e33 100644 --- a/kleros-sdk/dataMappings/utils/actionTypes.ts +++ b/kleros-sdk/dataMappings/utils/actionTypes.ts @@ -43,4 +43,15 @@ export type FetchIpfsJsonMapping = { populate: string[]; }; -export type ActionMapping = SubgraphMapping | AbiEventMapping | AbiCallMapping | JsonMapping | FetchIpfsJsonMapping; +export type RealityMapping = { + type: "reality"; + realityQuestionID: string; +}; + +export type ActionMapping = + | SubgraphMapping + | AbiEventMapping + | AbiCallMapping + | JsonMapping + | FetchIpfsJsonMapping + | RealityMapping; diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index 0c8b4cf3c..e49f72f98 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -5,7 +5,6 @@ import PolicyIcon from "svgs/icons/policy.svg"; import ReactMarkdown from "components/ReactMarkdown"; import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; import { configureSDK } from "@kleros/kleros-sdk/dataMappings/utils/configureSDK"; -import { retrieveRealityData } from "@kleros/kleros-sdk/dataMappings/retrieveRealityData"; import { executeActions } from "@kleros/kleros-sdk/dataMappings/executeActions"; import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; import { Answer, DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; From 93c6aa332f4f55ed4b8b0de44ec5b750bd7a382a Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 10 Jan 2024 16:20:53 +0000 Subject: [PATCH 30/37] fix: mapping example --- .../v2-disputetemplate/reality/example3/DisputeMappings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeMappings.json b/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeMappings.json index 197db3a76..cedf70a21 100644 --- a/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeMappings.json +++ b/kleros-sdk/config/v2-disputetemplate/reality/example3/DisputeMappings.json @@ -2,7 +2,7 @@ { "type": "json", "source": { - "question": "**Kleros Moderate:** Did the user, **degenape6** (ID: 1554345080), break the Telegram group, ***[Kleros Trading Group]()*** (ID: -1001151472172), ***[rules](https://ipfs.kleros.io/ipfs/Qme3Qbj9rKUNHUe9vj9rqCLnTVUCWKy2YfveQF8HiuWQSu/Kleros%20Moderate%20Community%20Rules.pdf)*** due to conduct related to the ***[message](https://t.me/c/1151472172/116662)*** (***[backup](https://ipfs.kleros.io/ipfs/QmVbFrZR1bcyQzZjvLyXwL9ekDxrqHERykdreRxXrw4nqg/animations_file_23.mp4)***)?", + "value": "**Kleros Moderate:** Did the user, **degenape6** (ID: 1554345080), break the Telegram group, ***[Kleros Trading Group]()*** (ID: -1001151472172), ***[rules](https://ipfs.kleros.io/ipfs/Qme3Qbj9rKUNHUe9vj9rqCLnTVUCWKy2YfveQF8HiuWQSu/Kleros%20Moderate%20Community%20Rules.pdf)*** due to conduct related to the ***[message](https://t.me/c/1151472172/116662)*** (***[backup](https://ipfs.kleros.io/ipfs/QmVbFrZR1bcyQzZjvLyXwL9ekDxrqHERykdreRxXrw4nqg/animations_file_23.mp4)***)?", "type": "single-select", "answers": [ { From 6fcd056b2ceaeff15a8176c4ebe66edbd5f6d014 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 11 Jan 2024 19:48:12 +0000 Subject: [PATCH 31/37] chore: lock file --- yarn.lock | 69 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/yarn.lock b/yarn.lock index d9c933282..8404573b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7978,20 +7978,20 @@ __metadata: languageName: node linkType: hard -"@reality.eth/contracts@npm:^3.0.45": - version: 3.0.45 - resolution: "@reality.eth/contracts@npm:3.0.45" +"@reality.eth/contracts@npm:^3.0.46": + version: 3.0.46 + resolution: "@reality.eth/contracts@npm:3.0.46" dependencies: ethers: ^5.6.8 - checksum: e6e802fdf78d4bf1a6459bd78febddd6190fe3bc6448cc4dbc08203ebdccc25c99bf873951dd5f4c4523ff84e8f936981b0ef932377ae9ca7b884780904f9c15 + checksum: bd20adad520a3189bd484218232c40be4f5019047fabff590b3dc54061f498009fa6ffb94033108fcebbd68210eff7bc884544569bfb1124773fd11e3846a8d3 languageName: node linkType: hard "@reality.eth/reality-eth-lib@npm:^3.2.29": - version: 3.2.29 - resolution: "@reality.eth/reality-eth-lib@npm:3.2.29" + version: 3.2.30 + resolution: "@reality.eth/reality-eth-lib@npm:3.2.30" dependencies: - "@reality.eth/contracts": ^3.0.45 + "@reality.eth/contracts": ^3.0.46 bignumber.js: ^7.2.1 bn.js: ^5.2.1 ethereumjs-abi: ^0.6.5 @@ -7999,7 +7999,7 @@ __metadata: isomorphic-dompurify: ^0.23.0 marked: ^4.1.1 sprintf-js: ^1.1.1 - checksum: 2142e90b048b8f0f2b1228e8549880cb6ce306af22bdbb5ec174fe1285611e747680165b4fd82f4feb900a42a3465f8d76302cf3e38899f907a7cf1a58999b10 + checksum: c8d1324979d0f2713970b6c4e757c6fdf3d164b89e4732e8a231d1d3d664d8f51aecf959770770d829101dae404a600f49002ae32855c640ae853ebecd1e51c3 languageName: node linkType: hard @@ -9772,9 +9772,9 @@ __metadata: linkType: hard "@types/mustache@npm:^4.2.3": - version: 4.2.3 - resolution: "@types/mustache@npm:4.2.3" - checksum: c2c7cf749a84a622648c7088fb10350b84ea935145514b6c51d17e808a4b4972fb137273339f4d93160a3c496a3943dab3be93251d74c185730daa300a299e2f + version: 4.2.5 + resolution: "@types/mustache@npm:4.2.5" + checksum: 0ff1d52022fd3ab0db1c97964ca0c24b45ad74e81ec62e05d27eab5b66ef1d78ff257f4cfb481c72b8b511f15520ca48717e000dc5fa8c3fdf732790b28f05cb languageName: node linkType: hard @@ -10061,9 +10061,9 @@ __metadata: linkType: hard "@types/trusted-types@npm:*": - version: 2.0.4 - resolution: "@types/trusted-types@npm:2.0.4" - checksum: 5256c4576cd1c90d33ddd9cc9cbd4f202b39c98cbe8b7f74963298f9eb2159c285ea5c25a6181b4c594d8d75641765bff85d72c2d251ad076e6529ce0eeedd1c + version: 2.0.7 + resolution: "@types/trusted-types@npm:2.0.7" + checksum: 8e4202766a65877efcf5d5a41b7dd458480b36195e580a3b1085ad21e948bc417d55d6f8af1fd2a7ad008015d4117d5fdfe432731157da3c68678487174e4ba3 languageName: node linkType: hard @@ -11514,7 +11514,14 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.0.2, acorn-walk@npm:^8.1.1": +"acorn-walk@npm:^8.0.2": + version: 8.3.2 + resolution: "acorn-walk@npm:8.3.2" + checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 + languageName: node + linkType: hard + +"acorn-walk@npm:^8.1.1": version: 8.2.0 resolution: "acorn-walk@npm:8.2.0" checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 @@ -13136,7 +13143,7 @@ __metadata: languageName: node linkType: hard -"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.0.1": +"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.0": version: 4.1.0 resolution: "browserify-rsa@npm:4.1.0" dependencies: @@ -13147,19 +13154,19 @@ __metadata: linkType: hard "browserify-sign@npm:^4.0.0": - version: 4.2.1 - resolution: "browserify-sign@npm:4.2.1" + version: 4.2.2 + resolution: "browserify-sign@npm:4.2.2" dependencies: - bn.js: ^5.1.1 - browserify-rsa: ^4.0.1 + bn.js: ^5.2.1 + browserify-rsa: ^4.1.0 create-hash: ^1.2.0 create-hmac: ^1.1.7 - elliptic: ^6.5.3 + elliptic: ^6.5.4 inherits: ^2.0.4 - parse-asn1: ^5.1.5 - readable-stream: ^3.6.0 - safe-buffer: ^5.2.0 - checksum: 0221f190e3f5b2d40183fa51621be7e838d9caa329fe1ba773406b7637855f37b30f5d83e52ff8f244ed12ffe6278dd9983638609ed88c841ce547e603855707 + parse-asn1: ^5.1.6 + readable-stream: ^3.6.2 + safe-buffer: ^5.2.1 + checksum: b622730c0fc183328c3a1c9fdaaaa5118821ed6822b266fa6b0375db7e20061ebec87301d61931d79b9da9a96ada1cab317fce3c68f233e5e93ed02dbb35544c languageName: node linkType: hard @@ -26327,7 +26334,7 @@ __metadata: languageName: node linkType: hard -"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.5": +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.6": version: 5.1.6 resolution: "parse-asn1@npm:5.1.6" dependencies: @@ -28753,7 +28760,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": +"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -29640,7 +29647,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 @@ -34354,8 +34361,8 @@ __metadata: linkType: hard "ws@npm:^8.11.0": - version: 8.14.2 - resolution: "ws@npm:8.14.2" + version: 8.16.0 + resolution: "ws@npm:8.16.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -34364,7 +34371,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 3ca0dad26e8cc6515ff392b622a1467430814c463b3368b0258e33696b1d4bed7510bc7030f7b72838b9fdeb8dbd8839cbf808367d6aae2e1d668ce741d4308b + checksum: feb3eecd2bae82fa8a8beef800290ce437d8b8063bdc69712725f21aef77c49cb2ff45c6e5e7fce622248f9c7abaee506bae0a9064067ffd6935460c7357321b languageName: node linkType: hard From ac22739c2cd1b498d48ded9696d23e621200348d Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Thu, 11 Jan 2024 20:42:15 +0000 Subject: [PATCH 32/37] chore: dependency hell --- bot-pinner/package.json | 2 +- contracts/package.json | 6 +- kleros-sdk/package.json | 10 +- web/package.json | 6 +- yarn.lock | 263 +++++++++++++++++----------------------- 5 files changed, 122 insertions(+), 165 deletions(-) diff --git a/bot-pinner/package.json b/bot-pinner/package.json index d1cb6102e..00aeb2904 100644 --- a/bot-pinner/package.json +++ b/bot-pinner/package.json @@ -20,6 +20,6 @@ "node": ">=16.13.0" }, "devDependencies": { - "@dappnode/dappnodesdk": "^0.3.8" + "@dappnode/dappnodesdk": "^0.3.11" } } diff --git a/contracts/package.json b/contracts/package.json index 4b09fb6df..6af11864c 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -68,7 +68,7 @@ "@typechain/hardhat": "^7.0.0", "@types/chai": "^4.3.11", "@types/mocha": "^10.0.6", - "@types/node": "^16.18.68", + "@types/node": "^16.18.70", "@wagmi/cli": "^1.5.2", "abitype": "^0.10.3", "chai": "^4.3.10", @@ -79,8 +79,8 @@ "graphql-request": "^6.1.0", "hardhat": "2.15.0", "hardhat-contract-sizer": "^2.10.0", - "hardhat-deploy": "^0.11.42", - "hardhat-deploy-ethers": "^0.4.0-next.1", + "hardhat-deploy": "0.11.42", + "hardhat-deploy-ethers": "0.4.0-next.1", "hardhat-deploy-tenderly": "^0.2.0", "hardhat-docgen": "^1.3.0", "hardhat-gas-reporter": "^1.0.9", diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 6d7092baf..608353d58 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -20,15 +20,15 @@ "test-data-mappings": "mocha -r ts-node/register/transpile-only dataMappings/test.ts" }, "devDependencies": { - "@types/chai": "^4.3.6", - "@types/mocha": "^10.0.1", + "@types/chai": "^4.3.11", + "@types/mocha": "^10.0.6", "chai": "^4.3.8", "dotenv": "^16.3.1", "mocha": "^10.2.0", - "ts-node": "^10.9.1", - "typescript": "^5.2.2" + "ts-node": "^10.9.2", + "typescript": "^5.3.3" }, "dependencies": { - "@reality.eth/reality-eth-lib": "^3.2.29" + "@reality.eth/reality-eth-lib": "^3.2.30" } } diff --git a/web/package.json b/web/package.json index 4f32ca9de..a3b1642d5 100644 --- a/web/package.json +++ b/web/package.json @@ -52,7 +52,7 @@ "@parcel/watcher": "~2.2.0", "@types/amqplib": "^0.10.4", "@types/busboy": "^1.5.3", - "@types/mustache": "^4.2.3", + "@types/mustache": "^4.2.5", "@types/react": "^18.2.14", "@types/react-dom": "^18.2.7", "@types/styled-components": "^5.1.26", @@ -107,8 +107,8 @@ "react-toastify": "^9.1.3", "react-use": "^17.4.0", "styled-components": "^5.3.9", - "viem": "^1.21.1", - "wagmi": "^1.4.12" + "viem": "^1.21.4", + "wagmi": "^1.4.13" }, "volta": { "node": "16.20.2", diff --git a/yarn.lock b/yarn.lock index 8404573b7..1b0fe1a9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3467,11 +3467,11 @@ __metadata: languageName: node linkType: hard -"@dappnode/dappnodesdk@npm:^0.3.8": - version: 0.3.8 - resolution: "@dappnode/dappnodesdk@npm:0.3.8" +"@dappnode/dappnodesdk@npm:^0.3.11": + version: 0.3.11 + resolution: "@dappnode/dappnodesdk@npm:0.3.11" dependencies: - "@dappnode/schemas": ^0.1.6 + "@dappnode/schemas": ^0.1.8 "@dappnode/toolkit": 0.1.20 "@dappnode/types": ^0.1.17 "@octokit/rest": ^18.0.12 @@ -3502,19 +3502,19 @@ __metadata: yargs: ^17.7.1 bin: dappnodesdk: dist/dappnodesdk.js - checksum: a9aa07e14ad2072860ba291e41c7dcada5a3fbad8b4212292cb30d4f4d0e4f6fe56062eab4c60feb75ed922ab614ae7e935eba2d7caa381e7119f9b63de43db1 + checksum: b066ab374ea1a286bb39ab05f2cfc859137d3791bb1e0d90ef9542fef44f08a8b0da3841e94cacc8bfba57afee2684e31dab3c6861205bf9aacfd522e9c3cfe5 languageName: node linkType: hard -"@dappnode/schemas@npm:^0.1.6": - version: 0.1.7 - resolution: "@dappnode/schemas@npm:0.1.7" +"@dappnode/schemas@npm:^0.1.8": + version: 0.1.8 + resolution: "@dappnode/schemas@npm:0.1.8" dependencies: "@dappnode/types": ^0.1.9 ajv: ^8.12.0 ajv-errors: ^3.0.0 semver: ^7.5.0 - checksum: e353a50db72ba5d11f6aeb18fe2a19dc7395766d438e8b0f86eab9e86eec6abb0520a928780c1fa54bb349fdc5a9c1cc5ffde062b651f2e7931cc6b833d0894f + checksum: f8b13283e22783f442e99185dc8a2207b8e6e22f4166a37c8e45c97db4253b322f799e46b2baa450e24446eedd2c90aedc2419c00bbcef933c0ccfef0b9ec4a7 languageName: node linkType: hard @@ -5445,14 +5445,14 @@ __metadata: version: 0.0.0-use.local resolution: "@kleros/kleros-sdk@workspace:kleros-sdk" dependencies: - "@reality.eth/reality-eth-lib": ^3.2.29 - "@types/chai": ^4.3.6 - "@types/mocha": ^10.0.1 + "@reality.eth/reality-eth-lib": ^3.2.30 + "@types/chai": ^4.3.11 + "@types/mocha": ^10.0.6 chai: ^4.3.8 dotenv: ^16.3.1 mocha: ^10.2.0 - ts-node: ^10.9.1 - typescript: ^5.2.2 + ts-node: ^10.9.2 + typescript: ^5.3.3 languageName: unknown linkType: soft @@ -5460,7 +5460,7 @@ __metadata: version: 0.0.0-use.local resolution: "@kleros/kleros-v2-bot-pinner@workspace:bot-pinner" dependencies: - "@dappnode/dappnodesdk": ^0.3.8 + "@dappnode/dappnodesdk": ^0.3.11 languageName: unknown linkType: soft @@ -5481,7 +5481,7 @@ __metadata: "@typechain/hardhat": ^7.0.0 "@types/chai": ^4.3.11 "@types/mocha": ^10.0.6 - "@types/node": ^16.18.68 + "@types/node": ^16.18.70 "@wagmi/cli": ^1.5.2 abitype: ^0.10.3 chai: ^4.3.10 @@ -5492,8 +5492,8 @@ __metadata: graphql-request: ^6.1.0 hardhat: 2.15.0 hardhat-contract-sizer: ^2.10.0 - hardhat-deploy: ^0.11.42 - hardhat-deploy-ethers: ^0.4.0-next.1 + hardhat-deploy: 0.11.42 + hardhat-deploy-ethers: 0.4.0-next.1 hardhat-deploy-tenderly: ^0.2.0 hardhat-docgen: ^1.3.0 hardhat-gas-reporter: ^1.0.9 @@ -5585,7 +5585,7 @@ __metadata: "@tanstack/react-query": ^4.28.0 "@types/amqplib": ^0.10.4 "@types/busboy": ^1.5.3 - "@types/mustache": ^4.2.3 + "@types/mustache": ^4.2.5 "@types/react": ^18.2.14 "@types/react-dom": ^18.2.7 "@types/react-modal": ^3.16.0 @@ -5630,8 +5630,8 @@ __metadata: styled-components: ^5.3.9 supabase: ^1.102.2 typescript: ^5.3.3 - viem: ^1.21.1 - wagmi: ^1.4.12 + viem: ^1.21.4 + wagmi: ^1.4.13 languageName: unknown linkType: soft @@ -7987,7 +7987,7 @@ __metadata: languageName: node linkType: hard -"@reality.eth/reality-eth-lib@npm:^3.2.29": +"@reality.eth/reality-eth-lib@npm:^3.2.30": version: 3.2.30 resolution: "@reality.eth/reality-eth-lib@npm:3.2.30" dependencies: @@ -9440,7 +9440,7 @@ __metadata: languageName: node linkType: hard -"@types/chai@npm:^4.3.11, @types/chai@npm:^4.3.6": +"@types/chai@npm:^4.3.11": version: 4.3.11 resolution: "@types/chai@npm:4.3.11" checksum: d0c05fe5d02b2e6bbca2bd4866a2ab20a59cf729bc04af0060e7a3277eaf2fb65651b90d4c74b0ebf1d152b4b1d49fa8e44143acef276a2bbaa7785fbe5642d3 @@ -9757,7 +9757,7 @@ __metadata: languageName: node linkType: hard -"@types/mocha@npm:^10.0.1, @types/mocha@npm:^10.0.6": +"@types/mocha@npm:^10.0.6": version: 10.0.6 resolution: "@types/mocha@npm:10.0.6" checksum: f7c836cf6cf27dc0f5970d262591b56f2a3caeaec8cfdc612c12e1cfbb207f601f710ece207e935164d4e3343b93be5054d0db5544f31f453b3923775d82099f @@ -9771,7 +9771,7 @@ __metadata: languageName: node linkType: hard -"@types/mustache@npm:^4.2.3": +"@types/mustache@npm:^4.2.5": version: 4.2.5 resolution: "@types/mustache@npm:4.2.5" checksum: 0ff1d52022fd3ab0db1c97964ca0c24b45ad74e81ec62e05d27eab5b66ef1d78ff257f4cfb481c72b8b511f15520ca48717e000dc5fa8c3fdf732790b28f05cb @@ -9813,10 +9813,10 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^16.18.68": - version: 16.18.68 - resolution: "@types/node@npm:16.18.68" - checksum: 094ae9ed80eed2af4bd34d551467e307f2ecb6efb0f8b872feebfb9da5ea4b446c5883c9abe2349f8ea2b78bdacd8726a946c27c2a246676c4c330e41ccb9284 +"@types/node@npm:^16.18.70": + version: 16.18.70 + resolution: "@types/node@npm:16.18.70" + checksum: 0c8a1ee93f6c0940629fbf6245ff22e0c7423b7c7c74c47e7171dc6342d279c2f931d50894c3d1b9a66238469b2b3d2d3c7fcf21eb3af6a03fc588f9ab6db849 languageName: node linkType: hard @@ -10479,17 +10479,17 @@ __metadata: languageName: node linkType: hard -"@wagmi/connectors@npm:3.1.10": - version: 3.1.10 - resolution: "@wagmi/connectors@npm:3.1.10" +"@wagmi/connectors@npm:3.1.11": + version: 3.1.11 + resolution: "@wagmi/connectors@npm:3.1.11" dependencies: "@coinbase/wallet-sdk": ^3.6.6 "@safe-global/safe-apps-provider": ^0.18.1 "@safe-global/safe-apps-sdk": ^8.1.0 - "@walletconnect/ethereum-provider": 2.10.6 + "@walletconnect/ethereum-provider": 2.11.0 "@walletconnect/legacy-provider": ^2.0.0 "@walletconnect/modal": 2.6.2 - "@walletconnect/utils": 2.10.2 + "@walletconnect/utils": 2.11.0 abitype: 0.8.7 eventemitter3: ^4.0.7 peerDependencies: @@ -10498,15 +10498,15 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 65eeb30881fbbf018ec842eb156f4119090c804450f55de60d95c92b124d86b5a769cdc02f4db0bc04ae481b678375d6061d67a86b14b30b62527c202a688574 + checksum: c198b04751df5e39c37e0a7077f7dcaad7a19b15a71538ee03d5cec066b1c82a3e4b7cc8882b671c49b57066ffd7887dbcad19ed411f98f20e6588455142e9d5 languageName: node linkType: hard -"@wagmi/core@npm:1.4.12": - version: 1.4.12 - resolution: "@wagmi/core@npm:1.4.12" +"@wagmi/core@npm:1.4.13": + version: 1.4.13 + resolution: "@wagmi/core@npm:1.4.13" dependencies: - "@wagmi/connectors": 3.1.10 + "@wagmi/connectors": 3.1.11 abitype: 0.8.7 eventemitter3: ^4.0.7 zustand: ^4.3.1 @@ -10516,13 +10516,13 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 4f1e7c532e7f8a984c6918328a6690543cf77d224f0e1119a7eba4e3495da466d7a2c64718922bc5e3741cabf17c20ff0de2600531ea3f9bd07ba4b27067d68b + checksum: e35c5f8ec3ca066cab6affcb551c784e44bcce07742913ebb1285cc58648f5b2cab98d7a014cd6b8cfa1afb2eaa7047523f17d90519982458d2c9b3b6f7e2c9f languageName: node linkType: hard -"@walletconnect/core@npm:2.10.6": - version: 2.10.6 - resolution: "@walletconnect/core@npm:2.10.6" +"@walletconnect/core@npm:2.11.0": + version: 2.11.0 + resolution: "@walletconnect/core@npm:2.11.0" dependencies: "@walletconnect/heartbeat": 1.2.1 "@walletconnect/jsonrpc-provider": 1.0.13 @@ -10535,12 +10535,13 @@ __metadata: "@walletconnect/relay-auth": ^1.0.4 "@walletconnect/safe-json": ^1.0.2 "@walletconnect/time": ^1.0.2 - "@walletconnect/types": 2.10.6 - "@walletconnect/utils": 2.10.6 + "@walletconnect/types": 2.11.0 + "@walletconnect/utils": 2.11.0 events: ^3.3.0 + isomorphic-unfetch: 3.1.0 lodash.isequal: 4.5.0 uint8arrays: ^3.1.0 - checksum: 7ed74d0feaf4f4b332da2e82932340e6897e26910ae66c111e8724f41b15f14376fd9fd4b93ba9395107d24d2147932ef29bd7b7edce1bbde89e4258e8b2f574 + checksum: 419eff78df347eb5d5c51c2dbf60e3246b5dda00afdd77279795a89627285839cb769e1115e751026756d37e26e6bd708452170ded08be074d64256afd8a8663 languageName: node linkType: hard @@ -10578,21 +10579,21 @@ __metadata: languageName: node linkType: hard -"@walletconnect/ethereum-provider@npm:2.10.6": - version: 2.10.6 - resolution: "@walletconnect/ethereum-provider@npm:2.10.6" +"@walletconnect/ethereum-provider@npm:2.11.0": + version: 2.11.0 + resolution: "@walletconnect/ethereum-provider@npm:2.11.0" dependencies: "@walletconnect/jsonrpc-http-connection": ^1.0.7 "@walletconnect/jsonrpc-provider": ^1.0.13 "@walletconnect/jsonrpc-types": ^1.0.3 "@walletconnect/jsonrpc-utils": ^1.0.8 - "@walletconnect/modal": ^2.4.3 - "@walletconnect/sign-client": 2.10.6 - "@walletconnect/types": 2.10.6 - "@walletconnect/universal-provider": 2.10.6 - "@walletconnect/utils": 2.10.6 + "@walletconnect/modal": ^2.6.2 + "@walletconnect/sign-client": 2.11.0 + "@walletconnect/types": 2.11.0 + "@walletconnect/universal-provider": 2.11.0 + "@walletconnect/utils": 2.11.0 events: ^3.3.0 - checksum: 02452044400ef751358598aada659ce77ae69495f3b01f040a6888289d74d22a03c1736a4860a9e1157bc0211bbcde1e3b0eb01d4ff209c2bf14efe7172774c9 + checksum: 8b45eb7e6679d340e6d976c6c10b10b4ce0435b959d35b627677d946b9f152f20fc242e581a16e9b6f7ed98c5352748213856e342f55f3dbd4cd9130965d542c languageName: node linkType: hard @@ -10673,24 +10674,6 @@ __metadata: languageName: node linkType: hard -"@walletconnect/keyvaluestorage@npm:^1.0.2": - version: 1.0.2 - resolution: "@walletconnect/keyvaluestorage@npm:1.0.2" - dependencies: - safe-json-utils: ^1.1.1 - tslib: 1.14.1 - peerDependencies: - "@react-native-async-storage/async-storage": 1.x - lokijs: 1.x - peerDependenciesMeta: - "@react-native-async-storage/async-storage": - optional: true - lokijs: - optional: true - checksum: d695c2efcfa013a43cfaa20c85281df7d364a4452d11a4312a695298bd0e50d04b0e21c828f33f46fb020ea9796e60a6b23041a85f29bd10beeba7d0da24539f - languageName: node - linkType: hard - "@walletconnect/keyvaluestorage@npm:^1.1.1": version: 1.1.1 resolution: "@walletconnect/keyvaluestorage@npm:1.1.1" @@ -10808,7 +10791,7 @@ __metadata: languageName: node linkType: hard -"@walletconnect/modal@npm:2.6.2, @walletconnect/modal@npm:^2.4.3": +"@walletconnect/modal@npm:2.6.2, @walletconnect/modal@npm:^2.6.2": version: 2.6.2 resolution: "@walletconnect/modal@npm:2.6.2" dependencies: @@ -10863,20 +10846,20 @@ __metadata: languageName: node linkType: hard -"@walletconnect/sign-client@npm:2.10.6": - version: 2.10.6 - resolution: "@walletconnect/sign-client@npm:2.10.6" +"@walletconnect/sign-client@npm:2.11.0": + version: 2.11.0 + resolution: "@walletconnect/sign-client@npm:2.11.0" dependencies: - "@walletconnect/core": 2.10.6 + "@walletconnect/core": 2.11.0 "@walletconnect/events": ^1.0.1 "@walletconnect/heartbeat": 1.2.1 "@walletconnect/jsonrpc-utils": 1.0.8 "@walletconnect/logger": ^2.0.1 "@walletconnect/time": ^1.0.2 - "@walletconnect/types": 2.10.6 - "@walletconnect/utils": 2.10.6 + "@walletconnect/types": 2.11.0 + "@walletconnect/utils": 2.11.0 events: ^3.3.0 - checksum: 610dd354d53159eb26ec61d3399507ba63739d9070a458b3a791a944d8b62d9b55d487d3d41c68aa9af0052fc04daea0a05a2f5d664c6ff21cb89e0909a1323b + checksum: 89230cf4ca95f9feb06104cc8097340e345b2b21257d45acf16729342ddcf5248bbf05097343b21e4dbebfa4fbacb6fe067099ee6127169a6b464563985d4716 languageName: node linkType: hard @@ -10889,23 +10872,9 @@ __metadata: languageName: node linkType: hard -"@walletconnect/types@npm:2.10.2": - version: 2.10.2 - resolution: "@walletconnect/types@npm:2.10.2" - dependencies: - "@walletconnect/events": ^1.0.1 - "@walletconnect/heartbeat": 1.2.1 - "@walletconnect/jsonrpc-types": 1.0.3 - "@walletconnect/keyvaluestorage": ^1.0.2 - "@walletconnect/logger": ^2.0.1 - events: ^3.3.0 - checksum: dafcb840b2b93343db56ca6684edfe8a20d9b2f703f81b2d1fdbea558fe41de9fbddec12c24e9d51a50c75ee6298a1cfd347d7fa0202146033788670371cfd6a - languageName: node - linkType: hard - -"@walletconnect/types@npm:2.10.6": - version: 2.10.6 - resolution: "@walletconnect/types@npm:2.10.6" +"@walletconnect/types@npm:2.11.0": + version: 2.11.0 + resolution: "@walletconnect/types@npm:2.11.0" dependencies: "@walletconnect/events": ^1.0.1 "@walletconnect/heartbeat": 1.2.1 @@ -10913,52 +10882,30 @@ __metadata: "@walletconnect/keyvaluestorage": ^1.1.1 "@walletconnect/logger": ^2.0.1 events: ^3.3.0 - checksum: 84f411fd41debc310b4aae4969e5a78074f1f8cc937c4f1a6f92fa80775dd88bb400b365533396fc9325109a3c5dc4c4951615f2e265b5f82e9f454b17b96d5e + checksum: 32d0d7972b90683467e47eabf92005c7c5d1ae76400eb221576ac0d32501b9f0a414d5921f0c881efe86f07485db807e3e9d370c6b9cc264771822916dc4cca5 languageName: node linkType: hard -"@walletconnect/universal-provider@npm:2.10.6": - version: 2.10.6 - resolution: "@walletconnect/universal-provider@npm:2.10.6" +"@walletconnect/universal-provider@npm:2.11.0": + version: 2.11.0 + resolution: "@walletconnect/universal-provider@npm:2.11.0" dependencies: "@walletconnect/jsonrpc-http-connection": ^1.0.7 "@walletconnect/jsonrpc-provider": 1.0.13 "@walletconnect/jsonrpc-types": ^1.0.2 "@walletconnect/jsonrpc-utils": ^1.0.7 "@walletconnect/logger": ^2.0.1 - "@walletconnect/sign-client": 2.10.6 - "@walletconnect/types": 2.10.6 - "@walletconnect/utils": 2.10.6 + "@walletconnect/sign-client": 2.11.0 + "@walletconnect/types": 2.11.0 + "@walletconnect/utils": 2.11.0 events: ^3.3.0 - checksum: c09fd28819389d990edafb261d0570d54527f0872dd3c2ac38ac0c6fc25905dc2248809fc4fea2de382b2f68c86eee8e1d192fb46402bcc49370d76959662436 + checksum: 7f4f187cd9148dc2e262e4afecadf0d0e136ae4183a60779562fef142411b927a3305c90793ef98dc3ecc61e4e2d4cfc8ac5491b1b42054021cfc4383f7ab81e languageName: node linkType: hard -"@walletconnect/utils@npm:2.10.2": - version: 2.10.2 - resolution: "@walletconnect/utils@npm:2.10.2" - dependencies: - "@stablelib/chacha20poly1305": 1.0.1 - "@stablelib/hkdf": 1.0.1 - "@stablelib/random": ^1.0.2 - "@stablelib/sha256": 1.0.1 - "@stablelib/x25519": ^1.0.3 - "@walletconnect/relay-api": ^1.0.9 - "@walletconnect/safe-json": ^1.0.2 - "@walletconnect/time": ^1.0.2 - "@walletconnect/types": 2.10.2 - "@walletconnect/window-getters": ^1.0.1 - "@walletconnect/window-metadata": ^1.0.1 - detect-browser: 5.3.0 - query-string: 7.1.3 - uint8arrays: ^3.1.0 - checksum: 168e65d48ce6121f04f040662668fce63c8e42050c7c7d1da2948cf2e486657f8bf972f3386dc84251fcabf3626a26bb696e3363d55bc92826ec1602d7b493c7 - languageName: node - linkType: hard - -"@walletconnect/utils@npm:2.10.6": - version: 2.10.6 - resolution: "@walletconnect/utils@npm:2.10.6" +"@walletconnect/utils@npm:2.11.0": + version: 2.11.0 + resolution: "@walletconnect/utils@npm:2.11.0" dependencies: "@stablelib/chacha20poly1305": 1.0.1 "@stablelib/hkdf": 1.0.1 @@ -10968,13 +10915,13 @@ __metadata: "@walletconnect/relay-api": ^1.0.9 "@walletconnect/safe-json": ^1.0.2 "@walletconnect/time": ^1.0.2 - "@walletconnect/types": 2.10.6 + "@walletconnect/types": 2.11.0 "@walletconnect/window-getters": ^1.0.1 "@walletconnect/window-metadata": ^1.0.1 detect-browser: 5.3.0 query-string: 7.1.3 uint8arrays: ^3.1.0 - checksum: f6543601897aaa00f7aa0178df1cb88cca8f06f65846d3f4be85c458e79d04c462ad45e1f38d3fc993fcfa4f77871c92308e81620d6256da8138ae10e4b7546c + checksum: 9d8259ea6a2850e620eb366b26fc3f17cf7bf75ae9c50fdfa3252b9dd152d1c10444009dfad1aa5a0a7d1ed844e5efd76581540e973315ec289fba7b51ebf7d7 languageName: node linkType: hard @@ -19410,7 +19357,7 @@ __metadata: languageName: node linkType: hard -"hardhat-deploy-ethers@npm:^0.4.0-next.1": +"hardhat-deploy-ethers@npm:0.4.0-next.1": version: 0.4.0-next.1 resolution: "hardhat-deploy-ethers@npm:0.4.0-next.1" peerDependencies: @@ -19434,7 +19381,7 @@ __metadata: languageName: node linkType: hard -"hardhat-deploy@npm:^0.11.42": +"hardhat-deploy@npm:0.11.42": version: 0.11.42 resolution: "hardhat-deploy@npm:0.11.42" dependencies: @@ -21520,6 +21467,16 @@ __metadata: languageName: node linkType: hard +"isomorphic-unfetch@npm:3.1.0": + version: 3.1.0 + resolution: "isomorphic-unfetch@npm:3.1.0" + dependencies: + node-fetch: ^2.6.1 + unfetch: ^4.2.0 + checksum: 82b92fe4ec2823a81ab0fc0d11bd94d710e6f9a940d56b3cba31896d4345ec9ffc7949f4ff31ebcae84f6b95f7ebf3474c4c7452b834eb4078ea3f2c37e459c5 + languageName: node + linkType: hard + "isomorphic-ws@npm:5.0.0, isomorphic-ws@npm:^5.0.0": version: 5.0.0 resolution: "isomorphic-ws@npm:5.0.0" @@ -29654,13 +29611,6 @@ __metadata: languageName: node linkType: hard -"safe-json-utils@npm:^1.1.1": - version: 1.1.1 - resolution: "safe-json-utils@npm:1.1.1" - checksum: f82a5833b7f6f25583c46520b3e158da3864d4f6f85b7cd68ec956ae7023395872e834d75f7f6216c109c546d10b6ee15c066d849f75ac2a7b86b8a041b4f01f - languageName: node - linkType: hard - "safe-regex-test@npm:^1.0.0": version: 1.0.0 resolution: "safe-regex-test@npm:1.0.0" @@ -32568,7 +32518,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.2.2, typescript@npm:^5.3.3": +"typescript@npm:^5.3.3": version: 5.3.3 resolution: "typescript@npm:5.3.3" bin: @@ -32588,7 +32538,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@^5.2.2#~builtin, typescript@patch:typescript@^5.3.3#~builtin": +"typescript@patch:typescript@^5.3.3#~builtin": version: 5.3.3 resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=e012d7" bin: @@ -32710,6 +32660,13 @@ __metadata: languageName: node linkType: hard +"unfetch@npm:^4.2.0": + version: 4.2.0 + resolution: "unfetch@npm:4.2.0" + checksum: 6a4b2557e1d921eaa80c4425ce27a404945ec26491ed06e62598f333996a91a44c7908cb26dc7c2746d735762b13276cf4aa41829b4c8f438dde63add3045d7a + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -33300,9 +33257,9 @@ __metadata: languageName: node linkType: hard -"viem@npm:^1.21.1": - version: 1.21.1 - resolution: "viem@npm:1.21.1" +"viem@npm:^1.21.4": + version: 1.21.4 + resolution: "viem@npm:1.21.4" dependencies: "@adraffy/ens-normalize": 1.10.0 "@noble/curves": 1.2.0 @@ -33317,7 +33274,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: ba6d296ce271e8068d0dd3cecfbe254cc046cda4acf9393f36045d1a60aa6c669b259dc82a09a3a100c8cb0930142906280782181f341b43496789239332cd9b + checksum: c351fdea2d53d2d781ac73c964348b3b9fc5dd46f9eb53903e867705fc9e30a893cb9f2c8d7a00acdcdeca27d14eeebf976eed9f948c28c47018dc9211369117 languageName: node linkType: hard @@ -33437,14 +33394,14 @@ __metadata: languageName: node linkType: hard -"wagmi@npm:^1.4.12": - version: 1.4.12 - resolution: "wagmi@npm:1.4.12" +"wagmi@npm:^1.4.13": + version: 1.4.13 + resolution: "wagmi@npm:1.4.13" dependencies: "@tanstack/query-sync-storage-persister": ^4.27.1 "@tanstack/react-query": ^4.28.0 "@tanstack/react-query-persist-client": ^4.28.0 - "@wagmi/core": 1.4.12 + "@wagmi/core": 1.4.13 abitype: 0.8.7 use-sync-external-store: ^1.2.0 peerDependencies: @@ -33454,7 +33411,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 7c1cb64c53e29899d508142e43a450b07f7f4f0ac2a19f5651f0f3dbfe2bb5b159d2b6251f6f613bd9bae007dc8390383ff79f5ab7bdf8d06788fe0bbdb3f8ab + checksum: f53ac4837506cc5d7d71f3a104e100aadfe5e5fe00f46e741eaf03c3dbfa8c4a2a47800221f5b0c454a0826d1539837a2e4e858eb606c3f17ed04dd7c252af14 languageName: node linkType: hard From 0ef5d26d1e900f03badcad1c06db6e08b49ac484 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 12 Jan 2024 02:08:33 +0000 Subject: [PATCH 33/37] feat(sdk): zod validation and vitest testing --- .../dataMappings/utils/disputeDetailsTypes.ts | 52 +- kleros-sdk/package.json | 11 +- .../test.ts => test/dataMappings.test.ts} | 14 +- kleros-sdk/test/disputeDetailsSchema.test.ts | 97 ++ kleros-sdk/tsconfig.json | 5 +- kleros-sdk/vite.config.ts | 12 + web/src/context/NewDisputeContext.tsx | 2 + yarn.lock | 858 +++++++++++++++++- 8 files changed, 992 insertions(+), 59 deletions(-) rename kleros-sdk/{dataMappings/test.ts => test/dataMappings.test.ts} (92%) create mode 100644 kleros-sdk/test/disputeDetailsSchema.test.ts create mode 100644 kleros-sdk/vite.config.ts diff --git a/kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts b/kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts index ee29cbd3d..58d563932 100644 --- a/kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts +++ b/kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts @@ -1,44 +1,8 @@ -export type DisputeDetails = { - title: string; - description: string; - question: string; - type: QuestionType; - answers: Answer[]; - policyURI: string; - attachment: Attachment; - frontendUrl: string; - arbitrableChainID: string; - arbitrableAddress: `0x${string}`; - arbitratorChainID: string; - arbitratorAddress: `0x${string}`; - category: string; - lang: string; - specification: string; - aliases?: Alias[]; - version: string; -}; - -export enum QuestionType { - Bool = "bool", - Datetime = "datetime", - MultipleSelect = "multiple-select", - SingleSelect = "single-select", - Uint = "uint", -} - -export type Answer = { - title: string; - description: string; - id: `0x${string}`; - reserved: boolean; -}; - -export type Alias = { - name: string; - address: `0x${string}` | `${string}.eth`; -}; - -export type Attachment = { - label: string; - uri: string; -}; +import { z } from "zod"; +import DisputeDetailsSchema, { AliasSchema, AnswerSchema, AttachmentSchema } from "./disputeDetailsSchema"; + +export { QuestionType } from "./disputeDetailsSchema"; +export type DisputeDetails = z.infer; +export type Answer = z.infer; +export type Alias = z.infer; +export type Attachment = z.infer; diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 608353d58..98006ac8f 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -17,18 +17,23 @@ }, "scripts": { "build": "your-build-script", - "test-data-mappings": "mocha -r ts-node/register/transpile-only dataMappings/test.ts" + "test": "vitest", + "test:ui": "vitest --ui", + "test:run": "vitest run" }, "devDependencies": { "@types/chai": "^4.3.11", "@types/mocha": "^10.0.6", + "@vitest/ui": "^1.1.3", "chai": "^4.3.8", "dotenv": "^16.3.1", "mocha": "^10.2.0", "ts-node": "^10.9.2", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "vitest": "^1.1.3" }, "dependencies": { - "@reality.eth/reality-eth-lib": "^3.2.30" + "@reality.eth/reality-eth-lib": "^3.2.30", + "zod": "^3.22.4" } } diff --git a/kleros-sdk/dataMappings/test.ts b/kleros-sdk/test/dataMappings.test.ts similarity index 92% rename from kleros-sdk/dataMappings/test.ts rename to kleros-sdk/test/dataMappings.test.ts index 65a67fb64..6d2c8208f 100644 --- a/kleros-sdk/dataMappings/test.ts +++ b/kleros-sdk/test/dataMappings.test.ts @@ -1,10 +1,10 @@ -import { expect } from "chai"; -import { populateTemplate } from "./utils/populateTemplate"; -import { jsonAction } from "./actions/jsonAction"; -import { subgraphAction } from "./actions/subgraphAction"; -import { callAction } from "./actions/callAction"; -import { eventAction } from "./actions/eventAction"; -import { fetchIpfsJsonAction } from "./actions/fetchIpfsJsonAction"; +import { describe, expect, it } from "vitest"; +import { populateTemplate } from "dataMappings/utils/populateTemplate"; +import { jsonAction } from "dataMappings/actions/jsonAction"; +import { subgraphAction } from "dataMappings/actions/subgraphAction"; +import { callAction } from "dataMappings/actions/callAction"; +import { eventAction } from "dataMappings/actions/eventAction"; +import { fetchIpfsJsonAction } from "dataMappings/actions/fetchIpfsJsonAction"; const exampleObject = { evidence: { diff --git a/kleros-sdk/test/disputeDetailsSchema.test.ts b/kleros-sdk/test/disputeDetailsSchema.test.ts new file mode 100644 index 000000000..873dc0771 --- /dev/null +++ b/kleros-sdk/test/disputeDetailsSchema.test.ts @@ -0,0 +1,97 @@ +import { describe, expect, it } from "vitest"; +import { ethAddressSchema, ensNameSchema, ethAddressOrEnsNameSchema } from "dataMappings/utils/disputeDetailsSchema"; + +describe("Dispute Details Schema", () => { + it("snapshot", () => { + expect({ foo: "bar" }).toMatchSnapshot(); + }); + + const validAddresses = [ + "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", // checksummed + "0xD8DA6BF26964AF9D7EED9E03E53415D37AA96045", // uppercase + "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", // lowercase + ]; + + const invalidAddressesNoEns = [ + "", + "yo", + "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA960", + "d8dA6BF26964aF9D7eEd9e03E53415D37aA960", + "xd8dA6BF26964aF9D7eEd9e03E53415D37aA960", + "0xd8Wa6bf26964af9d7eed9e03e53415d37aa96045", + ]; + + const validEnsNames = ["vitalik.eth", "vitalik.eth.eth"]; + + const invalidEnsNamesNoAddress = ["", "vitalik", "vitalik.ether", "vitalik.sol", "eth.vitalik"]; + + describe("ethAddressSchema", () => { + it("Should accept a valid address", async () => { + validAddresses.forEach((address) => { + expect(() => ethAddressSchema.parse(address)).not.toThrow(); + }); + }); + + it("Should refuse an invalid address", async () => { + expect(() => ethAddressSchema.parse(undefined)).toThrowError("invalid_type"); + + const invalidAddress = "Provided address is invalid."; + [...invalidAddressesNoEns, ...validEnsNames].forEach((address) => { + expect(() => ethAddressSchema.parse(address)).toThrowError(invalidAddress); + }); + }); + }); + + describe("ensNameSchema", () => { + it("Should accept a valid ENS name", async () => { + validEnsNames.forEach((ensName) => { + expect(() => ensNameSchema.parse(ensName)).not.toThrow(); + }); + }); + + it("Should refuse an invalid ENS name", async () => { + expect(() => ensNameSchema.parse(undefined)).toThrowError("invalid_type"); + + const invalidEns = "Provided ENS name is invalid."; + [...invalidEnsNamesNoAddress, ...validAddresses].forEach((ensName) => { + expect(() => ensNameSchema.parse(ensName)).toThrowError(invalidEns); + }); + }); + }); + + describe("ethAddressOrEnsNameSchema", () => { + it("Should accept a valid address", async () => { + validAddresses.forEach((address) => { + expect(() => ethAddressOrEnsNameSchema.parse(address)).not.toThrow(); + }); + }); + + it("Should accept a valid ENS name", async () => { + validEnsNames.forEach((ensName) => { + expect(() => ethAddressOrEnsNameSchema.parse(ensName)).not.toThrow(); + }); + }); + + it("Should refuse an invalid address", async () => { + expect(() => ethAddressOrEnsNameSchema.parse(undefined)).toThrowError("invalid_type"); + + invalidAddressesNoEns.forEach((address) => { + // FIXME: the errorMap is not working, expecting "Provided address or ENS name is invalid."); + expect(() => ethAddressOrEnsNameSchema.parse(address)).toThrowError("custom"); + }); + }); + + it("Should refuse an invalid ENS name", async () => { + expect(() => ethAddressOrEnsNameSchema.parse(undefined)).toThrowError("invalid_type"); + + invalidEnsNamesNoAddress.forEach((ensName) => { + // FIXME: the errorMap is not working, expecting "Provided address or ENS name is invalid."); + expect(() => ethAddressOrEnsNameSchema.parse(ensName)).toThrowError("custom"); + }); + }); + }); + + describe("disputeDetailsSchema", () => { + // TODO: add tests + }); +}); diff --git a/kleros-sdk/tsconfig.json b/kleros-sdk/tsconfig.json index 74e37a08f..54d1b65e7 100644 --- a/kleros-sdk/tsconfig.json +++ b/kleros-sdk/tsconfig.json @@ -4,7 +4,6 @@ "baseUrl": ".", "target": "ES6", "module": "CommonJS", - "rootDir": "./", "outDir": "build/dist", "allowJs": true, "forceConsistentCasingInFileNames": true, @@ -15,6 +14,10 @@ "removeComments": true, "isolatedModules": true }, + "include": [ + ".", + "test" + ], "exclude": [ "node_modules", "build", diff --git a/kleros-sdk/vite.config.ts b/kleros-sdk/vite.config.ts new file mode 100644 index 000000000..36bfcfdc4 --- /dev/null +++ b/kleros-sdk/vite.config.ts @@ -0,0 +1,12 @@ +/// + +// Configure Vitest (https://vitest.dev/config/) + +import { defineConfig } from "vite"; + +export default defineConfig({ + test: { + /* for example, use global to avoid globals imports (describe, test, expect): */ + // globals: true, + }, +}); diff --git a/web/src/context/NewDisputeContext.tsx b/web/src/context/NewDisputeContext.tsx index 6e992ed4b..7060cbe0a 100644 --- a/web/src/context/NewDisputeContext.tsx +++ b/web/src/context/NewDisputeContext.tsx @@ -32,6 +32,8 @@ export interface IDisputeTemplate { question: string; specification?: string; title: string; + // attachment: Attachment; + // type: string; } interface IDisputeData extends IDisputeTemplate { diff --git a/yarn.lock b/yarn.lock index 1b0fe1a9f..4a760fa96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3593,6 +3593,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/aix-ppc64@npm:0.19.11" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/android-arm64@npm:0.16.17" @@ -3600,6 +3607,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/android-arm64@npm:0.19.11" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/android-arm@npm:0.16.17" @@ -3607,6 +3621,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/android-arm@npm:0.19.11" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/android-x64@npm:0.16.17" @@ -3614,6 +3635,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/android-x64@npm:0.19.11" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/darwin-arm64@npm:0.16.17" @@ -3621,6 +3649,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/darwin-arm64@npm:0.19.11" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/darwin-x64@npm:0.16.17" @@ -3628,6 +3663,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/darwin-x64@npm:0.19.11" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/freebsd-arm64@npm:0.16.17" @@ -3635,6 +3677,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/freebsd-arm64@npm:0.19.11" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/freebsd-x64@npm:0.16.17" @@ -3642,6 +3691,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/freebsd-x64@npm:0.19.11" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-arm64@npm:0.16.17" @@ -3649,6 +3705,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-arm64@npm:0.19.11" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-arm@npm:0.16.17" @@ -3656,6 +3719,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-arm@npm:0.19.11" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-ia32@npm:0.16.17" @@ -3663,6 +3733,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-ia32@npm:0.19.11" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-loong64@npm:0.16.17" @@ -3670,6 +3747,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-loong64@npm:0.19.11" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-mips64el@npm:0.16.17" @@ -3677,6 +3761,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-mips64el@npm:0.19.11" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-ppc64@npm:0.16.17" @@ -3684,6 +3775,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-ppc64@npm:0.19.11" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-riscv64@npm:0.16.17" @@ -3691,6 +3789,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-riscv64@npm:0.19.11" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-s390x@npm:0.16.17" @@ -3698,6 +3803,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-s390x@npm:0.19.11" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/linux-x64@npm:0.16.17" @@ -3705,6 +3817,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/linux-x64@npm:0.19.11" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/netbsd-x64@npm:0.16.17" @@ -3712,6 +3831,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/netbsd-x64@npm:0.19.11" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/openbsd-x64@npm:0.16.17" @@ -3719,6 +3845,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/openbsd-x64@npm:0.19.11" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/sunos-x64@npm:0.16.17" @@ -3726,6 +3859,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/sunos-x64@npm:0.19.11" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/win32-arm64@npm:0.16.17" @@ -3733,6 +3873,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/win32-arm64@npm:0.19.11" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/win32-ia32@npm:0.16.17" @@ -3740,6 +3887,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/win32-ia32@npm:0.19.11" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.16.17": version: 0.16.17 resolution: "@esbuild/win32-x64@npm:0.16.17" @@ -3747,6 +3901,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.19.11": + version: 0.19.11 + resolution: "@esbuild/win32-x64@npm:0.19.11" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -5261,6 +5422,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": ^0.27.8 + checksum: 910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 + languageName: node + linkType: hard + "@jest/source-map@npm:^27.5.1": version: 27.5.1 resolution: "@jest/source-map@npm:27.5.1" @@ -5407,7 +5577,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10": +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.15": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 @@ -5448,11 +5618,14 @@ __metadata: "@reality.eth/reality-eth-lib": ^3.2.30 "@types/chai": ^4.3.11 "@types/mocha": ^10.0.6 + "@vitest/ui": ^1.1.3 chai: ^4.3.8 dotenv: ^16.3.1 mocha: ^10.2.0 ts-node: ^10.9.2 typescript: ^5.3.3 + vitest: ^1.1.3 + zod: ^3.22.4 languageName: unknown linkType: soft @@ -7896,6 +8069,13 @@ __metadata: languageName: node linkType: hard +"@polka/url@npm:^1.0.0-next.24": + version: 1.0.0-next.24 + resolution: "@polka/url@npm:1.0.0-next.24" + checksum: 00baec4458ac86ca27edf7ce807ccfad97cd1d4b67bdedaf3401a9e755757588f3331e891290d1deea52d88df2bf2387caf8d94a6835b614d5b37b638a688273 + languageName: node + linkType: hard + "@prettier/sync@npm:^0.3.0": version: 0.3.0 resolution: "@prettier/sync@npm:0.3.0" @@ -8082,6 +8262,97 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.9.4" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-android-arm64@npm:4.9.4" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-darwin-arm64@npm:4.9.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-darwin-x64@npm:4.9.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.9.4" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.9.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.9.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.9.4" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.9.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.9.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.9.4" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.9.4" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.9.4" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rushstack/eslint-patch@npm:^1.1.0": version: 1.3.2 resolution: "@rushstack/eslint-patch@npm:1.3.2" @@ -8397,6 +8668,13 @@ __metadata: languageName: node linkType: hard +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1 + languageName: node + linkType: hard + "@sindresorhus/is@npm:^2.0.0": version: 2.1.1 resolution: "@sindresorhus/is@npm:2.1.1" @@ -9536,6 +9814,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a + languageName: node + linkType: hard + "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": version: 4.17.35 resolution: "@types/express-serve-static-core@npm:4.17.35" @@ -10393,6 +10678,77 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:1.1.3": + version: 1.1.3 + resolution: "@vitest/expect@npm:1.1.3" + dependencies: + "@vitest/spy": 1.1.3 + "@vitest/utils": 1.1.3 + chai: ^4.3.10 + checksum: 971492347e91af81a8c309bc6dff4369afe0f533ac73a73e4a568111ea0fa7d6dc45b69b209490ad588578fd905773e6bd4fcbe8d517ac7aeb57efb1e9c59083 + languageName: node + linkType: hard + +"@vitest/runner@npm:1.1.3": + version: 1.1.3 + resolution: "@vitest/runner@npm:1.1.3" + dependencies: + "@vitest/utils": 1.1.3 + p-limit: ^5.0.0 + pathe: ^1.1.1 + checksum: a2875fab07c307aee5c7b3e4e821c2f36a561d86412edeb69f47daed10fa26fb5ba222841cf093372bce95a7384ff3a9302d69b3e594468aa565cbd5b2fe4316 + languageName: node + linkType: hard + +"@vitest/snapshot@npm:1.1.3": + version: 1.1.3 + resolution: "@vitest/snapshot@npm:1.1.3" + dependencies: + magic-string: ^0.30.5 + pathe: ^1.1.1 + pretty-format: ^29.7.0 + checksum: 731af9f71f57c0a4830a2e8c6c9c354fe80b7ad00d38cd19354aaa61c1e0353a3d09b427f2a69e81b5bccce4576e2c1e8a538bce3dfbbdc080126d23ee2edb14 + languageName: node + linkType: hard + +"@vitest/spy@npm:1.1.3": + version: 1.1.3 + resolution: "@vitest/spy@npm:1.1.3" + dependencies: + tinyspy: ^2.2.0 + checksum: 592a9a2bad31c2655fdc6ae87f44b36bc25aafb7efd3a750228409ab4e98bff31888d806c29c6e7bfc029a5ee225f7dc998565115b4fa452429eaa579cc0eec7 + languageName: node + linkType: hard + +"@vitest/ui@npm:^1.1.3": + version: 1.1.3 + resolution: "@vitest/ui@npm:1.1.3" + dependencies: + "@vitest/utils": 1.1.3 + fast-glob: ^3.3.2 + fflate: ^0.8.1 + flatted: ^3.2.9 + pathe: ^1.1.1 + picocolors: ^1.0.0 + sirv: ^2.0.4 + peerDependencies: + vitest: ^1.0.0 + checksum: ef31bef05dca11ec0e435a8499a00ecfb021f6ec9062684a7229744f4620a175124208562944387fa5c04b8c7aa64b6633bb212dfb24472c80e43da84b27310e + languageName: node + linkType: hard + +"@vitest/utils@npm:1.1.3": + version: 1.1.3 + resolution: "@vitest/utils@npm:1.1.3" + dependencies: + diff-sequences: ^29.6.3 + estree-walker: ^3.0.3 + loupe: ^2.3.7 + pretty-format: ^29.7.0 + checksum: d345b8c862c51b734d9fe53397a125485797cae2a4c1630cea1235f3f0987df479c84ac958f5250e77892afdc12f6d863628d619fc1bb5e34c05c3fa8a86d289 + languageName: node + linkType: hard + "@vue/compiler-sfc@npm:2.7.14": version: 2.7.14 resolution: "@vue/compiler-sfc@npm:2.7.14" @@ -11461,7 +11817,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.0.2": +"acorn-walk@npm:^8.0.2, acorn-walk@npm:^8.3.1": version: 8.3.2 resolution: "acorn-walk@npm:8.3.2" checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 @@ -13293,7 +13649,7 @@ __metadata: languageName: node linkType: hard -"cac@npm:^6.7.12": +"cac@npm:^6.7.12, cac@npm:^6.7.14": version: 6.7.14 resolution: "cac@npm:6.7.14" checksum: 45a2496a9443abbe7f52a49b22fbe51b1905eff46e03fd5e6c98e3f85077be3f8949685a1849b1a9cd2bc3e5567dfebcf64f01ce01847baf918f1b37c839791a @@ -15772,6 +16128,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: f4914158e1f2276343d98ff5b31fc004e7304f5470bf0f1adb2ac6955d85a531a6458d33e87667f98f6ae52ebd3891bb47d420bb48a5bd8b7a27ee25b20e33aa + languageName: node + linkType: hard + "diff@npm:3.5.0": version: 3.5.0 resolution: "diff@npm:3.5.0" @@ -16647,6 +17010,86 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.19.3": + version: 0.19.11 + resolution: "esbuild@npm:0.19.11" + dependencies: + "@esbuild/aix-ppc64": 0.19.11 + "@esbuild/android-arm": 0.19.11 + "@esbuild/android-arm64": 0.19.11 + "@esbuild/android-x64": 0.19.11 + "@esbuild/darwin-arm64": 0.19.11 + "@esbuild/darwin-x64": 0.19.11 + "@esbuild/freebsd-arm64": 0.19.11 + "@esbuild/freebsd-x64": 0.19.11 + "@esbuild/linux-arm": 0.19.11 + "@esbuild/linux-arm64": 0.19.11 + "@esbuild/linux-ia32": 0.19.11 + "@esbuild/linux-loong64": 0.19.11 + "@esbuild/linux-mips64el": 0.19.11 + "@esbuild/linux-ppc64": 0.19.11 + "@esbuild/linux-riscv64": 0.19.11 + "@esbuild/linux-s390x": 0.19.11 + "@esbuild/linux-x64": 0.19.11 + "@esbuild/netbsd-x64": 0.19.11 + "@esbuild/openbsd-x64": 0.19.11 + "@esbuild/sunos-x64": 0.19.11 + "@esbuild/win32-arm64": 0.19.11 + "@esbuild/win32-ia32": 0.19.11 + "@esbuild/win32-x64": 0.19.11 + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: ae949a796d1d06b55275ae7491ce137857468f69a93d8cc9c0943d2a701ac54e14dbb250a2ba56f2ad98283669578f1ec3bd85a4681910a5ff29a2470c3bd62c + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -17336,6 +17779,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": ^1.0.0 + checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -17707,6 +18159,23 @@ __metadata: languageName: node linkType: hard +"execa@npm:^8.0.1": + version: 8.0.1 + resolution: "execa@npm:8.0.1" + dependencies: + cross-spawn: ^7.0.3 + get-stream: ^8.0.1 + human-signals: ^5.0.0 + is-stream: ^3.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^5.1.0 + onetime: ^6.0.0 + signal-exit: ^4.1.0 + strip-final-newline: ^3.0.0 + checksum: cac1bf86589d1d9b73bdc5dda65c52012d1a9619c44c526891956745f7b366ca2603d29fe3f7460bacc2b48c6eab5d6a4f7afe0534b31473d3708d1265545e1f + languageName: node + linkType: hard + "exenv@npm:^1.2.0": version: 1.2.2 resolution: "exenv@npm:1.2.2" @@ -17882,6 +18351,19 @@ __metadata: languageName: node linkType: hard +"fast-glob@npm:^3.3.2": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" + dependencies: + "@nodelib/fs.stat": ^2.0.2 + "@nodelib/fs.walk": ^1.2.3 + glob-parent: ^5.1.2 + merge2: ^1.3.0 + micromatch: ^4.0.4 + checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 + languageName: node + linkType: hard + "fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": version: 2.1.0 resolution: "fast-json-stable-stringify@npm:2.1.0" @@ -18032,6 +18514,13 @@ __metadata: languageName: node linkType: hard +"fflate@npm:^0.8.1": + version: 0.8.1 + resolution: "fflate@npm:0.8.1" + checksum: 7207e2d333243724485d2488095256b776184bd4545aa9967b655feaee5dc18e9525ed9b6d75f94cfd71d98fb285336f4902641683472f1d0c19a99137084cec + languageName: node + linkType: hard + "figlet@npm:^1.2.3": version: 1.6.0 resolution: "figlet@npm:1.6.0" @@ -18238,6 +18727,13 @@ __metadata: languageName: node linkType: hard +"flatted@npm:^3.2.9": + version: 3.2.9 + resolution: "flatted@npm:3.2.9" + checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 + languageName: node + linkType: hard + "fmix@npm:^0.1.0": version: 0.1.0 resolution: "fmix@npm:0.1.0" @@ -18538,6 +19034,16 @@ __metadata: languageName: node linkType: hard +"fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + "fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin": version: 2.3.2 resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" @@ -18556,6 +19062,15 @@ __metadata: languageName: node linkType: hard +"fsevents@patch:fsevents@~2.3.3#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + "function-bind@npm:^1.1.1": version: 1.1.1 resolution: "function-bind@npm:1.1.1" @@ -18741,6 +19256,13 @@ __metadata: languageName: node linkType: hard +"get-stream@npm:^8.0.1": + version: 8.0.1 + resolution: "get-stream@npm:8.0.1" + checksum: 01e3d3cf29e1393f05f44d2f00445c5f9ec3d1c49e8179b31795484b9c117f4c695e5e07b88b50785d5c8248a788c85d9913a79266fc77e3ef11f78f10f1b974 + languageName: node + linkType: hard + "get-symbol-description@npm:^1.0.0": version: 1.0.0 resolution: "get-symbol-description@npm:1.0.0" @@ -20118,6 +20640,13 @@ __metadata: languageName: node linkType: hard +"human-signals@npm:^5.0.0": + version: 5.0.0 + resolution: "human-signals@npm:5.0.0" + checksum: 6504560d5ed91444f16bea3bd9dfc66110a339442084e56c3e7fa7bbdf3f406426d6563d662bdce67064b165eac31eeabfc0857ed170aaa612cf14ec9f9a464c + languageName: node + linkType: hard + "humanize-ms@npm:^1.2.1": version: 1.2.1 resolution: "humanize-ms@npm:1.2.1" @@ -23447,6 +23976,16 @@ __metadata: languageName: node linkType: hard +"local-pkg@npm:^0.5.0": + version: 0.5.0 + resolution: "local-pkg@npm:0.5.0" + dependencies: + mlly: ^1.4.2 + pkg-types: ^1.0.3 + checksum: b0a6931e588ad4f7bf4ab49faacf49e07fc4d05030f895aa055d46727a15b99300d39491cf2c3e3f05284aec65565fb760debb74c32e64109f4a101f9300d81a + languageName: node + linkType: hard + "locate-path@npm:^2.0.0": version: 2.0.0 resolution: "locate-path@npm:2.0.0" @@ -23810,7 +24349,7 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.6": +"loupe@npm:^2.3.6, loupe@npm:^2.3.7": version: 2.3.7 resolution: "loupe@npm:2.3.7" dependencies: @@ -23909,6 +24448,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.5": + version: 0.30.5 + resolution: "magic-string@npm:0.30.5" + dependencies: + "@jridgewell/sourcemap-codec": ^1.4.15 + checksum: da10fecff0c0a7d3faf756913ce62bd6d5e7b0402be48c3b27bfd651b90e29677e279069a63b764bcdc1b8ecdcdb898f29a5c5ec510f2323e8d62ee057a6eb18 + languageName: node + linkType: hard + "make-dir@npm:^3.0.0, make-dir@npm:^3.0.2, make-dir@npm:^3.1.0": version: 3.1.0 resolution: "make-dir@npm:3.1.0" @@ -24970,6 +25518,13 @@ __metadata: languageName: node linkType: hard +"mrmime@npm:^2.0.0": + version: 2.0.0 + resolution: "mrmime@npm:2.0.0" + checksum: f6fe11ec667c3d96f1ce5fd41184ed491d5f0a5f4045e82446a471ccda5f84c7f7610dff61d378b73d964f73a320bd7f89788f9e6b9403e32cc4be28ba99f569 + languageName: node + linkType: hard + "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -25195,6 +25750,15 @@ __metadata: languageName: node linkType: hard +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 + languageName: node + linkType: hard + "nanoid@npm:^4.0.0": version: 4.0.2 resolution: "nanoid@npm:4.0.2" @@ -26137,6 +26701,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^5.0.0": + version: 5.0.0 + resolution: "p-limit@npm:5.0.0" + dependencies: + yocto-queue: ^1.0.0 + checksum: 87bf5837dee6942f0dbeff318436179931d9a97848d1b07dbd86140a477a5d2e6b90d9701b210b4e21fe7beaea2979dfde366e4f576fa644a59bd4d6a6371da7 + languageName: node + linkType: hard + "p-locate@npm:^2.0.0": version: 2.0.0 resolution: "p-locate@npm:2.0.0" @@ -27619,6 +28192,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.4.32": + version: 8.4.33 + resolution: "postcss@npm:8.4.33" + dependencies: + nanoid: ^3.3.7 + picocolors: ^1.0.0 + source-map-js: ^1.0.2 + checksum: 6f98b2af4b76632a3de20c4f47bf0e984a1ce1a531cf11adcb0b1d63a6cbda0aae4165e578b66c32ca4879038e3eaad386a6be725a8fb4429c78e3c1ab858fe9 + languageName: node + linkType: hard + "posthtml-parser@npm:^0.10.1": version: 0.10.2 resolution: "posthtml-parser@npm:0.10.2" @@ -27757,6 +28341,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": ^29.6.3 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: 032c1602383e71e9c0c02a01bbd25d6759d60e9c7cf21937dde8357aa753da348fcec5def5d1002c9678a8524d5fe099ad98861286550ef44de8808cc61e43b6 + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -29486,6 +30081,60 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.2.0": + version: 4.9.4 + resolution: "rollup@npm:4.9.4" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.9.4 + "@rollup/rollup-android-arm64": 4.9.4 + "@rollup/rollup-darwin-arm64": 4.9.4 + "@rollup/rollup-darwin-x64": 4.9.4 + "@rollup/rollup-linux-arm-gnueabihf": 4.9.4 + "@rollup/rollup-linux-arm64-gnu": 4.9.4 + "@rollup/rollup-linux-arm64-musl": 4.9.4 + "@rollup/rollup-linux-riscv64-gnu": 4.9.4 + "@rollup/rollup-linux-x64-gnu": 4.9.4 + "@rollup/rollup-linux-x64-musl": 4.9.4 + "@rollup/rollup-win32-arm64-msvc": 4.9.4 + "@rollup/rollup-win32-ia32-msvc": 4.9.4 + "@rollup/rollup-win32-x64-msvc": 4.9.4 + "@types/estree": 1.0.5 + fsevents: ~2.3.2 + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 134b1fd8886a1dc86b2cadada979174e736a39aec12d069261fe8b799ad0c4aa3213188ea49adeee155669315016617260e43eea754436c50121aa359899da4d + languageName: node + linkType: hard + "rpc-websockets@npm:^7.5.1": version: 7.5.1 resolution: "rpc-websockets@npm:7.5.1" @@ -30175,6 +30824,13 @@ __metadata: languageName: node linkType: hard +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 8aa5a98640ca09fe00d74416eca97551b3e42991614a3d1b824b115fc1401543650914f651ab1311518177e4d297e80b953f4cd4cd7ea1eabe824e8f2091de01 + languageName: node + linkType: hard + "signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -30189,6 +30845,13 @@ __metadata: languageName: node linkType: hard +"signal-exit@npm:^4.1.0": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 + languageName: node + linkType: hard + "signedsource@npm:^1.0.0": version: 1.0.0 resolution: "signedsource@npm:1.0.0" @@ -30223,6 +30886,17 @@ __metadata: languageName: node linkType: hard +"sirv@npm:^2.0.4": + version: 2.0.4 + resolution: "sirv@npm:2.0.4" + dependencies: + "@polka/url": ^1.0.0-next.24 + mrmime: ^2.0.0 + totalist: ^3.0.0 + checksum: 6853384a51d6ee9377dd657e2b257e0e98b29abbfbfa6333e105197f0f100c8c56a4520b47028b04ab1833cf2312526206f38fcd4f891c6df453f40da1a15a57 + languageName: node + linkType: hard + "sisteransi@npm:^1.0.5": version: 1.0.5 resolution: "sisteransi@npm:1.0.5" @@ -30776,6 +31450,13 @@ __metadata: languageName: node linkType: hard +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 2d4dc4e64e2db796de4a3c856d5943daccdfa3dd092e452a1ce059c81e9a9c29e0b9badba91b43ef0d5ff5c04ee62feb3bcc559a804e16faf447bac2d883aa99 + languageName: node + linkType: hard + "stackframe@npm:^1.3.4": version: 1.3.4 resolution: "stackframe@npm:1.3.4" @@ -30841,6 +31522,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^3.5.0": + version: 3.7.0 + resolution: "std-env@npm:3.7.0" + checksum: 4f489d13ff2ab838c9acd4ed6b786b51aa52ecacdfeaefe9275fcb220ff2ac80c6e95674723508fd29850a694569563a8caaaea738eb82ca16429b3a0b50e510 + languageName: node + linkType: hard + "stdin-discarder@npm:^0.1.0": version: 0.1.0 resolution: "stdin-discarder@npm:0.1.0" @@ -31236,6 +31924,15 @@ __metadata: languageName: node linkType: hard +"strip-literal@npm:^1.3.0": + version: 1.3.0 + resolution: "strip-literal@npm:1.3.0" + dependencies: + acorn: ^8.10.0 + checksum: f5fa7e289df8ebe82e90091fd393974faf8871be087ca50114327506519323cf15f2f8fee6ebe68b5e58bfc795269cae8bdc7cb5a83e27b02b3fe953f37b0a89 + languageName: node + linkType: hard + "strnum@npm:^1.0.5": version: 1.0.5 resolution: "strnum@npm:1.0.5" @@ -31939,6 +32636,27 @@ __metadata: languageName: node linkType: hard +"tinybench@npm:^2.5.1": + version: 2.5.1 + resolution: "tinybench@npm:2.5.1" + checksum: 6d98526c00b68b50ab0a37590b3cc6713b96fee7dd6756a2a77bab071ed1b4a4fc54e7b11e28b35ec2f761c6a806c2befa95f10acf2fee111c49327b6fc3386f + languageName: node + linkType: hard + +"tinypool@npm:^0.8.1": + version: 0.8.1 + resolution: "tinypool@npm:0.8.1" + checksum: e1162629b32a694edd92323fe7cc57379723f36b03f37e3f9442cb8fd3a99785b2b9416ef586d2f4cec8624f356b38558c2cfd272eb265a30841371d3d67d37a + languageName: node + linkType: hard + +"tinyspy@npm:^2.2.0": + version: 2.2.0 + resolution: "tinyspy@npm:2.2.0" + checksum: 36431acaa648054406147a92b9bde494b7548d0f9f3ffbcc02113c25a6e59f3310cbe924353d7f4c51436299150bec2dbb3dc595748f58c4ddffea22d5baaadb + languageName: node + linkType: hard + "title-case@npm:^3.0.3": version: 3.0.3 resolution: "title-case@npm:3.0.3" @@ -32026,6 +32744,13 @@ __metadata: languageName: node linkType: hard +"totalist@npm:^3.0.0": + version: 3.0.1 + resolution: "totalist@npm:3.0.1" + checksum: 5132d562cf88ff93fd710770a92f31dbe67cc19b5c6ccae2efc0da327f0954d211bbfd9456389655d726c624f284b4a23112f56d1da931ca7cfabbe1f45e778a + languageName: node + linkType: hard + "tough-cookie@npm:^2.3.3, tough-cookie@npm:~2.5.0": version: 2.5.0 resolution: "tough-cookie@npm:2.5.0" @@ -33278,6 +34003,112 @@ __metadata: languageName: node linkType: hard +"vite-node@npm:1.1.3": + version: 1.1.3 + resolution: "vite-node@npm:1.1.3" + dependencies: + cac: ^6.7.14 + debug: ^4.3.4 + pathe: ^1.1.1 + picocolors: ^1.0.0 + vite: ^5.0.0 + bin: + vite-node: vite-node.mjs + checksum: 077691a293fb4151267d7bb4ed322e3d4ce427bd06c02f7d08d7411f9fc96f98ada1aa0da172c02648b44680ba16c57a40b1aa9b98231f68ea5862a00dcdb1dd + languageName: node + linkType: hard + +"vite@npm:^5.0.0": + version: 5.0.11 + resolution: "vite@npm:5.0.11" + dependencies: + esbuild: ^0.19.3 + fsevents: ~2.3.3 + postcss: ^8.4.32 + rollup: ^4.2.0 + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 262e41f25ce0cc5fc3c2065b1796f64ec115d3ac2d9625dbfb36d6628ba10e63684ef5515bb2ff1aa8e34c6f89e9c10e8211cb88f6c7f0da6869362851345437 + languageName: node + linkType: hard + +"vitest@npm:^1.1.3": + version: 1.1.3 + resolution: "vitest@npm:1.1.3" + dependencies: + "@vitest/expect": 1.1.3 + "@vitest/runner": 1.1.3 + "@vitest/snapshot": 1.1.3 + "@vitest/spy": 1.1.3 + "@vitest/utils": 1.1.3 + acorn-walk: ^8.3.1 + cac: ^6.7.14 + chai: ^4.3.10 + debug: ^4.3.4 + execa: ^8.0.1 + local-pkg: ^0.5.0 + magic-string: ^0.30.5 + pathe: ^1.1.1 + picocolors: ^1.0.0 + std-env: ^3.5.0 + strip-literal: ^1.3.0 + tinybench: ^2.5.1 + tinypool: ^0.8.1 + vite: ^5.0.0 + vite-node: 1.1.3 + why-is-node-running: ^2.2.2 + peerDependencies: + "@edge-runtime/vm": "*" + "@types/node": ^18.0.0 || >=20.0.0 + "@vitest/browser": ^1.0.0 + "@vitest/ui": ^1.0.0 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 35087400a0e2b2f0f1f451d0da41abafd8c55112e143a2643286bf0d3d4567b057b40dc391c4b2a05a947edc48d981a6b8c961dc32c6642d84cd8d717bd168bc + languageName: node + linkType: hard + "vue-hot-reload-api@npm:^2.3.0": version: 2.3.4 resolution: "vue-hot-reload-api@npm:2.3.4" @@ -33896,6 +34727,18 @@ __metadata: languageName: node linkType: hard +"why-is-node-running@npm:^2.2.2": + version: 2.2.2 + resolution: "why-is-node-running@npm:2.2.2" + dependencies: + siginfo: ^2.0.0 + stackback: 0.0.2 + bin: + why-is-node-running: cli.js + checksum: 50820428f6a82dfc3cbce661570bcae9b658723217359b6037b67e495255409b4c8bc7931745f5c175df71210450464517cab32b2f7458ac9c40b4925065200a + languageName: node + linkType: hard + "wide-align@npm:1.1.3": version: 1.1.3 resolution: "wide-align@npm:1.1.3" @@ -34629,6 +35472,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:^3.22.4": + version: 3.22.4 + resolution: "zod@npm:3.22.4" + checksum: 80bfd7f8039b24fddeb0718a2ec7c02aa9856e4838d6aa4864335a047b6b37a3273b191ef335bf0b2002e5c514ef261ffcda5a589fb084a48c336ffc4cdbab7f + languageName: node + linkType: hard + "zustand@npm:^4.3.1": version: 4.3.8 resolution: "zustand@npm:4.3.8" From 14d36d22197ad338d2bde9b9f2553bcbec1d435a Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 12 Jan 2024 03:22:33 +0000 Subject: [PATCH 34/37] refactor(sdk): moved things around into a new src/ folder --- .../dataMappings/utils/actionTypeDetectors.ts | 27 ------ kleros-sdk/dataMappings/utils/isHexAddress.ts | 1 - kleros-sdk/dataMappings/utils/isHexId.ts | 1 - kleros-sdk/package.json | 4 + .../utils/maxByteSize.ts => src/consts.ts} | 0 .../dataMappings/actions/callAction.ts | 6 +- .../dataMappings/actions/eventAction.ts | 6 +- .../actions/fetchIpfsJsonAction.ts | 6 +- .../dataMappings/actions/jsonAction.ts | 2 +- .../dataMappings/actions/subgraphAction.ts | 2 +- kleros-sdk/src/dataMappings/dataMapping.json | 75 +++++++++++++++ kleros-sdk/src/dataMappings/dataMapping.ts | 92 +++++++++++++++++++ kleros-sdk/src/dataMappings/decoder.ts | 55 +++++++++++ kleros-sdk/src/dataMappings/disputeDetails.ts | 39 ++++++++ .../{ => src}/dataMappings/executeActions.ts | 43 +++------ .../dataMappings/retrieveRealityData.ts | 0 .../utils/DisputeDetailsValidator.ts} | 8 +- .../utils/actionTypeValidators.ts | 51 ++++++++++ .../dataMappings/utils/actionTypes.ts | 0 .../dataMappings/utils/createResultObject.ts | 1 + .../utils/disputeDetailsSchema.ts | 66 +++++++++++++ .../dataMappings/utils/disputeDetailsTypes.ts | 0 .../dataMappings/utils/populateTemplate.ts | 4 +- .../utils/replacePlaceholdersWithValues.ts | 1 + .../utils/configureSDK.ts => src/sdk.ts} | 0 kleros-sdk/test/dataMappings.test.ts | 17 ++-- kleros-sdk/test/disputeDetailsSchema.test.ts | 8 +- kleros-sdk/tsconfig.json | 13 ++- kleros-sdk/vite.config.ts | 12 --- web/src/components/DisputeCard/index.tsx | 4 +- .../DisputePreview/DisputeContext.tsx | 2 +- .../Cases/CaseDetails/Overview/index.tsx | 8 +- web/src/pages/DisputeTemplateView.tsx | 8 +- 33 files changed, 455 insertions(+), 107 deletions(-) delete mode 100644 kleros-sdk/dataMappings/utils/actionTypeDetectors.ts delete mode 100644 kleros-sdk/dataMappings/utils/isHexAddress.ts delete mode 100644 kleros-sdk/dataMappings/utils/isHexId.ts rename kleros-sdk/{dataMappings/utils/maxByteSize.ts => src/consts.ts} (100%) rename kleros-sdk/{ => src}/dataMappings/actions/callAction.ts (71%) rename kleros-sdk/{ => src}/dataMappings/actions/eventAction.ts (78%) rename kleros-sdk/{ => src}/dataMappings/actions/fetchIpfsJsonAction.ts (82%) rename kleros-sdk/{ => src}/dataMappings/actions/jsonAction.ts (72%) rename kleros-sdk/{ => src}/dataMappings/actions/subgraphAction.ts (87%) create mode 100644 kleros-sdk/src/dataMappings/dataMapping.json create mode 100644 kleros-sdk/src/dataMappings/dataMapping.ts create mode 100644 kleros-sdk/src/dataMappings/decoder.ts create mode 100644 kleros-sdk/src/dataMappings/disputeDetails.ts rename kleros-sdk/{ => src}/dataMappings/executeActions.ts (55%) rename kleros-sdk/{ => src}/dataMappings/retrieveRealityData.ts (100%) rename kleros-sdk/{dataMappings/utils/isValidDisputeDetails.ts => src/dataMappings/utils/DisputeDetailsValidator.ts} (81%) create mode 100644 kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts rename kleros-sdk/{ => src}/dataMappings/utils/actionTypes.ts (100%) rename kleros-sdk/{ => src}/dataMappings/utils/createResultObject.ts (93%) create mode 100644 kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts rename kleros-sdk/{ => src}/dataMappings/utils/disputeDetailsTypes.ts (100%) rename kleros-sdk/{ => src}/dataMappings/utils/populateTemplate.ts (83%) rename kleros-sdk/{ => src}/dataMappings/utils/replacePlaceholdersWithValues.ts (94%) rename kleros-sdk/{dataMappings/utils/configureSDK.ts => src/sdk.ts} (100%) delete mode 100644 kleros-sdk/vite.config.ts diff --git a/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts b/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts deleted file mode 100644 index d42b9bc34..000000000 --- a/kleros-sdk/dataMappings/utils/actionTypeDetectors.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { - SubgraphMapping, - AbiEventMapping, - AbiCallMapping, - JsonMapping, - ActionMapping, - FetchIpfsJsonMapping, - RealityMapping, -} from "./actionTypes"; - -export const isSubgraphMapping = (mapping: ActionMapping): mapping is SubgraphMapping => - (mapping as SubgraphMapping).endpoint !== undefined; - -export const isAbiEventMapping = (mapping: ActionMapping): mapping is AbiEventMapping => - (mapping as AbiEventMapping).abi !== undefined && (mapping as AbiEventMapping).eventFilter !== undefined; - -export const isAbiCallMapping = (mapping: ActionMapping): mapping is AbiCallMapping => - (mapping as AbiCallMapping).abi !== undefined && (mapping as AbiCallMapping).args !== undefined; - -export const isJsonMapping = (mapping: ActionMapping): mapping is JsonMapping => - (mapping as JsonMapping).value !== undefined; - -export const isFetchIpfsJsonMapping = (mapping: ActionMapping): mapping is FetchIpfsJsonMapping => - (mapping as FetchIpfsJsonMapping).ipfsUri !== undefined; - -export const isRealityMapping = (mapping: ActionMapping): mapping is RealityMapping => - mapping.type === "reality" && typeof (mapping as RealityMapping).realityQuestionID === "string"; diff --git a/kleros-sdk/dataMappings/utils/isHexAddress.ts b/kleros-sdk/dataMappings/utils/isHexAddress.ts deleted file mode 100644 index ffe33b251..000000000 --- a/kleros-sdk/dataMappings/utils/isHexAddress.ts +++ /dev/null @@ -1 +0,0 @@ -export const isHexAddress = (str: string): boolean => /^0x[a-fA-F0-9]{40}$/.test(str); diff --git a/kleros-sdk/dataMappings/utils/isHexId.ts b/kleros-sdk/dataMappings/utils/isHexId.ts deleted file mode 100644 index 39266f013..000000000 --- a/kleros-sdk/dataMappings/utils/isHexId.ts +++ /dev/null @@ -1 +0,0 @@ -export const isHexId = (str: string): boolean => /^0x[a-fA-F0-9]{1,64}$/.test(str); diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 98006ac8f..e7fbf8949 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -6,6 +6,10 @@ "repository": "git@github.com:kleros/kleros-v2.git", "author": "Kleros", "license": "MIT", + "alias": { + "src": "./src", + "dataMappings": "./src/dataMappings" + }, "packageManager": "yarn@3.3.1", "engines": { "node": ">=16.0.0" diff --git a/kleros-sdk/dataMappings/utils/maxByteSize.ts b/kleros-sdk/src/consts.ts similarity index 100% rename from kleros-sdk/dataMappings/utils/maxByteSize.ts rename to kleros-sdk/src/consts.ts diff --git a/kleros-sdk/dataMappings/actions/callAction.ts b/kleros-sdk/src/dataMappings/actions/callAction.ts similarity index 71% rename from kleros-sdk/dataMappings/actions/callAction.ts rename to kleros-sdk/src/dataMappings/actions/callAction.ts index e8302be54..24cb7a170 100644 --- a/kleros-sdk/dataMappings/actions/callAction.ts +++ b/kleros-sdk/src/dataMappings/actions/callAction.ts @@ -1,7 +1,7 @@ import { parseAbiItem } from "viem"; -import { AbiCallMapping } from "../utils/actionTypes"; -import { createResultObject } from "../utils/createResultObject"; -import { configureSDK, getPublicClient } from "../utils/configureSDK"; +import { AbiCallMapping } from "src/dataMappings/utils/actionTypes"; +import { createResultObject } from "src/dataMappings/utils/createResultObject"; +import { configureSDK, getPublicClient } from "src/sdk"; export const callAction = async (mapping: AbiCallMapping) => { configureSDK({ apiKey: process.env.ALCHEMY_API_KEY }); diff --git a/kleros-sdk/dataMappings/actions/eventAction.ts b/kleros-sdk/src/dataMappings/actions/eventAction.ts similarity index 78% rename from kleros-sdk/dataMappings/actions/eventAction.ts rename to kleros-sdk/src/dataMappings/actions/eventAction.ts index 452dd3c7f..02273fa79 100644 --- a/kleros-sdk/dataMappings/actions/eventAction.ts +++ b/kleros-sdk/src/dataMappings/actions/eventAction.ts @@ -1,7 +1,7 @@ import { parseAbiItem } from "viem"; -import { AbiEventMapping } from "../utils/actionTypes"; -import { createResultObject } from "../utils/createResultObject"; -import { configureSDK, getPublicClient } from "../utils/configureSDK"; +import { AbiEventMapping } from "src/dataMappings/utils/actionTypes"; +import { createResultObject } from "src/dataMappings/utils/createResultObject"; +import { configureSDK, getPublicClient } from "src/sdk"; export const eventAction = async (mapping: AbiEventMapping) => { configureSDK({ apiKey: process.env.ALCHEMY_API_KEY }); diff --git a/kleros-sdk/dataMappings/actions/fetchIpfsJsonAction.ts b/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts similarity index 82% rename from kleros-sdk/dataMappings/actions/fetchIpfsJsonAction.ts rename to kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts index 5d1933c28..37f0ae080 100644 --- a/kleros-sdk/dataMappings/actions/fetchIpfsJsonAction.ts +++ b/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts @@ -1,7 +1,7 @@ import fetch from "node-fetch"; -import { FetchIpfsJsonMapping } from "../utils/actionTypes"; -import { createResultObject } from "../utils/createResultObject"; -import { MAX_BYTE_SIZE } from "../utils/maxByteSize"; +import { FetchIpfsJsonMapping } from "src/dataMappings/utils/actionTypes"; +import { createResultObject } from "src/dataMappings/utils/createResultObject"; +import { MAX_BYTE_SIZE } from "src/consts"; export const fetchIpfsJsonAction = async (mapping: FetchIpfsJsonMapping) => { const { ipfsUri, seek, populate } = mapping; diff --git a/kleros-sdk/dataMappings/actions/jsonAction.ts b/kleros-sdk/src/dataMappings/actions/jsonAction.ts similarity index 72% rename from kleros-sdk/dataMappings/actions/jsonAction.ts rename to kleros-sdk/src/dataMappings/actions/jsonAction.ts index 3d4922f2e..3857b4006 100644 --- a/kleros-sdk/dataMappings/actions/jsonAction.ts +++ b/kleros-sdk/src/dataMappings/actions/jsonAction.ts @@ -1,5 +1,5 @@ import { JsonMapping } from "../utils/actionTypes"; -import { createResultObject } from "../utils/createResultObject"; +import { createResultObject } from "src/dataMappings/utils/createResultObject"; export const jsonAction = (mapping: JsonMapping) => { const { value: source, seek, populate } = mapping; diff --git a/kleros-sdk/dataMappings/actions/subgraphAction.ts b/kleros-sdk/src/dataMappings/actions/subgraphAction.ts similarity index 87% rename from kleros-sdk/dataMappings/actions/subgraphAction.ts rename to kleros-sdk/src/dataMappings/actions/subgraphAction.ts index f3fce37de..382bb66e8 100644 --- a/kleros-sdk/dataMappings/actions/subgraphAction.ts +++ b/kleros-sdk/src/dataMappings/actions/subgraphAction.ts @@ -1,6 +1,6 @@ import fetch from "node-fetch"; import { SubgraphMapping } from "../utils/actionTypes"; -import { createResultObject } from "../utils/createResultObject"; +import { createResultObject } from "src/dataMappings/utils/createResultObject"; export const subgraphAction = async (mapping: SubgraphMapping) => { const { endpoint, query, variables, seek, populate } = mapping; diff --git a/kleros-sdk/src/dataMappings/dataMapping.json b/kleros-sdk/src/dataMappings/dataMapping.json new file mode 100644 index 000000000..27f5ed4fd --- /dev/null +++ b/kleros-sdk/src/dataMappings/dataMapping.json @@ -0,0 +1,75 @@ +[ + { + "type": "subgraph", + "endpoint": "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2", + "query": "query($id: ID!) { pair(id: $id) { id token0Price token1Price } }", + "seek": [ + "token0Price", + "token1Price" + ], + "populate": [ + "price1", + "price2" + ] + }, + { + "type": "abi/event", + "abi": "event StakeSet(address indexed _address, uint256 _courtID, uint256 _amount)", + "address": "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2", + "eventFilter": { + "fromBlock": "36205881", + "toBlock": "latest", + "args": { + "_courtID": 1 + } + }, + "seek": [ + "amount" + ], + "populate": [ + "amount" + ] + }, + { + "type": "abi/call", + "abi": "function appealCost(uint256 _disputeID) public view returns (uint256)", + "address": "0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", + "args": [ + "1" + ], + "seek": [ + "cost" + ], + "populate": [ + "cost" + ] + }, + { + "type": "json", + "value": { + "name": "John Doe", + "age": 30, + "email": "johndoe@example.com" + }, + "seek": [ + "name", + "age", + "email" + ], + "populate": [ + "name", + "age", + "email" + ] + }, + { + "type": "fetch/ipfs/json", + "ipfsUri": "ipfs://QmZ3Cmnip8bmFNruuTuCdxPymEjyK9VcQEyf2beDYcaHaK/metaEvidence.json", + "seek": [ + "title" + ], + "populate": [ + "title" + ] + } +] diff --git a/kleros-sdk/src/dataMappings/dataMapping.ts b/kleros-sdk/src/dataMappings/dataMapping.ts new file mode 100644 index 000000000..17dafb8f1 --- /dev/null +++ b/kleros-sdk/src/dataMappings/dataMapping.ts @@ -0,0 +1,92 @@ +export type SubgraphMapping = { + endpoint: string; // Subgraph endpoint + query: string; // Subgraph query + seek: string[]; // Subgraph query parameters value used to populate the template variables + populate: string[]; // Populated template variables +}; + +export type AbiEventMapping = { + abi: string; // ABI of the contract emitting the event + address: string; // Address of the contract emitting the event + eventFilter: { + // Event filter (eg. specific parameter value, block number range, event index) + fromBlock: BigInt | string; // Block number range start + toBlock: BigInt | string; // Block number range end + args: any; // Event parameter value to filter on + }; + seek: string[]; // Event parameters value used to populate the template variables + populate: string[]; // Populated template variables +}; + +export type AbiCallMapping = { + abi: string; // ABI of the contract emitting the event + address: string; // Address of the contract emitting the event + args: any[]; // Function arguments + seek: string[]; // Call return parameters used to populate the template variables + populate: string[]; // Populated template variables +}; + +export type JsonMapping = { + value: object; // Hardcoded object, to be stringified. + seek: string[]; // JSON keys used to populate the template variables + populate: string[]; // Populated template variables +}; + +export type FetchIpfsJsonMapping = { + ipfsUri: string; // IPFS URL + seek: string[]; // JSON keys used to populate the template variables + populate: string[]; // Populated template variables +}; + +const subgraphMappingExample: SubgraphMapping = { + endpoint: "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2", + query: ` + query($id: ID!) { + pair(id: $id) { + id + token0Price + token1Price + } + } + `, + seek: ["token0Price", "token1Price"], + populate: ["price1", "price2"], +}; + +const abiEventMappingExample: AbiEventMapping = { + abi: "event StakeSet(address indexed _address, uint256 _courtID, uint256 _amount)", + address: "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2", + eventFilter: { + fromBlock: BigInt(36205881), + toBlock: "latest", + args: { + _courtID: 1, + }, + }, + seek: ["amount"], + populate: ["amount"], +}; + +const abiCallMappingExample: AbiCallMapping = { + abi: "function appealCost(uint256 _disputeID) public view returns (uint256)", + address: "0x5a2bC1477ABE705dB4955Cda7DE064eA79D563d1", + args: [BigInt(1)], + seek: ["cost"], + populate: ["cost"], +}; + +const jsonMappingExample: JsonMapping = { + value: { + name: "John Doe", + age: 30, + email: "johndoe@example.com", + }, + seek: ["name", "age", "email"], + populate: ["name", "age", "email"], +}; + +const fetchIpfsJsonMappingExample: FetchIpfsJsonMapping = { + ipfsUri: "ipfs://QmZ3Cmnip8bmFNruuTuCdxPymEjyK9VcQEyf2beDYcaHaK/metaEvidence.json", + seek: ["title"], + populate: ["title"], +}; diff --git a/kleros-sdk/src/dataMappings/decoder.ts b/kleros-sdk/src/dataMappings/decoder.ts new file mode 100644 index 000000000..b30e6e927 --- /dev/null +++ b/kleros-sdk/src/dataMappings/decoder.ts @@ -0,0 +1,55 @@ +import request from "graphql-request"; +import { TypedDocumentNode } from "@graphql-typed-document-node/core"; +import { DisputeDetails } from "./disputeDetails"; + +export type Decoder = (externalDisputeID: string, disputeTemplate: Partial) => Promise; + +// https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md +export type CAIP10 = `eip155:${number}:0x${string}`; + +export const graphqlQueryFnHelper = async ( + url: string, + query: TypedDocumentNode, + parametersObject: Record, + chainId = 421613 +) => { + return request(url, query, parametersObject); +}; + +// TODO: generate graphql query +const disputeTemplateQuery = graphql(` + query DisputeTemplate($id: ID!) { + disputeTemplate(id: $id) { + id + templateTag + templateData + templateDataMappings + } + } +`); + +export const genericDecoder = async ( + externalDisputeID: string, + arbitrableDisputeID: string, + disputeTemplateID: string, + disputeTemplateRegistry: CAIP10 +): Promise => { + let subgraphUrl; + switch (disputeTemplateRegistry) { + case "eip155:421613:0x22A58a17F12A718d18C9B6Acca3E311Da1b00A04": // Devnet + subgraphUrl = process.env.REACT_APP_DISPUTE_TEMPLATE_ARBGOERLI_SUBGRAPH_DEVNET; + break; + case "eip155:421613:0xA55D4b90c1F8D1fD0408232bF6FA498dD6786385": // Testnet + subgraphUrl = process.env.REACT_APP_DISPUTE_TEMPLATE_ARBGOERLI_SUBGRAPH_TESTNET; + break; + default: + throw new Error(`Unsupported dispute template registry: ${disputeTemplateRegistry}`); + } + const { disputeTemplate } = await request(subgraphUrl, disputeTemplateQuery, { id: disputeTemplateID.toString() }); + switch (disputeTemplate.specification) { + case "KIP99": + return await kip99Decoder(externalDisputeID, disputeTemplate); + default: + throw new Error(`Unsupported dispute template specification: ${disputeTemplate.specification}`); + } +}; diff --git a/kleros-sdk/src/dataMappings/disputeDetails.ts b/kleros-sdk/src/dataMappings/disputeDetails.ts new file mode 100644 index 000000000..28a3133a6 --- /dev/null +++ b/kleros-sdk/src/dataMappings/disputeDetails.ts @@ -0,0 +1,39 @@ +export type DisputeDetails = { + title: string; + description: string; + question: string; + type: QuestionType; + answers: Answer[]; + policyURI: string; + attachment: Attachment; + frontendUrl: string; + arbitrableChainID: string; + arbitrableAddress: `0x${string}`; + arbitratorChainID: string; + arbitratorAddress: `0x${string}`; + category: string; + lang: string; + specification: string; + version: string; + // missing metadata +}; + +export enum QuestionType { + Bool = "bool", + Datetime = "datetime", + MultipleSelect = "multiple-select", + SingleSelect = "single-select", + Uint = "uint", +} + +export type Answer = { + title: string; + description: string; + id: `0x${string}`; + reserved: boolean; +}; + +export type Attachment = { + label: string; + uri: string; +}; diff --git a/kleros-sdk/dataMappings/executeActions.ts b/kleros-sdk/src/dataMappings/executeActions.ts similarity index 55% rename from kleros-sdk/dataMappings/executeActions.ts rename to kleros-sdk/src/dataMappings/executeActions.ts index 21766a03f..a6fda7969 100644 --- a/kleros-sdk/dataMappings/executeActions.ts +++ b/kleros-sdk/src/dataMappings/executeActions.ts @@ -5,13 +5,13 @@ import { jsonAction } from "./actions/jsonAction"; import { subgraphAction } from "./actions/subgraphAction"; import { retrieveRealityData } from "./retrieveRealityData"; import { - isAbiCallMapping, - isAbiEventMapping, - isFetchIpfsJsonMapping, - isJsonMapping, - isRealityMapping, - isSubgraphMapping, -} from "./utils/actionTypeDetectors"; + validateAbiCallMapping, + validateAbiEventMapping, + validateFetchIpfsJsonMapping, + validateJsonMapping, + validateRealityMapping, + validateSubgraphMapping, +} from "./utils/actionTypeValidators"; import { ActionMapping } from "./utils/actionTypes"; import { replacePlaceholdersWithValues } from "./utils/replacePlaceholdersWithValues"; @@ -20,34 +20,17 @@ export const executeAction = async (mapping: ActionMapping, context = {}) => { switch (mapping.type) { case "graphql": - if (!isSubgraphMapping(mapping)) { - throw new Error("Invalid mapping for graphql action."); - } - return await subgraphAction(mapping); + return await subgraphAction(validateSubgraphMapping(mapping)); case "json": - if (!isJsonMapping(mapping)) { - throw new Error("Invalid mapping for json action."); - } - return jsonAction(mapping); + return jsonAction(validateJsonMapping(mapping)); case "abi/call": - if (!isAbiCallMapping(mapping)) { - throw new Error("Invalid mapping for abi/call action."); - } - return await callAction(mapping); + return await callAction(validateAbiCallMapping(mapping)); case "abi/event": - if (!isAbiEventMapping(mapping)) { - throw new Error("Invalid mapping for abi/event action."); - } - return await eventAction(mapping); + return await eventAction(validateAbiEventMapping(mapping)); case "fetch/ipfs/json": - if (!isFetchIpfsJsonMapping(mapping)) { - throw new Error("Invalid mapping for fetch/ipfs/json action."); - } - return await fetchIpfsJsonAction(mapping); + return await fetchIpfsJsonAction(validateFetchIpfsJsonMapping(mapping)); case "reality": - if (!isRealityMapping(mapping)) { - throw new Error("Invalid mapping for reality action."); - } + mapping = validateRealityMapping(mapping); return await retrieveRealityData(mapping.realityQuestionID, context.arbitrable); default: throw new Error(`Unsupported action type: ${mapping.type}`); diff --git a/kleros-sdk/dataMappings/retrieveRealityData.ts b/kleros-sdk/src/dataMappings/retrieveRealityData.ts similarity index 100% rename from kleros-sdk/dataMappings/retrieveRealityData.ts rename to kleros-sdk/src/dataMappings/retrieveRealityData.ts diff --git a/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts b/kleros-sdk/src/dataMappings/utils/DisputeDetailsValidator.ts similarity index 81% rename from kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts rename to kleros-sdk/src/dataMappings/utils/DisputeDetailsValidator.ts index ce105896f..13356f131 100644 --- a/kleros-sdk/dataMappings/utils/isValidDisputeDetails.ts +++ b/kleros-sdk/src/dataMappings/utils/DisputeDetailsValidator.ts @@ -1,8 +1,10 @@ import { DisputeDetails, QuestionType } from "./disputeDetailsTypes"; -import { isHexAddress } from "./isHexAddress"; -import { isHexId } from "./isHexId"; -export const isValidDisputeDetails = (data: any): data is DisputeDetails => { +const isHexAddress = (str: string): boolean => /^0x[a-fA-F0-9]{40}$/.test(str); + +const isHexId = (str: string): boolean => /^0x[a-fA-F0-9]{1,64}$/.test(str); + +export const validate = (data: any): data is DisputeDetails => { return ( typeof data.title === "string" && typeof data.description === "string" && diff --git a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts new file mode 100644 index 000000000..c40b9fdf8 --- /dev/null +++ b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts @@ -0,0 +1,51 @@ +import { + SubgraphMapping, + AbiEventMapping, + AbiCallMapping, + JsonMapping, + ActionMapping, + FetchIpfsJsonMapping, + RealityMapping, +} from "./actionTypes"; + +export const validateSubgraphMapping = (mapping: ActionMapping) => { + if ((mapping as SubgraphMapping).endpoint !== undefined) { + throw new Error("Invalid mapping for graphql action."); + } + return mapping as SubgraphMapping; +}; + +export const validateAbiEventMapping = (mapping: ActionMapping) => { + if ((mapping as AbiEventMapping).abi === undefined || (mapping as AbiEventMapping).eventFilter === undefined) { + throw new Error("Invalid mapping for abi/event action."); + } + return mapping as AbiEventMapping; +}; + +export const validateAbiCallMapping = (mapping: ActionMapping) => { + if ((mapping as AbiCallMapping).abi === undefined || (mapping as AbiCallMapping).args === undefined) { + throw new Error("Invalid mapping for abi/call action."); + } + return mapping as AbiCallMapping; +}; + +export const validateJsonMapping = (mapping: ActionMapping) => { + if ((mapping as JsonMapping).value === undefined) { + throw new Error("Invalid mapping for json action."); + } + return mapping as JsonMapping; +}; + +export const validateFetchIpfsJsonMapping = (mapping: ActionMapping) => { + if ((mapping as FetchIpfsJsonMapping).ipfsUri === undefined) { + throw new Error("Invalid mapping for fetch/ipfs/json action."); + } + return mapping as FetchIpfsJsonMapping; +}; + +export const validateRealityMapping = (mapping: ActionMapping) => { + if (mapping.type !== "reality" || typeof (mapping as RealityMapping).realityQuestionID !== "string") { + throw new Error("Invalid mapping for reality action."); + } + return mapping as RealityMapping; +}; diff --git a/kleros-sdk/dataMappings/utils/actionTypes.ts b/kleros-sdk/src/dataMappings/utils/actionTypes.ts similarity index 100% rename from kleros-sdk/dataMappings/utils/actionTypes.ts rename to kleros-sdk/src/dataMappings/utils/actionTypes.ts diff --git a/kleros-sdk/dataMappings/utils/createResultObject.ts b/kleros-sdk/src/dataMappings/utils/createResultObject.ts similarity index 93% rename from kleros-sdk/dataMappings/utils/createResultObject.ts rename to kleros-sdk/src/dataMappings/utils/createResultObject.ts index 9c265a4a8..7a76f9f6d 100644 --- a/kleros-sdk/dataMappings/utils/createResultObject.ts +++ b/kleros-sdk/src/dataMappings/utils/createResultObject.ts @@ -1,3 +1,4 @@ +// Can this be replaced by Mustache ? export const createResultObject = (sourceData, seek, populate) => { let result = {}; seek.forEach((key, idx) => { diff --git a/kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts b/kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts new file mode 100644 index 000000000..af9eb36ee --- /dev/null +++ b/kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts @@ -0,0 +1,66 @@ +import { z } from "zod"; +import { isAddress } from "viem"; +import { normalize } from "viem/ens"; + +export const ethAddressSchema = z.string().refine((value) => isAddress(value), { + message: "Provided address is invalid.", +}); + +export const ensNameSchema = z + .string() + .refine((value) => typeof normalize(value) === "string" && value.endsWith(".eth"), { + message: "Provided ENS name is invalid.", + }); + +export const ethAddressOrEnsNameSchema = z.union([ethAddressSchema, ensNameSchema], { + errorMap: () => ({ message: "Provided address or ENS name is invalid." }), +}); + +export enum QuestionType { + Bool = "bool", + Datetime = "datetime", + MultipleSelect = "multiple-select", + SingleSelect = "single-select", + Uint = "uint", +} +export const QuestionTypeSchema = z.nativeEnum(QuestionType); + +export const AnswerSchema = z.object({ + id: z.string().regex(/^0x[0-9a-fA-F]+$/), // should be a bigint + title: z.string(), + description: z.string(), + reserved: z.boolean(), +}); + +export const AttachmentSchema = z.object({ + label: z.string(), + uri: z.string(), +}); + +export const AliasSchema = z.object({ + id: z.string().optional(), + name: z.string(), + address: ethAddressOrEnsNameSchema, +}); + +const DisputeDetailsSchema = z.object({ + title: z.string(), + description: z.string(), + question: z.string(), + type: QuestionTypeSchema, + answers: z.array(AnswerSchema), + policyURI: z.string(), + attachment: AttachmentSchema, + frontendUrl: z.string(), + arbitrableChainID: z.string(), + arbitrableAddress: ethAddressSchema, + arbitratorChainID: z.string(), + arbitratorAddress: ethAddressSchema, + category: z.string(), + lang: z.string(), + specification: z.string(), + aliases: z.array(AliasSchema).optional(), + version: z.string(), +}); + +export default DisputeDetailsSchema; diff --git a/kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts b/kleros-sdk/src/dataMappings/utils/disputeDetailsTypes.ts similarity index 100% rename from kleros-sdk/dataMappings/utils/disputeDetailsTypes.ts rename to kleros-sdk/src/dataMappings/utils/disputeDetailsTypes.ts diff --git a/kleros-sdk/dataMappings/utils/populateTemplate.ts b/kleros-sdk/src/dataMappings/utils/populateTemplate.ts similarity index 83% rename from kleros-sdk/dataMappings/utils/populateTemplate.ts rename to kleros-sdk/src/dataMappings/utils/populateTemplate.ts index 56ebf5ea0..9f240df3b 100644 --- a/kleros-sdk/dataMappings/utils/populateTemplate.ts +++ b/kleros-sdk/src/dataMappings/utils/populateTemplate.ts @@ -1,6 +1,6 @@ import mustache from "mustache"; import { DisputeDetails } from "./disputeDetailsTypes"; -import { isValidDisputeDetails } from "./isValidDisputeDetails"; +import { validate } from "./DisputeDetailsValidator"; export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { const render = mustache.render(mustacheTemplate, data); @@ -8,7 +8,7 @@ export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDe const dispute = JSON.parse(render); // TODO: the validation below is too strict, it should be fixed, disabled for now, FIXME - if (!isValidDisputeDetails(dispute)) { + if (!validate(dispute)) { // throw new Error(`Invalid dispute details format: ${JSON.stringify(dispute)}`); } diff --git a/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts b/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts similarity index 94% rename from kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts rename to kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts index af45e5e11..6277f9394 100644 --- a/kleros-sdk/dataMappings/utils/replacePlaceholdersWithValues.ts +++ b/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts @@ -1,3 +1,4 @@ +// Replace by Mustache ? export const replacePlaceholdersWithValues = (mapping: any, context: any) => { let mappingAsString = JSON.stringify(mapping); diff --git a/kleros-sdk/dataMappings/utils/configureSDK.ts b/kleros-sdk/src/sdk.ts similarity index 100% rename from kleros-sdk/dataMappings/utils/configureSDK.ts rename to kleros-sdk/src/sdk.ts diff --git a/kleros-sdk/test/dataMappings.test.ts b/kleros-sdk/test/dataMappings.test.ts index 6d2c8208f..6c31b664c 100644 --- a/kleros-sdk/test/dataMappings.test.ts +++ b/kleros-sdk/test/dataMappings.test.ts @@ -1,10 +1,10 @@ import { describe, expect, it } from "vitest"; -import { populateTemplate } from "dataMappings/utils/populateTemplate"; -import { jsonAction } from "dataMappings/actions/jsonAction"; -import { subgraphAction } from "dataMappings/actions/subgraphAction"; -import { callAction } from "dataMappings/actions/callAction"; -import { eventAction } from "dataMappings/actions/eventAction"; -import { fetchIpfsJsonAction } from "dataMappings/actions/fetchIpfsJsonAction"; +import { populateTemplate } from "src/dataMappings/utils/populateTemplate"; +import { jsonAction } from "src/dataMappings/actions/jsonAction"; +import { subgraphAction } from "src/dataMappings/actions/subgraphAction"; +import { callAction } from "../src/dataMappings/actions/callAction"; +import { eventAction } from "src/dataMappings/actions/eventAction"; +import { fetchIpfsJsonAction } from "src/dataMappings/actions/fetchIpfsJsonAction"; const exampleObject = { evidence: { @@ -18,6 +18,7 @@ const exampleObject = { describe("jsonAction", () => { it("should extract and map data correctly", () => { const mapping = { + type: "json", value: exampleObject.evidence.fileURI, seek: ["photo", "video"], populate: ["photoUrl", "videoUrl"], @@ -49,6 +50,7 @@ describe("subgraphAction with variables", () => { const populate = ["escrowsData"]; const mapping = { + type: "graphql", endpoint: endpoint, query: query, variables: variables, @@ -75,6 +77,7 @@ describe("callAction", () => { const knownAddress = "0x0000000000000000000000000000000000000000"; const mapping = { + type: "abi/call", abi: abi, address: contractAddress, args: [knownAddress], @@ -97,6 +100,7 @@ describe("eventAction", () => { const toBlock = "latest"; const mapping = { + type: "abi/event", abi: eventAbi, address: contractAddress, eventFilter: { @@ -123,6 +127,7 @@ describe("fetchIpfsJsonAction", () => { const populate = ["name", "firstName", "lastName", "anotherFile"]; const mapping = { + type: "fetch/ipfs/json", ipfsUri: ipfsUri, seek: seek, populate: populate, diff --git a/kleros-sdk/test/disputeDetailsSchema.test.ts b/kleros-sdk/test/disputeDetailsSchema.test.ts index 873dc0771..ac2c7878a 100644 --- a/kleros-sdk/test/disputeDetailsSchema.test.ts +++ b/kleros-sdk/test/disputeDetailsSchema.test.ts @@ -1,5 +1,9 @@ import { describe, expect, it } from "vitest"; -import { ethAddressSchema, ensNameSchema, ethAddressOrEnsNameSchema } from "dataMappings/utils/disputeDetailsSchema"; +import { + ethAddressSchema, + ensNameSchema, + ethAddressOrEnsNameSchema, +} from "src/dataMappings/utils/disputeDetailsSchema"; describe("Dispute Details Schema", () => { it("snapshot", () => { @@ -91,7 +95,7 @@ describe("Dispute Details Schema", () => { }); }); - describe("disputeDetailsSchema", () => { + describe.skip("disputeDetailsSchema", () => { // TODO: add tests }); }); diff --git a/kleros-sdk/tsconfig.json b/kleros-sdk/tsconfig.json index 54d1b65e7..6a9b24bb5 100644 --- a/kleros-sdk/tsconfig.json +++ b/kleros-sdk/tsconfig.json @@ -2,6 +2,17 @@ "extends": "@kleros/kleros-v2-tsconfig/react-library.json", "compilerOptions": { "baseUrl": ".", + "paths": { + "~*": [ + "./*" + ], + "src*": [ + "./src*" + ], + "dataMappings*": [ + "./src/dataMappings*" + ] + }, "target": "ES6", "module": "CommonJS", "outDir": "build/dist", @@ -15,7 +26,7 @@ "isolatedModules": true }, "include": [ - ".", + "src", "test" ], "exclude": [ diff --git a/kleros-sdk/vite.config.ts b/kleros-sdk/vite.config.ts deleted file mode 100644 index 36bfcfdc4..000000000 --- a/kleros-sdk/vite.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -/// - -// Configure Vitest (https://vitest.dev/config/) - -import { defineConfig } from "vite"; - -export default defineConfig({ - test: { - /* for example, use global to avoid globals imports (describe, test, expect): */ - // globals: true, - }, -}); diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index 0b79647e1..3a897c8eb 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -16,8 +16,8 @@ import PeriodBanner from "./PeriodBanner"; import { isUndefined } from "utils/index"; import { getLocalRounds } from "utils/getLocalRounds"; import { responsiveSize } from "styles/responsiveSize"; -import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; -import { DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; +import { populateTemplate } from "@kleros/kleros-sdk/src/dataMappings/utils/populateTemplate"; +import { DisputeDetails } from "@kleros/kleros-sdk/src/dataMappings/utils/disputeDetailsTypes"; import { INVALID_DISPUTE_DATA_ERROR } from "consts/index"; const StyledCard = styled(Card)` diff --git a/web/src/components/DisputePreview/DisputeContext.tsx b/web/src/components/DisputePreview/DisputeContext.tsx index b23c26ee0..8f425f20d 100644 --- a/web/src/components/DisputePreview/DisputeContext.tsx +++ b/web/src/components/DisputePreview/DisputeContext.tsx @@ -6,7 +6,7 @@ import { isUndefined } from "utils/index"; import { Answer as IAnswer } from "context/NewDisputeContext"; import AliasDisplay from "./Alias"; import { responsiveSize } from "styles/responsiveSize"; -import { DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; +import { DisputeDetails } from "@kleros/kleros-sdk/src/dataMappings/utils/disputeDetailsTypes"; const StyledH1 = styled.h1` margin: 0; diff --git a/web/src/pages/Cases/CaseDetails/Overview/index.tsx b/web/src/pages/Cases/CaseDetails/Overview/index.tsx index 399bcbe4b..dacdb80e5 100644 --- a/web/src/pages/Cases/CaseDetails/Overview/index.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview/index.tsx @@ -5,11 +5,11 @@ import { formatEther } from "viem"; import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { useCourtPolicy } from "queries/useCourtPolicy"; -import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; -import { executeActions } from "@kleros/kleros-sdk/dataMappings/executeActions"; -import { configureSDK } from "@kleros/kleros-sdk/dataMappings/utils/configureSDK"; +import { populateTemplate } from "@kleros/kleros-sdk/src/dataMappings/utils/populateTemplate"; +import { executeActions } from "@kleros/kleros-sdk/src/dataMappings/executeActions"; +import { configureSDK } from "@kleros/kleros-sdk/src/sdk"; import { alchemyApiKey } from "context/Web3Provider"; -import { DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; +import { DisputeDetails } from "@kleros/kleros-sdk/src/dataMappings/utils/disputeDetailsTypes"; import { Periods } from "consts/periods"; import DisputeInfo from "components/DisputeCard/DisputeInfo"; import Verdict from "components/Verdict/index"; diff --git a/web/src/pages/DisputeTemplateView.tsx b/web/src/pages/DisputeTemplateView.tsx index e1d8dadb1..171f156e2 100644 --- a/web/src/pages/DisputeTemplateView.tsx +++ b/web/src/pages/DisputeTemplateView.tsx @@ -4,10 +4,10 @@ import { Textarea } from "@kleros/ui-components-library"; import PolicyIcon from "svgs/icons/policy.svg"; import ReactMarkdown from "components/ReactMarkdown"; import { INVALID_DISPUTE_DATA_ERROR, IPFS_GATEWAY } from "consts/index"; -import { configureSDK } from "@kleros/kleros-sdk/dataMappings/utils/configureSDK"; -import { executeActions } from "@kleros/kleros-sdk/dataMappings/executeActions"; -import { populateTemplate } from "@kleros/kleros-sdk/dataMappings/utils/populateTemplate"; -import { Answer, DisputeDetails } from "@kleros/kleros-sdk/dataMappings/utils/disputeDetailsTypes"; +import { configureSDK } from "@kleros/kleros-sdk/src/sdk"; +import { executeActions } from "@kleros/kleros-sdk/src/dataMappings/executeActions"; +import { populateTemplate } from "@kleros/kleros-sdk/src/dataMappings/utils/populateTemplate"; +import { Answer, DisputeDetails } from "@kleros/kleros-sdk/src/dataMappings/utils/disputeDetailsTypes"; import { alchemyApiKey } from "context/Web3Provider"; const Container = styled.div` From ef4296976f6bafeb22a5ed98d163d6040706e0ce Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 12 Jan 2024 03:29:57 +0000 Subject: [PATCH 35/37] chore: web is not depending on the contracts package indirectly via the SDK --- kleros-sdk/package.json | 4 +--- web/package.json | 1 - yarn.lock | 20 +------------------- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index e7fbf8949..2c628617b 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -26,10 +26,7 @@ "test:run": "vitest run" }, "devDependencies": { - "@types/chai": "^4.3.11", - "@types/mocha": "^10.0.6", "@vitest/ui": "^1.1.3", - "chai": "^4.3.8", "dotenv": "^16.3.1", "mocha": "^10.2.0", "ts-node": "^10.9.2", @@ -37,6 +34,7 @@ "vitest": "^1.1.3" }, "dependencies": { + "@kleros/kleros-v2-contracts": "workspace:^", "@reality.eth/reality-eth-lib": "^3.2.30", "zod": "^3.22.4" } diff --git a/web/package.json b/web/package.json index a3b1642d5..3c86e7d74 100644 --- a/web/package.json +++ b/web/package.json @@ -73,7 +73,6 @@ "dependencies": { "@filebase/client": "^0.0.5", "@kleros/kleros-sdk": "workspace:^", - "@kleros/kleros-v2-contracts": "workspace:^", "@kleros/ui-components-library": "^2.6.3", "@sentry/react": "^7.55.2", "@sentry/tracing": "^7.55.2", diff --git a/yarn.lock b/yarn.lock index 4a760fa96..4e9ef2a60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5615,11 +5615,9 @@ __metadata: version: 0.0.0-use.local resolution: "@kleros/kleros-sdk@workspace:kleros-sdk" dependencies: + "@kleros/kleros-v2-contracts": "workspace:^" "@reality.eth/reality-eth-lib": ^3.2.30 - "@types/chai": ^4.3.11 - "@types/mocha": ^10.0.6 "@vitest/ui": ^1.1.3 - chai: ^4.3.8 dotenv: ^16.3.1 mocha: ^10.2.0 ts-node: ^10.9.2 @@ -5744,7 +5742,6 @@ __metadata: "@graphql-codegen/cli": ^4.0.1 "@graphql-codegen/client-preset": ^4.1.0 "@kleros/kleros-sdk": "workspace:^" - "@kleros/kleros-v2-contracts": "workspace:^" "@kleros/kleros-v2-eslint-config": "workspace:^" "@kleros/kleros-v2-prettier-config": "workspace:^" "@kleros/kleros-v2-tsconfig": "workspace:^" @@ -13911,21 +13908,6 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.8": - version: 4.4.0 - resolution: "chai@npm:4.4.0" - dependencies: - assertion-error: ^1.1.0 - check-error: ^1.0.3 - deep-eql: ^4.1.3 - get-func-name: ^2.0.2 - loupe: ^2.3.6 - pathval: ^1.1.1 - type-detect: ^4.0.8 - checksum: 2509a0acc2707f0664157cdc9d72b1466c71cedba19a22fec80ae550593fdcfc108fd86d4a7fec3be631b6c0589bf4f05652ee73fa55dbc748387ff6cc85c6b3 - languageName: node - linkType: hard - "chalk@npm:3.0.0": version: 3.0.0 resolution: "chalk@npm:3.0.0" From d91cab7e59c9c9e78ffa465668a84d524bd1133b Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Tue, 23 Jan 2024 18:56:24 +0000 Subject: [PATCH 36/37] chore: lockfile --- yarn.lock | 414 +++++++++++++++++++++++++++--------------------------- 1 file changed, 207 insertions(+), 207 deletions(-) diff --git a/yarn.lock b/yarn.lock index bfad94de4..255fa3a6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3593,9 +3593,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/aix-ppc64@npm:0.19.11" +"@esbuild/aix-ppc64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/aix-ppc64@npm:0.19.12" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard @@ -3607,9 +3607,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/android-arm64@npm:0.19.11" +"@esbuild/android-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/android-arm64@npm:0.19.12" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -3621,9 +3621,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/android-arm@npm:0.19.11" +"@esbuild/android-arm@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/android-arm@npm:0.19.12" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -3635,9 +3635,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/android-x64@npm:0.19.11" +"@esbuild/android-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/android-x64@npm:0.19.12" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -3649,9 +3649,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/darwin-arm64@npm:0.19.11" +"@esbuild/darwin-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/darwin-arm64@npm:0.19.12" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -3663,9 +3663,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/darwin-x64@npm:0.19.11" +"@esbuild/darwin-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/darwin-x64@npm:0.19.12" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -3677,9 +3677,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/freebsd-arm64@npm:0.19.11" +"@esbuild/freebsd-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/freebsd-arm64@npm:0.19.12" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -3691,9 +3691,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/freebsd-x64@npm:0.19.11" +"@esbuild/freebsd-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/freebsd-x64@npm:0.19.12" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -3705,9 +3705,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-arm64@npm:0.19.11" +"@esbuild/linux-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-arm64@npm:0.19.12" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -3719,9 +3719,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-arm@npm:0.19.11" +"@esbuild/linux-arm@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-arm@npm:0.19.12" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -3733,9 +3733,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-ia32@npm:0.19.11" +"@esbuild/linux-ia32@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-ia32@npm:0.19.12" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -3747,9 +3747,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-loong64@npm:0.19.11" +"@esbuild/linux-loong64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-loong64@npm:0.19.12" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -3761,9 +3761,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-mips64el@npm:0.19.11" +"@esbuild/linux-mips64el@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-mips64el@npm:0.19.12" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -3775,9 +3775,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-ppc64@npm:0.19.11" +"@esbuild/linux-ppc64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-ppc64@npm:0.19.12" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -3789,9 +3789,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-riscv64@npm:0.19.11" +"@esbuild/linux-riscv64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-riscv64@npm:0.19.12" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -3803,9 +3803,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-s390x@npm:0.19.11" +"@esbuild/linux-s390x@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-s390x@npm:0.19.12" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -3817,9 +3817,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/linux-x64@npm:0.19.11" +"@esbuild/linux-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-x64@npm:0.19.12" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -3831,9 +3831,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/netbsd-x64@npm:0.19.11" +"@esbuild/netbsd-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/netbsd-x64@npm:0.19.12" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -3845,9 +3845,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/openbsd-x64@npm:0.19.11" +"@esbuild/openbsd-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/openbsd-x64@npm:0.19.12" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -3859,9 +3859,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/sunos-x64@npm:0.19.11" +"@esbuild/sunos-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/sunos-x64@npm:0.19.12" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -3873,9 +3873,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/win32-arm64@npm:0.19.11" +"@esbuild/win32-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/win32-arm64@npm:0.19.12" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -3887,9 +3887,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/win32-ia32@npm:0.19.11" +"@esbuild/win32-ia32@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/win32-ia32@npm:0.19.12" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -3901,9 +3901,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.19.11": - version: 0.19.11 - resolution: "@esbuild/win32-x64@npm:0.19.11" +"@esbuild/win32-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/win32-x64@npm:0.19.12" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -8259,93 +8259,93 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.9.4" +"@rollup/rollup-android-arm-eabi@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.9.6" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-android-arm64@npm:4.9.4" +"@rollup/rollup-android-arm64@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-android-arm64@npm:4.9.6" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-darwin-arm64@npm:4.9.4" +"@rollup/rollup-darwin-arm64@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-darwin-arm64@npm:4.9.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-darwin-x64@npm:4.9.4" +"@rollup/rollup-darwin-x64@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-darwin-x64@npm:4.9.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.9.4" +"@rollup/rollup-linux-arm-gnueabihf@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.9.6" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.9.4" +"@rollup/rollup-linux-arm64-gnu@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.9.6" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.9.4" +"@rollup/rollup-linux-arm64-musl@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.9.6" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.9.4" +"@rollup/rollup-linux-riscv64-gnu@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.9.6" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.9.4" +"@rollup/rollup-linux-x64-gnu@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.9.6" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.9.4" +"@rollup/rollup-linux-x64-musl@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.9.6" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.9.4" +"@rollup/rollup-win32-arm64-msvc@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.9.6" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.9.4" +"@rollup/rollup-win32-ia32-msvc@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.9.6" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.9.4": - version: 4.9.4 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.9.4" +"@rollup/rollup-win32-x64-msvc@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.9.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -10096,9 +10096,9 @@ __metadata: linkType: hard "@types/node@npm:^16.18.70": - version: 16.18.70 - resolution: "@types/node@npm:16.18.70" - checksum: 0c8a1ee93f6c0940629fbf6245ff22e0c7423b7c7c74c47e7171dc6342d279c2f931d50894c3d1b9a66238469b2b3d2d3c7fcf21eb3af6a03fc588f9ab6db849 + version: 16.18.74 + resolution: "@types/node@npm:16.18.74" + checksum: 33d8f157b51cb2f6907a7019e0bef0733f6ebd025f208863e6e6ea4721348902f2c7ac9eeaadff9f1e138927921e620c7f0a655475a298569d7551f2d28e35f3 languageName: node linkType: hard @@ -10675,53 +10675,53 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:1.1.3": - version: 1.1.3 - resolution: "@vitest/expect@npm:1.1.3" +"@vitest/expect@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/expect@npm:1.2.1" dependencies: - "@vitest/spy": 1.1.3 - "@vitest/utils": 1.1.3 + "@vitest/spy": 1.2.1 + "@vitest/utils": 1.2.1 chai: ^4.3.10 - checksum: 971492347e91af81a8c309bc6dff4369afe0f533ac73a73e4a568111ea0fa7d6dc45b69b209490ad588578fd905773e6bd4fcbe8d517ac7aeb57efb1e9c59083 + checksum: d87a2dd646f523eaf68185e85f05412969fda55f228be4806d038550f446d3235ebee57f7d3882d0fcf16cfe2e3ac7d10d311df4894fa71548ae9852c8dbd23d languageName: node linkType: hard -"@vitest/runner@npm:1.1.3": - version: 1.1.3 - resolution: "@vitest/runner@npm:1.1.3" +"@vitest/runner@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/runner@npm:1.2.1" dependencies: - "@vitest/utils": 1.1.3 + "@vitest/utils": 1.2.1 p-limit: ^5.0.0 pathe: ^1.1.1 - checksum: a2875fab07c307aee5c7b3e4e821c2f36a561d86412edeb69f47daed10fa26fb5ba222841cf093372bce95a7384ff3a9302d69b3e594468aa565cbd5b2fe4316 + checksum: 3a3941392e8c6359e19c3ac5c2923150251d9d32bf1252bc2951487d799ac19a7cc43eb3c02eb642c1b02f65ad365273f053bcb37153659c35a345b628baef65 languageName: node linkType: hard -"@vitest/snapshot@npm:1.1.3": - version: 1.1.3 - resolution: "@vitest/snapshot@npm:1.1.3" +"@vitest/snapshot@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/snapshot@npm:1.2.1" dependencies: magic-string: ^0.30.5 pathe: ^1.1.1 pretty-format: ^29.7.0 - checksum: 731af9f71f57c0a4830a2e8c6c9c354fe80b7ad00d38cd19354aaa61c1e0353a3d09b427f2a69e81b5bccce4576e2c1e8a538bce3dfbbdc080126d23ee2edb14 + checksum: 6efee401eaab9868c7f7834fd8ec9495c83c0a5eeb632942e6a5eb1ae5a876e91ac9a1b0b760e7bfde5d80cfc3a618e668b080c01882f5eb3b79a4c588185aa4 languageName: node linkType: hard -"@vitest/spy@npm:1.1.3": - version: 1.1.3 - resolution: "@vitest/spy@npm:1.1.3" +"@vitest/spy@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/spy@npm:1.2.1" dependencies: tinyspy: ^2.2.0 - checksum: 592a9a2bad31c2655fdc6ae87f44b36bc25aafb7efd3a750228409ab4e98bff31888d806c29c6e7bfc029a5ee225f7dc998565115b4fa452429eaa579cc0eec7 + checksum: 22a4b4539f69b28f6b0d907d6b7997972a09d85c9a136e0f953dfea45a12bc2ec8678f8d62cbc1ecfc803a0926df8901c6b5d9f8625196f68785965e1c14172c languageName: node linkType: hard "@vitest/ui@npm:^1.1.3": - version: 1.1.3 - resolution: "@vitest/ui@npm:1.1.3" + version: 1.2.1 + resolution: "@vitest/ui@npm:1.2.1" dependencies: - "@vitest/utils": 1.1.3 + "@vitest/utils": 1.2.1 fast-glob: ^3.3.2 fflate: ^0.8.1 flatted: ^3.2.9 @@ -10730,19 +10730,19 @@ __metadata: sirv: ^2.0.4 peerDependencies: vitest: ^1.0.0 - checksum: ef31bef05dca11ec0e435a8499a00ecfb021f6ec9062684a7229744f4620a175124208562944387fa5c04b8c7aa64b6633bb212dfb24472c80e43da84b27310e + checksum: 40e2c3d80fd687915698a8860dec1b6bdc633bfb9fdb7e5091b0850194e63e166906253578870ba774d9fa902f8c8d271f37d17648a6c672a1b7cd4a045971b5 languageName: node linkType: hard -"@vitest/utils@npm:1.1.3": - version: 1.1.3 - resolution: "@vitest/utils@npm:1.1.3" +"@vitest/utils@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/utils@npm:1.2.1" dependencies: diff-sequences: ^29.6.3 estree-walker: ^3.0.3 loupe: ^2.3.7 pretty-format: ^29.7.0 - checksum: d345b8c862c51b734d9fe53397a125485797cae2a4c1630cea1235f3f0987df479c84ac958f5250e77892afdc12f6d863628d619fc1bb5e34c05c3fa8a86d289 + checksum: 72b54d27e55b9805ab9a8224712584e8db232bd4ce6406e845fbeaf95d8845595791071868b3fdb2ca234acfaea6e7b323d25e419059ef3eb66aa2b4f5c29354 languageName: node linkType: hard @@ -11814,7 +11814,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.0.2, acorn-walk@npm:^8.3.1": +"acorn-walk@npm:^8.0.2, acorn-walk@npm:^8.3.2": version: 8.3.2 resolution: "acorn-walk@npm:8.3.2" checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 @@ -16993,32 +16993,32 @@ __metadata: linkType: hard "esbuild@npm:^0.19.3": - version: 0.19.11 - resolution: "esbuild@npm:0.19.11" - dependencies: - "@esbuild/aix-ppc64": 0.19.11 - "@esbuild/android-arm": 0.19.11 - "@esbuild/android-arm64": 0.19.11 - "@esbuild/android-x64": 0.19.11 - "@esbuild/darwin-arm64": 0.19.11 - "@esbuild/darwin-x64": 0.19.11 - "@esbuild/freebsd-arm64": 0.19.11 - "@esbuild/freebsd-x64": 0.19.11 - "@esbuild/linux-arm": 0.19.11 - "@esbuild/linux-arm64": 0.19.11 - "@esbuild/linux-ia32": 0.19.11 - "@esbuild/linux-loong64": 0.19.11 - "@esbuild/linux-mips64el": 0.19.11 - "@esbuild/linux-ppc64": 0.19.11 - "@esbuild/linux-riscv64": 0.19.11 - "@esbuild/linux-s390x": 0.19.11 - "@esbuild/linux-x64": 0.19.11 - "@esbuild/netbsd-x64": 0.19.11 - "@esbuild/openbsd-x64": 0.19.11 - "@esbuild/sunos-x64": 0.19.11 - "@esbuild/win32-arm64": 0.19.11 - "@esbuild/win32-ia32": 0.19.11 - "@esbuild/win32-x64": 0.19.11 + version: 0.19.12 + resolution: "esbuild@npm:0.19.12" + dependencies: + "@esbuild/aix-ppc64": 0.19.12 + "@esbuild/android-arm": 0.19.12 + "@esbuild/android-arm64": 0.19.12 + "@esbuild/android-x64": 0.19.12 + "@esbuild/darwin-arm64": 0.19.12 + "@esbuild/darwin-x64": 0.19.12 + "@esbuild/freebsd-arm64": 0.19.12 + "@esbuild/freebsd-x64": 0.19.12 + "@esbuild/linux-arm": 0.19.12 + "@esbuild/linux-arm64": 0.19.12 + "@esbuild/linux-ia32": 0.19.12 + "@esbuild/linux-loong64": 0.19.12 + "@esbuild/linux-mips64el": 0.19.12 + "@esbuild/linux-ppc64": 0.19.12 + "@esbuild/linux-riscv64": 0.19.12 + "@esbuild/linux-s390x": 0.19.12 + "@esbuild/linux-x64": 0.19.12 + "@esbuild/netbsd-x64": 0.19.12 + "@esbuild/openbsd-x64": 0.19.12 + "@esbuild/sunos-x64": 0.19.12 + "@esbuild/win32-arm64": 0.19.12 + "@esbuild/win32-ia32": 0.19.12 + "@esbuild/win32-x64": 0.19.12 dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -17068,7 +17068,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: ae949a796d1d06b55275ae7491ce137857468f69a93d8cc9c0943d2a701ac54e14dbb250a2ba56f2ad98283669578f1ec3bd85a4681910a5ff29a2470c3bd62c + checksum: 2936e29107b43e65a775b78b7bc66ddd7d76febd73840ac7e825fb22b65029422ff51038a08d19b05154f543584bd3afe7d1ef1c63900429475b17fbe61cb61f languageName: node linkType: hard @@ -30064,22 +30064,22 @@ __metadata: linkType: hard "rollup@npm:^4.2.0": - version: 4.9.4 - resolution: "rollup@npm:4.9.4" - dependencies: - "@rollup/rollup-android-arm-eabi": 4.9.4 - "@rollup/rollup-android-arm64": 4.9.4 - "@rollup/rollup-darwin-arm64": 4.9.4 - "@rollup/rollup-darwin-x64": 4.9.4 - "@rollup/rollup-linux-arm-gnueabihf": 4.9.4 - "@rollup/rollup-linux-arm64-gnu": 4.9.4 - "@rollup/rollup-linux-arm64-musl": 4.9.4 - "@rollup/rollup-linux-riscv64-gnu": 4.9.4 - "@rollup/rollup-linux-x64-gnu": 4.9.4 - "@rollup/rollup-linux-x64-musl": 4.9.4 - "@rollup/rollup-win32-arm64-msvc": 4.9.4 - "@rollup/rollup-win32-ia32-msvc": 4.9.4 - "@rollup/rollup-win32-x64-msvc": 4.9.4 + version: 4.9.6 + resolution: "rollup@npm:4.9.6" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.9.6 + "@rollup/rollup-android-arm64": 4.9.6 + "@rollup/rollup-darwin-arm64": 4.9.6 + "@rollup/rollup-darwin-x64": 4.9.6 + "@rollup/rollup-linux-arm-gnueabihf": 4.9.6 + "@rollup/rollup-linux-arm64-gnu": 4.9.6 + "@rollup/rollup-linux-arm64-musl": 4.9.6 + "@rollup/rollup-linux-riscv64-gnu": 4.9.6 + "@rollup/rollup-linux-x64-gnu": 4.9.6 + "@rollup/rollup-linux-x64-musl": 4.9.6 + "@rollup/rollup-win32-arm64-msvc": 4.9.6 + "@rollup/rollup-win32-ia32-msvc": 4.9.6 + "@rollup/rollup-win32-x64-msvc": 4.9.6 "@types/estree": 1.0.5 fsevents: ~2.3.2 dependenciesMeta: @@ -30113,7 +30113,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 134b1fd8886a1dc86b2cadada979174e736a39aec12d069261fe8b799ad0c4aa3213188ea49adeee155669315016617260e43eea754436c50121aa359899da4d + checksum: cdc0bdd41ee2d3fe7f01df26f5a85921caf46ffe0ae118b2f3deebdf569e8b1c1800b8eee04960425e67aecbd9ccdd37bcdb92595866adb3968d223a07e9b7e6 languageName: node linkType: hard @@ -32619,16 +32619,16 @@ __metadata: linkType: hard "tinybench@npm:^2.5.1": - version: 2.5.1 - resolution: "tinybench@npm:2.5.1" - checksum: 6d98526c00b68b50ab0a37590b3cc6713b96fee7dd6756a2a77bab071ed1b4a4fc54e7b11e28b35ec2f761c6a806c2befa95f10acf2fee111c49327b6fc3386f + version: 2.6.0 + resolution: "tinybench@npm:2.6.0" + checksum: a621ac66ac17ec5da7e9ac10b3c27040e58c3cd843ccedd8e1e3fab5702d6337b80d02b7bfbf420ab5f029dcb7895657fb80ce21181896e170fa4e6d2c2eebc4 languageName: node linkType: hard "tinypool@npm:^0.8.1": - version: 0.8.1 - resolution: "tinypool@npm:0.8.1" - checksum: e1162629b32a694edd92323fe7cc57379723f36b03f37e3f9442cb8fd3a99785b2b9416ef586d2f4cec8624f356b38558c2cfd272eb265a30841371d3d67d37a + version: 0.8.2 + resolution: "tinypool@npm:0.8.2" + checksum: b0993207b89ab8ab565e1eb03287aa3f15bc648c2e1da889bcfad003244271a5efe5c215d8074c3b8798ae7ea9c54678b6c9b09e7e5c8e82285177792e7ac30a languageName: node linkType: hard @@ -33985,9 +33985,9 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:1.1.3": - version: 1.1.3 - resolution: "vite-node@npm:1.1.3" +"vite-node@npm:1.2.1": + version: 1.2.1 + resolution: "vite-node@npm:1.2.1" dependencies: cac: ^6.7.14 debug: ^4.3.4 @@ -33996,13 +33996,13 @@ __metadata: vite: ^5.0.0 bin: vite-node: vite-node.mjs - checksum: 077691a293fb4151267d7bb4ed322e3d4ce427bd06c02f7d08d7411f9fc96f98ada1aa0da172c02648b44680ba16c57a40b1aa9b98231f68ea5862a00dcdb1dd + checksum: 2d2679a8dfecd8de6a2296c72a3d6662597ccf20cb90e4626a2df335556d8b18dbad3ae2be06e644bf905693dbdb558ff003c6dc990c6bc662adcee9e4f0fa6f languageName: node linkType: hard "vite@npm:^5.0.0": - version: 5.0.11 - resolution: "vite@npm:5.0.11" + version: 5.0.12 + resolution: "vite@npm:5.0.12" dependencies: esbuild: ^0.19.3 fsevents: ~2.3.3 @@ -34036,20 +34036,20 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 262e41f25ce0cc5fc3c2065b1796f64ec115d3ac2d9625dbfb36d6628ba10e63684ef5515bb2ff1aa8e34c6f89e9c10e8211cb88f6c7f0da6869362851345437 + checksum: b97b6f1c204d9091d0973626827a6e9d8e8b1959ebd0877b6f76e7068e1e7adf9ecd3b1cc382cbab9d421e3eeca5e1a95f27f9c1734439b229f5a58ef2052fa4 languageName: node linkType: hard "vitest@npm:^1.1.3": - version: 1.1.3 - resolution: "vitest@npm:1.1.3" - dependencies: - "@vitest/expect": 1.1.3 - "@vitest/runner": 1.1.3 - "@vitest/snapshot": 1.1.3 - "@vitest/spy": 1.1.3 - "@vitest/utils": 1.1.3 - acorn-walk: ^8.3.1 + version: 1.2.1 + resolution: "vitest@npm:1.2.1" + dependencies: + "@vitest/expect": 1.2.1 + "@vitest/runner": 1.2.1 + "@vitest/snapshot": 1.2.1 + "@vitest/spy": 1.2.1 + "@vitest/utils": 1.2.1 + acorn-walk: ^8.3.2 cac: ^6.7.14 chai: ^4.3.10 debug: ^4.3.4 @@ -34063,7 +34063,7 @@ __metadata: tinybench: ^2.5.1 tinypool: ^0.8.1 vite: ^5.0.0 - vite-node: 1.1.3 + vite-node: 1.2.1 why-is-node-running: ^2.2.2 peerDependencies: "@edge-runtime/vm": "*" @@ -34087,7 +34087,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 35087400a0e2b2f0f1f451d0da41abafd8c55112e143a2643286bf0d3d4567b057b40dc391c4b2a05a947edc48d981a6b8c961dc32c6642d84cd8d717bd168bc + checksum: be5cf1ebde0ff7fd534d4c5c710b9d63b3bd7a899f1fcceab82779949cfb8c962f82bb827652debe2d0553d6f786cf76998e6f346e46e03b14e720b121ff540e languageName: node linkType: hard From 7001003476631a8b38f4a35eb1e8e1f74d485c0a Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Tue, 23 Jan 2024 19:07:14 +0000 Subject: [PATCH 37/37] fix: linting --- .../src/dataMappings/actions/callAction.ts | 6 ++--- .../src/dataMappings/actions/eventAction.ts | 4 ++-- kleros-sdk/src/dataMappings/executeActions.ts | 2 +- .../src/dataMappings/retrieveRealityData.ts | 2 +- .../dataMappings/utils/createResultObject.ts | 2 +- kleros-sdk/test/dataMappings.test.ts | 22 +++++++++---------- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/kleros-sdk/src/dataMappings/actions/callAction.ts b/kleros-sdk/src/dataMappings/actions/callAction.ts index 24cb7a170..256696551 100644 --- a/kleros-sdk/src/dataMappings/actions/callAction.ts +++ b/kleros-sdk/src/dataMappings/actions/callAction.ts @@ -8,12 +8,12 @@ export const callAction = async (mapping: AbiCallMapping) => { const publicClient = getPublicClient(); const { abi: source, address, args, seek, populate } = mapping; - let parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; + const parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; const data = await publicClient.readContract({ - address: address, + address, abi: [parsedAbi], - args: args, + args, }); return createResultObject(data, seek, populate); diff --git a/kleros-sdk/src/dataMappings/actions/eventAction.ts b/kleros-sdk/src/dataMappings/actions/eventAction.ts index 02273fa79..ac02ef8d8 100644 --- a/kleros-sdk/src/dataMappings/actions/eventAction.ts +++ b/kleros-sdk/src/dataMappings/actions/eventAction.ts @@ -8,10 +8,10 @@ export const eventAction = async (mapping: AbiEventMapping) => { const publicClient = getPublicClient(); const { abi: source, address, eventFilter, seek, populate } = mapping; - let parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; + const parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; const filter = await publicClient.createEventFilter({ - address: address, + address, event: parsedAbi, args: eventFilter.args, fromBlock: eventFilter.fromBlock, diff --git a/kleros-sdk/src/dataMappings/executeActions.ts b/kleros-sdk/src/dataMappings/executeActions.ts index a6fda7969..049c31a87 100644 --- a/kleros-sdk/src/dataMappings/executeActions.ts +++ b/kleros-sdk/src/dataMappings/executeActions.ts @@ -38,7 +38,7 @@ export const executeAction = async (mapping: ActionMapping, context = {}) => { }; export const executeActions = async (mappings, initialContext = {}) => { - let context = { ...initialContext }; + const context = { ...initialContext }; for (const mapping of mappings) { const actionResult = await executeAction(mapping, context); diff --git a/kleros-sdk/src/dataMappings/retrieveRealityData.ts b/kleros-sdk/src/dataMappings/retrieveRealityData.ts index 58314e190..d7004693d 100644 --- a/kleros-sdk/src/dataMappings/retrieveRealityData.ts +++ b/kleros-sdk/src/dataMappings/retrieveRealityData.ts @@ -102,6 +102,6 @@ export const retrieveRealityData = async (realityQuestionID: string, arbitrable? realityAddress: questionData.arbitrator, questionId: questionData.realityQuestionID, realityUser: questionData.realityUser, - answers: answers, + answers, }; }; diff --git a/kleros-sdk/src/dataMappings/utils/createResultObject.ts b/kleros-sdk/src/dataMappings/utils/createResultObject.ts index 7a76f9f6d..cc910c063 100644 --- a/kleros-sdk/src/dataMappings/utils/createResultObject.ts +++ b/kleros-sdk/src/dataMappings/utils/createResultObject.ts @@ -1,6 +1,6 @@ // Can this be replaced by Mustache ? export const createResultObject = (sourceData, seek, populate) => { - let result = {}; + const result = {}; seek.forEach((key, idx) => { let foundValue; if (typeof sourceData !== "object" || key === "0") { diff --git a/kleros-sdk/test/dataMappings.test.ts b/kleros-sdk/test/dataMappings.test.ts index 6c31b664c..bd2730b3f 100644 --- a/kleros-sdk/test/dataMappings.test.ts +++ b/kleros-sdk/test/dataMappings.test.ts @@ -51,11 +51,11 @@ describe("subgraphAction with variables", () => { const mapping = { type: "graphql", - endpoint: endpoint, - query: query, - variables: variables, - seek: seek, - populate: populate, + endpoint, + query, + variables, + seek, + populate, }; const result = await subgraphAction(mapping); @@ -78,7 +78,7 @@ describe("callAction", () => { const mapping = { type: "abi/call", - abi: abi, + abi, address: contractAddress, args: [knownAddress], seek: [""], @@ -104,8 +104,8 @@ describe("eventAction", () => { abi: eventAbi, address: contractAddress, eventFilter: { - fromBlock: fromBlock, - toBlock: toBlock, + fromBlock, + toBlock, }, seek: ["from", "to", "value"], populate: ["fromAddress", "toAddress", "transferValue"], @@ -128,9 +128,9 @@ describe("fetchIpfsJsonAction", () => { const mapping = { type: "fetch/ipfs/json", - ipfsUri: ipfsUri, - seek: seek, - populate: populate, + ipfsUri, + seek, + populate, }; const result = await fetchIpfsJsonAction(mapping);