From dbb89d250f0a7a8184aa5b56e9ea025f0b0a5a8c Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 8 Oct 2024 16:24:49 +0530 Subject: [PATCH 01/37] feat(sdk): dynamic-context-validation --- .../utils/replacePlaceholdersWithValues.ts | 17 ++++++++++++++++ .../dataMappings/utils/retrieveVariables.ts | 20 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 kleros-sdk/src/dataMappings/utils/retrieveVariables.ts diff --git a/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts b/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts index 2a54ad231..5cd55281c 100644 --- a/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts +++ b/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts @@ -1,8 +1,10 @@ import mustache from "mustache"; +import retrieveVariables from "./retrieveVariables"; export const replacePlaceholdersWithValues = (mapping: any, context: Record) => { const replace = (obj) => { if (typeof obj === "string") { + validateContext(obj, context); return mustache.render(obj, context); } else if (Array.isArray(obj)) { return obj.map(replace); @@ -15,3 +17,18 @@ export const replacePlaceholdersWithValues = (mapping: any, context: Record) => { + const variables = retrieveVariables(template); + + variables.forEach((variable) => { + if (!context[variable]) throw new Error(`Expected key : "${variable}" to be provided in context.`); + }); + return true; +}; diff --git a/kleros-sdk/src/dataMappings/utils/retrieveVariables.ts b/kleros-sdk/src/dataMappings/utils/retrieveVariables.ts new file mode 100644 index 000000000..386dbe4a7 --- /dev/null +++ b/kleros-sdk/src/dataMappings/utils/retrieveVariables.ts @@ -0,0 +1,20 @@ +import mustache from "mustache"; + +/** + * + * @param template + * @returns Variables[] returns the variables in a template string + * @note This is a naive implementation and wil not work for complex tags, only works for {{}} and {{{}}} tags for now. + * Reference : https://github.com/janl/mustache.js/issues/538 + */ +const retrieveVariables = (template: string) => + mustache + .parse(template) + .filter(function (v) { + return v[0] === "name" || v[0] === "&"; + }) // add more conditions here to include more tags + .map(function (v) { + return v[1]; + }); + +export default retrieveVariables; From 85f3668057ae2c3f04ff61e079233fdf064183c3 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 8 Oct 2024 16:27:49 +0530 Subject: [PATCH 02/37] chore(web): add-graph-api-key-env --- web/.env.devnet-university.public | 3 +++ web/.env.devnet.public | 3 +++ web/.env.local.public | 3 +++ web/.env.testnet.public | 3 +++ web/src/pages/DisputeTemplateView/index.tsx | 1 + 5 files changed, 13 insertions(+) diff --git a/web/.env.devnet-university.public b/web/.env.devnet-university.public index fb26be0b6..55ad0f793 100644 --- a/web/.env.devnet-university.public +++ b/web/.env.devnet-university.public @@ -8,3 +8,6 @@ export REACT_APP_ARBITRATOR_TYPE=university export WALLETCONNECT_PROJECT_ID= export ALCHEMY_API_KEY= export NODE_OPTIONS='--max-old-space-size=7680' + +# devtools +export REACT_APP_GRAPH_API_KEY= \ No newline at end of file diff --git a/web/.env.devnet.public b/web/.env.devnet.public index 0fca24c7b..552b3566a 100644 --- a/web/.env.devnet.public +++ b/web/.env.devnet.public @@ -7,3 +7,6 @@ export REACT_APP_GENESIS_BLOCK_ARBSEPOLIA=3084598 export WALLETCONNECT_PROJECT_ID= export ALCHEMY_API_KEY= export NODE_OPTIONS='--max-old-space-size=7680' + +# devtools +export REACT_APP_GRAPH_API_KEY= diff --git a/web/.env.local.public b/web/.env.local.public index 3128b605e..d54967d71 100644 --- a/web/.env.local.public +++ b/web/.env.local.public @@ -5,3 +5,6 @@ export REACT_APP_DRT_ARBSEPOLIA_SUBGRAPH=https://api.thegraph.com/subgraphs/name export WALLETCONNECT_PROJECT_ID= export ALCHEMY_API_KEY= export NODE_OPTIONS='--max-old-space-size=7680' + +# devtools +export REACT_APP_GRAPH_API_KEY= \ No newline at end of file diff --git a/web/.env.testnet.public b/web/.env.testnet.public index da92c1742..df48e0419 100644 --- a/web/.env.testnet.public +++ b/web/.env.testnet.public @@ -7,3 +7,6 @@ export REACT_APP_GENESIS_BLOCK_ARBSEPOLIA=3842783 export WALLETCONNECT_PROJECT_ID= export ALCHEMY_API_KEY= export NODE_OPTIONS='--max-old-space-size=7680' + +# devtools +export REACT_APP_GRAPH_API_KEY= \ No newline at end of file diff --git a/web/src/pages/DisputeTemplateView/index.tsx b/web/src/pages/DisputeTemplateView/index.tsx index 510cf6fbc..38e4a5ddb 100644 --- a/web/src/pages/DisputeTemplateView/index.tsx +++ b/web/src/pages/DisputeTemplateView/index.tsx @@ -173,6 +173,7 @@ const DisputeTemplateView = () => { templateID: debouncedParams._templateId, templateUri: debouncedParams._templateUri, alchemyApiKey: import.meta.env.ALCHEMY_API_KEY, + graphApiKey: import.meta.env.REACT_APP_GRAPH_API_KEY, }; const fetchData = async () => { From cdbbcf2d06ac4e51ca076e9d23e0ef8afc938013 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Fri, 11 Oct 2024 10:55:44 +0530 Subject: [PATCH 03/37] feat(subgraph): fetch-dispute-request-event-data-within-subgraph --- subgraph/core/schema.graphql | 4 ++ subgraph/core/src/entities/Dispute.ts | 70 +++++++++++++++++++++++++++ subgraph/core/subgraph.yaml | 13 ++--- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/subgraph/core/schema.graphql b/subgraph/core/schema.graphql index 3ed29d85f..0da8fa48a 100644 --- a/subgraph/core/schema.graphql +++ b/subgraph/core/schema.graphql @@ -174,6 +174,10 @@ type Dispute @entity { jurors: [User!]! @derivedFrom(field: "disputes") shifts: [TokenAndETHShift!]! @derivedFrom(field: "dispute") disputeKitDispute: [DisputeKitDispute!]! @derivedFrom(field: "coreDispute") + isCrossChain: Boolean + arbitrableChainId:BigInt + externalDisputeId:BigInt + templateId:BigInt } type PeriodIndexCounter @entity { diff --git a/subgraph/core/src/entities/Dispute.ts b/subgraph/core/src/entities/Dispute.ts index 5fe16c892..4bf09e697 100644 --- a/subgraph/core/src/entities/Dispute.ts +++ b/subgraph/core/src/entities/Dispute.ts @@ -1,3 +1,4 @@ +import { BigInt, ByteArray, crypto, dataSource, ethereum } from "@graphprotocol/graph-ts"; import { KlerosCore, DisputeCreation } from "../../generated/KlerosCore/KlerosCore"; import { Court, Dispute } from "../../generated/schema"; import { ZERO } from "../utils"; @@ -27,4 +28,73 @@ export function createDisputeFromEvent(event: DisputeCreation): void { const roundID = `${disputeID.toString()}-${ZERO.toString()}`; dispute.currentRound = roundID; dispute.save(); + + updateDisputeRequestData(event); +} + +const DisputeRequest = "DisputeRequest(address,uint256,uint256,uint256,string)"; + +const DisputeRequestSignature = crypto.keccak256(ByteArray.fromUTF8(DisputeRequest)); + +// note : we are using bytes32 in place of string as strings cannot be decoded and it breaks the function. +// It is okay for us, as we are interested in the uint256 in front +// _externalDisputeId,_templateId,_tenplateUri +const DisputeRequestTypestring = "(uint256,uint256,bytes32)"; + +const CrossChainDisputeIncoming = + "CrossChainDisputeIncoming(address,uint256,address,uint256,uint256,uint256,uint256,string)"; + +const CrossChainDisputeIncomingSignature = crypto.keccak256(ByteArray.fromUTF8(CrossChainDisputeIncoming)); + +// arbitrator, _arbitrableChainId, _externalDisputeId, _templateId, _templateUri +// note : arbitrable is an indexed arg, so it will topic[1] +const CrossChainDisputeIncomingTypestring = "(address,uint256,uint256,uint256,string)"; + +export const updateDisputeRequestData = (event: DisputeCreation): void => { + const dispute = Dispute.load(event.params._disputeID.toString()); + + if (!dispute) return; + + const receipt = event.receipt; + if (!receipt) return; + + const logs = receipt.logs; + + // note that the topic at 0th index is always the event signature + const disputeRequestEventIndex = logs.findIndex((log) => log.topics[0] == DisputeRequestSignature); + + const crossChainDisputeEventIndex = logs.findIndex((log) => log.topics[0] == CrossChainDisputeIncomingSignature); + + if (crossChainDisputeEventIndex !== -1) { + const crossChainDisputeEvent = logs[crossChainDisputeEventIndex]; + + const decoded = ethereum.decode(CrossChainDisputeIncomingTypestring, crossChainDisputeEvent.data); + + if (!decoded) return; + + dispute.isCrossChain = true; + dispute.arbitrableChainId = decoded.toTuple()[1].toBigInt(); + dispute.externalDisputeId = decoded.toTuple()[2].toBigInt(); + dispute.templateId = decoded.toTuple()[3].toBigInt(); + dispute.save(); + return; + } else if (disputeRequestEventIndex !== -1) { + const disputeRequestEvent = logs[disputeRequestEventIndex]; + + const decoded = ethereum.decode(DisputeRequestTypestring, disputeRequestEvent.data); + if (!decoded) return; + dispute.isCrossChain = false; + dispute.arbitrableChainId = getChainId(dataSource.network()); + dispute.externalDisputeId = decoded.toTuple()[0].toBigInt(); + dispute.templateId = decoded.toTuple()[1].toBigInt(); + dispute.save(); + return; + } +}; + +// workaround, since hashmap don't work in subgraphs +function getChainId(name: string): BigInt { + if (name == "arbitrum-one") return BigInt.fromI32(42161); + else if (name == "arbitrum-sepolia") return BigInt.fromI32(421614); + else return BigInt.fromI32(1); } diff --git a/subgraph/core/subgraph.yaml b/subgraph/core/subgraph.yaml index f431077d9..fc3501e9c 100644 --- a/subgraph/core/subgraph.yaml +++ b/subgraph/core/subgraph.yaml @@ -1,4 +1,4 @@ -specVersion: 0.0.4 +specVersion: 0.0.5 schema: file: ./schema.graphql features: @@ -14,7 +14,7 @@ dataSources: startBlock: 3638878 mapping: kind: ethereum/events - apiVersion: 0.0.6 + apiVersion: 0.0.7 language: wasm/assemblyscript entities: - User @@ -39,6 +39,7 @@ dataSources: handler: handleAppealDecision - event: DisputeCreation(indexed uint256,indexed address) handler: handleDisputeCreation + receipt: true - event: Draw(indexed address,indexed uint256,uint256,uint256) handler: handleDraw - event: NewPeriod(indexed uint256,uint8) @@ -69,7 +70,7 @@ dataSources: startBlock: 3084568 mapping: kind: ethereum/events - apiVersion: 0.0.6 + apiVersion: 0.0.7 language: wasm/assemblyscript entities: - Court @@ -89,7 +90,7 @@ dataSources: startBlock: 3638835 mapping: kind: ethereum/events - apiVersion: 0.0.6 + apiVersion: 0.0.7 language: wasm/assemblyscript entities: - ClassicDispute @@ -124,7 +125,7 @@ dataSources: startBlock: 3638735 mapping: kind: ethereum/events - apiVersion: 0.0.6 + apiVersion: 0.0.7 language: wasm/assemblyscript entities: - ClassicEvidenceGroup @@ -145,7 +146,7 @@ dataSources: startBlock: 3638850 mapping: kind: ethereum/events - apiVersion: 0.0.6 + apiVersion: 0.0.7 language: wasm/assemblyscript entities: - JurorTokensPerCourt From c59e102b176f1f5462b54d1dc80abc19fb8b8357 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 14 Oct 2024 13:07:43 +0530 Subject: [PATCH 04/37] feat(kleros-sdk): get-dispute-function --- kleros-sdk/package.json | 1 + kleros-sdk/src/dataMappings/executeActions.ts | 2 +- .../src/requests/fetchDisputeDetails.ts | 40 ++++++ .../requests/fetchDisputeTemplateFromId.ts | 32 +++++ kleros-sdk/src/sdk.ts | 19 ++- kleros-sdk/src/types/index.ts | 17 +++ kleros-sdk/src/utils/getDispute.ts | 46 +++++++ yarn.lock | 114 +++++++++++++++++- 8 files changed, 256 insertions(+), 15 deletions(-) create mode 100644 kleros-sdk/src/requests/fetchDisputeDetails.ts create mode 100644 kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts create mode 100644 kleros-sdk/src/types/index.ts create mode 100644 kleros-sdk/src/utils/getDispute.ts diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 9f2421d07..d32585e12 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -35,6 +35,7 @@ "dependencies": { "@kleros/kleros-v2-contracts": "workspace:^", "@reality.eth/reality-eth-lib": "^3.2.30", + "graphql-request": "^7.1.0", "mustache": "^4.2.0", "zod": "^3.22.4" } diff --git a/kleros-sdk/src/dataMappings/executeActions.ts b/kleros-sdk/src/dataMappings/executeActions.ts index c5b7c8fbc..71e598ce3 100644 --- a/kleros-sdk/src/dataMappings/executeActions.ts +++ b/kleros-sdk/src/dataMappings/executeActions.ts @@ -37,7 +37,7 @@ export const executeAction = async (mapping: ActionMapping, context: Record { +export const executeActions = async (mappings, initialContext: Record = {}) => { const context = { ...initialContext }; for (const mapping of mappings) { diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts new file mode 100644 index 000000000..b530b1e7e --- /dev/null +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -0,0 +1,40 @@ +import { request } from "graphql-request"; + +type DisputeDetailsQueryResponse = { + dispute: { + arbitrated: { + id: string; + }; + arbitrableChainId: number; + externalDisputeId: number; + templateId: number; + }; +}; + +const fetchDisputeDetails = (endpoint: string, id: number) => { + const query = ` + query DisputeDetails { + dispute(id: ${id}) { + arbitrated { + id + } + arbitrableChainId + externalDisputeId + templateId + } + } +`; + + try { + return request(endpoint, query) + .then((res) => res) + .catch((err) => { + throw new Error(`Error querying Dispute Details , endpoint : ${endpoint}, message : ${err?.message}`); + }); + } catch (error: any) { + console.log(`Query Error : ${error?.message}`); + return undefined; + } +}; + +export default fetchDisputeDetails; diff --git a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts new file mode 100644 index 000000000..d70a64437 --- /dev/null +++ b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts @@ -0,0 +1,32 @@ +import { request } from "graphql-request"; + +type DisputeTemplateQueryResponse = { + disputeTemplate: { + templateData: string; + templateDataMappings: string; + }; +}; + +const fetchDisputeTemplateFromId = (endpoint: string, id: number) => { + const query = ` + query DisputeTemplate { + disputeTemplate(id: ${id}) { + templateData + templateDataMappings + } + } +`; + + try { + return request(endpoint, query) + .then((res) => res) + .catch((err) => { + throw new Error(`Error querying Dispute Template Registry , endpoint : ${endpoint}, message : ${err?.message}`); + }); + } catch (error: any) { + console.log(`Query Error : ${error?.message}`); + return undefined; + } +}; + +export default fetchDisputeTemplateFromId; diff --git a/kleros-sdk/src/sdk.ts b/kleros-sdk/src/sdk.ts index 9a9202a3e..cce4605e2 100644 --- a/kleros-sdk/src/sdk.ts +++ b/kleros-sdk/src/sdk.ts @@ -1,20 +1,15 @@ -import { createPublicClient, webSocket } from "viem"; -import { arbitrumSepolia } from "viem/chains"; +import { createPublicClient, type PublicClient } from "viem"; +import { SdkConfig } from "./types"; -let publicClient; +let publicClient: PublicClient | undefined; -export const configureSDK = (config: { apiKey?: string }) => { - if (config.apiKey) { - const ALCHEMY_API_KEY = config.apiKey; - const transport = webSocket(`wss://arb-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}`); - publicClient = createPublicClient({ - chain: arbitrumSepolia, - transport, - }); +export const configureSDK = (config: SdkConfig) => { + if (config.client) { + publicClient = createPublicClient(config.client); } }; -export const getPublicClient = () => { +export const getPublicClient = (): PublicClient | undefined => { if (!publicClient) { throw new Error("SDK not configured. Please call `configureSDK` before using."); } diff --git a/kleros-sdk/src/types/index.ts b/kleros-sdk/src/types/index.ts new file mode 100644 index 000000000..7c0d5ea9a --- /dev/null +++ b/kleros-sdk/src/types/index.ts @@ -0,0 +1,17 @@ +import { PublicClientConfig } from "viem"; + +export type SdkConfig = { + client: PublicClientConfig; +}; + +type GetDisputeParametersOptions = { + sdkConfig: SdkConfig; + additionalContext: Record; +}; + +export type GetDisputeParameters = { + disputeId: number; + coreSubgraph: string; + dtrSubgraph: string; + options: GetDisputeParametersOptions | undefined; +}; diff --git a/kleros-sdk/src/utils/getDispute.ts b/kleros-sdk/src/utils/getDispute.ts new file mode 100644 index 000000000..f24b251bb --- /dev/null +++ b/kleros-sdk/src/utils/getDispute.ts @@ -0,0 +1,46 @@ +import { type GetDisputeParameters } from "src/types"; +import { configureSDK } from "src/sdk"; +import fetchDisputeDetails from "src/requests/fetchDisputeDetails"; +import fetchDisputeTemplateFromId from "src/requests/fetchDisputeTemplateFromId"; +import { executeActions } from "dataMappings/executeActions"; +import { populateTemplate } from "dataMappings/utils/populateTemplate"; +import { DisputeDetails } from "dataMappings/utils/disputeDetailsTypes"; + +/** + * Retrieves dispute parameters based on the provided dispute ID and subgraph endpoints. + * + * @param {GetDisputeParameters} disputeParameters - The parameters required to get the dispute. + * @param {number} disputeParameters.disputeId - A unique numeric identifier of the dispute in the Kleros Core contract. + * @param {string} disputeParameters.coreSubgraph - Endpoint for the Kleros core subgraph to use. + * @param {string} disputeParameters.dtrSubgraph - Endpoint for the Kleros dispute template registry subgraph. + * @param {GetDisputeParametersOptions | undefined} disputeParameters.options - Optional parameters to configure the SDK and provide additional context, if not configured already. + */ +export const getDispute = async (disputeParameters: GetDisputeParameters): Promise => { + if (disputeParameters.options?.sdkConfig) { + configureSDK(disputeParameters.options.sdkConfig); + } + const { disputeId, dtrSubgraph, coreSubgraph, options } = disputeParameters; + + const disputeDetails = await fetchDisputeDetails(coreSubgraph, disputeId); + + if (!disputeDetails || !disputeDetails.dispute) return; + + const template = await fetchDisputeTemplateFromId(dtrSubgraph, disputeDetails.dispute.templateId); + + if (!template) return; + + const { templateData, templateDataMappings } = template.disputeTemplate; + + const initialContext = { + arbitrableAddress: disputeDetails.dispute.arbitrated.id, + arbitrableChainID: disputeDetails.dispute.arbitrableChainId, + externalDisputeID: disputeDetails.dispute.externalDisputeId, + ...options?.additionalContext, + }; + + const data = templateDataMappings ? await executeActions(JSON.parse(templateDataMappings), initialContext) : {}; + + const populatedTemplate = populateTemplate(templateData, data); + + return populatedTemplate; +}; diff --git a/yarn.lock b/yarn.lock index 6897e8531..9247612e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6437,6 +6437,7 @@ __metadata: "@reality.eth/reality-eth-lib": "npm:^3.2.30" "@types/mustache": "npm:^4.2.5" "@vitest/ui": "npm:^1.1.3" + graphql-request: "npm:^7.1.0" mocha: "npm:^10.2.0" mustache: "npm:^4.2.0" ts-node: "npm:^10.9.2" @@ -7334,6 +7335,34 @@ __metadata: languageName: node linkType: hard +"@molt/command@npm:^0.9.0": + version: 0.9.0 + resolution: "@molt/command@npm:0.9.0" + dependencies: + "@molt/types": "npm:0.2.0" + alge: "npm:0.8.1" + chalk: "npm:^5.3.0" + lodash.camelcase: "npm:^4.3.0" + lodash.snakecase: "npm:^4.1.1" + readline-sync: "npm:^1.4.10" + string-length: "npm:^6.0.0" + strip-ansi: "npm:^7.1.0" + ts-toolbelt: "npm:^9.6.0" + type-fest: "npm:^4.3.1" + zod: "npm:^3.22.2" + checksum: e6ec7c6c2c6a64a1b28e09074196e5aa891bdcbff4129e54c59b902e1b6f4151033fd92c8535666be32267163d04ce3ce454ca0df0a4d5669a8506817131984e + languageName: node + linkType: hard + +"@molt/types@npm:0.2.0": + version: 0.2.0 + resolution: "@molt/types@npm:0.2.0" + dependencies: + ts-toolbelt: "npm:^9.6.0" + checksum: 0c7eab1dda0d689fda7025b4e4b37ffc290a7e2f7bfb0463a8bffc5834c30af66ab92d63bc2f71dc515cdd0121fc3587596690353a7e1c40d530395135540063 + languageName: node + linkType: hard + "@motionone/animation@npm:^10.15.1": version: 10.15.1 resolution: "@motionone/animation@npm:10.15.1" @@ -13031,6 +13060,18 @@ __metadata: languageName: node linkType: hard +"alge@npm:0.8.1": + version: 0.8.1 + resolution: "alge@npm:0.8.1" + dependencies: + lodash.ismatch: "npm:^4.4.0" + remeda: "npm:^1.0.0" + ts-toolbelt: "npm:^9.6.0" + zod: "npm:^3.17.3" + checksum: 11483523289bc7750b6462698a2b61c816bf3c7eada2ade206bc02b964679b6bf4b298cc561ae267f382573668b68ff311a0aec60c5ae011aecde491932240e8 + languageName: node + linkType: hard + "amdefine@npm:>=0.0.4": version: 1.0.1 resolution: "amdefine@npm:1.0.1" @@ -15089,7 +15130,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:5.3.0": +"chalk@npm:5.3.0, chalk@npm:^5.3.0": version: 5.3.0 resolution: "chalk@npm:5.3.0" checksum: 6373caaab21bd64c405bfc4bd9672b145647fc9482657b5ea1d549b3b2765054e9d3d928870cdf764fb4aad67555f5061538ff247b8310f110c5c888d92397ea @@ -21343,6 +21384,31 @@ __metadata: languageName: node linkType: hard +"graphql-request@npm:^7.1.0": + version: 7.1.0 + resolution: "graphql-request@npm:7.1.0" + dependencies: + "@graphql-typed-document-node/core": "npm:^3.2.0" + "@molt/command": "npm:^0.9.0" + zod: "npm:^3.23.8" + peerDependencies: + "@dprint/formatter": ^0.3.0 + "@dprint/typescript": ^0.91.1 + dprint: ^0.46.2 + graphql: 14 - 16 + peerDependenciesMeta: + "@dprint/formatter": + optional: true + "@dprint/typescript": + optional: true + dprint: + optional: true + bin: + graffle: build/cli/generate.js + checksum: 6e61cd8200f9842569a657b0fdc0cb45a8433d8afa730ace911fa9a09318fb3cae3ccd9396a9ab2e1795bf9ccbce976fc90fb0bfac9dfe2fc821e74845be57d9 + languageName: node + linkType: hard + "graphql-tag@npm:^2.11.0": version: 2.12.6 resolution: "graphql-tag@npm:2.12.6" @@ -31351,6 +31417,13 @@ __metadata: languageName: node linkType: hard +"readline-sync@npm:^1.4.10": + version: 1.4.10 + resolution: "readline-sync@npm:1.4.10" + checksum: 5eb6465f5c5391e32cb525022a307a910a565828cd53da87ac05fca291607df54099dd65bc9c7a513ac53a5eb4e11454d48f0dcf4ad54126d36dec5fcec4a8f0 + languageName: node + linkType: hard + "real-require@npm:^0.1.0": version: 0.1.0 resolution: "real-require@npm:0.1.0" @@ -31598,6 +31671,13 @@ __metadata: languageName: node linkType: hard +"remeda@npm:^1.0.0": + version: 1.61.0 + resolution: "remeda@npm:1.61.0" + checksum: 0b0ec8688e340c7525a8788e99701b174ddca2eaf230d47f9e087d9aaccd54c7181a1f58bf4f95cb9c12bc1d26f03b17e3d3d9046a59225074a7ac3fa1356da3 + languageName: node + linkType: hard + "remedial@npm:^1.0.7": version: 1.0.8 resolution: "remedial@npm:1.0.8" @@ -33913,6 +33993,15 @@ __metadata: languageName: node linkType: hard +"string-length@npm:^6.0.0": + version: 6.0.0 + resolution: "string-length@npm:6.0.0" + dependencies: + strip-ansi: "npm:^7.1.0" + checksum: b171e9e193ec292ad71f8b2a36e20478bf1bac8cd5beec062fb126942d627dfd9311959e271e9ab7b0a383d16b85b9e25a183d15786e30f22104d152e7627f99 + languageName: node + linkType: hard + "string-natural-compare@npm:^3.0.1": version: 3.0.1 resolution: "string-natural-compare@npm:3.0.1" @@ -34128,7 +34217,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.1": +"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": version: 7.1.0 resolution: "strip-ansi@npm:7.1.0" dependencies: @@ -35300,6 +35389,13 @@ __metadata: languageName: node linkType: hard +"ts-toolbelt@npm:^9.6.0": + version: 9.6.0 + resolution: "ts-toolbelt@npm:9.6.0" + checksum: 2c2dea2631dbd7372a79cccc6d09a377a6ca2f319f767fd239d2e312cd1d9165a90f8c1777a047227bfdcda6aeba3addbadce88fdfc7f43caf4534d385a43c82 + languageName: node + linkType: hard + "tsconfck@npm:^3.0.3": version: 3.0.3 resolution: "tsconfck@npm:3.0.3" @@ -35509,6 +35605,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^4.3.1": + version: 4.26.1 + resolution: "type-fest@npm:4.26.1" + checksum: b82676194f80af228cb852e320d2ea8381c89d667d2e4d9f2bdfc8f254bccc039c7741a90c53617a4de0c9fdca8265ed18eb0888cd628f391c5c381c33a9f94b + languageName: node + linkType: hard + "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -38133,6 +38236,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:^3.17.3, zod@npm:^3.23.8": + version: 3.23.8 + resolution: "zod@npm:3.23.8" + checksum: 846fd73e1af0def79c19d510ea9e4a795544a67d5b34b7e1c4d0425bf6bfd1c719446d94cdfa1721c1987d891321d61f779e8236fde517dc0e524aa851a6eff1 + languageName: node + linkType: hard + "zod@npm:^3.21.4": version: 3.21.4 resolution: "zod@npm:3.21.4" From 220ea2f23745f5326747c0e7b236213f211e778f Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 14 Oct 2024 17:26:12 +0530 Subject: [PATCH 05/37] chore(web): update-dispute-population-flow --- .../hooks/queries/useDisputeDetailsQuery.ts | 4 ++ web/src/hooks/queries/useEvidenceGroup.ts | 41 ----------- .../hooks/queries/usePopulatedDisputeData.ts | 62 ++++------------- web/src/hooks/useIsCrossChainDispute.ts | 69 ------------------- .../Cases/CaseDetails/Evidence/index.tsx | 10 +-- web/src/pages/Cases/CaseDetails/index.tsx | 2 +- 6 files changed, 23 insertions(+), 165 deletions(-) delete mode 100644 web/src/hooks/queries/useEvidenceGroup.ts delete mode 100644 web/src/hooks/useIsCrossChainDispute.ts diff --git a/web/src/hooks/queries/useDisputeDetailsQuery.ts b/web/src/hooks/queries/useDisputeDetailsQuery.ts index 4fd0e5029..c5b359d08 100644 --- a/web/src/hooks/queries/useDisputeDetailsQuery.ts +++ b/web/src/hooks/queries/useDisputeDetailsQuery.ts @@ -30,6 +30,10 @@ const disputeDetailsQuery = graphql(` nbVotes } currentRoundIndex + isCrossChain + arbitrableChainId + externalDisputeId + templateId } } `); diff --git a/web/src/hooks/queries/useEvidenceGroup.ts b/web/src/hooks/queries/useEvidenceGroup.ts deleted file mode 100644 index d1e09f90a..000000000 --- a/web/src/hooks/queries/useEvidenceGroup.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { getContract } from "viem"; -import { usePublicClient } from "wagmi"; - -import { GENESIS_BLOCK_ARBSEPOLIA } from "consts/index"; -import { iArbitrableV2Abi } from "hooks/contracts/generated"; -import { isUndefined } from "utils/index"; - -export const useEvidenceGroup = (disputeID?: string, arbitrableAddress?: `0x${string}`) => { - const isEnabled = !isUndefined(arbitrableAddress); - const publicClient = usePublicClient(); - return useQuery({ - queryKey: [`EvidenceGroup${disputeID}${arbitrableAddress}`], - enabled: isEnabled, - staleTime: Infinity, - queryFn: async () => { - if (arbitrableAddress && !isUndefined(disputeID)) { - const arbitrable = getContract({ - abi: iArbitrableV2Abi, - address: arbitrableAddress, - client: { public: publicClient }, - }); - const disputeFilter = await arbitrable.createEventFilter.DisputeRequest( - { - _arbitrableDisputeID: BigInt(disputeID), - }, - { - fromBlock: GENESIS_BLOCK_ARBSEPOLIA, - toBlock: "latest", - } - ); - - const disputeEvents = await publicClient.getFilterLogs({ - filter: disputeFilter, - }); - - return disputeEvents[0].args._externalDisputeID; - } else throw Error; - }, - }); -}; diff --git a/web/src/hooks/queries/usePopulatedDisputeData.ts b/web/src/hooks/queries/usePopulatedDisputeData.ts index 93e79d3a8..8175d6354 100644 --- a/web/src/hooks/queries/usePopulatedDisputeData.ts +++ b/web/src/hooks/queries/usePopulatedDisputeData.ts @@ -1,22 +1,17 @@ import { useQuery } from "@tanstack/react-query"; -import { getContract, HttpRequestError, PublicClient, RpcError } from "viem"; -import { usePublicClient } from "wagmi"; +import { HttpRequestError, RpcError } from "viem"; import { executeActions } from "@kleros/kleros-sdk/src/dataMappings/executeActions"; import { DisputeDetails } from "@kleros/kleros-sdk/src/dataMappings/utils/disputeDetailsTypes"; import { populateTemplate } from "@kleros/kleros-sdk/src/dataMappings/utils/populateTemplate"; -import { GENESIS_BLOCK_ARBSEPOLIA } from "consts/index"; import { useGraphqlBatcher } from "context/GraphqlBatcher"; -import { iArbitrableV2Abi } from "hooks/contracts/generated"; -import { useEvidenceGroup } from "queries/useEvidenceGroup"; import { debounceErrorToast } from "utils/debounceErrorToast"; import { isUndefined } from "utils/index"; -import { DEFAULT_CHAIN } from "consts/chains"; import { graphql } from "src/graphql"; -import { useIsCrossChainDispute } from "../useIsCrossChainDispute"; +import { useDisputeDetailsQuery } from "./useDisputeDetailsQuery"; const disputeTemplateQuery = graphql(` query DisputeTemplate($id: ID!) { @@ -30,33 +25,27 @@ const disputeTemplateQuery = graphql(` `); export const usePopulatedDisputeData = (disputeID?: string, arbitrableAddress?: `0x${string}`) => { - const publicClient = usePublicClient(); - const { data: crossChainData, isError } = useIsCrossChainDispute(disputeID, arbitrableAddress); + const { data: disputeData } = useDisputeDetailsQuery(disputeID); const { graphqlBatcher } = useGraphqlBatcher(); - const { data: externalDisputeID } = useEvidenceGroup(disputeID, arbitrableAddress); const isEnabled = !isUndefined(disputeID) && - !isUndefined(crossChainData) && - !isUndefined(arbitrableAddress) && - !isUndefined(externalDisputeID); + !isUndefined(disputeData) && + !isUndefined(disputeData?.dispute) && + !isUndefined(disputeData.dispute?.arbitrableChainId) && + !isUndefined(disputeData.dispute?.externalDisputeId) && + !isUndefined(disputeData.dispute?.templateId); return useQuery({ - queryKey: [`DisputeTemplate${disputeID}${arbitrableAddress}${externalDisputeID}`], + queryKey: [`DisputeTemplate${disputeID}${arbitrableAddress}${disputeData?.dispute?.externalDisputeId}`], enabled: isEnabled, staleTime: Infinity, queryFn: async () => { - if (isEnabled && !isError) { + if (isEnabled) { try { - const { isCrossChainDispute, crossChainTemplateId } = crossChainData; - - const templateId = isCrossChainDispute - ? crossChainTemplateId - : await getTemplateId(arbitrableAddress, disputeID, publicClient); - const { disputeTemplate } = await graphqlBatcher.fetch({ id: crypto.randomUUID(), document: disputeTemplateQuery, - variables: { id: templateId.toString() }, + variables: { id: disputeData.dispute?.templateId.toString() }, isDisputeTemplate: true, }); @@ -66,10 +55,10 @@ export const usePopulatedDisputeData = (disputeID?: string, arbitrableAddress?: const initialContext = { disputeID: disputeID, arbitrableAddress: arbitrableAddress, - arbitrableChainID: isCrossChainDispute ? crossChainData.crossChainId.toString() : DEFAULT_CHAIN.toString(), + arbitrableChainID: disputeData.dispute?.arbitrableChainId, graphApiKey: import.meta.env.REACT_APP_GRAPH_API_KEY, alchemyApiKey: import.meta.env.ALCHEMY_API_KEY, - externalDisputeID: externalDisputeID, + externalDisputeID: disputeData.dispute?.externalDisputeId, }; const data = dataMappings ? await executeActions(JSON.parse(dataMappings), initialContext) : {}; @@ -88,28 +77,3 @@ export const usePopulatedDisputeData = (disputeID?: string, arbitrableAddress?: }, }); }; - -const getTemplateId = async ( - arbitrableAddress: `0x${string}`, - disputeID: string, - publicClient: PublicClient -): Promise => { - const arbitrable = getContract({ - abi: iArbitrableV2Abi, - address: arbitrableAddress, - client: { public: publicClient }, - }); - const disputeFilter = await arbitrable.createEventFilter.DisputeRequest( - { - _arbitrableDisputeID: BigInt(disputeID), - }, - { - fromBlock: GENESIS_BLOCK_ARBSEPOLIA, - toBlock: "latest", - } - ); - const disputeEvents = await publicClient.getFilterLogs({ - filter: disputeFilter, - }); - return disputeEvents[0].args._templateId ?? 0n; -}; diff --git a/web/src/hooks/useIsCrossChainDispute.ts b/web/src/hooks/useIsCrossChainDispute.ts deleted file mode 100644 index 61540a080..000000000 --- a/web/src/hooks/useIsCrossChainDispute.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { HttpRequestError, RpcError, getContract } from "viem"; -import { usePublicClient } from "wagmi"; - -import { GENESIS_BLOCK_ARBSEPOLIA } from "consts/index"; -import { iHomeGatewayAbi } from "hooks/contracts/generated"; -import { debounceErrorToast } from "utils/debounceErrorToast"; -import { isUndefined } from "utils/index"; - -interface IIsCrossChainDispute { - isCrossChainDispute: boolean; - crossChainId: bigint; - crossChainTemplateId: bigint; - crossChainArbitrableAddress: `0x${string}`; -} - -export const useIsCrossChainDispute = (disputeID?: string, arbitrableAddress?: `0x${string}`) => { - const isEnabled = !isUndefined(arbitrableAddress) && !isUndefined(disputeID); - const publicClient = usePublicClient(); - return useQuery({ - queryKey: [`IsCrossChainDispute${disputeID}`], - enabled: isEnabled, - staleTime: Infinity, - queryFn: async () => { - if (isEnabled) { - try { - const arbitrable = getContract({ - abi: iHomeGatewayAbi, - address: arbitrableAddress, - client: { public: publicClient }, - }); - const crossChainDisputeFilter = await arbitrable.createEventFilter.CrossChainDisputeIncoming( - { - _arbitratorDisputeID: BigInt(disputeID), - }, - { - fromBlock: GENESIS_BLOCK_ARBSEPOLIA, - toBlock: "latest", - } - ); - const crossChainDisputeEvents = await publicClient.getFilterLogs({ - filter: crossChainDisputeFilter, - }); - - if (crossChainDisputeEvents.length > 0) { - return { - isCrossChainDispute: true, - crossChainId: crossChainDisputeEvents[0].args._arbitrableChainId ?? 0n, - crossChainTemplateId: crossChainDisputeEvents[0].args._templateId ?? 0n, - crossChainArbitrableAddress: crossChainDisputeEvents[0].args._arbitrable ?? "0x", - }; - } else { - return { - isCrossChainDispute: false, - crossChainId: 0n, - crossChainTemplateId: 0n, - crossChainArbitrableAddress: "0x", - }; - } - } catch (error) { - if (error instanceof HttpRequestError || error instanceof RpcError) { - debounceErrorToast("RPC failed!, Please avoid voting."); - } - throw Error; - } - } else throw Error; - }, - }); -}; diff --git a/web/src/pages/Cases/CaseDetails/Evidence/index.tsx b/web/src/pages/Cases/CaseDetails/Evidence/index.tsx index 8c088edfc..361936cd4 100644 --- a/web/src/pages/Cases/CaseDetails/Evidence/index.tsx +++ b/web/src/pages/Cases/CaseDetails/Evidence/index.tsx @@ -8,7 +8,7 @@ import { Button } from "@kleros/ui-components-library"; import DownArrow from "svgs/icons/arrow-down.svg"; -import { useEvidenceGroup } from "queries/useEvidenceGroup"; +import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { useEvidences } from "queries/useEvidences"; import { responsiveSize } from "styles/responsiveSize"; @@ -54,14 +54,14 @@ const ScrollButton = styled(Button)` } `; -const Evidence: React.FC<{ arbitrable?: `0x${string}` }> = ({ arbitrable }) => { +const Evidence: React.FC = () => { const { id } = useParams(); - const { data: evidenceGroup } = useEvidenceGroup(id, arbitrable); + const { data: disputeData } = useDisputeDetailsQuery(id); const ref = useRef(null); const [search, setSearch] = useState(); const [debouncedSearch, setDebouncedSearch] = useState(); - const { data } = useEvidences(evidenceGroup?.toString(), debouncedSearch); + const { data } = useEvidences(disputeData?.dispute?.externalDisputeId?.toString(), debouncedSearch); useDebounce(() => setDebouncedSearch(search), 500, [search]); @@ -76,7 +76,7 @@ const Evidence: React.FC<{ arbitrable?: `0x${string}` }> = ({ arbitrable }) => { return ( - + {data ? ( data.evidences.map(({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => ( diff --git a/web/src/pages/Cases/CaseDetails/index.tsx b/web/src/pages/Cases/CaseDetails/index.tsx index 3f624c000..aa4e54047 100644 --- a/web/src/pages/Cases/CaseDetails/index.tsx +++ b/web/src/pages/Cases/CaseDetails/index.tsx @@ -64,7 +64,7 @@ const CaseDetails: React.FC = () => { } /> - } /> + } /> } /> } /> } /> From 6974fdbc34ebf8d44c8a38db06c128df5675b989 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 14 Oct 2024 20:49:16 +0530 Subject: [PATCH 06/37] chore(web): configure-sdk-with-web3-context --- web/src/context/Web3Provider.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/web/src/context/Web3Provider.tsx b/web/src/context/Web3Provider.tsx index acb3f0784..3bf2a0e32 100644 --- a/web/src/context/Web3Provider.tsx +++ b/web/src/context/Web3Provider.tsx @@ -6,6 +6,8 @@ import { createConfig, fallback, http, WagmiProvider, webSocket } from "wagmi"; import { mainnet, arbitrumSepolia, arbitrum, gnosisChiado, gnosis, sepolia } from "wagmi/chains"; import { walletConnect } from "wagmi/connectors"; +import { configureSDK } from "@kleros/kleros-sdk/src/sdk"; + import { ALL_CHAINS, DEFAULT_CHAIN } from "consts/chains"; import { isProductionDeployment } from "consts/index"; @@ -36,9 +38,10 @@ export const getDefaultChainRpcUrl = (protocol: AlchemyProtocol) => { return getChainRpcUrl(protocol, DEFAULT_CHAIN); }; +const alchemyTransport = (chain: Chain) => + fallback([http(alchemyURL("https", chain.id)), webSocket(alchemyURL("wss", chain.id))]); + export const getTransports = () => { - const alchemyTransport = (chain: Chain) => - fallback([http(alchemyURL("https", chain.id)), webSocket(alchemyURL("wss", chain.id))]); const defaultTransport = (chain: Chain) => fallback([http(chain.rpcUrls.default?.http?.[0]), webSocket(chain.rpcUrls.default?.webSocket?.[0])]); @@ -62,6 +65,13 @@ const wagmiConfig = createConfig({ connectors: [walletConnect({ projectId, showQrModal: false })], }); +configureSDK({ + client: { + chain: isProduction ? arbitrum : arbitrumSepolia, + transport: isProduction ? alchemyTransport(arbitrum) : alchemyTransport(arbitrumSepolia), + }, +}); + createWeb3Modal({ wagmiConfig, projectId, From 88963e7207dde4a23bb2c62f2eda22cac38a318b Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 14 Oct 2024 20:50:03 +0530 Subject: [PATCH 07/37] chore(kleros-sdk): make-configuring-sdk-explicit --- kleros-sdk/src/dataMappings/actions/callAction.ts | 5 ++--- kleros-sdk/src/dataMappings/actions/eventAction.ts | 5 ++--- kleros-sdk/src/dataMappings/executeActions.ts | 4 ++-- kleros-sdk/src/utils/getDispute.ts | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/kleros-sdk/src/dataMappings/actions/callAction.ts b/kleros-sdk/src/dataMappings/actions/callAction.ts index 795e8ceca..77e69d4b9 100644 --- a/kleros-sdk/src/dataMappings/actions/callAction.ts +++ b/kleros-sdk/src/dataMappings/actions/callAction.ts @@ -1,10 +1,9 @@ import { parseAbiItem } from "viem"; import { AbiCallMapping } from "src/dataMappings/utils/actionTypes"; import { createResultObject } from "src/dataMappings/utils/createResultObject"; -import { configureSDK, getPublicClient } from "src/sdk"; +import { getPublicClient } from "src/sdk"; -export const callAction = async (mapping: AbiCallMapping, alchemyApiKey: string) => { - configureSDK({ apiKey: alchemyApiKey }); +export const callAction = async (mapping: AbiCallMapping) => { const publicClient = getPublicClient(); const { abi: source, address, args, seek, populate } = mapping; diff --git a/kleros-sdk/src/dataMappings/actions/eventAction.ts b/kleros-sdk/src/dataMappings/actions/eventAction.ts index 73895720b..311598f6d 100644 --- a/kleros-sdk/src/dataMappings/actions/eventAction.ts +++ b/kleros-sdk/src/dataMappings/actions/eventAction.ts @@ -1,10 +1,9 @@ import { parseAbiItem } from "viem"; import { AbiEventMapping } from "src/dataMappings/utils/actionTypes"; import { createResultObject } from "src/dataMappings/utils/createResultObject"; -import { configureSDK, getPublicClient } from "src/sdk"; +import { getPublicClient } from "src/sdk"; -export const eventAction = async (mapping: AbiEventMapping, alchemyApiKey: string) => { - configureSDK({ apiKey: alchemyApiKey }); +export const eventAction = async (mapping: AbiEventMapping) => { const publicClient = getPublicClient(); const { abi: source, address, eventFilter, seek, populate } = mapping; diff --git a/kleros-sdk/src/dataMappings/executeActions.ts b/kleros-sdk/src/dataMappings/executeActions.ts index 71e598ce3..08d91a3dd 100644 --- a/kleros-sdk/src/dataMappings/executeActions.ts +++ b/kleros-sdk/src/dataMappings/executeActions.ts @@ -24,9 +24,9 @@ export const executeAction = async (mapping: ActionMapping, context: Record Date: Mon, 14 Oct 2024 21:07:02 +0530 Subject: [PATCH 08/37] refactor(kleros-sdk): implement-rabbit-ai-feedback --- kleros-sdk/src/requests/fetchDisputeDetails.ts | 11 +++-------- .../src/requests/fetchDisputeTemplateFromId.ts | 11 +++-------- kleros-sdk/src/utils/getDispute.ts | 17 ++++++++++++++--- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts index b530b1e7e..0b1796f2b 100644 --- a/kleros-sdk/src/requests/fetchDisputeDetails.ts +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -11,7 +11,7 @@ type DisputeDetailsQueryResponse = { }; }; -const fetchDisputeDetails = (endpoint: string, id: number) => { +const fetchDisputeDetails = async (endpoint: string, id: number) => { const query = ` query DisputeDetails { dispute(id: ${id}) { @@ -26,14 +26,9 @@ const fetchDisputeDetails = (endpoint: string, id: number) => { `; try { - return request(endpoint, query) - .then((res) => res) - .catch((err) => { - throw new Error(`Error querying Dispute Details , endpoint : ${endpoint}, message : ${err?.message}`); - }); + return await request(endpoint, query); } catch (error: any) { - console.log(`Query Error : ${error?.message}`); - return undefined; + throw new Error(`Error querying Dispute Details , endpoint : ${endpoint}, message : ${error?.message}`); } }; diff --git a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts index d70a64437..b31d1b321 100644 --- a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts +++ b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts @@ -7,7 +7,7 @@ type DisputeTemplateQueryResponse = { }; }; -const fetchDisputeTemplateFromId = (endpoint: string, id: number) => { +const fetchDisputeTemplateFromId = async (endpoint: string, id: number) => { const query = ` query DisputeTemplate { disputeTemplate(id: ${id}) { @@ -18,14 +18,9 @@ const fetchDisputeTemplateFromId = (endpoint: string, id: number) => { `; try { - return request(endpoint, query) - .then((res) => res) - .catch((err) => { - throw new Error(`Error querying Dispute Template Registry , endpoint : ${endpoint}, message : ${err?.message}`); - }); + return await request(endpoint, query); } catch (error: any) { - console.log(`Query Error : ${error?.message}`); - return undefined; + throw new Error(`Error querying Dispute Template Registry , endpoint : ${endpoint}, message : ${error?.message}`); } }; diff --git a/kleros-sdk/src/utils/getDispute.ts b/kleros-sdk/src/utils/getDispute.ts index 2562c8cd8..3dbdd646a 100644 --- a/kleros-sdk/src/utils/getDispute.ts +++ b/kleros-sdk/src/utils/getDispute.ts @@ -23,11 +23,15 @@ export const getDispute = async (disputeParameters: GetDisputeParameters): Promi const disputeDetails = await fetchDisputeDetails(coreSubgraph, disputeId); - if (!disputeDetails?.dispute) return; + if (!disputeDetails?.dispute) { + throw new Error(`Dispute details not found for disputeId: ${disputeId}`); + } const template = await fetchDisputeTemplateFromId(dtrSubgraph, disputeDetails.dispute.templateId); - if (!template) return; + if (!template) { + throw new Error(`Template not found for template ID: ${disputeDetails.dispute.templateId}`); + } const { templateData, templateDataMappings } = template.disputeTemplate; @@ -38,7 +42,14 @@ export const getDispute = async (disputeParameters: GetDisputeParameters): Promi ...options?.additionalContext, }; - const data = templateDataMappings ? await executeActions(JSON.parse(templateDataMappings), initialContext) : {}; + let data = {}; + if (templateDataMappings) { + try { + data = await executeActions(JSON.parse(templateDataMappings), initialContext); + } catch (err: any) { + throw new Error(err); + } + } const populatedTemplate = populateTemplate(templateData, data); From 25063c79ff48c2632058275b29fdff5f3522dc65 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Tue, 15 Oct 2024 11:42:30 +0100 Subject: [PATCH 09/37] chore: fixed the SDK tests, minor tweaks --- kleros-sdk/test/dataMappings.test.ts | 50 ++++++++++++++++++++++----- subgraph/core/src/entities/Dispute.ts | 23 +++++------- web/src/context/Web3Provider.tsx | 7 ++-- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/kleros-sdk/test/dataMappings.test.ts b/kleros-sdk/test/dataMappings.test.ts index 2b9559197..297281c36 100644 --- a/kleros-sdk/test/dataMappings.test.ts +++ b/kleros-sdk/test/dataMappings.test.ts @@ -174,6 +174,7 @@ describe("full flow test", () => { { title: "Yes", description: "User is responsible", id: "0x01" }, { title: "No", description: "User is not responsible", id: "0x02" }, ], + policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", details: { ruling: "{{ruling}}", tied: "{{tied}}", @@ -182,6 +183,9 @@ describe("full flow test", () => { toAddress: "{{toAddress}}", transferValue: "{{transferValue}}", }, + arbitratorChainID: "421613", + arbitratorAddress: "0x0987654321098765432109876543210987654321", + version: "1.0", }); const initialContext = { alchemyApiKey: "mocked_api_key" }; @@ -199,6 +203,7 @@ describe("full flow test", () => { { title: "Yes", description: "User is responsible", id: "0x01" }, { title: "No", description: "User is not responsible", id: "0x02" }, ], + policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", details: { ruling: "1", tied: "false", @@ -207,6 +212,9 @@ describe("full flow test", () => { toAddress: "0x0987654321098765432109876543210987654321", transferValue: "100", }, + arbitratorChainID: "421613", + arbitratorAddress: "0x0987654321098765432109876543210987654321", + version: "1.0", }); }); }); @@ -345,10 +353,7 @@ describe("populateTemplate", () => { reserved: false, }, ], - policyURI: "https://example.com/policy", - frontendUrl: "https://example.com", - arbitrableChainID: "100", - arbitrableAddress: "0x1234567890123456789012345678901234567890", + policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", arbitratorChainID: "421613", arbitratorAddress: "0x0987654321098765432109876543210987654321", category: "General", @@ -376,10 +381,7 @@ describe("populateTemplate", () => { reserved: false, }, ], - policyURI: "https://example.com/policy", - frontendUrl: "https://example.com", - arbitrableChainID: "100", - arbitrableAddress: "0x1234567890123456789012345678901234567890", + policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", arbitratorChainID: "421613", arbitratorAddress: "0x0987654321098765432109876543210987654321", category: "General", @@ -394,6 +396,22 @@ describe("populateTemplate", () => { title: "Test Title", description: "Test Description", question: "{{missingQuestion}}", + type: "single-select", + answers: [ + { + title: "Yes", + description: "Affirmative", + id: "0x01", + reserved: false, + }, + ], + policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", + arbitratorChainID: "421613", + arbitratorAddress: "0x0987654321098765432109876543210987654321", + category: "General", + lang: "en_US", + specification: "Spec", + version: "1.0", }); const data = { @@ -406,6 +424,22 @@ describe("populateTemplate", () => { title: "Test Title", description: "Test Description", question: "", + type: "single-select", + answers: [ + { + title: "Yes", + description: "Affirmative", + id: "0x01", + reserved: false, + }, + ], + policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", + arbitratorChainID: "421613", + arbitratorAddress: "0x0987654321098765432109876543210987654321", + category: "General", + lang: "en_US", + specification: "Spec", + version: "1.0", }); }); diff --git a/subgraph/core/src/entities/Dispute.ts b/subgraph/core/src/entities/Dispute.ts index 4bf09e697..49bea55ad 100644 --- a/subgraph/core/src/entities/Dispute.ts +++ b/subgraph/core/src/entities/Dispute.ts @@ -32,27 +32,24 @@ export function createDisputeFromEvent(event: DisputeCreation): void { updateDisputeRequestData(event); } +// source: contracts/src/arbitration/interfaces/IArbitrableV2.sol const DisputeRequest = "DisputeRequest(address,uint256,uint256,uint256,string)"; - const DisputeRequestSignature = crypto.keccak256(ByteArray.fromUTF8(DisputeRequest)); // note : we are using bytes32 in place of string as strings cannot be decoded and it breaks the function. -// It is okay for us, as we are interested in the uint256 in front -// _externalDisputeId,_templateId,_tenplateUri -const DisputeRequestTypestring = "(uint256,uint256,bytes32)"; +// It is okay for us, as we are only interested in the uint256 in frontend. +const DisputeRequestTypestring = "(uint256,uint256,bytes32)"; // _externalDisputeId,_templateId,_templateUri +// source: contracts/src/gateway/interfaces/IHomeGateway.sol const CrossChainDisputeIncoming = "CrossChainDisputeIncoming(address,uint256,address,uint256,uint256,uint256,uint256,string)"; - const CrossChainDisputeIncomingSignature = crypto.keccak256(ByteArray.fromUTF8(CrossChainDisputeIncoming)); -// arbitrator, _arbitrableChainId, _externalDisputeId, _templateId, _templateUri // note : arbitrable is an indexed arg, so it will topic[1] -const CrossChainDisputeIncomingTypestring = "(address,uint256,uint256,uint256,string)"; +const CrossChainDisputeIncomingTypestring = "(address,uint256,uint256,uint256,string)"; // arbitrator, _arbitrableChainId, _externalDisputeId, _templateId, _templateUri export const updateDisputeRequestData = (event: DisputeCreation): void => { const dispute = Dispute.load(event.params._disputeID.toString()); - if (!dispute) return; const receipt = event.receipt; @@ -62,16 +59,13 @@ export const updateDisputeRequestData = (event: DisputeCreation): void => { // note that the topic at 0th index is always the event signature const disputeRequestEventIndex = logs.findIndex((log) => log.topics[0] == DisputeRequestSignature); - const crossChainDisputeEventIndex = logs.findIndex((log) => log.topics[0] == CrossChainDisputeIncomingSignature); if (crossChainDisputeEventIndex !== -1) { const crossChainDisputeEvent = logs[crossChainDisputeEventIndex]; const decoded = ethereum.decode(CrossChainDisputeIncomingTypestring, crossChainDisputeEvent.data); - if (!decoded) return; - dispute.isCrossChain = true; dispute.arbitrableChainId = decoded.toTuple()[1].toBigInt(); dispute.externalDisputeId = decoded.toTuple()[2].toBigInt(); @@ -84,7 +78,7 @@ export const updateDisputeRequestData = (event: DisputeCreation): void => { const decoded = ethereum.decode(DisputeRequestTypestring, disputeRequestEvent.data); if (!decoded) return; dispute.isCrossChain = false; - dispute.arbitrableChainId = getChainId(dataSource.network()); + dispute.arbitrableChainId = getHomeChainId(dataSource.network()); dispute.externalDisputeId = decoded.toTuple()[0].toBigInt(); dispute.templateId = decoded.toTuple()[1].toBigInt(); dispute.save(); @@ -92,8 +86,9 @@ export const updateDisputeRequestData = (event: DisputeCreation): void => { } }; -// workaround, since hashmap don't work in subgraphs -function getChainId(name: string): BigInt { +// workaround, since hashmap don't work in subgraphs. +// https://thegraph.com/docs/en/developing/supported-networks/ +function getHomeChainId(name: string): BigInt { if (name == "arbitrum-one") return BigInt.fromI32(42161); else if (name == "arbitrum-sepolia") return BigInt.fromI32(421614); else return BigInt.fromI32(1); diff --git a/web/src/context/Web3Provider.tsx b/web/src/context/Web3Provider.tsx index 3bf2a0e32..342ac5ed9 100644 --- a/web/src/context/Web3Provider.tsx +++ b/web/src/context/Web3Provider.tsx @@ -38,10 +38,9 @@ export const getDefaultChainRpcUrl = (protocol: AlchemyProtocol) => { return getChainRpcUrl(protocol, DEFAULT_CHAIN); }; -const alchemyTransport = (chain: Chain) => - fallback([http(alchemyURL("https", chain.id)), webSocket(alchemyURL("wss", chain.id))]); - export const getTransports = () => { + const alchemyTransport = (chain: Chain) => + fallback([http(alchemyURL("https", chain.id)), webSocket(alchemyURL("wss", chain.id))]); const defaultTransport = (chain: Chain) => fallback([http(chain.rpcUrls.default?.http?.[0]), webSocket(chain.rpcUrls.default?.webSocket?.[0])]); @@ -68,7 +67,7 @@ const wagmiConfig = createConfig({ configureSDK({ client: { chain: isProduction ? arbitrum : arbitrumSepolia, - transport: isProduction ? alchemyTransport(arbitrum) : alchemyTransport(arbitrumSepolia), + transport: transports[isProduction ? arbitrum.id : arbitrumSepolia.id], }, }); From 3abfbc5e0b3cdf1936b1fbe982caa6848b2a4d73 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 15 Oct 2024 15:33:08 +0530 Subject: [PATCH 10/37] fix(kleros-sdk): public-client-null-check --- kleros-sdk/src/dataMappings/actions/callAction.ts | 4 ++++ kleros-sdk/src/dataMappings/actions/eventAction.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/kleros-sdk/src/dataMappings/actions/callAction.ts b/kleros-sdk/src/dataMappings/actions/callAction.ts index b86d203c4..2f732b5a6 100644 --- a/kleros-sdk/src/dataMappings/actions/callAction.ts +++ b/kleros-sdk/src/dataMappings/actions/callAction.ts @@ -6,6 +6,10 @@ import { getPublicClient } from "src/sdk"; export const callAction = async (mapping: AbiCallMapping) => { const publicClient = getPublicClient(); + if (!publicClient) { + throw new Error("SDK not configured. Please call `configureSDK` before using."); + } + const { abi: source, address, args, seek, populate } = mapping; const parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; diff --git a/kleros-sdk/src/dataMappings/actions/eventAction.ts b/kleros-sdk/src/dataMappings/actions/eventAction.ts index b7207bc47..93a140b75 100644 --- a/kleros-sdk/src/dataMappings/actions/eventAction.ts +++ b/kleros-sdk/src/dataMappings/actions/eventAction.ts @@ -7,6 +7,10 @@ import { getPublicClient } from "src/sdk"; export const eventAction = async (mapping: AbiEventMapping) => { const publicClient = getPublicClient(); + if (!publicClient) { + throw new Error("SDK not configured. Please call `configureSDK` before using."); + } + const { abi: source, address, eventFilter, seek, populate } = mapping; const parsedAbi = parseAbiItem(source) as AbiEvent; From 914051807bac33f1fb77cbd61ae4514ca0b22a65 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 15 Oct 2024 16:40:24 +0530 Subject: [PATCH 11/37] chore(subgraph): redeploy-subgraphs --- subgraph/core-neo/subgraph.yaml | 1 - subgraph/core-university/subgraph.yaml | 1 - subgraph/core/subgraph.yaml | 1 - subgraph/package.json | 2 +- 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/subgraph/core-neo/subgraph.yaml b/subgraph/core-neo/subgraph.yaml index e98508cc4..bfcbf3ad9 100644 --- a/subgraph/core-neo/subgraph.yaml +++ b/subgraph/core-neo/subgraph.yaml @@ -3,7 +3,6 @@ schema: file: ./schema.graphql features: - fullTextSearch - dataSources: - kind: ethereum name: KlerosCore diff --git a/subgraph/core-university/subgraph.yaml b/subgraph/core-university/subgraph.yaml index 03c1f6c72..bf28f408a 100644 --- a/subgraph/core-university/subgraph.yaml +++ b/subgraph/core-university/subgraph.yaml @@ -3,7 +3,6 @@ schema: file: ./schema.graphql features: - fullTextSearch - dataSources: - kind: ethereum name: KlerosCore diff --git a/subgraph/core/subgraph.yaml b/subgraph/core/subgraph.yaml index fc3501e9c..ba08525c9 100644 --- a/subgraph/core/subgraph.yaml +++ b/subgraph/core/subgraph.yaml @@ -3,7 +3,6 @@ schema: file: ./schema.graphql features: - fullTextSearch - dataSources: - kind: ethereum name: KlerosCore diff --git a/subgraph/package.json b/subgraph/package.json index 71f1166ef..546f90ad5 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-v2-subgraph", - "version": "0.7.6", + "version": "0.8.6", "license": "MIT", "scripts": { "update:core:arbitrum-sepolia-devnet": "./scripts/update.sh arbitrumSepoliaDevnet arbitrum-sepolia core/subgraph.yaml", From e8cd12d544ee4944a08dfa317226c8abafe81189 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Oct 2024 00:26:53 +0100 Subject: [PATCH 12/37] fix(sdk): types and unit tests --- kleros-sdk/package.json | 4 +- .../src/dataMappings/actions/callAction.ts | 4 +- .../src/dataMappings/actions/eventAction.ts | 4 +- 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/executeActions.ts | 2 +- .../src/dataMappings/retrieveRealityData.ts | 20 ++-- .../utils/actionTypeValidators.ts | 2 +- .../src/dataMappings/utils/actionTypes.ts | 43 ++++----- .../disputeDetailsSchema.test.ts.snap | 19 ++++ .../test/__snapshots__/schema.test.ts.snap | 7 ++ kleros-sdk/test/dataMappings.test.ts | 39 +++++--- yarn.lock | 1 + 14 files changed, 88 insertions(+), 279 deletions(-) delete mode 100644 kleros-sdk/src/dataMappings/dataMapping.json delete mode 100644 kleros-sdk/src/dataMappings/dataMapping.ts delete mode 100644 kleros-sdk/src/dataMappings/decoder.ts create mode 100644 kleros-sdk/test/__snapshots__/disputeDetailsSchema.test.ts.snap create mode 100644 kleros-sdk/test/__snapshots__/schema.test.ts.snap diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index d32585e12..94ee6b2da 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -19,7 +19,8 @@ "node": "20.11.0" }, "scripts": { - "build": "your-build-script", + "clean": "rimraf lib", + "build": "yarn clean && tsc", "test": "vitest", "test:ui": "vitest --ui", "test:run": "vitest run" @@ -28,6 +29,7 @@ "@types/mustache": "^4.2.5", "@vitest/ui": "^1.1.3", "mocha": "^10.2.0", + "rimraf": "^6.0.1", "ts-node": "^10.9.2", "typescript": "^5.3.3", "vitest": "^1.1.3" diff --git a/kleros-sdk/src/dataMappings/actions/callAction.ts b/kleros-sdk/src/dataMappings/actions/callAction.ts index 2f732b5a6..d7b2a63bf 100644 --- a/kleros-sdk/src/dataMappings/actions/callAction.ts +++ b/kleros-sdk/src/dataMappings/actions/callAction.ts @@ -10,13 +10,13 @@ export const callAction = async (mapping: AbiCallMapping) => { throw new Error("SDK not configured. Please call `configureSDK` before using."); } - const { abi: source, address, args, seek, populate } = mapping; + const { abi: source, address, functionName, args, seek, populate } = mapping; const parsedAbi = typeof source === "string" ? parseAbiItem(source) : source; const data = await publicClient.readContract({ address, abi: [parsedAbi], - functionName: "TODO: FIX ME", + functionName, args, }); diff --git a/kleros-sdk/src/dataMappings/actions/eventAction.ts b/kleros-sdk/src/dataMappings/actions/eventAction.ts index 93a140b75..852a05066 100644 --- a/kleros-sdk/src/dataMappings/actions/eventAction.ts +++ b/kleros-sdk/src/dataMappings/actions/eventAction.ts @@ -18,8 +18,8 @@ export const eventAction = async (mapping: AbiEventMapping) => { address, event: parsedAbi, args: eventFilter.args, - fromBlock: eventFilter.fromBlock ? BigInt(eventFilter.fromBlock.toString()) : undefined, - toBlock: eventFilter.toBlock ? BigInt(eventFilter.toBlock.toString()) : undefined, + fromBlock: eventFilter.fromBlock, + toBlock: eventFilter.toBlock, }); const contractEvent = await publicClient.getFilterLogs({ filter }); diff --git a/kleros-sdk/src/dataMappings/dataMapping.json b/kleros-sdk/src/dataMappings/dataMapping.json deleted file mode 100644 index 27f5ed4fd..000000000 --- a/kleros-sdk/src/dataMappings/dataMapping.json +++ /dev/null @@ -1,75 +0,0 @@ -[ - { - "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 deleted file mode 100644 index 17dafb8f1..000000000 --- a/kleros-sdk/src/dataMappings/dataMapping.ts +++ /dev/null @@ -1,92 +0,0 @@ -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 deleted file mode 100644 index b30e6e927..000000000 --- a/kleros-sdk/src/dataMappings/decoder.ts +++ /dev/null @@ -1,55 +0,0 @@ -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/executeActions.ts b/kleros-sdk/src/dataMappings/executeActions.ts index c863866f8..06052b6a9 100644 --- a/kleros-sdk/src/dataMappings/executeActions.ts +++ b/kleros-sdk/src/dataMappings/executeActions.ts @@ -41,7 +41,7 @@ export const executeAction = async ( mapping = validateRealityMapping(mapping); return await retrieveRealityData(mapping.realityQuestionID, context.arbitrableAddress as Address); default: - throw new Error(`Unsupported action type: ${mapping.type}`); + throw new Error(`Unsupported action type: ${JSON.stringify(mapping)}`); } }; diff --git a/kleros-sdk/src/dataMappings/retrieveRealityData.ts b/kleros-sdk/src/dataMappings/retrieveRealityData.ts index be3b377a1..d2b5294cf 100644 --- a/kleros-sdk/src/dataMappings/retrieveRealityData.ts +++ b/kleros-sdk/src/dataMappings/retrieveRealityData.ts @@ -1,6 +1,14 @@ import { executeAction } from "./executeActions"; import { AbiEventMapping } from "./utils/actionTypes"; +export type RealityAnswer = { + title: string; + description: string; + id: string; + reserved: boolean; + last?: boolean; +}; + export const retrieveRealityData = async (realityQuestionID: string, arbitrable?: `0x${string}`) => { if (!arbitrable) { throw new Error("No arbitrable address provided"); @@ -11,7 +19,7 @@ export const retrieveRealityData = async (realityQuestionID: string, arbitrable? address: arbitrable, eventFilter: { args: [realityQuestionID], - fromBlock: "0x1", + fromBlock: "earliest", toBlock: "latest", }, seek: [ @@ -49,7 +57,7 @@ export const retrieveRealityData = async (realityQuestionID: string, arbitrable? address: arbitrable, eventFilter: { args: [0], - fromBlock: "0x1", + fromBlock: "earliest", toBlock: "latest", }, seek: ["template_id", "question_text"], @@ -71,14 +79,6 @@ export const retrieveRealityData = async (realityQuestionID: string, arbitrable? console.log("populatedTemplate", populatedTemplate); - interface RealityAnswer { - title: string; - description: string; - id: string; - reserved: boolean; - last?: boolean; - } - let answers: RealityAnswer[] = []; if (populatedTemplate.type === "bool") { answers = [ diff --git a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts index b95296043..593c6f544 100644 --- a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts +++ b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts @@ -23,7 +23,7 @@ export const validateAbiEventMapping = (mapping: ActionMapping) => { }; export const validateAbiCallMapping = (mapping: ActionMapping) => { - if ((mapping as AbiCallMapping).abi === undefined || (mapping as AbiCallMapping).args === undefined) { + if ((mapping as AbiCallMapping).abi === undefined || (mapping as AbiCallMapping).functionName === undefined) { throw new Error("Invalid mapping for abi/call action."); } return mapping as AbiCallMapping; diff --git a/kleros-sdk/src/dataMappings/utils/actionTypes.ts b/kleros-sdk/src/dataMappings/utils/actionTypes.ts index efc7a2343..630afda6b 100644 --- a/kleros-sdk/src/dataMappings/utils/actionTypes.ts +++ b/kleros-sdk/src/dataMappings/utils/actionTypes.ts @@ -1,52 +1,45 @@ -import { type Address } from "viem"; +import { type Address, type BlockNumber, type BlockTag } from "viem"; -export type JsonMapping = { - type: string; - value: object; +type MappingType = "graphql" | "abi/call" | "abi/event" | "json" | "fetch/ipfs/json" | "reality"; + +type AbstractMapping = { + type: T; seek: string[]; populate: string[]; }; -export interface SubgraphMapping { - type: string; +export type JsonMapping = AbstractMapping<"json"> & { + value: object; +}; + +export type SubgraphMapping = AbstractMapping<"graphql"> & { endpoint: string; query: string; variables: { [key: string]: unknown }; - seek: string[]; - populate: string[]; -} +}; -export type AbiCallMapping = { - type: string; +export type AbiCallMapping = AbstractMapping<"abi/call"> & { abi: string; address: Address; + functionName: string; args: any[]; - seek: string[]; - populate: string[]; }; -export type AbiEventMapping = { - type: string; +export type AbiEventMapping = AbstractMapping<"abi/event"> & { abi: string; address: Address; eventFilter: { - fromBlock: BigInt | string; - toBlock: BigInt | string; + fromBlock: BlockNumber | BlockTag; + toBlock: BlockNumber | BlockTag; args: any; }; - seek: string[]; - populate: string[]; }; -export type FetchIpfsJsonMapping = { - type: string; +export type FetchIpfsJsonMapping = AbstractMapping<"fetch/ipfs/json"> & { ipfsUri: string; - seek: string[]; - populate: string[]; }; -export type RealityMapping = { - type: "reality"; +export type RealityMapping = AbstractMapping<"reality"> & { realityQuestionID: string; }; diff --git a/kleros-sdk/test/__snapshots__/disputeDetailsSchema.test.ts.snap b/kleros-sdk/test/__snapshots__/disputeDetailsSchema.test.ts.snap new file mode 100644 index 000000000..35eaeb093 --- /dev/null +++ b/kleros-sdk/test/__snapshots__/disputeDetailsSchema.test.ts.snap @@ -0,0 +1,19 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Dispute Details Schema > snapshot 1`] = ` +{ + "foo": "bar", +} +`; + +exports[`Kleros SDK schema > snapshot 1`] = ` +{ + "foo": "bar", +} +`; + +exports[`Kleros SDK schemas > snapshot 1`] = ` +{ + "foo": "bar", +} +`; diff --git a/kleros-sdk/test/__snapshots__/schema.test.ts.snap b/kleros-sdk/test/__snapshots__/schema.test.ts.snap new file mode 100644 index 000000000..6ee93505c --- /dev/null +++ b/kleros-sdk/test/__snapshots__/schema.test.ts.snap @@ -0,0 +1,7 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Kleros SDK schema > snapshot 1`] = ` +{ + "foo": "bar", +} +`; diff --git a/kleros-sdk/test/dataMappings.test.ts b/kleros-sdk/test/dataMappings.test.ts index 297281c36..b36ee7d12 100644 --- a/kleros-sdk/test/dataMappings.test.ts +++ b/kleros-sdk/test/dataMappings.test.ts @@ -7,6 +7,13 @@ import { eventAction } from "src/dataMappings/actions/eventAction"; import { fetchIpfsJsonAction } from "src/dataMappings/actions/fetchIpfsJsonAction"; import { createResultObject } from "src/dataMappings/utils/createResultObject"; import { executeActions } from "src/dataMappings/executeActions"; +import { + AbiCallMapping, + AbiEventMapping, + FetchIpfsJsonMapping, + JsonMapping, + SubgraphMapping, +} from "src/dataMappings/utils/actionTypes"; global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ @@ -136,6 +143,7 @@ describe("full flow test", () => { type: "abi/call", abi: "function currentRuling(uint256 _disputeID) public view returns (uint256 ruling, bool tied, bool overridden)", address: "0xA54e7A16d7460e38a8F324eF46782FB520d58CE8", + functionName: "currentRuling", args: ["0"], seek: ["0", "1", "2"], populate: ["ruling", "tied", "overridden"], @@ -145,7 +153,7 @@ describe("full flow test", () => { abi: "event Transfer(address indexed from, address indexed to, uint256 value)", address: "0xa8e4235129258404A2ed3D36DAd20708CcB2d0b7", eventFilter: { - fromBlock: "earliest", + fromBlock: "123", toBlock: "latest", args: [], }, @@ -183,7 +191,7 @@ describe("full flow test", () => { toAddress: "{{toAddress}}", transferValue: "{{transferValue}}", }, - arbitratorChainID: "421613", + arbitratorChainID: "421614", arbitratorAddress: "0x0987654321098765432109876543210987654321", version: "1.0", }); @@ -212,7 +220,7 @@ describe("full flow test", () => { toAddress: "0x0987654321098765432109876543210987654321", transferValue: "100", }, - arbitratorChainID: "421613", + arbitratorChainID: "421614", arbitratorAddress: "0x0987654321098765432109876543210987654321", version: "1.0", }); @@ -221,7 +229,7 @@ describe("full flow test", () => { describe("jsonAction", () => { it("should extract and map data correctly", () => { - const mapping = { + const mapping: JsonMapping = { type: "json", value: exampleObject.evidence.fileURI, seek: ["photo", "video"], @@ -235,7 +243,7 @@ describe("jsonAction", () => { }); it("should handle empty JSON object gracefully", () => { - const mapping = { + const mapping: JsonMapping = { type: "json", value: {}, seek: ["nonexistentField"], @@ -248,7 +256,7 @@ describe("jsonAction", () => { describe("subgraphAction with variables", () => { it("should fetch GraphQL data with variables and return in expected format", async () => { - const mapping = { + const mapping: SubgraphMapping = { type: "graphql", endpoint: "mocked_endpoint", query: `query GetEscrows($buyer: Bytes!) { @@ -277,16 +285,17 @@ describe("subgraphAction with variables", () => { describe("callAction", () => { it("should call the contract and return in expected format", async () => { - const mapping = { + const mapping: AbiCallMapping = { type: "abi/call", abi: "function currentRuling(uint256 _disputeID) public view returns (uint256 ruling, bool tied, bool overridden)", + functionName: "currentRuling", address: "0xA54e7A16d7460e38a8F324eF46782FB520d58CE8", args: ["0"], seek: ["0", "1", "2"], populate: ["ruling", "tied", "overridden"], }; - const result = (await callAction(mapping, "")) as CallActionResult; + const result = (await callAction(mapping)) as CallActionResult; expect(result).to.have.property("ruling"); expect(result.ruling).to.be.a("bigint"); @@ -299,7 +308,7 @@ describe("callAction", () => { describe("eventAction", () => { it("should fetch event data and return populated data", async () => { - const mapping = { + const mapping: AbiEventMapping = { type: "abi/event", abi: "event Transfer(address indexed from, address indexed to, uint256 value)", address: "0xa8e4235129258404A2ed3D36DAd20708CcB2d0b7", @@ -312,7 +321,7 @@ describe("eventAction", () => { populate: ["fromAddress", "toAddress", "transferValue"], }; - const result = (await eventAction(mapping, "")) as EventActionResult; + const result = (await eventAction(mapping)) as EventActionResult; expect(result).to.have.property("fromAddress", "0x1234567890123456789012345678901234567890"); expect(result).to.have.property("toAddress", "0x0987654321098765432109876543210987654321"); @@ -322,7 +331,7 @@ describe("eventAction", () => { describe("fetchIpfsJsonAction", () => { it("should fetch JSON data from IPFS and return the expected result", async () => { - const mapping = { + const mapping: FetchIpfsJsonMapping = { type: "fetch/ipfs/json", ipfsUri: "/ipfs/QmQ2XoA25HmnPUEWDduxj6LYwMwp6jtXPFRMHcNF2EvJfU/file.json", seek: ["name", "firstName", "lastName", "anotherFile"], @@ -354,7 +363,7 @@ describe("populateTemplate", () => { }, ], policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", - arbitratorChainID: "421613", + arbitratorChainID: "421614", arbitratorAddress: "0x0987654321098765432109876543210987654321", category: "General", lang: "en_US", @@ -382,7 +391,7 @@ describe("populateTemplate", () => { }, ], policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", - arbitratorChainID: "421613", + arbitratorChainID: "421614", arbitratorAddress: "0x0987654321098765432109876543210987654321", category: "General", lang: "en_US", @@ -406,7 +415,7 @@ describe("populateTemplate", () => { }, ], policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", - arbitratorChainID: "421613", + arbitratorChainID: "421614", arbitratorAddress: "0x0987654321098765432109876543210987654321", category: "General", lang: "en_US", @@ -434,7 +443,7 @@ describe("populateTemplate", () => { }, ], policyURI: "/ipfs/QmUnPyGi31RoF4DRR8vT3u13YsppxtsbBKbdQAbcP8be4M/file.json", - arbitratorChainID: "421613", + arbitratorChainID: "421614", arbitratorAddress: "0x0987654321098765432109876543210987654321", category: "General", lang: "en_US", diff --git a/yarn.lock b/yarn.lock index f9ccbe4e8..5594a9f78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7899,6 +7899,7 @@ __metadata: graphql-request: "npm:^7.1.0" mocha: "npm:^10.2.0" mustache: "npm:^4.2.0" + rimraf: "npm:^6.0.1" ts-node: "npm:^10.9.2" typescript: "npm:^5.3.3" vitest: "npm:^1.1.3" From d3e4b5910aed160ae6ae4fab02a23bc3340a79a3 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Oct 2024 01:10:06 +0100 Subject: [PATCH 13/37] chore(sdk): release configuration for NPM, tsconfig tweaks --- contracts/package.json | 3 +- contracts/tsconfig.json | 2 +- kleros-sdk/.gitignore | 24 +++ kleros-sdk/package.json | 18 ++- .../src/dataMappings/actions/eventAction.ts | 3 +- kleros-sdk/src/dataMappings/executeActions.ts | 2 +- .../utils/disputeDetailsSchema.ts | 2 +- kleros-sdk/src/index.ts | 3 + kleros-sdk/tsconfig.json | 25 ++-- kleros-sdk/vitest.config.ts | 8 + tsconfig/base.json | 21 --- tsconfig/base18.json | 9 ++ tsconfig/base20.json | 9 ++ tsconfig/package.json | 7 +- tsconfig/react-library.json | 5 +- web/tsconfig.json | 1 - yarn.lock | 140 ++++++++++++++++++ 17 files changed, 231 insertions(+), 51 deletions(-) create mode 100644 kleros-sdk/.gitignore create mode 100644 kleros-sdk/src/index.ts create mode 100644 kleros-sdk/vitest.config.ts delete mode 100644 tsconfig/base.json create mode 100644 tsconfig/base18.json create mode 100644 tsconfig/base20.json diff --git a/contracts/package.json b/contracts/package.json index d2eb5fc23..6225f6dd1 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -102,6 +102,7 @@ "typescript": "^5.3.3" }, "dependencies": { - "@kleros/vea-contracts": "^0.4.0" + "@kleros/vea-contracts": "^0.4.0", + "viem": "^2.21.26" } } diff --git a/contracts/tsconfig.json b/contracts/tsconfig.json index c6e40bb30..932cefbdb 100644 --- a/contracts/tsconfig.json +++ b/contracts/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@kleros/kleros-v2-tsconfig/base.json", + "extends": "@kleros/kleros-v2-tsconfig/base18.json", "include": [ "./src", "./scripts", diff --git a/kleros-sdk/.gitignore b/kleros-sdk/.gitignore new file mode 100644 index 000000000..3ed7dc1bc --- /dev/null +++ b/kleros-sdk/.gitignore @@ -0,0 +1,24 @@ +node_modules + +# vite +development +build +dist +lib + +# misc +.eslintcache +.DS_Store +.env +.env.test +.env.testnet +.env.devnet +.env.local +.env.development.local +.env.test.local +.env.production.local + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 94ee6b2da..c53ecddb3 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -1,11 +1,17 @@ { "name": "@kleros/kleros-sdk", - "version": "0.1.0", + "version": "2.1.0", "description": "SDK for Kleros version 2", - "main": "index.ts", "repository": "git@github.com:kleros/kleros-v2.git", "author": "Kleros", "license": "MIT", + "main": "./lib/src/index.js", + "types": "./lib/src/index.d.ts", + "module": "./lib/src/index.js", + "files": [ + "lib/**/*", + "!lib/**/test/*" + ], "alias": { "src": "./src", "dataMappings": "./src/dataMappings" @@ -18,12 +24,17 @@ "volta": { "node": "20.11.0" }, + "publishConfig": { + "access": "public", + "tag": "latest" + }, "scripts": { "clean": "rimraf lib", "build": "yarn clean && tsc", "test": "vitest", "test:ui": "vitest --ui", - "test:run": "vitest run" + "test:run": "vitest run", + "publish": "yarn npm publish" }, "devDependencies": { "@types/mustache": "^4.2.5", @@ -39,6 +50,7 @@ "@reality.eth/reality-eth-lib": "^3.2.30", "graphql-request": "^7.1.0", "mustache": "^4.2.0", + "viem": "^2.21.26", "zod": "^3.22.4" } } diff --git a/kleros-sdk/src/dataMappings/actions/eventAction.ts b/kleros-sdk/src/dataMappings/actions/eventAction.ts index 852a05066..e3f36933c 100644 --- a/kleros-sdk/src/dataMappings/actions/eventAction.ts +++ b/kleros-sdk/src/dataMappings/actions/eventAction.ts @@ -1,5 +1,4 @@ -import { parseAbiItem } from "viem"; -import { type AbiEvent } from "abitype"; +import { parseAbiItem, type AbiEvent } from "viem"; import { AbiEventMapping } from "src/dataMappings/utils/actionTypes"; import { createResultObject } from "src/dataMappings/utils/createResultObject"; import { getPublicClient } from "src/sdk"; diff --git a/kleros-sdk/src/dataMappings/executeActions.ts b/kleros-sdk/src/dataMappings/executeActions.ts index 06052b6a9..0322e596c 100644 --- a/kleros-sdk/src/dataMappings/executeActions.ts +++ b/kleros-sdk/src/dataMappings/executeActions.ts @@ -1,5 +1,5 @@ import { callAction } from "./actions/callAction"; -import { eventAction } from "./actions/eventAction"; +import { eventAction } from "./actions/eventAction.js"; import { fetchIpfsJsonAction } from "./actions/fetchIpfsJsonAction"; import { jsonAction } from "./actions/jsonAction"; import { subgraphAction } from "./actions/subgraphAction"; diff --git a/kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts b/kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts index 3366cf750..d9948ea70 100644 --- a/kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts +++ b/kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts @@ -9,7 +9,7 @@ export const isMultiaddr = (str: string): boolean => str ); -export const ethAddressSchema = z.string().refine((value) => isAddress(value), { +export const ethAddressSchema = z.string().refine((value) => isAddress(value, { strict: false }), { message: "Provided address is invalid.", }); diff --git a/kleros-sdk/src/index.ts b/kleros-sdk/src/index.ts new file mode 100644 index 000000000..00223f12e --- /dev/null +++ b/kleros-sdk/src/index.ts @@ -0,0 +1,3 @@ +export * from "./sdk"; +export * from "./types"; +export * from "./utils/getDispute"; diff --git a/kleros-sdk/tsconfig.json b/kleros-sdk/tsconfig.json index 6a9b24bb5..af37852bd 100644 --- a/kleros-sdk/tsconfig.json +++ b/kleros-sdk/tsconfig.json @@ -1,7 +1,7 @@ { - "extends": "@kleros/kleros-v2-tsconfig/react-library.json", + "extends": "@kleros/kleros-v2-tsconfig/base20.json", "compilerOptions": { - "baseUrl": ".", + "outDir": "lib", "paths": { "~*": [ "./*" @@ -13,31 +13,26 @@ "./src/dataMappings*" ] }, - "target": "ES6", - "module": "CommonJS", - "outDir": "build/dist", "allowJs": true, "forceConsistentCasingInFileNames": true, - "strictNullChecks": true, - "noUnusedLocals": true, "skipLibCheck": true, "allowSyntheticDefaultImports": true, + "esModuleInterop": true, "removeComments": true, - "isolatedModules": true + "isolatedModules": true, + "noEmit": false, + "declaration": true }, "include": [ "src", "test" ], "exclude": [ - "node_modules", "build", - "scripts", - "acceptance-tests", - "webpack", - "jest", - "src/setupTests.ts", "dist", - "commitlint.config.js" + "lib", + "node_modules", + "scripts", + "webpack" ] } diff --git a/kleros-sdk/vitest.config.ts b/kleros-sdk/vitest.config.ts new file mode 100644 index 000000000..ea4060443 --- /dev/null +++ b/kleros-sdk/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; +import { configDefaults } from "vitest/config"; + +export default defineConfig({ + test: { + exclude: [...configDefaults.exclude, "**/lib/**"], + }, +}); diff --git a/tsconfig/base.json b/tsconfig/base.json deleted file mode 100644 index cbd15edc5..000000000 --- a/tsconfig/base.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "target": "es2021", - "module": "commonjs", - "moduleResolution": "node", - "outDir": "dist", - "strict": true, - "esModuleInterop": true, - "declaration": true, - "sourceMap": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noImplicitAny": false, - "resolveJsonModule": true, - "experimentalDecorators": true - }, - "exclude": [ - "node_modules" - ] -} diff --git a/tsconfig/base18.json b/tsconfig/base18.json new file mode 100644 index 000000000..8436dd693 --- /dev/null +++ b/tsconfig/base18.json @@ -0,0 +1,9 @@ +{ + "extends": "@tsconfig/node18/tsconfig.json", + "compilerOptions": { + "outDir": "dist" + }, + "exclude": [ + "node_modules" + ] +} diff --git a/tsconfig/base20.json b/tsconfig/base20.json new file mode 100644 index 000000000..45fcb964c --- /dev/null +++ b/tsconfig/base20.json @@ -0,0 +1,9 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "outDir": "dist" + }, + "exclude": [ + "node_modules" + ] +} diff --git a/tsconfig/package.json b/tsconfig/package.json index e07f71c30..47582628d 100644 --- a/tsconfig/package.json +++ b/tsconfig/package.json @@ -3,9 +3,12 @@ "version": "1.0.0", "private": true, "files": [ - "base.json" + "base18.json", + "base20.json" ], "devDependencies": { - "@kleros/kleros-v2-eslint-config": "*" + "@kleros/kleros-v2-eslint-config": "*", + "@tsconfig/node18": "^18.2.4", + "@tsconfig/node20": "^20.1.4" } } diff --git a/tsconfig/react-library.json b/tsconfig/react-library.json index 3f69cb2c3..81ef5ffa7 100644 --- a/tsconfig/react-library.json +++ b/tsconfig/react-library.json @@ -1,14 +1,13 @@ { - "$schema": "https://json.schemastore.org/tsconfig", "display": "React Library", - "extends": "./base.json", + "extends": "./base20.json", "compilerOptions": { "jsx": "react", "lib": [ "es6", "dom", "esnext.asynciterable", - "es2017" + "es2023" ], "module": "ESNext", "target": "es6" diff --git a/web/tsconfig.json b/web/tsconfig.json index 0f569d03f..b40e3fa6d 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -46,7 +46,6 @@ "./src/assets/svgs*" ] }, - "target": "es2020", "rootDir": "src", "outDir": "build/dist", "allowJs": true, diff --git a/yarn.lock b/yarn.lock index 5594a9f78..1894ffa5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,6 +30,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:1.11.0": + version: 1.11.0 + resolution: "@adraffy/ens-normalize@npm:1.11.0" + checksum: abef75f21470ea43dd6071168e092d2d13e38067e349e76186c78838ae174a46c3e18ca50921d05bea6ec3203074147c9e271f8cb6531d1c2c0e146f3199ddcb + languageName: node + linkType: hard + "@adraffy/ens-normalize@npm:1.9.0": version: 1.9.0 resolution: "@adraffy/ens-normalize@npm:1.9.0" @@ -7902,6 +7909,7 @@ __metadata: rimraf: "npm:^6.0.1" ts-node: "npm:^10.9.2" typescript: "npm:^5.3.3" + viem: "npm:^2.21.26" vitest: "npm:^1.1.3" zod: "npm:^3.22.4" languageName: unknown @@ -7960,6 +7968,7 @@ __metadata: ts-node: "npm:^10.9.2" typechain: "npm:^8.3.2" typescript: "npm:^5.3.3" + viem: "npm:^2.21.26" languageName: unknown linkType: soft @@ -8015,6 +8024,8 @@ __metadata: resolution: "@kleros/kleros-v2-tsconfig@workspace:tsconfig" dependencies: "@kleros/kleros-v2-eslint-config": "npm:*" + "@tsconfig/node18": "npm:^18.2.4" + "@tsconfig/node20": "npm:^20.1.4" languageName: unknown linkType: soft @@ -9462,6 +9473,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:1.6.0, @noble/curves@npm:^1.4.0, @noble/curves@npm:~1.6.0": + version: 1.6.0 + resolution: "@noble/curves@npm:1.6.0" + dependencies: + "@noble/hashes": "npm:1.5.0" + checksum: 9090b5a020b7e38c7b6d21506afaacd0c7557129d716a174334c1efc36385bf3ca6de16a543c216db58055e019c6a6c3bea8d9c0b79386e6bacff5c4c6b438a9 + languageName: node + linkType: hard + "@noble/curves@npm:^1.1.0, @noble/curves@npm:^1.4.2, @noble/curves@npm:~1.4.0": version: 1.4.2 resolution: "@noble/curves@npm:1.4.2" @@ -9513,6 +9533,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.5.0, @noble/hashes@npm:~1.5.0": + version: 1.5.0 + resolution: "@noble/hashes@npm:1.5.0" + checksum: da7fc7af52af7afcf59810a7eea6155075464ff462ffda2572dc6d57d53e2669b1ea2ec774e814f6273f1697e567f28d36823776c9bf7068cba2a2855140f26e + languageName: node + linkType: hard + "@noble/hashes@npm:^1.3.1, @noble/hashes@npm:~1.3.1": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" @@ -10909,6 +10936,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:~1.1.7, @scure/base@npm:~1.1.8": + version: 1.1.9 + resolution: "@scure/base@npm:1.1.9" + checksum: f0ab7f687bbcdee2a01377fe3cd808bf63977999672751295b6a92625d5322f4754a96d40f6bd579bc367aad48ecf8a4e6d0390e70296e6ded1076f52adb16bb + languageName: node + linkType: hard + "@scure/bip32@npm:1.1.5": version: 1.1.5 resolution: "@scure/bip32@npm:1.1.5" @@ -10953,6 +10987,17 @@ __metadata: languageName: node linkType: hard +"@scure/bip32@npm:1.5.0": + version: 1.5.0 + resolution: "@scure/bip32@npm:1.5.0" + dependencies: + "@noble/curves": "npm:~1.6.0" + "@noble/hashes": "npm:~1.5.0" + "@scure/base": "npm:~1.1.7" + checksum: 17e296a782e09aec18ed27e2e8bb6a76072604c40997ec49a6840f223296421612dbe6b44275f04db9acd6da6cefb0322141110f5ac9dc686eb0c44d5bd868fa + languageName: node + linkType: hard + "@scure/bip39@npm:1.1.1": version: 1.1.1 resolution: "@scure/bip39@npm:1.1.1" @@ -10983,6 +11028,16 @@ __metadata: languageName: node linkType: hard +"@scure/bip39@npm:1.4.0": + version: 1.4.0 + resolution: "@scure/bip39@npm:1.4.0" + dependencies: + "@noble/hashes": "npm:~1.5.0" + "@scure/base": "npm:~1.1.8" + checksum: f86e0e79768c95bc684ed6de92892b1a6f228db0f8fab836f091c0ec0f6d1e291b8c4391cfbeaa9ea83f41045613535b1940cd10e7d780a5b73db163b1e7f151 + languageName: node + linkType: hard + "@selderee/plugin-htmlparser2@npm:^0.6.0": version: 0.6.0 resolution: "@selderee/plugin-htmlparser2@npm:0.6.0" @@ -12170,6 +12225,20 @@ __metadata: languageName: node linkType: hard +"@tsconfig/node18@npm:^18.2.4": + version: 18.2.4 + resolution: "@tsconfig/node18@npm:18.2.4" + checksum: 80623cb9c129c78d51fe6c4a256ba986f12f02ff02dc2a1e5b33dd13a7983f767b6792cfcd51b3dd1c8256ea105f1fea31f64a2070564e37787ab3d9a1a1e7e3 + languageName: node + linkType: hard + +"@tsconfig/node20@npm:^20.1.4": + version: 20.1.4 + resolution: "@tsconfig/node20@npm:20.1.4" + checksum: 345dba8074647f6c11b8d78afa76d9c16e3436cb56a8e78fe2060014d33a09f3f4fd6ed81dc90e955d3509f926cd7fd61c6ddfd3d5a1d80758d7844f7cc3a99e + languageName: node + linkType: hard + "@typechain/ethers-v5@npm:^11.1.2": version: 11.1.2 resolution: "@typechain/ethers-v5@npm:11.1.2" @@ -14936,6 +15005,21 @@ __metadata: languageName: node linkType: hard +"abitype@npm:1.0.6": + version: 1.0.6 + resolution: "abitype@npm:1.0.6" + peerDependencies: + typescript: ">=5.0.4" + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + checksum: d04d58f90405c29a3c68353508502d7e870feb27418a6281ba9a13e6aaee42c26b2c5f08f648f058b8eaffac32927194b33f396d2451d18afeccfb654c7285c2 + languageName: node + linkType: hard + "abitype@npm:^0.10.3": version: 0.10.3 resolution: "abitype@npm:0.10.3" @@ -26880,6 +26964,15 @@ __metadata: languageName: node linkType: hard +"isows@npm:1.0.6": + version: 1.0.6 + resolution: "isows@npm:1.0.6" + peerDependencies: + ws: "*" + checksum: ab9e85b50bcc3d70aa5ec875aa2746c5daf9321cb376ed4e5434d3c2643c5d62b1f466d93a05cd2ad0ead5297224922748c31707cb4fbd68f5d05d0479dce99c + languageName: node + linkType: hard + "isstream@npm:~0.1.2": version: 0.1.2 resolution: "isstream@npm:0.1.2" @@ -40274,6 +40367,28 @@ __metadata: languageName: node linkType: hard +"viem@npm:^2.21.26": + version: 2.21.26 + resolution: "viem@npm:2.21.26" + dependencies: + "@adraffy/ens-normalize": "npm:1.11.0" + "@noble/curves": "npm:1.6.0" + "@noble/hashes": "npm:1.5.0" + "@scure/bip32": "npm:1.5.0" + "@scure/bip39": "npm:1.4.0" + abitype: "npm:1.0.6" + isows: "npm:1.0.6" + webauthn-p256: "npm:0.0.10" + ws: "npm:8.18.0" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 5233c9b34207c71b24a2d47abeefc9bf36b48f73b1601b2e4dfd5b71425f32902b11f85c14b00fd8b7f122469f584b21a49dc2f70a3068315182b487a42b31eb + languageName: node + linkType: hard + "vite-node@npm:1.2.1": version: 1.2.1 resolution: "vite-node@npm:1.2.1" @@ -40799,6 +40914,16 @@ __metadata: languageName: node linkType: hard +"webauthn-p256@npm:0.0.10": + version: 0.0.10 + resolution: "webauthn-p256@npm:0.0.10" + dependencies: + "@noble/curves": "npm:^1.4.0" + "@noble/hashes": "npm:^1.4.0" + checksum: dde2b6313b6a0f20996f7ee90181258fc7685bfff401df7d904578da75b374f25d5b9c1189cd2fcec30625b1f276b393188d156d49783f0611623cd713bb5b09 + languageName: node + linkType: hard + "webcrypto-core@npm:^1.7.7": version: 1.7.7 resolution: "webcrypto-core@npm:1.7.7" @@ -41608,6 +41733,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:8.18.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 + languageName: node + linkType: hard + "ws@npm:8.5.0": version: 8.5.0 resolution: "ws@npm:8.5.0" From 1a11c84c9c993edcbec87f4f6039210f9e0450ff Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Oct 2024 01:19:01 +0100 Subject: [PATCH 14/37] chore(sdk): release @kleros/kleros-sdk@2.1.1 --- kleros-sdk/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index c53ecddb3..2165e06cc 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-sdk", - "version": "2.1.0", + "version": "2.1.1", "description": "SDK for Kleros version 2", "repository": "git@github.com:kleros/kleros-v2.git", "author": "Kleros", From 98c290704be484dfc92a58f9580d9e880a6ca07a Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Oct 2024 01:37:47 +0100 Subject: [PATCH 15/37] chore(sdk): release @kleros/kleros-sdk@2.1.2 --- kleros-sdk/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 2165e06cc..5faec412f 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-sdk", - "version": "2.1.1", + "version": "2.1.2", "description": "SDK for Kleros version 2", "repository": "git@github.com:kleros/kleros-v2.git", "author": "Kleros", From b851f2acb1fe7b6465544ec36331bcd1b3e34342 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Oct 2024 01:57:22 +0100 Subject: [PATCH 16/37] chore(sdk): release @kleros/kleros-sdk@2.1.3 --- kleros-sdk/package.json | 2 +- kleros-sdk/src/index.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 5faec412f..7a401c999 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-sdk", - "version": "2.1.2", + "version": "2.1.3", "description": "SDK for Kleros version 2", "repository": "git@github.com:kleros/kleros-v2.git", "author": "Kleros", diff --git a/kleros-sdk/src/index.ts b/kleros-sdk/src/index.ts index 00223f12e..12a6e96d1 100644 --- a/kleros-sdk/src/index.ts +++ b/kleros-sdk/src/index.ts @@ -1,3 +1,4 @@ export * from "./sdk"; export * from "./types"; export * from "./utils/getDispute"; +export * from "./dataMappings/utils/disputeDetailsTypes"; From 57711badf51d5c97ab99e8d48581bc40c1bbc15a Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Oct 2024 02:06:04 +0100 Subject: [PATCH 17/37] docs(sdk): readme --- kleros-sdk/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kleros-sdk/README.md b/kleros-sdk/README.md index 1c929a4cc..28d807b82 100644 --- a/kleros-sdk/README.md +++ b/kleros-sdk/README.md @@ -1,4 +1,4 @@ -# @kleros/kleros-v2-sdk +# @kleros/kleros-sdk _Archon's successor_ From cbdd6d1da7e7dd81ab7f6b456d4f53e55fbdc8c1 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Oct 2024 11:21:34 +0100 Subject: [PATCH 18/37] chore: clean up --- kleros-sdk/package.json | 1 - kleros-sdk/src/dataMappings/disputeDetails.ts | 39 ------------------- yarn.lock | 3 +- 3 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 kleros-sdk/src/dataMappings/disputeDetails.ts diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 7a401c999..013d41b3b 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -46,7 +46,6 @@ "vitest": "^1.1.3" }, "dependencies": { - "@kleros/kleros-v2-contracts": "workspace:^", "@reality.eth/reality-eth-lib": "^3.2.30", "graphql-request": "^7.1.0", "mustache": "^4.2.0", diff --git a/kleros-sdk/src/dataMappings/disputeDetails.ts b/kleros-sdk/src/dataMappings/disputeDetails.ts deleted file mode 100644 index 28a3133a6..000000000 --- a/kleros-sdk/src/dataMappings/disputeDetails.ts +++ /dev/null @@ -1,39 +0,0 @@ -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/yarn.lock b/yarn.lock index 1894ffa5c..2fc260b26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7899,7 +7899,6 @@ __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": "npm:^3.2.30" "@types/mustache": "npm:^4.2.5" "@vitest/ui": "npm:^1.1.3" @@ -7923,7 +7922,7 @@ __metadata: languageName: unknown linkType: soft -"@kleros/kleros-v2-contracts@workspace:^, @kleros/kleros-v2-contracts@workspace:contracts": +"@kleros/kleros-v2-contracts@workspace:contracts": version: 0.0.0-use.local resolution: "@kleros/kleros-v2-contracts@workspace:contracts" dependencies: From 77b57e43d75441877467b20956f1a27ffac1214c Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Wed, 16 Oct 2024 15:58:25 +0530 Subject: [PATCH 19/37] chore(kleros-sdk): define-entry-points-for-files --- kleros-sdk/src/dataMappings/index.ts | 1 + kleros-sdk/src/dataMappings/utils/index.ts | 3 +++ kleros-sdk/src/index.ts | 5 +++-- kleros-sdk/src/utils/index.ts | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 kleros-sdk/src/dataMappings/index.ts create mode 100644 kleros-sdk/src/dataMappings/utils/index.ts create mode 100644 kleros-sdk/src/utils/index.ts diff --git a/kleros-sdk/src/dataMappings/index.ts b/kleros-sdk/src/dataMappings/index.ts new file mode 100644 index 000000000..74599330a --- /dev/null +++ b/kleros-sdk/src/dataMappings/index.ts @@ -0,0 +1 @@ +export * from "./executeActions"; diff --git a/kleros-sdk/src/dataMappings/utils/index.ts b/kleros-sdk/src/dataMappings/utils/index.ts new file mode 100644 index 000000000..bacf46150 --- /dev/null +++ b/kleros-sdk/src/dataMappings/utils/index.ts @@ -0,0 +1,3 @@ +export * from "./populateTemplate"; +export * from "./retrieveVariables"; +export * from "./disputeDetailsTypes"; diff --git a/kleros-sdk/src/index.ts b/kleros-sdk/src/index.ts index 12a6e96d1..92719d922 100644 --- a/kleros-sdk/src/index.ts +++ b/kleros-sdk/src/index.ts @@ -1,4 +1,5 @@ export * from "./sdk"; export * from "./types"; -export * from "./utils/getDispute"; -export * from "./dataMappings/utils/disputeDetailsTypes"; +export * from "./utils"; +export * from "./dataMappings"; +export * from "./dataMappings/utils"; diff --git a/kleros-sdk/src/utils/index.ts b/kleros-sdk/src/utils/index.ts new file mode 100644 index 000000000..4858866fa --- /dev/null +++ b/kleros-sdk/src/utils/index.ts @@ -0,0 +1 @@ +export * from "./getDispute"; From 71f851b6556c43ede554d81b0d25a79bf23af537 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 16 Oct 2024 13:10:01 +0100 Subject: [PATCH 20/37] chore(sdk): release @kleros/kleros-sdk@2.1.4 --- kleros-sdk/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 013d41b3b..97734b57b 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-sdk", - "version": "2.1.3", + "version": "2.1.4", "description": "SDK for Kleros version 2", "repository": "git@github.com:kleros/kleros-v2.git", "author": "Kleros", From ecc9edff604a52474208b1ab28e9c796f3dc0dac Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Sat, 19 Oct 2024 01:01:41 +0530 Subject: [PATCH 21/37] refactor(kleros-sdk): remove-path-aliasing --- kleros-sdk/package.json | 4 ---- .../src/dataMappings/actions/callAction.ts | 6 +++--- .../src/dataMappings/actions/eventAction.ts | 6 +++--- .../dataMappings/actions/fetchIpfsJsonAction.ts | 6 +++--- .../src/dataMappings/actions/jsonAction.ts | 2 +- .../src/dataMappings/actions/subgraphAction.ts | 2 +- kleros-sdk/src/dataMappings/executeActions.ts | 2 +- kleros-sdk/src/utils/getDispute.ts | 13 ++++++------- kleros-sdk/test/dataMappings.test.ts | 17 ++++++++--------- kleros-sdk/test/disputeDetailsSchema.test.ts | 2 +- kleros-sdk/tsconfig.json | 11 ----------- 11 files changed, 27 insertions(+), 44 deletions(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index 97734b57b..bb4c00e6f 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -12,10 +12,6 @@ "lib/**/*", "!lib/**/test/*" ], - "alias": { - "src": "./src", - "dataMappings": "./src/dataMappings" - }, "packageManager": "yarn@4.0.2+sha256.825003a0f561ad09a3b1ac4a3b3ea6207af2796d54f62a9420520915721f5186", "engines": { "node": ">=16.0.0" diff --git a/kleros-sdk/src/dataMappings/actions/callAction.ts b/kleros-sdk/src/dataMappings/actions/callAction.ts index d7b2a63bf..89c9fcb7f 100644 --- a/kleros-sdk/src/dataMappings/actions/callAction.ts +++ b/kleros-sdk/src/dataMappings/actions/callAction.ts @@ -1,7 +1,7 @@ import { parseAbiItem } from "viem"; -import { AbiCallMapping } from "src/dataMappings/utils/actionTypes"; -import { createResultObject } from "src/dataMappings/utils/createResultObject"; -import { getPublicClient } from "src/sdk"; +import { AbiCallMapping } from "../utils/actionTypes"; +import { createResultObject } from "../utils/createResultObject"; +import { getPublicClient } from "../../sdk"; export const callAction = async (mapping: AbiCallMapping) => { const publicClient = getPublicClient(); diff --git a/kleros-sdk/src/dataMappings/actions/eventAction.ts b/kleros-sdk/src/dataMappings/actions/eventAction.ts index e3f36933c..229d43fdd 100644 --- a/kleros-sdk/src/dataMappings/actions/eventAction.ts +++ b/kleros-sdk/src/dataMappings/actions/eventAction.ts @@ -1,7 +1,7 @@ import { parseAbiItem, type AbiEvent } from "viem"; -import { AbiEventMapping } from "src/dataMappings/utils/actionTypes"; -import { createResultObject } from "src/dataMappings/utils/createResultObject"; -import { getPublicClient } from "src/sdk"; +import { AbiEventMapping } from "../utils/actionTypes"; +import { createResultObject } from "../utils/createResultObject"; +import { getPublicClient } from "../../sdk"; export const eventAction = async (mapping: AbiEventMapping) => { const publicClient = getPublicClient(); diff --git a/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts b/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts index f2ea6f29c..861739b90 100644 --- a/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts +++ b/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts @@ -1,6 +1,6 @@ -import { FetchIpfsJsonMapping } from "src/dataMappings/utils/actionTypes"; -import { createResultObject } from "src/dataMappings/utils/createResultObject"; -import { MAX_BYTE_SIZE } from "src/consts"; +import { MAX_BYTE_SIZE } from "../../consts"; +import { FetchIpfsJsonMapping } from "../utils/actionTypes"; +import { createResultObject } from "../utils/createResultObject"; export const fetchIpfsJsonAction = async (mapping: FetchIpfsJsonMapping) => { const { ipfsUri, seek, populate } = mapping; diff --git a/kleros-sdk/src/dataMappings/actions/jsonAction.ts b/kleros-sdk/src/dataMappings/actions/jsonAction.ts index 87e787131..86b14447d 100644 --- a/kleros-sdk/src/dataMappings/actions/jsonAction.ts +++ b/kleros-sdk/src/dataMappings/actions/jsonAction.ts @@ -1,5 +1,5 @@ import { JsonMapping } from "../utils/actionTypes"; -import { createResultObject } from "src/dataMappings/utils/createResultObject"; +import { createResultObject } from "../utils/createResultObject"; export const jsonAction = (mapping: JsonMapping) => { const { value, seek, populate } = mapping; diff --git a/kleros-sdk/src/dataMappings/actions/subgraphAction.ts b/kleros-sdk/src/dataMappings/actions/subgraphAction.ts index 018579c04..4ef3373f0 100644 --- a/kleros-sdk/src/dataMappings/actions/subgraphAction.ts +++ b/kleros-sdk/src/dataMappings/actions/subgraphAction.ts @@ -1,5 +1,5 @@ import { SubgraphMapping } from "../utils/actionTypes"; -import { createResultObject } from "src/dataMappings/utils/createResultObject"; +import { createResultObject } from "../utils/createResultObject"; export const subgraphAction = async (mapping: SubgraphMapping) => { const { endpoint, query, variables, seek, populate } = mapping; diff --git a/kleros-sdk/src/dataMappings/executeActions.ts b/kleros-sdk/src/dataMappings/executeActions.ts index 0322e596c..06052b6a9 100644 --- a/kleros-sdk/src/dataMappings/executeActions.ts +++ b/kleros-sdk/src/dataMappings/executeActions.ts @@ -1,5 +1,5 @@ import { callAction } from "./actions/callAction"; -import { eventAction } from "./actions/eventAction.js"; +import { eventAction } from "./actions/eventAction"; import { fetchIpfsJsonAction } from "./actions/fetchIpfsJsonAction"; import { jsonAction } from "./actions/jsonAction"; import { subgraphAction } from "./actions/subgraphAction"; diff --git a/kleros-sdk/src/utils/getDispute.ts b/kleros-sdk/src/utils/getDispute.ts index 3dbdd646a..45e236b80 100644 --- a/kleros-sdk/src/utils/getDispute.ts +++ b/kleros-sdk/src/utils/getDispute.ts @@ -1,10 +1,9 @@ -import { type GetDisputeParameters } from "src/types"; -import { configureSDK } from "src/sdk"; -import fetchDisputeDetails from "src/requests/fetchDisputeDetails"; -import fetchDisputeTemplateFromId from "src/requests/fetchDisputeTemplateFromId"; -import { executeActions } from "dataMappings/executeActions"; -import { populateTemplate } from "dataMappings/utils/populateTemplate"; -import { DisputeDetails } from "dataMappings/utils/disputeDetailsTypes"; +import { executeActions } from "../dataMappings"; +import { DisputeDetails, populateTemplate } from "../dataMappings/utils"; +import fetchDisputeDetails from "../requests/fetchDisputeDetails"; +import fetchDisputeTemplateFromId from "../requests/fetchDisputeTemplateFromId"; +import { configureSDK } from "../sdk"; +import { GetDisputeParameters } from "../types"; /** * Retrieves dispute parameters based on the provided dispute ID and subgraph endpoints. diff --git a/kleros-sdk/test/dataMappings.test.ts b/kleros-sdk/test/dataMappings.test.ts index b36ee7d12..13cdc4490 100644 --- a/kleros-sdk/test/dataMappings.test.ts +++ b/kleros-sdk/test/dataMappings.test.ts @@ -1,19 +1,18 @@ import { describe, expect, it, vi } from "vitest"; -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"; -import { createResultObject } from "src/dataMappings/utils/createResultObject"; -import { executeActions } from "src/dataMappings/executeActions"; +import { createResultObject } from "../src/dataMappings/utils/createResultObject"; +import { executeActions, populateTemplate } from "../src"; import { AbiCallMapping, AbiEventMapping, FetchIpfsJsonMapping, JsonMapping, SubgraphMapping, -} from "src/dataMappings/utils/actionTypes"; +} from "../src/dataMappings/utils/actionTypes"; +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"; global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ diff --git a/kleros-sdk/test/disputeDetailsSchema.test.ts b/kleros-sdk/test/disputeDetailsSchema.test.ts index ac2c7878a..d9f132e73 100644 --- a/kleros-sdk/test/disputeDetailsSchema.test.ts +++ b/kleros-sdk/test/disputeDetailsSchema.test.ts @@ -3,7 +3,7 @@ import { ethAddressSchema, ensNameSchema, ethAddressOrEnsNameSchema, -} from "src/dataMappings/utils/disputeDetailsSchema"; +} from "../src/dataMappings/utils/disputeDetailsSchema"; describe("Dispute Details Schema", () => { it("snapshot", () => { diff --git a/kleros-sdk/tsconfig.json b/kleros-sdk/tsconfig.json index af37852bd..8ce8e0686 100644 --- a/kleros-sdk/tsconfig.json +++ b/kleros-sdk/tsconfig.json @@ -2,17 +2,6 @@ "extends": "@kleros/kleros-v2-tsconfig/base20.json", "compilerOptions": { "outDir": "lib", - "paths": { - "~*": [ - "./*" - ], - "src*": [ - "./src*" - ], - "dataMappings*": [ - "./src/dataMappings*" - ] - }, "allowJs": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true, From e69854858ef4e8f281e7973c923a5f684441ead6 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 21 Oct 2024 13:13:42 +0530 Subject: [PATCH 22/37] refactor(kleros-sdk): update-get-dispute-function-parameter-type --- kleros-sdk/src/requests/fetchDisputeDetails.ts | 4 ++-- kleros-sdk/src/types/index.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts index 0b1796f2b..4becbf5ef 100644 --- a/kleros-sdk/src/requests/fetchDisputeDetails.ts +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -11,10 +11,10 @@ type DisputeDetailsQueryResponse = { }; }; -const fetchDisputeDetails = async (endpoint: string, id: number) => { +const fetchDisputeDetails = async (endpoint: string, id: bigint) => { const query = ` query DisputeDetails { - dispute(id: ${id}) { + dispute(id: ${Number(id)}) { arbitrated { id } diff --git a/kleros-sdk/src/types/index.ts b/kleros-sdk/src/types/index.ts index 7c0d5ea9a..1d4c58190 100644 --- a/kleros-sdk/src/types/index.ts +++ b/kleros-sdk/src/types/index.ts @@ -5,13 +5,13 @@ export type SdkConfig = { }; type GetDisputeParametersOptions = { - sdkConfig: SdkConfig; - additionalContext: Record; + sdkConfig?: SdkConfig; + additionalContext?: Record; }; export type GetDisputeParameters = { - disputeId: number; + disputeId: bigint; coreSubgraph: string; dtrSubgraph: string; - options: GetDisputeParametersOptions | undefined; + options?: GetDisputeParametersOptions; }; From 93e59a101aed403e41421a40dc4761128fd756eb Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 21 Oct 2024 13:14:21 +0530 Subject: [PATCH 23/37] fix(web): typing --- web/.env.devnet.public | 2 -- web/tsconfig.json | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/web/.env.devnet.public b/web/.env.devnet.public index 4dff52c1d..e4742b7c0 100644 --- a/web/.env.devnet.public +++ b/web/.env.devnet.public @@ -5,8 +5,6 @@ export REACT_APP_DRT_ARBSEPOLIA_SUBGRAPH=https://api.studio.thegraph.com/query/6 export REACT_APP_STATUS_URL=https://kleros-v2-devnet.betteruptime.com/badge export REACT_APP_GENESIS_BLOCK_ARBSEPOLIA=3084598 export REACT_APP_DEVTOOLS_URL=https://dev--kleros-v2-testnet-devtools.netlify.app -export WALLETCONNECT_PROJECT_ID= -export ALCHEMY_API_KEY= export NODE_OPTIONS='--max-old-space-size=7680' # devtools export REACT_APP_GRAPH_API_KEY= diff --git a/web/tsconfig.json b/web/tsconfig.json index b40e3fa6d..fae4af75b 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -57,6 +57,14 @@ "allowSyntheticDefaultImports": true, "removeComments": true, "isolatedModules": true, + "moduleResolution": "node", + "strict": true, + "esModuleInterop": true, + "declaration": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": false, + "resolveJsonModule": true, "lib": [ "ESNext.Array" ], From 0a8422f89e1d8a4e7f700a5a5c5b9c7d63b9b380 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 21 Oct 2024 13:28:21 +0530 Subject: [PATCH 24/37] chore: update-yarn-lock --- yarn.lock | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/yarn.lock b/yarn.lock index 99ee8726c..578b50acc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40250,28 +40250,6 @@ __metadata: languageName: node linkType: hard -"viem@npm:^2.21.26": - version: 2.21.26 - resolution: "viem@npm:2.21.26" - dependencies: - "@adraffy/ens-normalize": "npm:1.11.0" - "@noble/curves": "npm:1.6.0" - "@noble/hashes": "npm:1.5.0" - "@scure/bip32": "npm:1.5.0" - "@scure/bip39": "npm:1.4.0" - abitype: "npm:1.0.6" - isows: "npm:1.0.6" - webauthn-p256: "npm:0.0.10" - ws: "npm:8.18.0" - peerDependencies: - typescript: ">=5.0.4" - peerDependenciesMeta: - typescript: - optional: true - checksum: 5233c9b34207c71b24a2d47abeefc9bf36b48f73b1601b2e4dfd5b71425f32902b11f85c14b00fd8b7f122469f584b21a49dc2f70a3068315182b487a42b31eb - languageName: node - linkType: hard - "vite-node@npm:1.2.1": version: 1.2.1 resolution: "vite-node@npm:1.2.1" From 04c80dbf6d7bba4e62667f2131ee4f473e03ec8f Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 21 Oct 2024 15:15:31 +0530 Subject: [PATCH 25/37] chore(kleros-sdk): update-get-dispute-id-spec --- kleros-sdk/src/utils/getDispute.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kleros-sdk/src/utils/getDispute.ts b/kleros-sdk/src/utils/getDispute.ts index 45e236b80..8a9d1b09c 100644 --- a/kleros-sdk/src/utils/getDispute.ts +++ b/kleros-sdk/src/utils/getDispute.ts @@ -9,7 +9,7 @@ import { GetDisputeParameters } from "../types"; * Retrieves dispute parameters based on the provided dispute ID and subgraph endpoints. * * @param {GetDisputeParameters} disputeParameters - The parameters required to get the dispute. - * @param {number} disputeParameters.disputeId - A unique numeric identifier of the dispute in the Kleros Core contract. + * @param {bigint} disputeParameters.disputeId - A unique numeric identifier of the dispute in the Kleros Core contract. * @param {string} disputeParameters.coreSubgraph - Endpoint for the Kleros core subgraph to use. * @param {string} disputeParameters.dtrSubgraph - Endpoint for the Kleros dispute template registry subgraph. * @param {GetDisputeParametersOptions | undefined} disputeParameters.options - Optional parameters to configure the SDK and provide additional context, if not configured already. From 9b4e9d2152d4b14e16bf53504a770cbd9ab28cf7 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 22 Oct 2024 14:21:14 +0530 Subject: [PATCH 26/37] feat(kleros-sdk): better-error-handling-and-optimisations --- .../src/dataMappings/actions/callAction.ts | 3 +- .../src/dataMappings/actions/eventAction.ts | 3 +- .../actions/fetchIpfsJsonAction.ts | 9 +- kleros-sdk/src/dataMappings/executeActions.ts | 3 +- .../src/dataMappings/retrieveRealityData.ts | 11 ++- .../utils/actionTypeValidators.ts | 37 ++++----- .../dataMappings/utils/populateTemplate.ts | 3 +- .../utils/replacePlaceholdersWithValues.ts | 3 +- kleros-sdk/src/errors/index.ts | 82 +++++++++++++++++++ .../src/requests/fetchDisputeDetails.ts | 13 ++- .../requests/fetchDisputeTemplateFromId.ts | 13 ++- kleros-sdk/src/sdk.ts | 3 +- kleros-sdk/src/utils/getDispute.ts | 10 ++- 13 files changed, 148 insertions(+), 45 deletions(-) create mode 100644 kleros-sdk/src/errors/index.ts diff --git a/kleros-sdk/src/dataMappings/actions/callAction.ts b/kleros-sdk/src/dataMappings/actions/callAction.ts index 89c9fcb7f..d8a2e7b0c 100644 --- a/kleros-sdk/src/dataMappings/actions/callAction.ts +++ b/kleros-sdk/src/dataMappings/actions/callAction.ts @@ -2,12 +2,13 @@ import { parseAbiItem } from "viem"; import { AbiCallMapping } from "../utils/actionTypes"; import { createResultObject } from "../utils/createResultObject"; import { getPublicClient } from "../../sdk"; +import { SdkNotConfiguredError } from "../../errors"; export const callAction = async (mapping: AbiCallMapping) => { const publicClient = getPublicClient(); if (!publicClient) { - throw new Error("SDK not configured. Please call `configureSDK` before using."); + throw new SdkNotConfiguredError(); } const { abi: source, address, functionName, args, seek, populate } = mapping; diff --git a/kleros-sdk/src/dataMappings/actions/eventAction.ts b/kleros-sdk/src/dataMappings/actions/eventAction.ts index 229d43fdd..0f460af1d 100644 --- a/kleros-sdk/src/dataMappings/actions/eventAction.ts +++ b/kleros-sdk/src/dataMappings/actions/eventAction.ts @@ -2,12 +2,13 @@ import { parseAbiItem, type AbiEvent } from "viem"; import { AbiEventMapping } from "../utils/actionTypes"; import { createResultObject } from "../utils/createResultObject"; import { getPublicClient } from "../../sdk"; +import { SdkNotConfiguredError } from "../../errors"; export const eventAction = async (mapping: AbiEventMapping) => { const publicClient = getPublicClient(); if (!publicClient) { - throw new Error("SDK not configured. Please call `configureSDK` before using."); + throw new SdkNotConfiguredError(); } const { abi: source, address, eventFilter, seek, populate } = mapping; diff --git a/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts b/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts index 861739b90..a6f3968eb 100644 --- a/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts +++ b/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts @@ -1,4 +1,5 @@ import { MAX_BYTE_SIZE } from "../../consts"; +import { RequestError } from "../../errors"; import { FetchIpfsJsonMapping } from "../utils/actionTypes"; import { createResultObject } from "../utils/createResultObject"; @@ -13,23 +14,23 @@ export const fetchIpfsJsonAction = async (mapping: FetchIpfsJsonMapping) => { } else if (!ipfsUri.startsWith("http")) { httpUri = `https://ipfs.io/ipfs/${ipfsUri}`; } else { - throw new Error("Invalid IPFS URI format"); + throw new RequestError("Invalid IPFS URI format", httpUri); } const response = await fetch(httpUri, { method: "GET" }); if (!response.ok) { - throw new Error("Failed to fetch data from IPFS"); + throw new RequestError("Failed to fetch data from IPFS", httpUri); } const contentLength = response.headers.get("content-length"); if (contentLength && parseInt(contentLength) > MAX_BYTE_SIZE) { - throw new Error("Response size is too large"); + throw new RequestError("Response size is too large", httpUri); } const contentType = response.headers.get("content-type"); if (!contentType || !contentType.includes("application/json")) { - throw new Error("Fetched data is not JSON"); + throw new RequestError("Fetched data is not JSON", httpUri); } const data = await response.json(); diff --git a/kleros-sdk/src/dataMappings/executeActions.ts b/kleros-sdk/src/dataMappings/executeActions.ts index 06052b6a9..f78e4e3b6 100644 --- a/kleros-sdk/src/dataMappings/executeActions.ts +++ b/kleros-sdk/src/dataMappings/executeActions.ts @@ -1,3 +1,4 @@ +import { UnsupportedActionError } from "../errors"; import { callAction } from "./actions/callAction"; import { eventAction } from "./actions/eventAction"; import { fetchIpfsJsonAction } from "./actions/fetchIpfsJsonAction"; @@ -41,7 +42,7 @@ export const executeAction = async ( mapping = validateRealityMapping(mapping); return await retrieveRealityData(mapping.realityQuestionID, context.arbitrableAddress as Address); default: - throw new Error(`Unsupported action type: ${JSON.stringify(mapping)}`); + throw new UnsupportedActionError(`Unsupported action type: ${JSON.stringify(mapping)}`); } }; diff --git a/kleros-sdk/src/dataMappings/retrieveRealityData.ts b/kleros-sdk/src/dataMappings/retrieveRealityData.ts index d2b5294cf..ab8b8f6b0 100644 --- a/kleros-sdk/src/dataMappings/retrieveRealityData.ts +++ b/kleros-sdk/src/dataMappings/retrieveRealityData.ts @@ -1,3 +1,4 @@ +import { InvalidContextError, NotFoundError } from "../errors"; import { executeAction } from "./executeActions"; import { AbiEventMapping } from "./utils/actionTypes"; @@ -11,7 +12,7 @@ export type RealityAnswer = { export const retrieveRealityData = async (realityQuestionID: string, arbitrable?: `0x${string}`) => { if (!arbitrable) { - throw new Error("No arbitrable address provided"); + throw new InvalidContextError("No arbitrable address provided"); } const questionMapping: AbiEventMapping = { type: "abi/event", @@ -67,8 +68,12 @@ export const retrieveRealityData = async (realityQuestionID: string, arbitrable? const templateData = await executeAction(templateMapping); console.log("templateData", templateData); - if (!templateData || !questionData) { - throw new Error("Failed to retrieve template or question data"); + if (!templateData) { + throw new NotFoundError("Template Data", "Failed to retrieve template data"); + } + + if (!questionData) { + throw new NotFoundError("Question Data", "Failed to retrieve question data"); } const rc_question = require("@reality.eth/reality-eth-lib/formatters/question.js"); diff --git a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts index 593c6f544..8ff28b699 100644 --- a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts +++ b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts @@ -1,3 +1,4 @@ +import { InvalidMappingError } from "../../errors"; import { SubgraphMapping, AbiEventMapping, @@ -9,43 +10,37 @@ import { } 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; + return validateMapping(mapping as SubgraphMapping, ["endpoint"]); }; 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; + return validateMapping(mapping as AbiEventMapping, ["abi", "eventFilter"]); }; export const validateAbiCallMapping = (mapping: ActionMapping) => { - if ((mapping as AbiCallMapping).abi === undefined || (mapping as AbiCallMapping).functionName === undefined) { - throw new Error("Invalid mapping for abi/call action."); - } - return mapping as AbiCallMapping; + return validateMapping(mapping as AbiCallMapping, ["abi", "functionName"]); }; export const validateJsonMapping = (mapping: ActionMapping) => { - if ((mapping as JsonMapping).value === undefined) { - throw new Error("Invalid mapping for json action."); - } - return mapping as JsonMapping; + return validateMapping(mapping as JsonMapping, ["value"]); }; 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; + return validateMapping(mapping as FetchIpfsJsonMapping, ["ipfsUri"]); }; export const validateRealityMapping = (mapping: ActionMapping) => { if (mapping.type !== "reality" || typeof (mapping as RealityMapping).realityQuestionID !== "string") { - throw new Error("Invalid mapping for reality action."); + throw new InvalidMappingError("Expected field 'realityQuestionID' to be a string."); } return mapping as RealityMapping; }; + +const validateMapping = (mapping: T, requiredFields: (keyof T)[]) => { + for (const field of requiredFields) { + if (mapping[field] === undefined) { + throw new InvalidMappingError(`${field.toString()} is required for ${mapping.type}`); + } + } + return mapping; +}; diff --git a/kleros-sdk/src/dataMappings/utils/populateTemplate.ts b/kleros-sdk/src/dataMappings/utils/populateTemplate.ts index 57377706b..1ad8c319b 100644 --- a/kleros-sdk/src/dataMappings/utils/populateTemplate.ts +++ b/kleros-sdk/src/dataMappings/utils/populateTemplate.ts @@ -1,6 +1,7 @@ import mustache from "mustache"; import { DisputeDetails } from "./disputeDetailsTypes"; import DisputeDetailsSchema from "./disputeDetailsSchema"; +import { InvalidFormatError } from "../../errors"; export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => { const render = mustache.render(mustacheTemplate, data); @@ -9,7 +10,7 @@ export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDe const validation = DisputeDetailsSchema.safeParse(dispute); if (!validation.success) { console.error("Validation errors:", validation.error.errors, "\n\nDispute details:", `${JSON.stringify(dispute)}`); - throw new Error("Invalid dispute details format"); + throw new InvalidFormatError("Invalid dispute details format"); } console.log(dispute); diff --git a/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts b/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts index 0c0379bad..2f5520ef7 100644 --- a/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts +++ b/kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts @@ -1,6 +1,7 @@ import mustache from "mustache"; import retrieveVariables from "./retrieveVariables"; import { ActionMapping } from "./actionTypes"; +import { InvalidContextError } from "../../errors"; export function replacePlaceholdersWithValues( mapping: ActionMapping, @@ -34,7 +35,7 @@ const validateContext = (template: string, context: Record) => const variables = retrieveVariables(template); variables.forEach((variable) => { - if (!context[variable]) throw new Error(`Expected key : "${variable}" to be provided in context.`); + if (!context[variable]) throw new InvalidContextError(`Expected key "${variable}" to be provided in context.`); }); return true; }; diff --git a/kleros-sdk/src/errors/index.ts b/kleros-sdk/src/errors/index.ts new file mode 100644 index 000000000..ed28b1f09 --- /dev/null +++ b/kleros-sdk/src/errors/index.ts @@ -0,0 +1,82 @@ +export class InvalidContextError extends Error { + constructor(message: string) { + super(message); + this.name = "InvalidContextError"; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } +} + +export class InvalidMappingError extends Error { + constructor(message: string) { + super(message); + this.name = "InvalidMappingError"; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } +} + +export class NotFoundError extends Error { + public resourceName: string; + + constructor(resourceName: string, message: string) { + super(message); + this.name = "NotFoundError"; + this.resourceName = resourceName; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } +} + +export class RequestError extends Error { + public endpoint: string | undefined; + + constructor(message: string, endpoint?: string) { + super(message); + this.name = "RequestError"; + this.endpoint = endpoint; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } +} + +export class UnsupportedActionError extends Error { + constructor(message: string) { + super(message); + this.name = "UnsupportedActionError"; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } +} + +export class InvalidFormatError extends Error { + constructor(message: string) { + super(message); + this.name = "InvalidFormatError"; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } +} + +export class SdkNotConfiguredError extends Error { + constructor() { + super("SDK not configured. Please call `configureSDK` before using."); + this.name = "SdkNotConfiguredError"; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } +} diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts index 4becbf5ef..44ab651e3 100644 --- a/kleros-sdk/src/requests/fetchDisputeDetails.ts +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -1,4 +1,5 @@ import { request } from "graphql-request"; +import { RequestError } from "../errors"; type DisputeDetailsQueryResponse = { dispute: { @@ -13,8 +14,8 @@ type DisputeDetailsQueryResponse = { const fetchDisputeDetails = async (endpoint: string, id: bigint) => { const query = ` - query DisputeDetails { - dispute(id: ${Number(id)}) { + query DisputeDetails($id: ID!) { + dispute(id: $id) { arbitrated { id } @@ -24,11 +25,15 @@ const fetchDisputeDetails = async (endpoint: string, id: bigint) => { } } `; + const variables = { id: Number(id) }; try { - return await request(endpoint, query); + return await request(endpoint, query, variables); } catch (error: any) { - throw new Error(`Error querying Dispute Details , endpoint : ${endpoint}, message : ${error?.message}`); + if (error instanceof Error) { + throw new RequestError(`Error querying Dispute Details: ${error.message}`, endpoint); + } + throw new RequestError("An unknown error occurred while querying Dispute Details", endpoint); } }; diff --git a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts index b31d1b321..e20cb0840 100644 --- a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts +++ b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts @@ -1,4 +1,5 @@ import { request } from "graphql-request"; +import { RequestError } from "../errors"; type DisputeTemplateQueryResponse = { disputeTemplate: { @@ -9,18 +10,22 @@ type DisputeTemplateQueryResponse = { const fetchDisputeTemplateFromId = async (endpoint: string, id: number) => { const query = ` - query DisputeTemplate { - disputeTemplate(id: ${id}) { + query DisputeTemplate ($id: ID!) { + disputeTemplate(id: $id) { templateData templateDataMappings } } `; + const variables = { id: id.toString() }; try { - return await request(endpoint, query); + return await request(endpoint, query, variables); } catch (error: any) { - throw new Error(`Error querying Dispute Template Registry , endpoint : ${endpoint}, message : ${error?.message}`); + if (error instanceof Error) { + throw new RequestError(`Error querying Dispute Template: ${error.message}`, endpoint); + } + throw new RequestError("An unknown error occurred while querying Dispute Template", endpoint); } }; diff --git a/kleros-sdk/src/sdk.ts b/kleros-sdk/src/sdk.ts index cce4605e2..00e9c2940 100644 --- a/kleros-sdk/src/sdk.ts +++ b/kleros-sdk/src/sdk.ts @@ -1,5 +1,6 @@ import { createPublicClient, type PublicClient } from "viem"; import { SdkConfig } from "./types"; +import { SdkNotConfiguredError } from "./errors"; let publicClient: PublicClient | undefined; @@ -11,7 +12,7 @@ export const configureSDK = (config: SdkConfig) => { export const getPublicClient = (): PublicClient | undefined => { if (!publicClient) { - throw new Error("SDK not configured. Please call `configureSDK` before using."); + throw new SdkNotConfiguredError(); } return publicClient; }; diff --git a/kleros-sdk/src/utils/getDispute.ts b/kleros-sdk/src/utils/getDispute.ts index 8a9d1b09c..c73fa1f24 100644 --- a/kleros-sdk/src/utils/getDispute.ts +++ b/kleros-sdk/src/utils/getDispute.ts @@ -1,5 +1,6 @@ import { executeActions } from "../dataMappings"; import { DisputeDetails, populateTemplate } from "../dataMappings/utils"; +import { NotFoundError } from "../errors"; import fetchDisputeDetails from "../requests/fetchDisputeDetails"; import fetchDisputeTemplateFromId from "../requests/fetchDisputeTemplateFromId"; import { configureSDK } from "../sdk"; @@ -23,13 +24,16 @@ export const getDispute = async (disputeParameters: GetDisputeParameters): Promi const disputeDetails = await fetchDisputeDetails(coreSubgraph, disputeId); if (!disputeDetails?.dispute) { - throw new Error(`Dispute details not found for disputeId: ${disputeId}`); + throw new NotFoundError("Dispute Details", `Dispute details not found for disputeId: ${disputeId}`); } const template = await fetchDisputeTemplateFromId(dtrSubgraph, disputeDetails.dispute.templateId); if (!template) { - throw new Error(`Template not found for template ID: ${disputeDetails.dispute.templateId}`); + throw new NotFoundError( + "Dispute Template", + `Template not found for template ID: ${disputeDetails.dispute.templateId}` + ); } const { templateData, templateDataMappings } = template.disputeTemplate; @@ -46,7 +50,7 @@ export const getDispute = async (disputeParameters: GetDisputeParameters): Promi try { data = await executeActions(JSON.parse(templateDataMappings), initialContext); } catch (err: any) { - throw new Error(err); + throw err; } } From 7d5ed21887fa975000651009e2c12d797045f2d6 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 22 Oct 2024 15:22:10 +0530 Subject: [PATCH 27/37] refactor(kleros-sdk): sonar-cloud-fixes --- kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts | 4 ++-- kleros-sdk/vitest.config.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts index 8ff28b699..459a857e3 100644 --- a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts +++ b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts @@ -30,10 +30,10 @@ export const validateFetchIpfsJsonMapping = (mapping: ActionMapping) => { }; export const validateRealityMapping = (mapping: ActionMapping) => { - if (mapping.type !== "reality" || typeof (mapping as RealityMapping).realityQuestionID !== "string") { + if (mapping.type !== "reality" || typeof mapping.realityQuestionID !== "string") { throw new InvalidMappingError("Expected field 'realityQuestionID' to be a string."); } - return mapping as RealityMapping; + return mapping; }; const validateMapping = (mapping: T, requiredFields: (keyof T)[]) => { diff --git a/kleros-sdk/vitest.config.ts b/kleros-sdk/vitest.config.ts index ea4060443..e87f6f23e 100644 --- a/kleros-sdk/vitest.config.ts +++ b/kleros-sdk/vitest.config.ts @@ -1,5 +1,4 @@ -import { defineConfig } from "vitest/config"; -import { configDefaults } from "vitest/config"; +import { defineConfig, configDefaults } from "vitest/config"; export default defineConfig({ test: { From 542a8d9c6381ca15a452a2ab3e1cced69ab94d1a Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 22 Oct 2024 15:27:13 +0530 Subject: [PATCH 28/37] refactor(kleros-sdk): remoev-unused-import --- kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts index 459a857e3..74b064922 100644 --- a/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts +++ b/kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts @@ -6,7 +6,6 @@ import { JsonMapping, ActionMapping, FetchIpfsJsonMapping, - RealityMapping, } from "./actionTypes"; export const validateSubgraphMapping = (mapping: ActionMapping) => { From 3d42edcae28205f59f0b460805a28ef13879673a Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 22 Oct 2024 16:01:15 +0530 Subject: [PATCH 29/37] refactor(kleros-sdk): address-coderabbit-feedback --- kleros-sdk/src/errors/index.ts | 28 ++++++++----------- .../src/requests/fetchDisputeDetails.ts | 14 +++++----- .../requests/fetchDisputeTemplateFromId.ts | 16 +++++------ 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/kleros-sdk/src/errors/index.ts b/kleros-sdk/src/errors/index.ts index ed28b1f09..612b3b05a 100644 --- a/kleros-sdk/src/errors/index.ts +++ b/kleros-sdk/src/errors/index.ts @@ -1,7 +1,7 @@ -export class InvalidContextError extends Error { - constructor(message: string) { +export class CustomError extends Error { + constructor(name: string, message: string) { super(message); - this.name = "InvalidContextError"; + this.name = name; if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); @@ -9,14 +9,15 @@ export class InvalidContextError extends Error { } } -export class InvalidMappingError extends Error { +export class InvalidContextError extends CustomError { constructor(message: string) { - super(message); - this.name = "InvalidMappingError"; + super("InvalidContextError", message); + } +} - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } +export class InvalidMappingError extends CustomError { + constructor(message: string) { + super("InvalidMappingError", message); } } @@ -48,14 +49,9 @@ export class RequestError extends Error { } } -export class UnsupportedActionError extends Error { +export class UnsupportedActionError extends CustomError { constructor(message: string) { - super(message); - this.name = "UnsupportedActionError"; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } + super("UnsupportedActionError", message); } } diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts index 44ab651e3..55c593f81 100644 --- a/kleros-sdk/src/requests/fetchDisputeDetails.ts +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -1,4 +1,4 @@ -import { request } from "graphql-request"; +import { request, gql } from "graphql-request"; import { RequestError } from "../errors"; type DisputeDetailsQueryResponse = { @@ -13,18 +13,18 @@ type DisputeDetailsQueryResponse = { }; const fetchDisputeDetails = async (endpoint: string, id: bigint) => { - const query = ` - query DisputeDetails($id: ID!) { - dispute(id: $id) { + const query = gql` + query DisputeDetails($id: ID!) { + dispute(id: $id) { arbitrated { - id + id } arbitrableChainId externalDisputeId templateId + } } - } -`; + `; const variables = { id: Number(id) }; try { diff --git a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts index e20cb0840..32c2d6ee6 100644 --- a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts +++ b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts @@ -1,4 +1,4 @@ -import { request } from "graphql-request"; +import { request, gql } from "graphql-request"; import { RequestError } from "../errors"; type DisputeTemplateQueryResponse = { @@ -9,14 +9,14 @@ type DisputeTemplateQueryResponse = { }; const fetchDisputeTemplateFromId = async (endpoint: string, id: number) => { - const query = ` - query DisputeTemplate ($id: ID!) { - disputeTemplate(id: $id) { - templateData - templateDataMappings - } + const query = gql` + query DisputeTemplate($id: ID!) { + disputeTemplate(id: $id) { + templateData + templateDataMappings + } } -`; + `; const variables = { id: id.toString() }; try { From a387e776fd6efe6e5162842c5ee81904009cae03 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Tue, 22 Oct 2024 16:14:06 +0530 Subject: [PATCH 30/37] refactor(kleros-sdk): refactor-error-classes --- kleros-sdk/src/errors/index.ts | 37 ++++--------------- .../src/requests/fetchDisputeDetails.ts | 2 +- 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/kleros-sdk/src/errors/index.ts b/kleros-sdk/src/errors/index.ts index 612b3b05a..af000ba37 100644 --- a/kleros-sdk/src/errors/index.ts +++ b/kleros-sdk/src/errors/index.ts @@ -21,31 +21,20 @@ export class InvalidMappingError extends CustomError { } } -export class NotFoundError extends Error { +export class NotFoundError extends CustomError { public resourceName: string; constructor(resourceName: string, message: string) { - super(message); - this.name = "NotFoundError"; + super("NotFoundError", message); this.resourceName = resourceName; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } } } - -export class RequestError extends Error { +export class RequestError extends CustomError { public endpoint: string | undefined; constructor(message: string, endpoint?: string) { - super(message); - this.name = "RequestError"; + super("RequestError", message); this.endpoint = endpoint; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } } } @@ -55,24 +44,14 @@ export class UnsupportedActionError extends CustomError { } } -export class InvalidFormatError extends Error { +export class InvalidFormatError extends CustomError { constructor(message: string) { - super(message); - this.name = "InvalidFormatError"; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } + super("InvalidFormatError", message); } } -export class SdkNotConfiguredError extends Error { +export class SdkNotConfiguredError extends CustomError { constructor() { - super("SDK not configured. Please call `configureSDK` before using."); - this.name = "SdkNotConfiguredError"; - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } + super("SdkNotConfiguredError", "SDK not configured. Please call `configureSDK` before using."); } } diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts index 55c593f81..923efb95d 100644 --- a/kleros-sdk/src/requests/fetchDisputeDetails.ts +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -25,7 +25,7 @@ const fetchDisputeDetails = async (endpoint: string, id: bigint) => { } } `; - const variables = { id: Number(id) }; + const variables = { id: id.toString() }; try { return await request(endpoint, query, variables); From 56853b99ae160ef1323e85e2e0c81d02cb66c1ba Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 23 Oct 2024 18:07:00 +0700 Subject: [PATCH 31/37] fix: test mocks --- kleros-sdk/test/dataMappings.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kleros-sdk/test/dataMappings.test.ts b/kleros-sdk/test/dataMappings.test.ts index 13cdc4490..ecff6a1eb 100644 --- a/kleros-sdk/test/dataMappings.test.ts +++ b/kleros-sdk/test/dataMappings.test.ts @@ -25,7 +25,7 @@ global.fetch = vi.fn().mockResolvedValue({ }), }); -vi.mock("src/sdk", () => ({ +vi.mock("../src/sdk", () => ({ configureSDK: vi.fn(), getPublicClient: vi.fn().mockReturnValue({ readContract: vi.fn().mockResolvedValue([BigInt(1), false, false]), @@ -106,7 +106,7 @@ vi.mock("src/dataMappings/actions/eventAction", () => ({ }), })); -vi.mock("src/dataMappings/actions/fetchIpfsJsonAction", () => ({ +vi.mock("../src/dataMappings/actions/fetchIpfsJsonAction", () => ({ fetchIpfsJsonAction: vi.fn(async (mapping) => { return createResultObject( { From 52b31a3880241d4fb17b5a3c9f6dbf22ebc7e685 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Wed, 23 Oct 2024 19:13:06 +0530 Subject: [PATCH 32/37] fix(kleros-sdk): replace-graphql-request-library-with-native-fetch --- kleros-sdk/package.json | 1 - .../actions/fetchIpfsJsonAction.ts | 2 +- .../dataMappings/actions/subgraphAction.ts | 2 +- .../src/requests/fetchDisputeDetails.ts | 24 +++++++++++++++--- .../requests/fetchDisputeTemplateFromId.ts | 25 ++++++++++++++++--- yarn.lock | 1 - 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index bb4c00e6f..b4b7a4b55 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -43,7 +43,6 @@ }, "dependencies": { "@reality.eth/reality-eth-lib": "^3.2.30", - "graphql-request": "^7.1.0", "mustache": "^4.2.0", "viem": "^2.21.26", "zod": "^3.22.4" diff --git a/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts b/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts index a6f3968eb..7a648dd02 100644 --- a/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts +++ b/kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts @@ -33,7 +33,7 @@ export const fetchIpfsJsonAction = async (mapping: FetchIpfsJsonMapping) => { throw new RequestError("Fetched data is not JSON", httpUri); } - const data = await response.json(); + const data = (await response.json()) as any; return createResultObject(data, seek, populate); }; diff --git a/kleros-sdk/src/dataMappings/actions/subgraphAction.ts b/kleros-sdk/src/dataMappings/actions/subgraphAction.ts index 4ef3373f0..d3d7b492b 100644 --- a/kleros-sdk/src/dataMappings/actions/subgraphAction.ts +++ b/kleros-sdk/src/dataMappings/actions/subgraphAction.ts @@ -13,7 +13,7 @@ export const subgraphAction = async (mapping: SubgraphMapping) => { body: JSON.stringify({ query, variables }), }); - const { data } = await response.json(); + const { data } = (await response.json()) as any; return createResultObject(data, seek, populate); }; diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts index 923efb95d..d0426dece 100644 --- a/kleros-sdk/src/requests/fetchDisputeDetails.ts +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -1,4 +1,3 @@ -import { request, gql } from "graphql-request"; import { RequestError } from "../errors"; type DisputeDetailsQueryResponse = { @@ -12,8 +11,8 @@ type DisputeDetailsQueryResponse = { }; }; -const fetchDisputeDetails = async (endpoint: string, id: bigint) => { - const query = gql` +const fetchDisputeDetails = async (endpoint: string, id: bigint): Promise => { + const query = ` query DisputeDetails($id: ID!) { dispute(id: $id) { arbitrated { @@ -28,7 +27,24 @@ const fetchDisputeDetails = async (endpoint: string, id: bigint) => { const variables = { id: id.toString() }; try { - return await request(endpoint, query, variables); + const response = await fetch(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ query, variables }), + }); + + if (!response.ok) { + const errorData = (await response.json()) as any; + throw new RequestError( + `Error querying Dispute Details: ${errorData?.errors?.[0]?.message || "Unknown error"}`, + endpoint + ); + } + + const json = (await response.json()) as { data: DisputeDetailsQueryResponse }; + return json.data; } catch (error: any) { if (error instanceof Error) { throw new RequestError(`Error querying Dispute Details: ${error.message}`, endpoint); diff --git a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts index 32c2d6ee6..3bd4da8fd 100644 --- a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts +++ b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts @@ -1,4 +1,3 @@ -import { request, gql } from "graphql-request"; import { RequestError } from "../errors"; type DisputeTemplateQueryResponse = { @@ -8,8 +7,8 @@ type DisputeTemplateQueryResponse = { }; }; -const fetchDisputeTemplateFromId = async (endpoint: string, id: number) => { - const query = gql` +const fetchDisputeTemplateFromId = async (endpoint: string, id: number): Promise => { + const query = ` query DisputeTemplate($id: ID!) { disputeTemplate(id: $id) { templateData @@ -19,8 +18,26 @@ const fetchDisputeTemplateFromId = async (endpoint: string, id: number) => { `; const variables = { id: id.toString() }; + try { - return await request(endpoint, query, variables); + const response = await fetch(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ query, variables }), + }); + + if (!response.ok) { + const errorData = (await response.json()) as any; + throw new RequestError( + `Error querying Dispute Template: ${errorData?.errors?.[0]?.message || "Unknown error"}`, + endpoint + ); + } + + const json = (await response.json()) as { data: DisputeTemplateQueryResponse }; + return json.data; } catch (error: any) { if (error instanceof Error) { throw new RequestError(`Error querying Dispute Template: ${error.message}`, endpoint); diff --git a/yarn.lock b/yarn.lock index 578b50acc..dd6522412 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7902,7 +7902,6 @@ __metadata: "@reality.eth/reality-eth-lib": "npm:^3.2.30" "@types/mustache": "npm:^4.2.5" "@vitest/ui": "npm:^1.1.3" - graphql-request: "npm:^7.1.0" mocha: "npm:^10.2.0" mustache: "npm:^4.2.0" rimraf: "npm:^6.0.1" From cab784b29e6d18eecd9db6149313ab6692380b09 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Thu, 24 Oct 2024 12:50:07 +0530 Subject: [PATCH 33/37] chore(kleros-sdk): use-urql-for-gql-queries --- kleros-sdk/package.json | 1 + .../src/requests/fetchDisputeDetails.ts | 58 +++++++++---------- .../requests/fetchDisputeTemplateFromId.ts | 52 ++++++++--------- yarn.lock | 30 ++++++++++ 4 files changed, 85 insertions(+), 56 deletions(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index b4b7a4b55..d6701c3ba 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -43,6 +43,7 @@ }, "dependencies": { "@reality.eth/reality-eth-lib": "^3.2.30", + "@urql/core": "^5.0.8", "mustache": "^4.2.0", "viem": "^2.21.26", "zod": "^3.22.4" diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts index d0426dece..61d99ebab 100644 --- a/kleros-sdk/src/requests/fetchDisputeDetails.ts +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -1,4 +1,5 @@ import { RequestError } from "../errors"; +import { cacheExchange, Client, CombinedError, fetchExchange, gql } from "@urql/core"; type DisputeDetailsQueryResponse = { dispute: { @@ -11,42 +12,41 @@ type DisputeDetailsQueryResponse = { }; }; -const fetchDisputeDetails = async (endpoint: string, id: bigint): Promise => { - const query = ` - query DisputeDetails($id: ID!) { - dispute(id: $id) { - arbitrated { - id - } - arbitrableChainId - externalDisputeId - templateId +const query = gql` + query DisputeDetails($id: ID!) { + dispute(id: $id) { + arbitrated { + id } + arbitrableChainId + externalDisputeId + templateId } - `; + } +`; + +const fetchDisputeDetails = async (endpoint: string, id: bigint) => { const variables = { id: id.toString() }; try { - const response = await fetch(endpoint, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ query, variables }), + const client = new Client({ + url: endpoint, + exchanges: [cacheExchange, fetchExchange], }); - if (!response.ok) { - const errorData = (await response.json()) as any; - throw new RequestError( - `Error querying Dispute Details: ${errorData?.errors?.[0]?.message || "Unknown error"}`, - endpoint - ); - } - - const json = (await response.json()) as { data: DisputeDetailsQueryResponse }; - return json.data; - } catch (error: any) { - if (error instanceof Error) { + return client + .query(query, variables) + .toPromise() + .then((res) => { + if (res?.error) { + throw res.error; + } + return res?.data; + }); + } catch (error: unknown) { + if (error instanceof CombinedError) { + throw error; + } else if (error instanceof Error) { throw new RequestError(`Error querying Dispute Details: ${error.message}`, endpoint); } throw new RequestError("An unknown error occurred while querying Dispute Details", endpoint); diff --git a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts index 3bd4da8fd..5d4a925b4 100644 --- a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts +++ b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts @@ -1,3 +1,4 @@ +import { cacheExchange, Client, CombinedError, fetchExchange, gql } from "@urql/core"; import { RequestError } from "../errors"; type DisputeTemplateQueryResponse = { @@ -6,40 +7,37 @@ type DisputeTemplateQueryResponse = { templateDataMappings: string; }; }; - -const fetchDisputeTemplateFromId = async (endpoint: string, id: number): Promise => { - const query = ` - query DisputeTemplate($id: ID!) { - disputeTemplate(id: $id) { - templateData - templateDataMappings - } +const query = gql` + query DisputeTemplate($id: ID!) { + disputeTemplate(id: $id) { + templateData + templateDataMappings } - `; + } +`; +const fetchDisputeTemplateFromId = async (endpoint: string, id: number) => { const variables = { id: id.toString() }; try { - const response = await fetch(endpoint, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ query, variables }), + const client = new Client({ + url: endpoint, + exchanges: [cacheExchange, fetchExchange], }); - if (!response.ok) { - const errorData = (await response.json()) as any; - throw new RequestError( - `Error querying Dispute Template: ${errorData?.errors?.[0]?.message || "Unknown error"}`, - endpoint - ); - } - - const json = (await response.json()) as { data: DisputeTemplateQueryResponse }; - return json.data; - } catch (error: any) { - if (error instanceof Error) { + return client + .query(query, variables) + .toPromise() + .then((res) => { + if (res?.error) { + throw res.error; + } + return res?.data; + }); + } catch (error: unknown) { + if (error instanceof CombinedError) { + throw error; + } else if (error instanceof Error) { throw new RequestError(`Error querying Dispute Template: ${error.message}`, endpoint); } throw new RequestError("An unknown error occurred while querying Dispute Template", endpoint); diff --git a/yarn.lock b/yarn.lock index dd6522412..1d7fc73bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,6 +5,18 @@ __metadata: version: 8 cacheKey: 10 +"@0no-co/graphql.web@npm:^1.0.5": + version: 1.0.9 + resolution: "@0no-co/graphql.web@npm:1.0.9" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + peerDependenciesMeta: + graphql: + optional: true + checksum: 3caf39263323ba2a51255035e92582573822d213117879e6d1b732e222a8d14fdc703828d46b4a46f86d2027ee08568196f1d64376ee74250fb58dc465698930 + languageName: node + linkType: hard + "@aashutoshrathi/word-wrap@npm:^1.2.3": version: 1.2.6 resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" @@ -7901,6 +7913,7 @@ __metadata: dependencies: "@reality.eth/reality-eth-lib": "npm:^3.2.30" "@types/mustache": "npm:^4.2.5" + "@urql/core": "npm:^5.0.8" "@vitest/ui": "npm:^1.1.3" mocha: "npm:^10.2.0" mustache: "npm:^4.2.0" @@ -13354,6 +13367,16 @@ __metadata: languageName: node linkType: hard +"@urql/core@npm:^5.0.8": + version: 5.0.8 + resolution: "@urql/core@npm:5.0.8" + dependencies: + "@0no-co/graphql.web": "npm:^1.0.5" + wonka: "npm:^6.3.2" + checksum: c973e6e89785ae45ef447726557143ce7bc9d9f5b887297f0b315b2ff546d20bdfb814a4c899644bd5c5814761fc8d75a8ac66f67f3d57a3c2eadd3ec88adb60 + languageName: node + linkType: hard + "@vitest/expect@npm:1.2.1": version: 1.2.1 resolution: "@vitest/expect@npm:1.2.1" @@ -41239,6 +41262,13 @@ __metadata: languageName: node linkType: hard +"wonka@npm:^6.3.2": + version: 6.3.4 + resolution: "wonka@npm:6.3.4" + checksum: 0f102630182828268b57b54102003449b97abbc2483392239baf856a2fca7b72ae9be67c208415124a3d26a320674ed64387e9bf07a8d0badedb5f607d2ccfdc + languageName: node + linkType: hard + "word-wrap@npm:^1.2.3, word-wrap@npm:~1.2.3": version: 1.2.3 resolution: "word-wrap@npm:1.2.3" From 0562712b450f2733ffc914439ed3d8c1fe90f7c1 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Thu, 24 Oct 2024 13:37:24 +0530 Subject: [PATCH 34/37] feat(kleros-sdk): gql-client-caching --- kleros-sdk/src/requests/fetchDisputeDetails.ts | 9 +++------ .../src/requests/fetchDisputeTemplateFromId.ts | 9 +++------ kleros-sdk/src/requests/gqlClient.ts | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 kleros-sdk/src/requests/gqlClient.ts diff --git a/kleros-sdk/src/requests/fetchDisputeDetails.ts b/kleros-sdk/src/requests/fetchDisputeDetails.ts index 61d99ebab..adb58c3f8 100644 --- a/kleros-sdk/src/requests/fetchDisputeDetails.ts +++ b/kleros-sdk/src/requests/fetchDisputeDetails.ts @@ -1,5 +1,6 @@ import { RequestError } from "../errors"; -import { cacheExchange, Client, CombinedError, fetchExchange, gql } from "@urql/core"; +import { CombinedError, gql } from "@urql/core"; +import getClient from "./gqlClient"; type DisputeDetailsQueryResponse = { dispute: { @@ -29,11 +30,7 @@ const fetchDisputeDetails = async (endpoint: string, id: bigint) => { const variables = { id: id.toString() }; try { - const client = new Client({ - url: endpoint, - exchanges: [cacheExchange, fetchExchange], - }); - + const client = getClient(endpoint); return client .query(query, variables) .toPromise() diff --git a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts index 5d4a925b4..acc57a3f3 100644 --- a/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts +++ b/kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts @@ -1,5 +1,6 @@ -import { cacheExchange, Client, CombinedError, fetchExchange, gql } from "@urql/core"; +import { CombinedError, gql } from "@urql/core"; import { RequestError } from "../errors"; +import getClient from "./gqlClient"; type DisputeTemplateQueryResponse = { disputeTemplate: { @@ -20,11 +21,7 @@ const fetchDisputeTemplateFromId = async (endpoint: string, id: number) => { const variables = { id: id.toString() }; try { - const client = new Client({ - url: endpoint, - exchanges: [cacheExchange, fetchExchange], - }); - + const client = getClient(endpoint); return client .query(query, variables) .toPromise() diff --git a/kleros-sdk/src/requests/gqlClient.ts b/kleros-sdk/src/requests/gqlClient.ts new file mode 100644 index 000000000..dcae74a31 --- /dev/null +++ b/kleros-sdk/src/requests/gqlClient.ts @@ -0,0 +1,18 @@ +import { cacheExchange, Client, fetchExchange } from "@urql/core"; + +const clients = new Map(); + +const getClient = (endpoint: string) => { + let client = clients.get(endpoint); + + if (!client) { + client = new Client({ + url: endpoint, + exchanges: [cacheExchange, fetchExchange], + }); + clients.set(endpoint, client); + } + return client; +}; + +export default getClient; From 078b23304e83915ab7b882957512d3feb8168221 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 25 Oct 2024 12:23:46 +0700 Subject: [PATCH 35/37] chore(sdk): release @kleros/kleros-sdk@2.1.6 --- kleros-sdk/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index d6701c3ba..e7516b31c 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-sdk", - "version": "2.1.4", + "version": "2.1.6", "description": "SDK for Kleros version 2", "repository": "git@github.com:kleros/kleros-v2.git", "author": "Kleros", From 128e1e5b6cc266ded69e780ef33dd4047facce6b Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 25 Oct 2024 12:44:18 +0700 Subject: [PATCH 36/37] chore(sdk): publish script --- kleros-sdk/package.json | 4 +++- kleros-sdk/scripts/publish.sh | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100755 kleros-sdk/scripts/publish.sh diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index e7516b31c..d15251fdc 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -30,7 +30,9 @@ "test": "vitest", "test:ui": "vitest --ui", "test:run": "vitest run", - "publish": "yarn npm publish" + "release:patch": "scripts/publish.sh patch", + "release:minor": "scripts/publish.sh minor", + "release:major": "scripts/publish.sh major" }, "devDependencies": { "@types/mustache": "^4.2.5", diff --git a/kleros-sdk/scripts/publish.sh b/kleros-sdk/scripts/publish.sh new file mode 100755 index 000000000..f0b957963 --- /dev/null +++ b/kleros-sdk/scripts/publish.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +#-------------------------------------- +# Error handling +#-------------------------------------- + +set -Ee +function _catch { + # Don't propagate to outer shell + exit 0 +} +function _finally { + # TODO: rollback version bump + rm -rf $SCRIPT_DIR/../dist +} +trap _catch ERR +trap _finally EXIT + +#-------------------------------------- + +# Check if any tracked files are currently changed, ignoring untracked files +if [ -n "$(git status --porcelain -uno)" ]; then + echo "Error: There are uncommitted changes in tracked files. Please commit or stash them before publishing." + exit 1 +fi + +yarn version $1 + +version=$(cat package.json | jq -r .version) +echo "Publishing version $version" + +git add package.json +git commit -m "chore(sdk): release @kleros/kleros-sdk@$version" +git tag "@kleros/kleros-sdk@$version" -m "@kleros/kleros-sdk@$version" +git push +git push --tags + +yarn clean +yarn build +yarn npm publish From d2cb2601127cb61ae7658e9e3c4b627bc2f12746 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 25 Oct 2024 12:44:32 +0700 Subject: [PATCH 37/37] chore(sdk): release @kleros/kleros-sdk@2.1.7 --- kleros-sdk/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kleros-sdk/package.json b/kleros-sdk/package.json index d15251fdc..cd19c32eb 100644 --- a/kleros-sdk/package.json +++ b/kleros-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-sdk", - "version": "2.1.6", + "version": "2.1.7", "description": "SDK for Kleros version 2", "repository": "git@github.com:kleros/kleros-v2.git", "author": "Kleros",