Skip to content

Commit dfe3858

Browse files
feat(kleros-sdk): Initial SDK documentation and README improvements
This commit introduces the first phase of enhancing the `kleros-sdk` package for better usability and maintainability. Key changes include: 1. **Enhanced README.md**: * Overhauled the README with a comprehensive introduction, installation instructions, a "Quick Start" guide, SDK configuration details, core concept explanations (Public Client, Data Mappings, Requests), and contribution guidelines. 2. **API Documentation (TSDoc)**: * Added TSDoc comments to functions and types in the following core modules: * `src/sdk.ts`: Documented `configureSDK` and `getPublicClient`. * `src/types/index.ts`: Documented `SdkConfig` and `GetDisputeParameters`. * `src/utils/getDispute.ts`: Refined existing TSDoc for the main `getDispute` utility function, detailing its parameters, return value, and potential errors. * `src/requests/gqlClient.ts`: Documented the internal GraphQL client helper. * `src/requests/fetchDisputeDetails.ts`: Documented the internal function for fetching dispute details from a subgraph. * `src/requests/fetchDisputeTemplateFromId.ts`: Documented the internal function for fetching dispute templates from a DTR subgraph. So far, my focus has been on establishing a solid foundation for the SDK's documentation, starting with the README and core utility/request functions. Next, I plan to dive deeper into the `dataMappings` module, which appears to contain a significant portion of the SDK's logic, and continue to add TSDoc comments throughout. I also plan to review error handling and build processes. I was about to start exploring the `dataMappings` module by examining its `index.ts` and `executeActions.ts` files to understand its public interface and internal workings, with the goal of adding comprehensive TSDoc comments.
1 parent 1ca9066 commit dfe3858

File tree

7 files changed

+483
-58
lines changed

7 files changed

+483
-58
lines changed

kleros-sdk/README.md

Lines changed: 156 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,164 @@
11
# @kleros/kleros-sdk
22

3-
_Archon's successor_
3+
**The official TypeScript SDK for interacting with the Kleros V2 protocol.**
44

5-
To run the data mappings tests, at the root folder level, do:
5+
_This SDK is the successor to Archon and provides developers with a comprehensive set of tools to build applications on top of Kleros._
6+
7+
## Table of Contents
8+
9+
- [Features](#features)
10+
- [Installation](#installation)
11+
- [Getting Started](#getting-started)
12+
- [Configuration](#configuration)
13+
- [Quick Start Example](#quick-start-example)
14+
- [Core Concepts](#core-concepts)
15+
- [Public Client](#public-client)
16+
- [Data Mappings](#data-mappings)
17+
- [Requests](#requests)
18+
- [API Documentation](#api-documentation)
19+
- [Examples](#examples)
20+
- [Contributing](#contributing)
21+
- [License](#license)
22+
23+
## Features
24+
25+
* **Viem Integration**: Leverages the power and efficiency of [Viem](httpsa://viem.sh/) for Ethereum blockchain interactions.
26+
* **Type-Safe**: Fully written in TypeScript for robust type checking and improved developer experience.
27+
* **Dispute Resolution**: Tools to fetch dispute details, and interact with the Kleros arbitration process.
28+
* **Data Handling**: Utilities for working with Kleros-specific data structures and evidence.
29+
* **Subgraph Interaction**: Functionality to query Kleros subgraphs for indexed data.
30+
* **IPFS Support**: Helpers for fetching data stored on IPFS.
31+
32+
## Installation
33+
34+
You can install the Kleros SDK using npm or yarn:
635

736
```bash
37+
# Using npm
38+
npm install @kleros/kleros-sdk viem
39+
40+
# Using yarn
41+
yarn add @kleros/kleros-sdk viem
42+
```
43+
44+
**Note:** `@kleros/kleros-sdk` has `viem` as a peer dependency, so you need to install it separately in your project.
45+
46+
## Getting Started
47+
48+
### Configuration
49+
50+
Before you can use the SDK, you need to configure it with a `viem` Public Client instance. This client will be used for all blockchain interactions.
51+
52+
```typescript
53+
import { configureSDK } from '@kleros/kleros-sdk';
54+
import { createPublicClient, http } from 'viem';
55+
import { mainnet } from 'viem/chains'; // Or your desired chain
56+
57+
// Create a viem public client
58+
const publicClient = createPublicClient({
59+
chain: mainnet,
60+
transport: http(), // Replace with your preferred transport (e.g., Infura, Alchemy)
61+
});
62+
63+
// Configure the Kleros SDK
64+
configureSDK({ client: publicClient });
65+
66+
console.log('Kleros SDK configured!');
67+
```
68+
69+
### Quick Start Example
70+
71+
Here's a simple example of how to fetch details for a specific dispute:
72+
73+
```typescript
74+
import { configureSDK, KlerosSDK } from '@kleros/kleros-sdk'; // Assuming KlerosSDK is the main class or namespace
75+
import { createPublicClient, http } from 'viem';
76+
import { mainnet } from 'viem/chains';
77+
78+
// Configure the SDK (as shown above)
79+
const publicClient = createPublicClient({
80+
chain: mainnet,
81+
transport: http(),
82+
});
83+
configureSDK({ client: publicClient });
84+
85+
// Example: Fetching dispute details (Illustrative - actual API might differ)
86+
// Replace with actual SDK usage once API is fully explored
87+
async function getDisputeExample(disputeId: string) {
88+
try {
89+
// Placeholder: Actual function to get dispute details needs to be identified
90+
// For now, we'll assume a function getDisputeDetails exists or similar
91+
// const disputeDetails = await KlerosSDK.getDisputeDetails(disputeId);
92+
// console.log('Dispute Details:', disputeDetails);
93+
94+
console.log(`Fetching details for dispute ${disputeId}... (Illustrative)`);
95+
// This part will be updated once the actual API for fetching disputes is clear.
96+
// For now, we refer to functions that might exist based on file names like 'getDispute.ts' or 'fetchDisputeDetails.ts'
97+
// For example, if 'getDispute' is the correct function:
98+
// import { getDispute } from '@kleros/kleros-sdk';
99+
// const dispute = await getDispute(disputeId, publicClient); // publicClient might be implicitly used or passed
100+
// console.log(dispute);
101+
102+
103+
} catch (error) {
104+
console.error('Error fetching dispute details:', error);
105+
}
106+
}
107+
108+
getDisputeExample('123'); // Replace '123' with an actual dispute ID
109+
```
110+
*Note: The Quick Start example is illustrative. The exact API usage, especially for fetching dispute details, will be refined as the SDK's public API is further clarified in subsequent steps.*
111+
112+
## Core Concepts
113+
114+
### Public Client
115+
116+
The SDK uses a `viem` Public Client for all on-chain interactions. You must provide this client during the SDK's configuration. This design gives you full control over the Ethereum connection (e.g., choice of RPC provider, chain).
117+
118+
### Data Mappings
119+
120+
The `dataMappings` module (found in `src/dataMappings`) is a powerful feature that allows for complex data retrieval and processing. It can execute a series of actions, such as:
121+
* Calling smart contract functions
122+
* Fetching JSON data from IPFS
123+
* Querying Kleros subgraphs
124+
It uses a template-based system to populate data structures based on the results of these actions. This is particularly useful for constructing the `metaEvidence` and `evidence` associated with disputes.
125+
126+
### Requests
127+
128+
The `requests` module (found in `src/requests`) provides functions for making specific queries, often to Kleros subgraphs via GraphQL. For example, `fetchDisputeDetails.ts` likely uses this module to retrieve detailed information about a dispute.
129+
130+
## API Documentation
131+
132+
Detailed API documentation will be generated from TSDoc comments and made available separately. (This will be addressed in Step 2 of the improvement plan).
133+
134+
For now, developers can explore the exported functions and types directly within their IDEs, leveraging TypeScript's autocompletion features.
135+
136+
## Examples
137+
138+
Additional runnable examples demonstrating various SDK features will be added to the `examples/` directory within this package. (This will be addressed in a later step of the improvement plan).
139+
140+
## Contributing
141+
142+
Contributions are welcome! If you find a bug, have a feature request, or want to contribute to the codebase, please:
143+
144+
1. Check the [issue tracker](https://github.com/kleros/kleros-v2/issues) for existing issues.
145+
2. Open a new issue if yours isn't listed.
146+
3. For code contributions, please fork the repository and submit a pull request to the `master` (or relevant development) branch.
147+
148+
We use ESLint for linting and Prettier for formatting. Please ensure your contributions adhere to these standards.
149+
150+
### Running Tests
151+
152+
To run the test suite (powered by Vitest):
153+
154+
```bash
155+
# From the root of the kleros-v2 monorepo
156+
yarn test packages/kleros-sdk
157+
158+
# Or, if you are inside the kleros-sdk package directory
8159
yarn test
9160
```
10161

11-
🚧 ⚖️ 🚧
162+
## License
163+
164+
This SDK is licensed under the [MIT License](./LICENSE).
Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
1-
import { RequestError } from "../errors";
2-
import { CombinedError, gql } from "@urql/core";
1+
import { RequestError, KlerosSDKError } from "../errors"; // Assuming KlerosSDKError as a base
2+
import { CombinedError, gql, type TypedDocumentNode } from "@urql/core";
33
import getClient from "./gqlClient";
44

5+
/**
6+
* Represents the structure of the response for a dispute details query.
7+
* @internal
8+
*/
59
type DisputeDetailsQueryResponse = {
610
dispute: {
11+
/** The address of the arbitrable contract involved in the dispute. */
712
arbitrated: {
813
id: string;
914
};
15+
/** The chain ID where the arbitrable contract resides. */
1016
arbitrableChainId: number;
17+
/** The identifier of the dispute within the context of the arbitrable contract. */
1118
externalDisputeId: number;
19+
/** The identifier of the dispute template associated with this dispute. */
1220
templateId: number;
13-
};
21+
} | null; // Dispute can be null if not found
1422
};
1523

16-
const query = gql`
24+
/**
25+
* GraphQL query to fetch core details of a dispute from a Kleros Core subgraph.
26+
* @internal
27+
*/
28+
const query: TypedDocumentNode<DisputeDetailsQueryResponse, { id: string }> = gql`
1729
query DisputeDetails($id: ID!) {
1830
dispute(id: $id) {
1931
arbitrated {
@@ -26,28 +38,63 @@ const query = gql`
2638
}
2739
`;
2840

29-
const fetchDisputeDetails = async (endpoint: string, id: bigint) => {
41+
/**
42+
* Fetches core details of a dispute from a specified Kleros Core subgraph.
43+
* This function is intended for internal use by the SDK, typically called by higher-level
44+
* functions like `getDispute`.
45+
*
46+
* @param {string} endpoint - The GraphQL endpoint URL of the Kleros Core subgraph.
47+
* @param {bigint} id - The unique identifier of the dispute (as a BigInt).
48+
* @returns {Promise<DisputeDetailsQueryResponse | undefined>} A promise that resolves to the dispute details
49+
* from the subgraph. Returns `undefined` if the
50+
* query is successful but yields no data.
51+
* @throws {CombinedError} If Urql client encounters a GraphQL error (e.g., network issues, invalid query).
52+
* This error object can contain multiple GraphQL errors.
53+
* @throws {RequestError} If there's a non-GraphQL error during the request or if the response
54+
* contains an error explicitly thrown by the promise chain.
55+
* @throws {KlerosSDKError} For other unexpected errors during the execution.
56+
*
57+
* @example
58+
* // Internal SDK usage:
59+
* // const disputeId = 123n;
60+
* // const coreSubgraphUrl = 'https://your-core-subgraph-url.com/graphql';
61+
* // try {
62+
* // const details = await fetchDisputeDetails(coreSubgraphUrl, disputeId);
63+
* // if (details?.dispute) {
64+
* // console.log('Arbitrated contract:', details.dispute.arbitrated.id);
65+
* // } else {
66+
* // console.log('Dispute not found.');
67+
* // }
68+
* // } catch (error) {
69+
* // console.error('Failed to fetch dispute details:', error);
70+
* // }
71+
*/
72+
const fetchDisputeDetails = async (endpoint: string, id: bigint): Promise<DisputeDetailsQueryResponse | undefined> => {
3073
const variables = { id: id.toString() };
3174

3275
try {
3376
const client = getClient(endpoint);
34-
return client
35-
.query<DisputeDetailsQueryResponse>(query, variables)
36-
.toPromise()
37-
.then((res) => {
38-
if (res?.error) {
39-
throw res.error;
40-
}
41-
return res?.data;
42-
});
77+
const result = await client
78+
.query<DisputeDetailsQueryResponse, { id: string }>(query, variables)
79+
.toPromise();
80+
81+
if (result.error) {
82+
// Let CombinedError be caught by the catch block for uniform error handling
83+
throw result.error;
84+
}
85+
return result.data;
4386
} catch (error: unknown) {
4487
if (error instanceof CombinedError) {
88+
// Re-throw to allow specific handling upstream if needed, or wrap if preferred
4589
throw error;
4690
} else if (error instanceof Error) {
47-
throw new RequestError(`Error querying Dispute Details: ${error.message}`, endpoint);
91+
// Wrap other errors in RequestError for consistent SDK error types
92+
throw new RequestError(`Error querying Dispute Details for ID ${id}: ${error.message}`, endpoint, { cause: error });
4893
}
49-
throw new RequestError("An unknown error occurred while querying Dispute Details", endpoint);
94+
// Fallback for unknown error types
95+
throw new KlerosSDKError(`An unknown error occurred while querying Dispute Details for ID ${id}`, { cause: error });
5096
}
5197
};
5298

5399
export default fetchDisputeDetails;
100+
```
Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
1-
import { CombinedError, gql } from "@urql/core";
2-
import { RequestError } from "../errors";
1+
import { CombinedError, gql, type TypedDocumentNode } from "@urql/core";
2+
import { RequestError, KlerosSDKError } from "../errors"; // Assuming KlerosSDKError as a base
33
import getClient from "./gqlClient";
44

5+
/**
6+
* Represents the structure of the response for a dispute template query from the DTR subgraph.
7+
* @internal
8+
*/
59
type DisputeTemplateQueryResponse = {
610
disputeTemplate: {
11+
/**
12+
* The raw template data, typically a JSON string defining the structure and questions of the dispute.
13+
*/
714
templateData: string;
15+
/**
16+
* JSON string defining how to fetch and map additional data required by the template.
17+
* This can include contract calls, IPFS fetches, or subgraph queries.
18+
*/
819
templateDataMappings: string;
9-
};
20+
} | null; // disputeTemplate can be null if not found
1021
};
11-
const query = gql`
22+
23+
/**
24+
* GraphQL query to fetch a dispute template from a Dispute Template Registry (DTR) subgraph.
25+
* @internal
26+
*/
27+
const query: TypedDocumentNode<DisputeTemplateQueryResponse, { id: string }> = gql`
1228
query DisputeTemplate($id: ID!) {
1329
disputeTemplate(id: $id) {
1430
templateData
@@ -17,28 +33,64 @@ const query = gql`
1733
}
1834
`;
1935

20-
const fetchDisputeTemplateFromId = async (endpoint: string, id: number) => {
36+
/**
37+
* Fetches a dispute template from a specified Dispute Template Registry (DTR) subgraph
38+
* based on its template ID.
39+
* This function is intended for internal use by the SDK, primarily by `getDispute`.
40+
*
41+
* @param {string} endpoint - The GraphQL endpoint URL of the DTR subgraph.
42+
* @param {number} id - The unique identifier of the dispute template.
43+
* @returns {Promise<DisputeTemplateQueryResponse | undefined>} A promise that resolves to the dispute template data.
44+
* Returns `undefined` if the query is successful but
45+
* yields no data (e.g., template not found).
46+
* @throws {CombinedError} If Urql client encounters a GraphQL error (e.g., network issues, invalid query).
47+
* This error object can contain multiple GraphQL errors.
48+
* @throws {RequestError} If there's a non-GraphQL error during the request or if the response
49+
* contains an error explicitly thrown by the promise chain.
50+
* @throws {KlerosSDKError} For other unexpected errors during the execution.
51+
*
52+
* @example
53+
* // Internal SDK usage:
54+
* // const templateId = 1;
55+
* // const dtrSubgraphUrl = 'https://your-dtr-subgraph-url.com/graphql';
56+
* // try {
57+
* // const templateResponse = await fetchDisputeTemplateFromId(dtrSubgraphUrl, templateId);
58+
* // if (templateResponse?.disputeTemplate) {
59+
* // console.log('Template Data:', templateResponse.disputeTemplate.templateData);
60+
* // } else {
61+
* // console.log('Dispute template not found.');
62+
* // }
63+
* // } catch (error) {
64+
* // console.error('Failed to fetch dispute template:', error);
65+
* // }
66+
*/
67+
const fetchDisputeTemplateFromId = async (endpoint: string, id: number): Promise<DisputeTemplateQueryResponse | undefined> => {
68+
// Convert ID to string for GraphQL variables, as GraphQL IDs are typically strings or numbers.
2169
const variables = { id: id.toString() };
2270

2371
try {
2472
const client = getClient(endpoint);
25-
return client
26-
.query<DisputeTemplateQueryResponse>(query, variables)
27-
.toPromise()
28-
.then((res) => {
29-
if (res?.error) {
30-
throw res.error;
31-
}
32-
return res?.data;
33-
});
73+
const result = await client
74+
.query<DisputeTemplateQueryResponse, { id: string }>(query, variables)
75+
.toPromise();
76+
77+
if (result.error) {
78+
// Let CombinedError be caught by the catch block for uniform error handling
79+
throw result.error;
80+
}
81+
return result.data;
3482
} catch (error: unknown) {
3583
if (error instanceof CombinedError) {
84+
// Re-throw to allow specific handling upstream if needed
3685
throw error;
3786
} else if (error instanceof Error) {
38-
throw new RequestError(`Error querying Dispute Template: ${error.message}`, endpoint);
87+
// Wrap other errors in RequestError for consistent SDK error types
88+
throw new RequestError(`Error querying Dispute Template for ID ${id}: ${error.message}`, endpoint, { cause: error });
3989
}
40-
throw new RequestError("An unknown error occurred while querying Dispute Template", endpoint);
90+
// Fallback for unknown error types
91+
throw new KlerosSDKError(`An unknown error occurred while querying Dispute Template for ID ${id}`, { cause: error });
4192
}
4293
};
4394

4495
export default fetchDisputeTemplateFromId;
96+
```

0 commit comments

Comments
 (0)